UNPKG

34.6 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4
5var _extends2 = require('babel-runtime/helpers/extends');
6
7var _extends3 = _interopRequireDefault(_extends2);
8
9var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
10
11var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
12
13var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
14
15var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
16
17var _inherits2 = require('babel-runtime/helpers/inherits');
18
19var _inherits3 = _interopRequireDefault(_inherits2);
20
21var _class, _temp; /* eslint-disable valid-jsdoc */
22
23
24var _react = require('react');
25
26var _react2 = _interopRequireDefault(_react);
27
28var _propTypes = require('prop-types');
29
30var _propTypes2 = _interopRequireDefault(_propTypes);
31
32var _classnames = require('classnames');
33
34var _classnames2 = _interopRequireDefault(_classnames);
35
36var _util = require('../util');
37
38var _tag = require('../tag');
39
40var _tag2 = _interopRequireDefault(_tag);
41
42var _input = require('../input');
43
44var _input2 = _interopRequireDefault(_input);
45
46var _icon = require('../icon');
47
48var _icon2 = _interopRequireDefault(_icon);
49
50var _base = require('./base');
51
52var _base2 = _interopRequireDefault(_base);
53
54var _util2 = require('./util');
55
56function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
57
58var bindCtx = _util.func.bindCtx,
59 noop = _util.func.noop;
60
61var isIE9 = _util.env.ieVersion === 9;
62
63/**
64 * 无障碍化注意事项:
65 * 1. Select 无搜索情况下,不应该让 Input 可focus,此时外层wrap必须可focus,并且需要相应focus事件让外边框发生变化
66 */
67
68// 自定义弹层:1. 不需要关心Menu的点击事件 2. 不需要关心dataSource变化
69
70/**
71 * Select
72 */
73var Select = (_temp = _class = function (_Base) {
74 (0, _inherits3.default)(Select, _Base);
75
76 function Select(props) {
77 (0, _classCallCheck3.default)(this, Select);
78
79 // @extend Base state
80 var _this = (0, _possibleConstructorReturn3.default)(this, _Base.call(this, props));
81
82 _this.handleWrapClick = function (e) {
83 // ignore click on input to choose text
84 if (e.target.nodeName !== 'INPUT') {
85 e.preventDefault();
86 }
87 _this.focusInput();
88 };
89
90 _this.handleArrowClick = function (e) {
91 e.preventDefault();
92 _this.focusInput();
93
94 // because of can not close Popup by click Input while hasSearch.
95 // so when Popup open and hasSearch, we should close Popup intentionally
96 _this.state.visible && _this.hasSearch() && _this.setVisible(false);
97 };
98
99 _this.handleClear = function (e) {
100 e.stopPropagation();
101
102 _this.handleChange(undefined, 'clear');
103 };
104
105 (0, _extends3.default)(_this.state, {
106 // search keyword
107 searchValue: 'searchValue' in props ? props.searchValue : ''
108 });
109
110 // because dataSource maybe updated while select a item, so we should cache choosen value's item
111 _this.valueDataSource = {
112 valueDS: [], // [{value,label}]
113 mapValueDS: {} // {value: {value,label}}
114 };
115
116 bindCtx(_this, ['handleMenuSelect', 'handleItemClick', 'handleSearch', 'handleSearchKeyDown', 'handleSelectAll']);
117 return _this;
118 }
119
120 Select.prototype.componentWillMount = function componentWillMount() {
121 this.dataStore.setOptions({
122 key: this.state.searchValue,
123 addonKey: this.props.mode === 'tag' // tag 模式手动输入的数据
124 });
125
126 _Base.prototype.componentWillMount.call(this);
127
128 // 根据value和计算后的dataSource,更新value对应的详细数据valueDataSource
129 if (typeof this.state.value !== 'undefined') {
130 this.valueDataSource = (0, _util2.getValueDataSource)(this.state.value, this.valueDataSource.mapValueDS, this.dataStore.getMapDS());
131 }
132
133 if (isIE9) {
134 this.ie9Hack();
135 }
136 };
137
138 Select.prototype.componentWillReceiveProps = function componentWillReceiveProps(nextProps) {
139 if ('searchValue' in nextProps) {
140 this.dataStore.setOptions({ key: nextProps.searchValue });
141 this.setState({
142 searchValue: typeof nextProps.searchValue === 'undefined' ? '' : nextProps.searchValue
143 });
144 }
145 if (this.props.mode !== nextProps.mode) {
146 this.dataStore.setOptions({
147 addonKey: nextProps.mode === 'tag'
148 });
149 }
150
151 this.dataStore.setOptions({
152 filter: nextProps.filter,
153 filterLocal: nextProps.filterLocal
154 });
155
156 if (nextProps.children !== this.props.children || nextProps.dataSource !== this.props.dataSource) {
157 var dataSource = this.setDataSource(nextProps);
158 this.setState({
159 dataSource: dataSource
160 });
161
162 // 远程数据有更新,并且还有搜索框
163 if (nextProps.showSearch && !nextProps.filterLocal && !nextProps.popupContent) {
164 this.setFirstHightLightKeyForMenu();
165 }
166 }
167
168 if ('value' in nextProps) {
169 this.setState({
170 value: nextProps.value
171 });
172
173 this.valueDataSource = (0, _util2.getValueDataSource)(nextProps.value, this.valueDataSource.mapValueDS, this.dataStore.getMapDS());
174 this.updateSelectAllYet(this.valueDataSource.value);
175 } else if ('defaultValue' in nextProps && nextProps.defaultValue === this.valueDataSource.value && (nextProps.children !== this.props.children || nextProps.dataSource !== this.props.dataSource)) {
176 //has defaultValue and value not changed and dataSource changed
177 this.valueDataSource = (0, _util2.getValueDataSource)(nextProps.defaultValue, this.valueDataSource.mapValueDS, this.dataStore.getMapDS());
178 }
179
180 if ('visible' in nextProps) {
181 this.setState({
182 visible: nextProps.visible
183 });
184 }
185 };
186
187 Select.prototype.componentDidMount = function componentDidMount() {
188 if (isIE9) {
189 this.ie9Hack();
190 }
191 _Base.prototype.componentDidMount.call(this);
192 };
193
194 // ie9 下 table-cell 布局不支持宽度超出隐藏
195
196
197 Select.prototype.ie9Hack = function ie9Hack() {
198 try {
199 var width = this.selectDOM.currentStyle.width;
200 this.setState({
201 fixWidth: width !== 'auto'
202 });
203 } catch (e) {
204 //
205 }
206 };
207
208 Select.prototype.componentDidUpdate = function componentDidUpdate(prevProps, prevState) {
209 var props = this.props;
210 // 随着输入自动伸展
211 if (/tag|multiple/.test(props.mode) && prevState.searchValue !== this.state.searchValue) {
212 this.syncWidth();
213 } else {
214 return _Base.prototype.componentDidUpdate.call(this, prevProps, prevState);
215 }
216 };
217
218 Select.prototype.useDetailValue = function useDetailValue() {
219 var _props = this.props,
220 popupContent = _props.popupContent,
221 useDetailValue = _props.useDetailValue,
222 dataSource = _props.dataSource;
223
224 return useDetailValue || popupContent && !dataSource;
225 };
226
227 Select.prototype.hasSearch = function hasSearch() {
228 var _props2 = this.props,
229 showSearch = _props2.showSearch,
230 mode = _props2.mode;
231
232 return showSearch || mode === 'tag';
233 };
234
235 /**
236 * Menu.Item onSelect
237 * @private
238 * @param {Array<string>} keys
239 * @
240 */
241
242
243 Select.prototype.handleMenuSelect = function handleMenuSelect(keys) {
244 var _props3 = this.props,
245 mode = _props3.mode,
246 readOnly = _props3.readOnly,
247 disabled = _props3.disabled;
248
249
250 if (readOnly || disabled) {
251 return false;
252 }
253
254 var isSingle = mode === 'single';
255
256 if (isSingle) {
257 // 单选
258 return this.handleSingleSelect(keys[0], 'itemClick');
259 } else {
260 // 正常多选
261 return this.handleMultipleSelect(keys, 'itemClick');
262 }
263 };
264
265 Select.prototype.handleItemClick = function handleItemClick() {
266 this.focusInput();
267 };
268
269 /**
270 * 单选模式
271 */
272
273
274 Select.prototype.handleSingleSelect = function handleSingleSelect(key, triggerType) {
275 var cacheValue = this.props.cacheValue;
276 // get data only from dataStore while cacheValue=false
277
278 var itemObj = (0, _util2.getValueDataSource)(key, cacheValue ? this.valueDataSource.mapValueDS : {}, this.dataStore.getMapDS());
279 this.valueDataSource = itemObj;
280
281 this.setVisible(false, triggerType);
282
283 if (this.useDetailValue()) {
284 return this.handleChange(itemObj.valueDS, triggerType);
285 } else {
286 this.handleChange(itemObj.value, triggerType, itemObj.valueDS);
287 }
288
289 this.setState({
290 highlightKey: key
291 });
292
293 // 清空搜索
294 if (!('searchValue' in this.props) && this.state.searchValue) {
295 this.handleSearchClear(triggerType);
296 }
297 };
298
299 /**
300 * 多选模式 multiple/tag
301 */
302
303
304 Select.prototype.handleMultipleSelect = function handleMultipleSelect(keys, triggerType) {
305 var _this2 = this;
306
307 var itemObj = (0, _util2.getValueDataSource)(keys, this.valueDataSource.mapValueDS, this.dataStore.getMapDS());
308
309 var _props4 = this.props,
310 cacheValue = _props4.cacheValue,
311 mode = _props4.mode,
312 hiddenSelected = _props4.hiddenSelected;
313
314 // cache those value maybe not exists in dataSource
315
316 if (cacheValue || mode === 'tag') {
317 this.valueDataSource = itemObj;
318 }
319
320 if (hiddenSelected) {
321 this.setVisible(false, triggerType);
322 }
323
324 if (this.useDetailValue()) {
325 this.handleChange(itemObj.valueDS, triggerType);
326 } else {
327 this.handleChange(itemObj.value, triggerType, itemObj.valueDS);
328 }
329
330 this.updateSelectAllYet(itemObj.value);
331
332 // 清空搜索
333 if (!('searchValue' in this.props) && this.state.searchValue) {
334 // 因为 SearchValue 被 clear 后会重新渲染 Menu,所以在 Overlay 检测 safeNode 的时候 e.target 可能会找不到导致弹窗关闭
335 setTimeout(function () {
336 _this2.handleSearchClear(triggerType);
337 });
338 }
339 };
340
341 Select.prototype.updateSelectAllYet = function updateSelectAllYet(value) {
342 var _this3 = this;
343
344 // multiple mode
345 // is current state select all or not
346 this.selectAllYet = false;
347 if (this.props.hasSelectAll && Array.isArray(value)) {
348 var selectAllValues = this.dataStore.getEnableDS().map(function (item) {
349 return item.value;
350 });
351
352 if (selectAllValues.length <= value.length) {
353 this.selectAllYet = true;
354
355 selectAllValues.forEach(function (val) {
356 if (value.indexOf(val) === -1) {
357 _this3.selectAllYet = false;
358 return;
359 }
360 });
361 }
362 }
363 };
364
365 Select.prototype.handleSearchValue = function handleSearchValue(value) {
366 if (this.state.searchValue === value) {
367 return;
368 }
369
370 var filterLocal = this.props.filterLocal;
371
372
373 if (filterLocal) {
374 if (!('searchValue' in this.props)) {
375 this.setState({
376 searchValue: value,
377 dataSource: this.dataStore.updateByKey(value)
378 });
379 this.setFirstHightLightKeyForMenu();
380 }
381 } else if (!('searchValue' in this.props)) {
382 this.setState({
383 searchValue: value
384 });
385 }
386 };
387
388 /**
389 * Handle search input change event
390 * @param {Event} e change Event
391 */
392
393
394 Select.prototype.handleSearch = function handleSearch(value) {
395 this.handleSearchValue(value);
396
397 // inputing should trigger popup open
398 if (!this.state.visible && value) {
399 this.setVisible(true);
400 }
401
402 this.props.onSearch(value);
403 };
404
405 Select.prototype.handleSearchClear = function handleSearchClear(triggerType) {
406 this.handleSearchValue('');
407 this.props.onSearchClear(triggerType);
408 };
409
410 // 搜索框 keyDown 事件
411
412
413 Select.prototype.handleSearchKeyDown = function handleSearchKeyDown(e) {
414 var _props5 = this.props,
415 popupContent = _props5.popupContent,
416 onKeyDown = _props5.onKeyDown,
417 showSearch = _props5.showSearch,
418 mode = _props5.mode,
419 hasClear = _props5.hasClear,
420 onToggleHighlightItem = _props5.onToggleHighlightItem;
421
422
423 if (popupContent) {
424 return onKeyDown(e);
425 }
426
427 var proxy = 'search';
428 var hasSearch = this.hasSearch();
429
430 switch (e.keyCode) {
431 case _util.KEYCODE.UP:
432 e.preventDefault();
433 onToggleHighlightItem(this.toggleHighlightItem(-1, e), 'up');
434 break;
435 case _util.KEYCODE.DOWN:
436 e.preventDefault();
437 onToggleHighlightItem(this.toggleHighlightItem(1, e), 'down');
438 break;
439 case _util.KEYCODE.ENTER:
440 e.preventDefault();
441 this.chooseHighlightItem(proxy, e);
442 break;
443 case _util.KEYCODE.ESC:
444 e.preventDefault();
445 this.state.visible && this.setVisible(false, 'keyDown');
446 break;
447 case _util.KEYCODE.SPACE:
448 e.stopPropagation();
449 !hasSearch && e.preventDefault();
450 break;
451 case _util.KEYCODE.BACKSPACE:
452 if (mode === 'multiple' && showSearch || mode === 'tag') {
453 // 在多选并且有搜索的情况下,删除最后一个 tag
454 this.handleDeleteTag(e);
455 } else if (mode === 'single' && hasClear && !this.state.visible) {
456 // 单选、非展开、并且可清除的情况,允许按删除键清除
457 this.handleClear(e);
458 }
459 break;
460 default:
461 break;
462 }
463
464 onKeyDown(e);
465 };
466
467 Select.prototype.chooseMultipleItem = function chooseMultipleItem(key) {
468 var value = this.state.value || [];
469 var keys = value.map(function (v) {
470 return (0, _util2.valueToSelectKey)(v);
471 });
472
473 var index = keys.map(function (v) {
474 return '' + v;
475 }).indexOf(key);
476
477 if (index > -1) {
478 // unselect
479 keys.splice(index, 1);
480 } else {
481 // select
482 keys.push(key);
483 }
484
485 this.handleMultipleSelect(keys, 'enter');
486 };
487
488 // 回车 选择高亮的 item
489
490
491 Select.prototype.chooseHighlightItem = function chooseHighlightItem(proxy, e) {
492 var prevVisible = this.state.visible;
493 var mode = this.props.mode;
494
495
496 if (!prevVisible) {
497 // input tag by itself
498 if (mode === 'tag' && this.state.searchValue) {
499 this.chooseMultipleItem(this.state.searchValue);
500 }
501 return false;
502 }
503
504 var highlightKey = this.state.highlightKey;
505
506 // 没有高亮选项 或者 没有可选菜单
507
508 if (highlightKey === null || !this.dataStore.getMenuDS().length) {
509 return;
510 }
511
512 if (mode === 'single') {
513 this.handleSingleSelect(highlightKey, 'enter');
514 } else {
515 this.chooseMultipleItem(highlightKey);
516 // 阻止事件冒泡到最外层,让Popup 监听到触发弹层关闭
517 e && e.stopPropagation();
518 }
519 };
520
521 /**
522 * Handle Tag close event
523 * @param {Object} item
524 * @return {Boolean} false return false to prevent auto close
525 * ----
526 * It MUST be multiple mode, needn't additional judgement
527 */
528
529
530 Select.prototype.handleTagClose = function handleTagClose(item) {
531 if (this.useDetailValue()) {
532 var value = this.state.value.filter(function (v) {
533 return item.value !== v.value;
534 });
535
536 this.handleChange(value, 'tag');
537 } else {
538 // filter out current item, and then call handleMenuSelect
539 var _value = this.state.value.filter(function (v) {
540 return item.value !== v;
541 });
542
543 this.handleMultipleSelect(_value, 'tag');
544 }
545
546 this.props.onRemove(item);
547
548 // prevent tag close
549 return false;
550 };
551
552 // eslint-disable-next-line valid-jsdoc
553 /**
554 * Handle BACKSPACE key event
555 * @param {Event} e keyDown event
556 * ---
557 * It MUST be multiple mode
558 */
559
560
561 Select.prototype.handleDeleteTag = function handleDeleteTag(e) {
562 var value = this.state.value;
563 var searchValue = this.state.searchValue;
564
565 if (searchValue || !value || !value.length) {
566 return false;
567 }
568
569 e.preventDefault();
570
571 var nextValues = value.slice(0, value.length - 1);
572 // 手动调用 handleMenuSelect 时直接传入原生的 value,可以减少 toString 的操作
573
574 if (this.useDetailValue()) {
575 this.handleChange(nextValues, 'tag');
576 } else {
577 this.handleMultipleSelect(nextValues, 'tag');
578 }
579 };
580
581 /**
582 * Handle SelectAll span click event
583 * @param {Event} e click event
584 */
585
586
587 Select.prototype.handleSelectAll = function handleSelectAll(e) {
588 e && e.preventDefault();
589 var nextValues = void 0;
590
591 if (this.selectAllYet) {
592 nextValues = [];
593 } else {
594 nextValues = this.dataStore.getEnableDS().map(function (item) {
595 return item.value;
596 });
597 }
598
599 // 直接传 values,减少 toString 操作
600 this.handleMultipleSelect(nextValues, 'selectAll');
601 };
602
603 Select.prototype.handleVisibleChange = function handleVisibleChange(visible, type) {
604 this.setVisible(visible, type);
605 };
606
607 Select.prototype.afterClose = function afterClose() {
608 // 关闭的时候清空搜索值
609 if (this.hasSearch()) {
610 this.handleSearchClear('popupClose');
611 }
612 };
613
614 /**
615 * 如果用户是自定义的弹层,则直接以 value 为准,不再校验 dataSource
616 * @param {object} props
617 */
618
619
620 Select.prototype.renderValues = function renderValues() {
621 var _this4 = this;
622
623 var _props6 = this.props,
624 mode = _props6.mode,
625 size = _props6.size,
626 valueRender = _props6.valueRender,
627 fillProps = _props6.fillProps,
628 disabled = _props6.disabled;
629
630 var value = this.state.value;
631
632 if ((0, _util2.isNull)(value)) {
633 return null;
634 }
635
636 // get detail value
637 if (!this.useDetailValue()) {
638 if (value === this.valueDataSource.value) {
639 value = this.valueDataSource.valueDS;
640 } else {
641 value = (0, _util2.getValueDataSource)(value, this.valueDataSource.mapValueDS, this.dataStore.getMapDS()).valueDS;
642 }
643 }
644
645 if (mode === 'single') {
646 if (!value) {
647 return null;
648 }
649
650 var retvalue = fillProps ? value[fillProps] : valueRender(value);
651 // 0 => '0'
652 return typeof retvalue === 'number' ? retvalue.toString() : retvalue;
653 } else if (value) {
654 if (!Array.isArray(value)) {
655 value = [value];
656 }
657 return value.map(function (v) {
658 if (!v) {
659 return null;
660 }
661
662 var labelNode = fillProps ? v[fillProps] : valueRender(v);
663 return _react2.default.createElement(
664 _tag2.default,
665 {
666 key: v.value,
667 disabled: disabled || v.disabled,
668 type: 'primary',
669 size: size === 'large' ? 'medium' : 'small',
670 animation: false,
671 onClose: _this4.handleTagClose.bind(_this4, v),
672 closable: true
673 },
674 labelNode
675 );
676 });
677 }
678
679 return null;
680 };
681 /**
682 * 1. fix flash while click <label/>
683 * 2. fix onBlur while has clear
684 * @returns
685 */
686
687
688 Select.prototype.hasClear = function hasClear() {
689 var _props7 = this.props,
690 hasClear = _props7.hasClear,
691 readOnly = _props7.readOnly,
692 disabled = _props7.disabled,
693 mode = _props7.mode,
694 showSearch = _props7.showSearch;
695 var _state = this.state,
696 value = _state.value,
697 visible = _state.visible;
698
699
700 return typeof value !== 'undefined' && hasClear && !readOnly && !disabled && mode === 'single' && !(showSearch && visible);
701 };
702
703 /**
704 * render arrow
705 * @param {object} props
706 * @param {function} [clickHandler]
707 */
708
709
710 Select.prototype.renderExtraNode = function renderExtraNode() {
711 var _props8 = this.props,
712 hasArrow = _props8.hasArrow,
713 hasClear = _props8.hasClear,
714 prefix = _props8.prefix;
715
716
717 var ret = [];
718
719 if (hasArrow) {
720 ret.push(_react2.default.createElement(
721 'span',
722 {
723 key: 'arrow',
724 'aria-hidden': true,
725 onClick: this.handleArrowClick,
726 className: prefix + 'select-arrow'
727 },
728 _react2.default.createElement(_icon2.default, { type: 'arrow-down' })
729 ));
730 }
731
732 // do not use this.hasClear() here, to make sure clear btn always exists, can not influenced by apis like `disabled` `readOnly`
733 if (hasClear) {
734 ret.push(_react2.default.createElement(
735 'span',
736 {
737 key: 'clear',
738 'aria-hidden': true,
739 onClick: this.handleClear,
740 className: prefix + 'select-clear'
741 },
742 _react2.default.createElement(_icon2.default, { type: 'delete-filling' })
743 ));
744 }
745
746 return ret;
747 };
748
749 /**
750 * 选择器
751 * @override
752 * @param {object} props
753 */
754
755
756 Select.prototype.renderSelect = function renderSelect() {
757 var _classNames,
758 _this5 = this;
759
760 var _props9 = this.props,
761 prefix = _props9.prefix,
762 showSearch = _props9.showSearch,
763 placeholder = _props9.placeholder,
764 mode = _props9.mode,
765 size = _props9.size,
766 className = _props9.className,
767 style = _props9.style,
768 readOnly = _props9.readOnly,
769 disabled = _props9.disabled,
770 hasBorder = _props9.hasBorder,
771 label = _props9.label,
772 locale = _props9.locale,
773 state = _props9.state,
774 onBlur = _props9.onBlur,
775 onFocus = _props9.onFocus,
776 rtl = _props9.rtl;
777
778 var others = _util.obj.pickOthers(Select.propTypes, this.props);
779 var othersData = _util.obj.pickAttrsWith(others, 'data-');
780
781 var visible = this.state.visible;
782 var isSingle = mode === 'single';
783 var hasSearch = this.hasSearch();
784 var valueNodes = this.renderValues();
785
786 // compatible with selectPlaceHolder. TODO: removed in 2.0 version
787 var _placeholder = placeholder || locale.selectPlaceholder || locale.selectPlaceHolder;
788 if (valueNodes && valueNodes.length) {
789 _placeholder = null;
790 }
791
792 // 弹窗展开时将当前的值作为 placeholder,这个功能的前提是 valueNode 必须是一个字符串
793 if (showSearch && visible && isSingle && typeof valueNodes === 'string') {
794 _placeholder = valueNodes;
795 }
796
797 // 下拉箭头
798 var extra = this.renderExtraNode();
799
800 var triggerClazz = (0, _classnames2.default)([prefix + 'select', prefix + 'select-trigger', prefix + 'select-' + mode, '' + prefix + size, className], (_classNames = {}, _classNames[prefix + 'active'] = visible, _classNames[prefix + 'inactive'] = !visible, _classNames[prefix + 'no-search'] = !hasSearch, _classNames[prefix + 'has-search'] = hasSearch, _classNames[prefix + 'select-in-ie'] = isIE9, _classNames[prefix + 'select-in-ie-fixwidth'] = this.state.fixWidth, _classNames[prefix + 'has-clear'] = this.hasClear(), _classNames));
801
802 var valuetext = this.valueDataSource.valueDS ? this.valueDataSource.valueDS.label : '';
803
804 return _react2.default.createElement(
805 'span',
806 (0, _extends3.default)({}, othersData, {
807 className: triggerClazz,
808 style: style,
809 dir: rtl ? 'rtl' : undefined,
810 ref: this.saveSelectRef,
811 onClick: this.handleWrapClick,
812 onMouseDown: this.handleWrapClick
813 }),
814 _react2.default.createElement(_input2.default, (0, _extends3.default)({
815 'aria-valuetext': valuetext
816 }, _util.obj.pickOthers(othersData, others), {
817 role: 'combobox',
818 tabIndex: 0,
819 'aria-expanded': this.state.visible,
820 'aria-disabled': disabled,
821 state: state,
822 label: label,
823 extra: extra,
824 value: this.state.searchValue,
825 size: size,
826 readOnly: !this.hasSearch() || readOnly,
827 disabled: disabled,
828 placeholder: _placeholder,
829 hasBorder: hasBorder,
830 hasClear: false,
831 htmlSize: '1',
832 inputRender: function inputRender(inputEl) {
833 return _this5.renderSearchInput(valueNodes, _placeholder, inputEl);
834 },
835 onChange: this.handleSearch,
836 onKeyDown: this.handleSearchKeyDown,
837 onFocus: onFocus,
838 onBlur: onBlur,
839 className: prefix + 'select-inner',
840 ref: this.saveInputRef
841 })),
842 _react2.default.createElement(
843 'span',
844 { className: prefix + 'sr-only', 'aria-live': 'polite' },
845 this.state.srReader
846 )
847 );
848 };
849
850 Select.prototype.renderSearchInput = function renderSearchInput(valueNodes, placeholder, inputEl) {
851 var _classNames2;
852
853 var _props10 = this.props,
854 prefix = _props10.prefix,
855 mode = _props10.mode;
856
857 var isSingle = mode === 'single';
858
859 var mirrorText = this.state.searchValue;
860
861 var cls = (0, _classnames2.default)((_classNames2 = {}, _classNames2[prefix + 'select-values'] = true, _classNames2[prefix + 'input-text-field'] = true, _classNames2));
862
863 return _react2.default.createElement(
864 'span',
865 { className: cls },
866 isSingle && valueNodes ? _react2.default.createElement(
867 'em',
868 null,
869 valueNodes
870 ) : valueNodes,
871 _react2.default.createElement(
872 'span',
873 { className: prefix + 'select-trigger-search' },
874 inputEl,
875 _react2.default.createElement(
876 'span',
877 { 'aria-hidden': true },
878 mirrorText || placeholder,
879 '\xA0'
880 )
881 )
882 );
883 };
884
885 /**
886 * 渲染弹层的 header 内容
887 * @override
888 * @param {object} props
889 */
890
891
892 Select.prototype.renderMenuHeader = function renderMenuHeader() {
893 var _classNames3, _classNames4;
894
895 var _props11 = this.props,
896 prefix = _props11.prefix,
897 hasSelectAll = _props11.hasSelectAll,
898 mode = _props11.mode;
899
900
901 var sourceCount = this.dataStore.getEnableDS().length;
902 // 多选模式下才有全选
903 if (!hasSelectAll || mode === 'single' || !sourceCount) {
904 return null;
905 }
906
907 var text = typeof hasSelectAll === 'boolean' ? 'Select All' : hasSelectAll;
908
909 var selectAllYet = this.selectAllYet;
910
911 var cls = (0, _classnames2.default)((_classNames3 = {}, _classNames3[prefix + 'select-all'] = true, _classNames3[prefix + 'selected'] = selectAllYet, _classNames3));
912
913 var clsInner = (0, _classnames2.default)((_classNames4 = {}, _classNames4[prefix + 'select-all-inner'] = true, _classNames4));
914
915 // remove style={{'lineHeight': 'unset'}} in next Y
916 // remove style={{'display': 'none'}} in next Y
917 return _react2.default.createElement(
918 'div',
919 {
920 key: 'all',
921 onClick: this.handleSelectAll,
922 className: cls,
923 style: { lineHeight: 'unset' }
924 },
925 selectAllYet ? _react2.default.createElement(_icon2.default, {
926 className: prefix + 'menu-icon-selected',
927 style: { display: 'none' },
928 type: 'select'
929 }) : null,
930 _react2.default.createElement(
931 'span',
932 { className: clsInner },
933 text
934 )
935 );
936 };
937
938 Select.prototype.render = function render() {
939 var mode = this.props.mode;
940
941 var props = (0, _extends3.default)({}, this.props);
942
943 // forbid to close Popup by click Input while hasSearch
944 if (this.hasSearch()) {
945 props.canCloseByTrigger = false;
946 }
947 if (mode === 'single') {
948 props.cache = true;
949 }
950 return _Base.prototype.render.call(this, props);
951 };
952
953 return Select;
954}(_base2.default), _class.propTypes = (0, _extends3.default)({}, _base2.default.propTypes, {
955 /**
956 * 选择器模式
957 */
958 mode: _propTypes2.default.oneOf(['single', 'multiple', 'tag']),
959 /**
960 * 当前值,用于受控模式
961 */
962 value: _propTypes2.default.any,
963 /**
964 * 初始的默认值
965 */
966 defaultValue: _propTypes2.default.any,
967 /**
968 * Select发生改变时触发的回调
969 * @param {*} value 选中的值
970 * @param {String} actionType 触发的方式, 'itemClick', 'enter', 'tag'
971 * @param {*} item 选中的值的对象数据 (useDetailValue=false有效)
972 */
973 onChange: _propTypes2.default.func,
974 /**
975 * 传入的数据源,可以动态渲染子项,详见 [dataSource的使用](#dataSource的使用)
976 */
977 dataSource: _propTypes2.default.arrayOf(_propTypes2.default.oneOfType([_propTypes2.default.shape({
978 value: _propTypes2.default.any,
979 label: _propTypes2.default.any,
980 disabled: _propTypes2.default.bool,
981 children: _propTypes2.default.array
982 }), _propTypes2.default.bool, _propTypes2.default.number, _propTypes2.default.string])),
983 /**
984 * 是否有边框
985 */
986 hasBorder: _propTypes2.default.bool,
987 /**
988 * 是否有下拉箭头
989 */
990 hasArrow: _propTypes2.default.bool,
991 /**
992 * 展开后是否能搜索(tag 模式下固定为true)
993 */
994 showSearch: _propTypes2.default.bool,
995 /**
996 * 当搜索框值变化时回调
997 * @param {String} value 数据
998 */
999 onSearch: _propTypes2.default.func,
1000 /**
1001 * 当搜索框值被清空时候的回调
1002 * @param {String} actionType 触发的方式, 'select'(选择清空), 'popupClose'(弹窗关闭清空)
1003 */
1004 onSearchClear: _propTypes2.default.func,
1005 /**
1006 * 多选模式下是否有全选功能
1007 */
1008 hasSelectAll: _propTypes2.default.oneOfType([_propTypes2.default.bool, _propTypes2.default.string]),
1009 /**
1010 * 填充到选择框里的值的 key
1011 */
1012 fillProps: _propTypes2.default.string,
1013 /**
1014 * onChange 返回的 value 使用 dataSource 的对象
1015 */
1016 useDetailValue: _propTypes2.default.bool,
1017 /**
1018 * dataSource 变化的时是否保留已选的内容
1019 */
1020 cacheValue: _propTypes2.default.bool,
1021 /**
1022 * 渲染 Select 展现内容的方法
1023 * @param {Object} item 渲染节点的item
1024 * @return {ReactNode} 展现内容
1025 * @default item => item.label \|\| item.value
1026 */
1027 valueRender: _propTypes2.default.func,
1028 /**
1029 * 渲染 MenuItem 内容的方法
1030 * @param {Object} item 渲染节点的item
1031 * @param {String} searchValue 搜索关键字(如果开启搜索)
1032 * @return {ReactNode} item node
1033 */
1034 itemRender: _propTypes2.default.func,
1035 /**
1036 * 弹层内容为空的文案
1037 */
1038 notFoundContent: _propTypes2.default.node,
1039 style: _propTypes2.default.object,
1040 /**
1041 * 受控搜索值,一般不需要设置
1042 * @type {[type]}
1043 */
1044 searchValue: _propTypes2.default.string,
1045 /**
1046 * 选择后是否立即隐藏菜单 (mode=multiple/tag 模式生效)
1047 */
1048 hiddenSelected: _propTypes2.default.bool,
1049 /**
1050 * tag 删除回调
1051 * @param {object} item 渲染节点的item
1052 */
1053 onRemove: _propTypes2.default.func,
1054 /**
1055 * 焦点事件
1056 */
1057 onFocus: _propTypes2.default.func,
1058 /**
1059 * 是否自动高亮第一个选项
1060 */
1061 // highlightFirstItem: PropTypes.bool,
1062 /**
1063 * 失去焦点事件
1064 */
1065 onBlur: _propTypes2.default.func,
1066 onKeyDown: _propTypes2.default.func
1067}), _class.defaultProps = (0, _extends3.default)({}, _base2.default.defaultProps, {
1068 mode: 'single',
1069 showSearch: false,
1070 cacheValue: true,
1071 onSearch: noop,
1072 onSearchClear: noop,
1073 hasArrow: true,
1074 onRemove: noop,
1075 // highlightFirstItem: true,
1076 valueRender: function valueRender(item) {
1077 return item.label || item.value;
1078 },
1079 onKeyDown: noop,
1080 onFocus: noop,
1081 onBlur: noop
1082}), _class.displayName = 'Select', _temp);
1083exports.default = Select;
1084module.exports = exports['default'];
\No newline at end of file