UNPKG

yqcloud-ui

Version:

An enterprise-class UI design language and React-based implementation

1,587 lines (1,447 loc) 47 kB
import _defineProperty from 'babel-runtime/helpers/defineProperty'; import _extends from 'babel-runtime/helpers/extends'; import _classCallCheck from 'babel-runtime/helpers/classCallCheck'; import _possibleConstructorReturn from 'babel-runtime/helpers/possibleConstructorReturn'; import _inherits from 'babel-runtime/helpers/inherits'; /* eslint func-names: 1 */ import React from 'react'; import ReactDOM from 'react-dom'; import KeyCode from '../util/KeyCode'; import childrenToArray from '../util/Children/toArray'; import classnames from 'classnames'; import classes from 'component-classes'; import { Item as MenuItem, ItemGroup as MenuItemGroup } from '../menu'; import warning from 'warning'; import Option from './Option'; import Button from '../../button'; import Ripple from '../../ripple'; import { defaultFilterFn, findFirstMenuItem, findIndexInValueBySingleValue, getLabelFromPropsValue, getMapKey, getPropValue, getValuePropValue, includesSeparators, isCombobox, isMultiple, isMultipleOrTags, isMultipleOrTagsOrCombobox, isSingleMode, isTags, preventDefaultEvent, saveRef, splitBySeparators, toArray, UNSELECTABLE_ATTRIBUTE, UNSELECTABLE_STYLE, validateOptionValue } from './util'; import SelectTrigger from './SelectTrigger'; import { SelectPropTypes } from './PropTypes'; function noop() {} function chaining() { for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) { fns[_key] = arguments[_key]; } return function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } // eslint-disable-line // eslint-disable-line for (var i = 0; i < fns.length; i++) { if (fns[i] && typeof fns[i] === 'function') { fns[i].apply(this, args); } } }; } var BUILT_IN_PLACEMENTS = { bottomLeft: { points: ['tl', 'tl'], offset: [0, 4], overflow: { adjustX: 0, adjustY: 1 } }, topLeft: { points: ['bl', 'bl'], offset: [0, -4], overflow: { adjustX: 0, adjustY: 1 } }, bottomRight: { points: ['tr', 'tr'], offset: [0, 4], overflow: { adjustX: 0, adjustY: 1 } } }; var BUILT_IN_PLACEMENTS_LABEL = { bottomLeft: { points: ['tl', 'tl'], offset: [0, 19], overflow: { adjustX: 0, adjustY: 1 } }, topLeft: { points: ['bl', 'bl'], offset: [0, -4], overflow: { adjustX: 0, adjustY: 1 } }, bottomRight: { points: ['tr', 'tr'], offset: [0, 19], overflow: { adjustX: 0, adjustY: 1 } } }; var Select = function (_React$Component) { _inherits(Select, _React$Component); function Select(props) { _classCallCheck(this, Select); var _this = _possibleConstructorReturn(this, _React$Component.call(this, props)); _initialiseProps.call(_this); var value = _this.getValueFromProps(props); var optionsInfo = _this.getOptionsInfoFromProps(props); var inputValue = ''; if (props.combobox) { inputValue = value.length ? _this.getLabelBySingleValue(value[0], optionsInfo) : ''; } var open = props.open; if (open === undefined) { open = props.defaultOpen; } var filterValue = props.filterValue || ''; _this.state = { value: value, inputValue: inputValue, open: open, optionsInfo: optionsInfo, filterValue: filterValue }; _this.adjustOpenState(); return _this; } Select.prototype.componentDidMount = function componentDidMount() { if (this.props.autoFocus) { this.focus(); } }; Select.prototype.componentWillUpdate = function componentWillUpdate(nextProps, nextState) { this.props = nextProps; this.state = nextState; this.adjustOpenState(); }; Select.prototype.componentDidUpdate = function componentDidUpdate() { if (isMultipleOrTags(this.props)) { var inputNode = this.getInputDOMNode(); var mirrorNode = this.getInputMirrorDOMNode(); if (inputNode.value) { inputNode.style.width = ''; inputNode.style.width = mirrorNode.clientWidth + 'px'; } else { inputNode.style.width = ''; } this.onChoiceAnimationLeave(); } }; Select.prototype.componentWillUnmount = function componentWillUnmount() { this.clearFocusTime(); this.clearBlurTime(); this.clearAdjustTimer(); if (this.dropdownContainer) { ReactDOM.unmountComponentAtNode(this.dropdownContainer); document.body.removeChild(this.dropdownContainer); this.dropdownContainer = null; } }; // combobox ignore Select.prototype.getBuiltinPlacements = function getBuiltinPlacements() { var _props = this.props, builtinPlacements = _props.builtinPlacements, label = _props.label; if (builtinPlacements) { return builtinPlacements; } if (!isTags(this.props) && !isCombobox(this.props)) { if (label) { return BUILT_IN_PLACEMENTS_LABEL; } return BUILT_IN_PLACEMENTS; } }; Select.prototype.getUnderLine = function getUnderLine() { var _props2 = this.props, prefixCls = _props2.prefixCls, className = _props2.className; if (className && className.includes(prefixCls + '-auto-complete')) { return null; } return React.createElement( 'div', { className: prefixCls + '-underline' }, React.createElement('span', { className: prefixCls + '-ripple' }) ); }; Select.prototype.renderClear = function renderClear() { var _props3 = this.props, prefixCls = _props3.prefixCls, allowClear = _props3.allowClear; var _state = this.state, value = _state.value, inputValue = _state.inputValue; var clear = React.createElement(Button, _extends({ key: 'clear', className: prefixCls + '-clear', style: UNSELECTABLE_STYLE }, UNSELECTABLE_ATTRIBUTE, { shape: 'circle', icon: 'close', size: 'small', onClick: this.onClearSelection, onMouseDown: preventDefaultEvent })); if (!allowClear) { return null; } if (isCombobox(this.props)) { if (inputValue) { return clear; } return null; } if (inputValue || value.length) { return clear; } return null; }; Select.prototype.render = function render() { var _rootCls; var props = this.props; var state = this.state; var className = props.className, disabled = props.disabled, prefixCls = props.prefixCls, label = props.label, placeholder = props.placeholder, defaultValue = props.defaultValue, loading = props.loading; var _state2 = this.state, open = _state2.open, value = _state2.value, inputValue = _state2.inputValue; var multiple = isMultipleOrTags(props); var ctrlNode = this.renderTopControlNode(); var extraSelectionProps = {}; var options = this._options; if (!isMultipleOrTagsOrCombobox(props)) { extraSelectionProps = _extends({}, extraSelectionProps, { onKeyDown: this.onKeyDown, tabIndex: disabled ? -1 : 0 }); } var rootCls = (_rootCls = {}, _defineProperty(_rootCls, className, !!className), _defineProperty(_rootCls, prefixCls, 1), _defineProperty(_rootCls, prefixCls + '-open', open), _defineProperty(_rootCls, prefixCls + '-focused', !isMultiple(props) && this._focused), _defineProperty(_rootCls, prefixCls + '-has-value', inputValue || value.length && value[0]), _defineProperty(_rootCls, prefixCls + '-has-label', label), _defineProperty(_rootCls, prefixCls + '-combobox', isCombobox(props)), _defineProperty(_rootCls, prefixCls + '-disabled', disabled), _defineProperty(_rootCls, prefixCls + '-enabled', !disabled), _defineProperty(_rootCls, prefixCls + '-allow-clear', !!props.allowClear), _defineProperty(_rootCls, prefixCls + '-tags', isTags(props)), _defineProperty(_rootCls, prefixCls + '-multiple', isMultiple(props)), _rootCls); return React.createElement( SelectTrigger, { onPopupFocus: this.onPopupFocus, onMouseEnter: props.onMouseEnter, onMouseLeave: props.onMouseLeave, checkAll: props.showCheckAll ? this.checkAll : undefined, dropdownAlign: props.dropdownAlign, dropdownClassName: props.dropdownClassName, dropdownMatchSelectWidth: props.dropdownMatchSelectWidth, defaultActiveFirstOption: props.defaultActiveFirstOption, dropdownMenuStyle: props.dropdownMenuStyle, transitionName: props.transitionName, animation: props.animation, prefixCls: props.prefixCls, dropdownStyle: props.dropdownStyle, combobox: props.combobox, showSearch: props.showSearch, options: options, multiple: multiple, disabled: disabled, visible: open, inputValue: state.inputValue, value: state.value, loading: loading, filter: props.filter, filterValue: state.filterValue, backfillValue: state.backfillValue, firstActiveValue: props.firstActiveValue, onFilterChange: this.onFilterChange, onDropdownVisibleChange: this.onDropdownVisibleChange, onDropdownMouseDown: props.onDropdownMouseDown, getPopupContainer: props.getPopupContainer, getRootDomNode: props.getRootDomNode, onMenuSelect: this.onMenuSelect, onMenuDeselect: this.onMenuDeselect, onPopupScroll: props.onPopupScroll, onKeyDown: chaining(this.onInputKeyDown, this.props.onInputKeyDown), filterPlaceholder: props.filterPlaceholder, builtinPlacements: this.getBuiltinPlacements(), footer: props.footer, virtualizedOptions: props.virtualizedOptions, virtualized: props.virtualized, ref: saveRef(this, 'selectTriggerRef') }, React.createElement( 'div', { style: props.style, ref: saveRef(this, 'rootRef'), onBlur: this.onOuterBlur, onFocus: this.onOuterFocus, className: classnames(rootCls) }, React.createElement( 'div', _extends({ ref: saveRef(this, 'selectionRef'), key: 'selection', className: prefixCls + '-selection\n ' + prefixCls + '-selection--' + (multiple ? 'multiple' : 'single'), role: 'combobox', 'aria-autocomplete': 'list', 'aria-haspopup': 'true', 'aria-expanded': open }, extraSelectionProps), label ? React.createElement( 'div', { className: prefixCls + '-selection-label' }, label ) : null, ctrlNode ), this.getUnderLine() ) ); }; return Select; }(React.Component); Select.propTypes = SelectPropTypes; Select.defaultProps = { prefixCls: 'rc-select', defaultOpen: false, labelInValue: false, defaultActiveFirstOption: true, showSearch: true, allowClear: false, onInput: noop, onChange: noop, onFocus: noop, onBlur: noop, onSelect: noop, onSearch: noop, onDeselect: noop, onInputKeyDown: noop, onChoiceItemClick: noop, showArrow: true, dropdownMatchSelectWidth: true, dropdownStyle: {}, dropdownMenuStyle: {}, optionFilterProp: 'value', optionLabelProp: 'value', notFoundContent: 'Not Found', backfill: false, tokenSeparators: [], showNotFindInputItem: true, showNotFindSelectedItem: true, placeholder: '', label: '', filterPlaceholder: 'Input for filter', showCheckAll: true, loading: false }; var _initialiseProps = function _initialiseProps() { var _this2 = this; this.needExpand = true; this.componentWillReceiveProps = function (nextProps) { var optionsInfo = _this2.getOptionsInfoFromProps(nextProps); _this2.setState({ optionsInfo: optionsInfo }); if ('value' in nextProps) { var value = _this2.getValueFromProps(nextProps); _this2.setState({ value: value }); if (nextProps.combobox) { _this2.setState({ inputValue: value.length ? _this2.getLabelBySingleValue(value[0], optionsInfo) : '' }); } } if ('filterValue' in nextProps) { _this2.setState({ filterValue: nextProps.filterValue }); } }; this.onFilterChange = function () { var val = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; var onFilterChange = _this2.props.onFilterChange; _this2.onInputValueChange(val); _this2.setState({ filterValue: val }); if (onFilterChange) { onFilterChange(val); } }; this.onInputValueChange = function (val) { var _props4 = _this2.props, tokenSeparators = _props4.tokenSeparators, onInput = _props4.onInput; onInput(val); if (isMultipleOrTags(_this2.props) && tokenSeparators.length && includesSeparators(val, tokenSeparators)) { var nextValue = _this2.getValueByInput(val); if (nextValue !== undefined) { _this2.fireChange(nextValue); } _this2.setOpenState(false, true); _this2.setInputValue('', false); return; } _this2.setInputValue(val); _this2.setState({ open: true }); if (isCombobox(_this2.props)) { _this2.fireChange([val]); } }; this.onInputChange = function (event) { var val = event.target.value; _this2.onInputValueChange(val); }; this.onDropdownVisibleChange = function (open) { var filter = _this2.props.filter; if (_this2.needExpand) { if (open && !_this2._focused) { _this2.clearBlurTime(); _this2.timeoutFocus(); _this2._focused = true; _this2.updateFocusClassName(); } if (filter) { _this2.onFilterChange(''); } if (open && filter) { setTimeout(function () { var filterInput = _this2.selectTriggerRef.getFilterInput(); filterInput && filterInput.focus(); }, 20); } _this2.setOpenState(open); } }; this.onKeyDown = function (event) { var props = _this2.props; if (props.disabled) { return; } var keyCode = event.keyCode; if (_this2.state.open && !_this2.getInputDOMNode()) { _this2.onInputKeyDown(event); } else if (keyCode === KeyCode.ENTER || keyCode === KeyCode.DOWN) { _this2.setOpenState(true); event.preventDefault(); } }; this.onInputKeyDown = function (event) { var props = _this2.props; if (props.disabled) { return; } var state = _this2.state; var keyCode = event.keyCode; if (isMultipleOrTags(props) && !event.target.value && keyCode === KeyCode.BACKSPACE) { event.preventDefault(); var value = state.value; if (value.length) { _this2.removeSelected(value[value.length - 1], value.length - 1); } return; } if (keyCode === KeyCode.DOWN) { if (!state.open) { _this2.openIfHasChildren(); event.preventDefault(); event.stopPropagation(); return; } } else if (keyCode === KeyCode.ESC) { if (state.open) { _this2.setOpenState(false); event.preventDefault(); event.stopPropagation(); } return; } if (state.open) { var menu = _this2.selectTriggerRef.getInnerMenu(); if (menu && menu.onKeyDown(event, _this2.handleBackfill)) { event.preventDefault(); event.stopPropagation(); } } }; this.onMenuSelect = function (_ref) { var item = _ref.item; var value = _this2.state.value; var props = _this2.props; var selectedValue = getValuePropValue(item); var lastValue = value[value.length - 1]; if (_this2.fireSelect(selectedValue) === false) { return; } if (isMultipleOrTags(props)) { if (findIndexInValueBySingleValue(value, selectedValue) !== -1) { return; } value = value.concat([selectedValue]); } else { if (isCombobox(props)) { _this2.skipAdjustOpen = true; _this2.clearAdjustTimer(); _this2.skipAdjustOpenTimer = setTimeout(function () { _this2.skipAdjustOpen = false; }, 0); } if (lastValue && lastValue === selectedValue && selectedValue !== _this2.state.backfillValue) { _this2.setOpenState(false, true); return; } value = [selectedValue]; _this2.setOpenState(false, true); } _this2.fireChange(value); var inputValue = void 0; if (isCombobox(props)) { inputValue = getPropValue(item, props.optionLabelProp); } else { inputValue = ''; } if (!_this2.props.filter) { _this2.setInputValue(inputValue, true); } }; this.onMenuDeselect = function (_ref2) { var item = _ref2.item, domEvent = _ref2.domEvent; if (domEvent.type === 'keydown' && domEvent.keyCode === KeyCode.ENTER) { _this2.removeSelected(getValuePropValue(item), null); return; } if (domEvent.type === 'click') { _this2.removeSelected(getValuePropValue(item), null); } var props = _this2.props; if (props.autoClearSearchValue) { _this2.setInputValue('', false); } }; this.onArrowClick = function (e) { e.stopPropagation(); e.preventDefault(); if (!_this2.props.disabled) { _this2.onDropdownVisibleChange(!_this2.state.open); } }; this.onOuterFocus = function (e) { if (_this2.props.disabled) { e.preventDefault(); return; } _this2.clearBlurTime(); if (!isMultipleOrTagsOrCombobox(_this2.props) && e.target === _this2.getInputDOMNode()) { return; } if (_this2._focused) { return; } _this2._focused = true; _this2.updateFocusClassName(); // only effect multiple or tag mode if (!isMultipleOrTags(_this2.props) || !_this2._mouseDown) { _this2.timeoutFocus(); } }; this.onPopupFocus = function () { // fix ie scrollbar, focus element again _this2.maybeFocus(true, true); }; this.onOuterBlur = function (e) { if (_this2.props.disabled) { e.preventDefault(); return; } _this2.blurTimer = setTimeout(function () { _this2._focused = false; _this2.updateFocusClassName(); var props = _this2.props; var value = _this2.state.value; var inputValue = _this2.state.inputValue; if (isSingleMode(props) && props.showSearch && inputValue && props.defaultActiveFirstOption) { var options = _this2._options || []; if (options.length) { var firstOption = findFirstMenuItem(options); if (firstOption) { value = [firstOption.key]; _this2.fireChange(value); } } } else if (isMultipleOrTags(props) && inputValue) { // why not use setState? _this2.state.inputValue = _this2.getInputDOMNode().value = ''; value = _this2.getValueByInput(inputValue); if (value !== undefined) { _this2.fireChange(value); } } props.onBlur(_this2.getVLForOnChange(value)); }, 10); }; this.onClearSelection = function (event) { var props = _this2.props; var state = _this2.state; if (props.disabled) { return; } var inputValue = state.inputValue, value = state.value; event.stopPropagation(); if (inputValue || value.length) { if (value.length) { _this2.fireChange([]); } _this2.setOpenState(false, true); if (inputValue) { _this2.setInputValue(''); } } }; this.onChoiceAnimationLeave = function () { _this2.selectTriggerRef.triggerRef.forcePopupAlign(); }; this.getValueFromProps = function (props) { var value = []; if ('value' in props) { value = toArray(props.value); } else { value = toArray(props.defaultValue); } if (props.labelInValue) { value = value.map(function (v) { return v.key; }); } if (isMultiple(props)) { value = value.filter(function (v) { return !!v; }); } return value; }; this.getOptionsInfoFromProps = function (props) { var options = _this2.getOptionsFromChildren(props.children); var oldOptionsInfo = _this2.state ? _this2.state.optionsInfo : {}; var value = _this2.state ? _this2.state.value : []; var optionsInfo = {}; options.forEach(function (option) { var singleValue = getValuePropValue(option); optionsInfo[getMapKey(singleValue)] = { option: option, value: singleValue, label: _this2.getLabelFromOption(option), title: option.props.title }; }); value.forEach(function (v) { var key = getMapKey(v); if (!optionsInfo[key]) { optionsInfo[key] = oldOptionsInfo[key]; } }); return optionsInfo; }; this.getOptionInfoBySingleValue = function (value, optionsInfo) { var info = void 0; optionsInfo = optionsInfo || _this2.state.optionsInfo; if (optionsInfo[getMapKey(value)]) { info = optionsInfo[getMapKey(value)]; } if (info) { return info; } var defaultLabel = value; if (_this2.props.labelInValue) { var label = getLabelFromPropsValue(_this2.props.value, value); if (label !== undefined) { defaultLabel = label; } } var defaultInfo = { option: React.createElement( Option, { value: value, key: value }, value ), value: value, label: defaultLabel }; return defaultInfo; }; this.getOptionBySingleValue = function (value) { var _getOptionInfoBySingl = _this2.getOptionInfoBySingleValue(value), option = _getOptionInfoBySingl.option; return option; }; this.getOptionsBySingleValue = function (values) { return values.map(function (value) { return _this2.getOptionBySingleValue(value); }); }; this.getOptionsFromChildren = function (children) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; React.Children.forEach(children, function (child) { if (!child) { return; } if (child.type.isSelectOptGroup) { _this2.getOptionsFromChildren(child.props.children, options); } else { options.push(child); } }); return options; }; this.getValueByLabel = function (label) { if (label === undefined) { return null; } var value = null; Object.keys(_this2.state.optionsInfo).forEach(function (key) { var info = _this2.state.optionsInfo[key]; if (toArray(info.label).join('') === label) { value = info.value; } }); return value; }; this.getLabelFromOption = function (option) { return getPropValue(option, _this2.props.optionLabelProp); }; this.getVLBySingleValue = function (value) { if (_this2.props.labelInValue) { return { key: value, label: _this2.getLabelBySingleValue(value) }; } return value; }; this.getVLForOnChange = function (vls_) { var vls = vls_; if (vls !== undefined) { if (!_this2.props.labelInValue) { vls = vls.map(function (v) { return v; }); } else { vls = vls.map(function (vl) { return { key: vl, label: _this2.getLabelBySingleValue(vl) }; }); } return isMultipleOrTags(_this2.props) ? vls : vls[0]; } return vls; }; this.getLabelBySingleValue = function (value, optionsInfo) { var _getOptionInfoBySingl2 = _this2.getOptionInfoBySingleValue(value, optionsInfo), label = _getOptionInfoBySingl2.label; return label; }; this.getDropdownContainer = function () { if (!_this2.dropdownContainer) { _this2.dropdownContainer = document.createElement('div'); document.body.appendChild(_this2.dropdownContainer); } return _this2.dropdownContainer; }; this.getPlaceholderElement = function () { var props = _this2.props, state = _this2.state; // let hidden = false; // if (props.label) { // hidden = true; // } // if (state.open) { // hidden = false; // } // if (state.inputValue) { // hidden = true; // } // if (state.value.length) { // hidden = true; // } // if (isCombobox(props) && state.value.length === 1 && !state.value[0]) { // hidden = false; // } var placeholder = props.placeholder; if (placeholder) { return React.createElement( 'div', { className: props.prefixCls + '-selection__placeholder' }, placeholder ); } return null; }; this.getInputElement = function () { var props = _this2.props; var inputElement = props.getInputElement ? props.getInputElement() : React.createElement('input', { id: props.id, autoComplete: 'off' }); var inputCls = classnames(inputElement.props.className, _defineProperty({}, props.prefixCls + '-search__field', true)); // https://github.com/ant-design/ant-design/issues/4992#issuecomment-281542159 // Add space to the end of the inputValue as the width measurement tolerance return React.createElement( 'div', { className: props.prefixCls + '-search__field__wrap' }, React.cloneElement(inputElement, { ref: saveRef(_this2, 'inputRef'), onChange: _this2.onInputChange, onKeyDown: chaining(_this2.onInputKeyDown, inputElement.props.onKeyDown, _this2.props.onInputKeyDown), value: _this2.state.inputValue, disabled: props.disabled, className: inputCls }), React.createElement( 'span', { ref: saveRef(_this2, 'inputMirrorRef'), className: props.prefixCls + '-search__field__mirror' }, _this2.state.inputValue, '\xA0' ) ); }; this.getInputDOMNode = function () { return _this2.topCtrlRef ? _this2.topCtrlRef.querySelector('input,textarea,div[contentEditable]') : _this2.inputRef; }; this.getInputMirrorDOMNode = function () { return _this2.inputMirrorRef; }; this.getPopupDOMNode = function () { return _this2.selectTriggerRef.getPopupDOMNode(); }; this.getPopupMenuComponent = function () { return _this2.selectTriggerRef.getInnerMenu(); }; this.setOpenState = function (open, needFocus) { var props = _this2.props, state = _this2.state; if (state.open === open) { _this2.maybeFocus(open, needFocus); return; } var nextState = { open: open, backfillValue: undefined }; // clear search input value when open is false in singleMode. if (!open && isSingleMode(props) && props.showSearch) { _this2.setInputValue(''); } if (!open) { _this2.maybeFocus(open, needFocus); } _this2.setState(nextState, function () { if (open) { _this2.maybeFocus(open, needFocus); } }); }; this.setInputValue = function (inputValue) { var fireSearch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (inputValue !== _this2.state.inputValue) { _this2.setState({ inputValue: inputValue }); if (fireSearch) { _this2.props.onSearch(inputValue); } } }; this.getValueByInput = function (string) { var _props5 = _this2.props, multiple = _props5.multiple, tokenSeparators = _props5.tokenSeparators; var nextValue = _this2.state.value; var hasNewValue = false; splitBySeparators(string, tokenSeparators).forEach(function (label) { var selectedValue = [label]; if (multiple) { var value = _this2.getValueByLabel(label); if (value && findIndexInValueBySingleValue(nextValue, value) === -1) { nextValue = nextValue.concat(value); hasNewValue = true; _this2.fireSelect(value); } } else { // tag if (findIndexInValueBySingleValue(nextValue, label) === -1) { nextValue = nextValue.concat(selectedValue); hasNewValue = true; _this2.fireSelect(label); } } }); return hasNewValue ? nextValue : undefined; }; this.getRealOpenState = function (state) { var _open = _this2.props.open; if (typeof _open === 'boolean') { return _open; } var open = (state || _this2.state).open; var options = _this2._options || []; if (isMultipleOrTagsOrCombobox(_this2.props) || !_this2.props.showSearch) { if (open && !options.length) { open = false; } } return open; }; this.focus = function () { if (isSingleMode(_this2.props)) { _this2.selectionRef.focus(); } else { _this2.getInputDOMNode().focus(); } }; this.blur = function () { if (isSingleMode(_this2.props)) { _this2.selectionRef.blur(); } else { _this2.getInputDOMNode().blur(); } }; this.handleBackfill = function (item) { if (!_this2.props.backfill || !(isSingleMode(_this2.props) || isCombobox(_this2.props))) { return; } var key = getValuePropValue(item); if (isCombobox(_this2.props)) { _this2.setInputValue(key, false); } _this2.setState({ value: [key], backfillValue: key }); }; this.filterOption = function (input, child) { var defaultFilter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultFilterFn; var value = _this2.state.value; var lastValue = value[value.length - 1]; if (!input || lastValue && lastValue === _this2.state.backfillValue) { return true; } var filterFn = _this2.props.filterOption; if ('filterOption' in _this2.props) { if (_this2.props.filterOption === true) { filterFn = defaultFilter; } } else { filterFn = defaultFilter; } if (!filterFn) { return true; } else if (typeof filterFn === 'function') { return filterFn.call(_this2, input, child); } else if (child.props.disabled) { return false; } return true; }; this.timeoutFocus = function () { if (_this2.focusTimer) { _this2.clearFocusTime(); } _this2.focusTimer = setTimeout(function () { _this2.props.onFocus(); }, 10); }; this.clearFocusTime = function () { if (_this2.focusTimer) { clearTimeout(_this2.focusTimer); _this2.focusTimer = null; } }; this.clearBlurTime = function () { if (_this2.blurTimer) { clearTimeout(_this2.blurTimer); _this2.blurTimer = null; } }; this.clearAdjustTimer = function () { if (_this2.skipAdjustOpenTimer) { clearTimeout(_this2.skipAdjustOpenTimer); _this2.skipAdjustOpenTimer = null; } }; this.updateFocusClassName = function () { var rootRef = _this2.rootRef, props = _this2.props; // avoid setState and its side effect if (_this2._focused) { classes(rootRef).add(props.prefixCls + '-focused'); } else { classes(rootRef).remove(props.prefixCls + '-focused'); } }; this.maybeFocus = function (open, needFocus) { if (needFocus || open) { var input = _this2.getInputDOMNode(); var _document = document, activeElement = _document.activeElement; if (input && (open || isMultipleOrTagsOrCombobox(_this2.props))) { if (activeElement !== input) { input.focus(); _this2._focused = true; } } else { if (activeElement !== _this2.selectionRef) { _this2.selectionRef.focus(); _this2._focused = true; } } } }; this.handleChoiceItemClick = function (selectedKey, e) { var props = _this2.props; if (props.disabled || _this2.isChildDisabled(selectedKey)) { return; } if (!e.isDefaultPrevented()) { props.onChoiceItemClick(_this2.getVLBySingleValue(selectedKey), _this2.getOptionBySingleValue(selectedKey)); } }; this.removeSelected = function (selectedKey, index, e) { _this2.needExpand = false; setTimeout(function () { _this2.needExpand = true; }, 100); if (e) { e.preventDefault(); } var props = _this2.props; if (props.disabled || _this2.isChildDisabled(selectedKey)) { return; } var value = _this2.state.value.filter(function (singleValue, i) { return singleValue !== selectedKey || index !== null && i !== index; }); var canMultiple = isMultipleOrTags(props); if (canMultiple) { var event = selectedKey; if (props.labelInValue) { event = { key: selectedKey, label: _this2.getLabelBySingleValue(selectedKey) }; } props.onDeselect(event, _this2.getOptionBySingleValue(selectedKey), index); if (typeof props.onChoiceRemove === 'function') { props.onChoiceRemove(selectedKey); } } _this2.fireChange(value); }; this.openIfHasChildren = function () { var props = _this2.props; if (React.Children.count(props.children) || isSingleMode(props)) { _this2.setOpenState(true); } }; this.fireSelect = function (value) { return _this2.props.onSelect(_this2.getVLBySingleValue(value), _this2.getOptionBySingleValue(value)); }; this.fireChange = function (value) { var props = _this2.props; if (!('value' in props)) { _this2.setState({ value: value }); } var vls = _this2.getVLForOnChange(value); var options = _this2.getOptionsBySingleValue(value); props.onChange(vls, isMultipleOrTags(_this2.props) ? options : options[0]); }; this.isChildDisabled = function (key) { return childrenToArray(_this2.props.children).some(function (child) { var childValue = getValuePropValue(child); return childValue === key && child.props && child.props.disabled; }); }; this.adjustOpenState = function () { if (_this2.skipAdjustOpen) { return; } var open = _this2.state.open; var options = []; // If hidden menu due to no options, then it should be calculated again if (open || _this2.hiddenForNoOptions) { options = _this2.renderFilterOptions(); } _this2._options = options; if (isMultipleOrTagsOrCombobox(_this2.props) || !_this2.props.showSearch) { if (open && !options.length) { open = false; _this2.hiddenForNoOptions = true; } // Keep menu open if there are options and hidden for no options before if (_this2.hiddenForNoOptions && options.length) { open = true; _this2.hiddenForNoOptions = false; } } _this2.state.open = open; }; this.renderFilterOptions = function () { var inputValue = _this2.state.inputValue; var _props6 = _this2.props, children = _props6.children, tags = _props6.tags, filterOption = _props6.filterOption, notFoundContent = _props6.notFoundContent, showNotFindInputItem = _props6.showNotFindInputItem, showNotFindSelectedItem = _props6.showNotFindSelectedItem; var menuItems = []; var childrenKeys = []; var options = _this2.renderFilterOptionsFromChildren(children, childrenKeys, menuItems); if (tags) { if (showNotFindSelectedItem) { // tags value must be string var value = _this2.state.value || []; value = value.filter(function (singleValue) { return childrenKeys.indexOf(singleValue) === -1 && (!inputValue || String(singleValue).indexOf(String(inputValue)) > -1); }); value.forEach(function (singleValue) { var key = singleValue; var menuItem = React.createElement( MenuItem, { style: UNSELECTABLE_STYLE, attribute: UNSELECTABLE_ATTRIBUTE, value: key, key: key }, key ); options.push(menuItem); menuItems.push(menuItem); }); } if (inputValue && showNotFindInputItem) { var notFindInputItem = menuItems.every(function (option) { // this.filterOption return true has two meaning, // 1, some one exists after filtering // 2, filterOption is set to false // condition 2 does not mean the option has same value with inputValue var filterFn = function filterFn() { return getValuePropValue(option) === inputValue; }; if (filterOption !== false) { return !_this2.filterOption.call(_this2, inputValue, option, filterFn); } return !filterFn(); }); if (notFindInputItem) { options.unshift(React.createElement( MenuItem, { style: UNSELECTABLE_STYLE, attribute: UNSELECTABLE_ATTRIBUTE, value: inputValue, onMouseDown: preventDefaultEvent, key: inputValue }, inputValue )); } } } var loading = _this2.props.loading; if (typeof loading === 'boolean') { loading = { spinning: loading }; } if (!options.length && notFoundContent) { options = [React.createElement( MenuItem, { style: UNSELECTABLE_STYLE, attribute: UNSELECTABLE_ATTRIBUTE, disabled: true, value: 'NOT_FOUND', key: 'NOT_FOUND' }, loading.spinning ? '' : notFoundContent )]; } return options; }; this.renderFilterOptionsFromChildren = function (children, childrenKeys, menuItems) { var sel = []; var props = _this2.props; var inputValue = _this2.state.inputValue; var tags = props.tags; React.Children.forEach(children, function (child) { if (!child) { return; } if (child.type.isSelectOptGroup) { var innerItems = _this2.renderFilterOptionsFromChildren(child.props.children, childrenKeys, menuItems); if (innerItems.length) { var label = child.props.label; var key = child.key; // if (!key && typeof label === 'string') { // key = label; // } // else if (!label && key) { // label = key; // } sel.push(React.createElement( MenuItemGroup, { key: key, title: label }, innerItems )); } return; } warning(child.type.isSelectOption, 'the children of `Select` should be `Select.Option` or `Select.OptGroup`, ' + ('instead of `' + (child.type.name || child.type.displayName || child.type) + '`.')); var childValue = getValuePropValue(child); validateOptionValue(childValue, _this2.props); if (_this2.filterOption(inputValue, child)) { var menuItem = React.createElement(MenuItem, _extends({ style: UNSELECTABLE_STYLE, attribute: UNSELECTABLE_ATTRIBUTE, value: childValue, key: childValue }, child.props)); sel.push(menuItem); menuItems.push(menuItem); } if (tags && !child.props.disabled) { childrenKeys.push(childValue); } }); return sel; }; this.isChoiceRemove = function (selectedKey) { var choiceRemove = _this2.props.choiceRemove; if (typeof choiceRemove === 'function') { return choiceRemove(selectedKey); } return choiceRemove; }; this.renderTopControlNode = function () { var _state3 = _this2.state, value = _state3.value, open = _state3.open, inputValue = _state3.inputValue; var props = _this2.props; var tags = isTags(props); var choiceTransitionName = props.choiceTransitionName, prefixCls = props.prefixCls, maxTagTextLength = props.maxTagTextLength, maxTagCount = props.maxTagCount, maxTagPlaceholder = props.maxTagPlaceholder, showSearch = props.showSearch, choiceRender = props.choiceRender; var className = prefixCls + '-selection__rendered'; // search input is inside topControlNode in single, multiple & combobox. 2016/04/13 var innerNode = null; if (isSingleMode(props)) { var selectedValue = null; var opacity = 1; if (value.length) { var showSelectedValue = false; if (!showSearch) { showSelectedValue = true; } else { if (open) { showSelectedValue = !inputValue; if (showSelectedValue) { opacity = 0.4; } } else { showSelectedValue = true; } } } var singleValue = value && value[0]; var _getOptionInfoBySingl3 = _this2.getOptionInfoBySingleValue(singleValue), label = _getOptionInfoBySingl3.label, title = _getOptionInfoBySingl3.title; selectedValue = React.createElement( 'div', { key: 'value', className: prefixCls + '-selection-selected-value', title: title || label, style: { opacity: opacity } }, choiceRender ? choiceRender(label) : label ); innerNode = [selectedValue]; } else { var selectedValueNodes = []; var limitedCountValue = value; var maxTagPlaceholderEl = void 0; if (maxTagCount !== undefined && value.length > maxTagCount) { limitedCountValue = limitedCountValue.slice(0, maxTagCount); var omittedValues = _this2.getVLForOnChange(value.slice(maxTagCount, value.length)); var content = '+ ' + (value.length - maxTagCount) + ' ...'; if (maxTagPlaceholder) { content = typeof maxTagPlaceholder === 'function' ? maxTagPlaceholder(omittedValues) : maxTagPlaceholder; } maxTagPlaceholderEl = React.createElement( 'li', _extends({ style: UNSELECTABLE_STYLE }, UNSELECTABLE_ATTRIBUTE, { onMouseDown: preventDefaultEvent, className: prefixCls + '-selection__choice ' + prefixCls + '-selection__choice__disabled ' + prefixCls + '-selection__max', key: 'maxTagPlaceholder' // title={content} }), React.createElement( 'div', { className: prefixCls + '-selection__choice__content' }, content ) ); } if (isMultipleOrTags(props)) { selectedValueNodes = limitedCountValue.map(function (singleValue, index) { var info = _this2.getOptionInfoBySingleValue(singleValue); var content = info.label; var title = info.title || content; if (maxTagTextLength && typeof content === 'string' && content.length > maxTagTextLength) { content = content.slice(0, maxTagTextLength) + '...'; } var disabled = _this2.isChildDisabled(singleValue); var choiceClassName = disabled ? prefixCls + '-selection__choice ' + prefixCls + '-selection__choice__disabled' : prefixCls + '-selection__choice'; var li = React.createElement( 'li', _extends({ style: UNSELECTABLE_STYLE }, UNSELECTABLE_ATTRIBUTE, { onMouseDown: preventDefaultEvent, onClick: _this2.handleChoiceItemClick.bind(_this2, singleValue), className: choiceClassName // title={title} }), React.createElement( 'div', { className: prefixCls + '-selection__choice__content' }, content ), disabled || !_this2.isChoiceRemove(singleValue) ? null : React.createElement( 'span', { className: prefixCls + '-selection__choice__remove', onClick: _this2.removeSelected.bind(_this2, singleValue, index) }, React.createElement('i', { className: 'icon icon-chacha' }) ) ); return React.createElement( Ripple, { key: singleValue + limitedCountValue.slice(0, index).filter(function (foundValue) { return foundValue === singleValue; }).length }, choiceRender ? choiceRender(li, singleValue) : li ); }); if (maxTagPlaceholderEl) { selectedValueNodes.push(maxTagPlaceholderEl); } selectedValueNodes.push(React.createElement( 'li', { className: prefixCls + '-search ' + prefixCls + '-search--inline', key: '__input' }, _this2.getInputElement() )); } else { selectedValueNodes.push(React.createElement( 'div', { className: prefixCls + '-search ' + prefixCls + '-search--inline', key: '__input', style: { display: 'inline-block' } }, _this2.getInputElement() )); } if (isMultipleOrTags(props)) { innerNode = React.createElement( 'ul', null, selectedValueNodes ); } else { innerNode = selectedValueNodes; } } return React.createElement( 'div', { className: className, ref: saveRef(_this2, 'topCtrlRef') }, _this2.getPlaceholderElement(), innerNode, _this2.renderClear(), tags || !props.showArrow ? null : React.createElement( 'span', _extends({ key: 'arrow', className: prefixCls + '-arrow', style: UNSELECTABLE_STYLE }, UNSELECTABLE_ATTRIBUTE, { onClick: _this2.onArrowClick }), React.createElement('i', { className: 'icon icon-quedingdexiaosanjiao' }), React.createElement('b', null) ) ); }; this.checkAll = function (event) { var name = event.target.getAttribute('name'); var props = _this2.props; var state = _this2.state; if (props.disabled) { return; } var newValues = void 0; var values = _this2._options.map(function (option) { return getValuePropValue(option); }); if (name === 'check-all') { newValues = new Set(state.value.concat(values)); _this2.fireChange(Array.from(newValues)); } else if (name === 'check-none') { newValues = state.value.filter(function (e) { return values.indexOf(e) < 0; }); _this2.fireChange(newValues); _this2.focus(); } }; }; export default Select; Select.displayName = 'Select';