1655 lines
50 KiB
JavaScript
1655 lines
50 KiB
JavaScript
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
|
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
|
|
|
|
function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
|
|
|
|
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
|
|
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
|
|
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
|
|
|
|
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
|
|
|
|
import classnames from 'classnames';
|
|
import classes from 'component-classes';
|
|
import Animate from 'rc-animate';
|
|
import { Item as MenuItem, ItemGroup as MenuItemGroup } from 'rc-menu';
|
|
import childrenToArray from "rc-util/es/Children/toArray";
|
|
import KeyCode from "rc-util/es/KeyCode";
|
|
import * as React from 'react';
|
|
import * as ReactDOM from 'react-dom';
|
|
import { polyfill } from 'react-lifecycles-compat';
|
|
import warning from 'warning';
|
|
import Option from './Option';
|
|
import SelectPropTypes from './PropTypes';
|
|
import SelectTrigger from './SelectTrigger';
|
|
import { defaultFilterFn, findFirstMenuItem, findIndexInValueBySingleValue, generateUUID, getLabelFromPropsValue, getMapKey, getPropValue, getValuePropValue, includesSeparators, isCombobox, isMultipleOrTags, isMultipleOrTagsOrCombobox, isSingleMode, preventDefaultEvent, saveRef, splitBySeparators, toArray, toTitle, UNSELECTABLE_ATTRIBUTE, UNSELECTABLE_STYLE, validateOptionValue } from './util';
|
|
var SELECT_EMPTY_VALUE_KEY = 'RC_SELECT_EMPTY_VALUE_KEY';
|
|
|
|
var noop = function noop() {
|
|
return null;
|
|
};
|
|
|
|
function chaining() {
|
|
for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
fns[_key] = arguments[_key];
|
|
}
|
|
|
|
return function () {
|
|
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
args[_key2] = arguments[_key2];
|
|
}
|
|
|
|
// tslint:disable-next-line:prefer-for-of
|
|
for (var i = 0; i < fns.length; i++) {
|
|
if (fns[i] && typeof fns[i] === 'function') {
|
|
fns[i].apply(chaining, args);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
var Select =
|
|
/*#__PURE__*/
|
|
function (_React$Component) {
|
|
_inherits(Select, _React$Component);
|
|
|
|
function Select(props) {
|
|
var _this;
|
|
|
|
_classCallCheck(this, Select);
|
|
|
|
_this = _possibleConstructorReturn(this, _getPrototypeOf(Select).call(this, props));
|
|
_this.inputRef = null;
|
|
_this.inputMirrorRef = null;
|
|
_this.topCtrlRef = null;
|
|
_this.selectTriggerRef = null;
|
|
_this.rootRef = null;
|
|
_this.selectionRef = null;
|
|
_this.dropdownContainer = null;
|
|
_this.blurTimer = null;
|
|
_this.focusTimer = null; // tslint:disable-next-line:variable-name
|
|
|
|
_this._focused = false; // tslint:disable-next-line:variable-name
|
|
|
|
_this._mouseDown = false; // tslint:disable-next-line:variable-name
|
|
|
|
_this._options = []; // tslint:disable-next-line:variable-name
|
|
|
|
_this._empty = false;
|
|
|
|
_this.onInputChange = function (event) {
|
|
var tokenSeparators = _this.props.tokenSeparators;
|
|
var val = event.target.value;
|
|
|
|
if (isMultipleOrTags(_this.props) && tokenSeparators.length && includesSeparators(val, tokenSeparators)) {
|
|
var nextValue = _this.getValueByInput(val);
|
|
|
|
if (nextValue !== undefined) {
|
|
_this.fireChange(nextValue);
|
|
}
|
|
|
|
_this.setOpenState(false, true);
|
|
|
|
_this.setInputValue('', false);
|
|
|
|
return;
|
|
}
|
|
|
|
_this.setInputValue(val);
|
|
|
|
_this.setState({
|
|
open: true
|
|
});
|
|
|
|
if (isCombobox(_this.props)) {
|
|
_this.fireChange([val]);
|
|
}
|
|
};
|
|
|
|
_this.onDropdownVisibleChange = function (open) {
|
|
if (open && !_this._focused) {
|
|
_this.clearBlurTime();
|
|
|
|
_this.timeoutFocus();
|
|
|
|
_this._focused = true;
|
|
|
|
_this.updateFocusClassName();
|
|
}
|
|
|
|
_this.setOpenState(open);
|
|
}; // combobox ignore
|
|
|
|
|
|
_this.onKeyDown = function (event) {
|
|
var open = _this.state.open;
|
|
var disabled = _this.props.disabled;
|
|
|
|
if (disabled) {
|
|
return;
|
|
}
|
|
|
|
var keyCode = event.keyCode;
|
|
|
|
if (open && !_this.getInputDOMNode()) {
|
|
_this.onInputKeyDown(event);
|
|
} else if (keyCode === KeyCode.ENTER || keyCode === KeyCode.DOWN) {
|
|
if (!open) {
|
|
_this.setOpenState(true);
|
|
}
|
|
|
|
event.preventDefault();
|
|
} else if (keyCode === KeyCode.SPACE) {
|
|
// Not block space if popup is shown
|
|
if (!open) {
|
|
_this.setOpenState(true);
|
|
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
};
|
|
|
|
_this.onInputKeyDown = function (event) {
|
|
var _this$props = _this.props,
|
|
disabled = _this$props.disabled,
|
|
combobox = _this$props.combobox;
|
|
|
|
if (disabled) {
|
|
return;
|
|
}
|
|
|
|
var state = _this.state;
|
|
|
|
var isRealOpen = _this.getRealOpenState(state); // magic code
|
|
|
|
|
|
var keyCode = event.keyCode;
|
|
|
|
if (isMultipleOrTags(_this.props) && !event.target.value && keyCode === KeyCode.BACKSPACE) {
|
|
event.preventDefault();
|
|
var value = state.value;
|
|
|
|
if (value.length) {
|
|
_this.removeSelected(value[value.length - 1]);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (keyCode === KeyCode.DOWN) {
|
|
if (!state.open) {
|
|
_this.openIfHasChildren();
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
return;
|
|
}
|
|
} else if (keyCode === KeyCode.ENTER && state.open) {
|
|
// Aviod trigger form submit when select item
|
|
// https://github.com/ant-design/ant-design/issues/10861
|
|
// https://github.com/ant-design/ant-design/issues/14544
|
|
if (isRealOpen || !combobox) {
|
|
event.preventDefault();
|
|
}
|
|
} else if (keyCode === KeyCode.ESC) {
|
|
if (state.open) {
|
|
_this.setOpenState(false);
|
|
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (isRealOpen && _this.selectTriggerRef) {
|
|
var menu = _this.selectTriggerRef.getInnerMenu();
|
|
|
|
if (menu && menu.onKeyDown(event, _this.handleBackfill)) {
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
}
|
|
}
|
|
};
|
|
|
|
_this.onMenuSelect = function (_ref) {
|
|
var item = _ref.item;
|
|
|
|
if (!item) {
|
|
return;
|
|
}
|
|
|
|
var value = _this.state.value;
|
|
var props = _this.props;
|
|
var selectedValue = getValuePropValue(item);
|
|
var lastValue = value[value.length - 1];
|
|
|
|
_this.fireSelect(selectedValue);
|
|
|
|
if (isMultipleOrTags(props)) {
|
|
if (findIndexInValueBySingleValue(value, selectedValue) !== -1) {
|
|
return;
|
|
}
|
|
|
|
value = value.concat([selectedValue]);
|
|
} else {
|
|
if (!isCombobox(props) && lastValue !== undefined && lastValue === selectedValue && selectedValue !== _this.state.backfillValue) {
|
|
_this.setOpenState(false, true);
|
|
|
|
return;
|
|
}
|
|
|
|
value = [selectedValue];
|
|
|
|
_this.setOpenState(false, true);
|
|
}
|
|
|
|
_this.fireChange(value);
|
|
|
|
var inputValue = isCombobox(props) ? getPropValue(item, props.optionLabelProp) : '';
|
|
|
|
if (props.autoClearSearchValue) {
|
|
_this.setInputValue(inputValue, false);
|
|
}
|
|
};
|
|
|
|
_this.onMenuDeselect = function (_ref2) {
|
|
var item = _ref2.item,
|
|
domEvent = _ref2.domEvent;
|
|
|
|
if (domEvent.type === 'keydown' && domEvent.keyCode === KeyCode.ENTER) {
|
|
_this.removeSelected(getValuePropValue(item));
|
|
|
|
return;
|
|
}
|
|
|
|
if (domEvent.type === 'click') {
|
|
_this.removeSelected(getValuePropValue(item));
|
|
}
|
|
|
|
var props = _this.props;
|
|
|
|
if (props.autoClearSearchValue) {
|
|
_this.setInputValue('', false);
|
|
}
|
|
};
|
|
|
|
_this.onArrowClick = function (e) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
|
|
if (!_this.props.disabled) {
|
|
_this.setOpenState(!_this.state.open, !_this.state.open);
|
|
}
|
|
};
|
|
|
|
_this.onPlaceholderClick = function () {
|
|
if (_this.getInputDOMNode && _this.getInputDOMNode()) {
|
|
_this.getInputDOMNode().focus();
|
|
}
|
|
};
|
|
|
|
_this.onOuterFocus = function (e) {
|
|
if (_this.props.disabled) {
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
|
|
_this.clearBlurTime();
|
|
|
|
if (!isMultipleOrTagsOrCombobox(_this.props) && e.target === _this.getInputDOMNode()) {
|
|
return;
|
|
}
|
|
|
|
if (_this._focused) {
|
|
return;
|
|
}
|
|
|
|
_this._focused = true;
|
|
|
|
_this.updateFocusClassName(); // only effect multiple or tag mode
|
|
|
|
|
|
if (!isMultipleOrTags(_this.props) || !_this._mouseDown) {
|
|
_this.timeoutFocus();
|
|
}
|
|
};
|
|
|
|
_this.onPopupFocus = function () {
|
|
// fix ie scrollbar, focus element again
|
|
_this.maybeFocus(true, true);
|
|
};
|
|
|
|
_this.onOuterBlur = function (e) {
|
|
if (_this.props.disabled) {
|
|
e.preventDefault();
|
|
return;
|
|
}
|
|
|
|
_this.blurTimer = window.setTimeout(function () {
|
|
_this._focused = false;
|
|
|
|
_this.updateFocusClassName();
|
|
|
|
var props = _this.props;
|
|
var value = _this.state.value;
|
|
var inputValue = _this.state.inputValue;
|
|
|
|
if (isSingleMode(props) && props.showSearch && inputValue && props.defaultActiveFirstOption) {
|
|
var options = _this._options || [];
|
|
|
|
if (options.length) {
|
|
var firstOption = findFirstMenuItem(options);
|
|
|
|
if (firstOption) {
|
|
value = [getValuePropValue(firstOption)];
|
|
|
|
_this.fireChange(value);
|
|
}
|
|
}
|
|
} else if (isMultipleOrTags(props) && inputValue) {
|
|
if (_this._mouseDown) {
|
|
// need update dropmenu when not blur
|
|
_this.setInputValue('');
|
|
} else {
|
|
// why not use setState?
|
|
// https://github.com/ant-design/ant-design/issues/14262
|
|
_this.state.inputValue = '';
|
|
|
|
if (_this.getInputDOMNode && _this.getInputDOMNode()) {
|
|
_this.getInputDOMNode().value = '';
|
|
}
|
|
}
|
|
|
|
var tmpValue = _this.getValueByInput(inputValue);
|
|
|
|
if (tmpValue !== undefined) {
|
|
value = tmpValue;
|
|
|
|
_this.fireChange(value);
|
|
}
|
|
} // if click the rest space of Select in multiple mode
|
|
|
|
|
|
if (isMultipleOrTags(props) && _this._mouseDown) {
|
|
_this.maybeFocus(true, true);
|
|
|
|
_this._mouseDown = false;
|
|
return;
|
|
}
|
|
|
|
_this.setOpenState(false);
|
|
|
|
if (props.onBlur) {
|
|
props.onBlur(_this.getVLForOnChange(value));
|
|
}
|
|
}, 10);
|
|
};
|
|
|
|
_this.onClearSelection = function (event) {
|
|
var props = _this.props;
|
|
var state = _this.state;
|
|
|
|
if (props.disabled) {
|
|
return;
|
|
}
|
|
|
|
var inputValue = state.inputValue;
|
|
var value = state.value;
|
|
event.stopPropagation();
|
|
|
|
if (inputValue || value.length) {
|
|
if (value.length) {
|
|
_this.fireChange([]);
|
|
}
|
|
|
|
_this.setOpenState(false, true);
|
|
|
|
if (inputValue) {
|
|
_this.setInputValue('');
|
|
}
|
|
}
|
|
};
|
|
|
|
_this.onChoiceAnimationLeave = function () {
|
|
_this.forcePopupAlign();
|
|
};
|
|
|
|
_this.getOptionInfoBySingleValue = function (value, optionsInfo) {
|
|
var info;
|
|
optionsInfo = optionsInfo || _this.state.optionsInfo;
|
|
|
|
if (optionsInfo[getMapKey(value)]) {
|
|
info = optionsInfo[getMapKey(value)];
|
|
}
|
|
|
|
if (info) {
|
|
return info;
|
|
}
|
|
|
|
var defaultLabel = value;
|
|
|
|
if (_this.props.labelInValue) {
|
|
var label = getLabelFromPropsValue(_this.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 _this$getOptionInfoBy = _this.getOptionInfoBySingleValue(value),
|
|
option = _this$getOptionInfoBy.option;
|
|
|
|
return option;
|
|
};
|
|
|
|
_this.getOptionsBySingleValue = function (values) {
|
|
return values.map(function (value) {
|
|
return _this.getOptionBySingleValue(value);
|
|
});
|
|
};
|
|
|
|
_this.getValueByLabel = function (label) {
|
|
if (label === undefined) {
|
|
return null;
|
|
}
|
|
|
|
var value = null;
|
|
Object.keys(_this.state.optionsInfo).forEach(function (key) {
|
|
var info = _this.state.optionsInfo[key];
|
|
var disabled = info.disabled;
|
|
|
|
if (disabled) {
|
|
return;
|
|
}
|
|
|
|
var oldLable = toArray(info.label);
|
|
|
|
if (oldLable && oldLable.join('') === label) {
|
|
value = info.value;
|
|
}
|
|
});
|
|
return value;
|
|
};
|
|
|
|
_this.getVLBySingleValue = function (value) {
|
|
if (_this.props.labelInValue) {
|
|
return {
|
|
key: value,
|
|
label: _this.getLabelBySingleValue(value)
|
|
};
|
|
}
|
|
|
|
return value;
|
|
};
|
|
|
|
_this.getVLForOnChange = function (vlsS) {
|
|
var vls = vlsS;
|
|
|
|
if (vls !== undefined) {
|
|
if (!_this.props.labelInValue) {
|
|
vls = vls.map(function (v) {
|
|
return v;
|
|
});
|
|
} else {
|
|
vls = vls.map(function (vl) {
|
|
return {
|
|
key: vl,
|
|
label: _this.getLabelBySingleValue(vl)
|
|
};
|
|
});
|
|
}
|
|
|
|
return isMultipleOrTags(_this.props) ? vls : vls[0];
|
|
}
|
|
|
|
return vls;
|
|
};
|
|
|
|
_this.getLabelBySingleValue = function (value, optionsInfo) {
|
|
var _this$getOptionInfoBy2 = _this.getOptionInfoBySingleValue(value, optionsInfo),
|
|
label = _this$getOptionInfoBy2.label;
|
|
|
|
return label;
|
|
};
|
|
|
|
_this.getDropdownContainer = function () {
|
|
if (!_this.dropdownContainer) {
|
|
_this.dropdownContainer = document.createElement('div');
|
|
document.body.appendChild(_this.dropdownContainer);
|
|
}
|
|
|
|
return _this.dropdownContainer;
|
|
};
|
|
|
|
_this.getPlaceholderElement = function () {
|
|
var props = _this.props;
|
|
var state = _this.state;
|
|
var hidden = false;
|
|
|
|
if (state.inputValue) {
|
|
hidden = true;
|
|
}
|
|
|
|
var value = state.value;
|
|
|
|
if (value.length) {
|
|
hidden = true;
|
|
}
|
|
|
|
if (isCombobox(props) && value.length === 1 && state.value && !state.value[0]) {
|
|
hidden = false;
|
|
}
|
|
|
|
var placeholder = props.placeholder;
|
|
|
|
if (placeholder) {
|
|
return React.createElement("div", _extends({
|
|
onMouseDown: preventDefaultEvent,
|
|
style: _extends({
|
|
display: hidden ? 'none' : 'block'
|
|
}, UNSELECTABLE_STYLE)
|
|
}, UNSELECTABLE_ATTRIBUTE, {
|
|
onClick: _this.onPlaceholderClick,
|
|
className: "".concat(props.prefixCls, "-selection__placeholder")
|
|
}), placeholder);
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
_this.getInputElement = function () {
|
|
var props = _this.props;
|
|
var defaultInput = React.createElement("input", {
|
|
id: props.id,
|
|
autoComplete: "off"
|
|
}); // tslint:disable-next-line:typedef-whitespace
|
|
|
|
var inputElement = props.getInputElement ? props.getInputElement() : defaultInput;
|
|
var inputCls = classnames(inputElement.props.className, _defineProperty({}, "".concat(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: "".concat(props.prefixCls, "-search__field__wrap")
|
|
}, React.cloneElement(inputElement, {
|
|
ref: _this.saveInputRef,
|
|
onChange: _this.onInputChange,
|
|
onKeyDown: chaining(_this.onInputKeyDown, inputElement.props.onKeyDown, _this.props.onInputKeyDown),
|
|
value: _this.state.inputValue,
|
|
disabled: props.disabled,
|
|
className: inputCls
|
|
}), React.createElement("span", {
|
|
ref: _this.saveInputMirrorRef,
|
|
className: "".concat(props.prefixCls, "-search__field__mirror")
|
|
}, _this.state.inputValue, "\xA0"));
|
|
};
|
|
|
|
_this.getInputDOMNode = function () {
|
|
return _this.topCtrlRef ? _this.topCtrlRef.querySelector('input,textarea,div[contentEditable]') : _this.inputRef;
|
|
};
|
|
|
|
_this.getInputMirrorDOMNode = function () {
|
|
return _this.inputMirrorRef;
|
|
};
|
|
|
|
_this.getPopupDOMNode = function () {
|
|
if (_this.selectTriggerRef) {
|
|
return _this.selectTriggerRef.getPopupDOMNode();
|
|
}
|
|
};
|
|
|
|
_this.getPopupMenuComponent = function () {
|
|
if (_this.selectTriggerRef) {
|
|
return _this.selectTriggerRef.getInnerMenu();
|
|
}
|
|
};
|
|
|
|
_this.setOpenState = function (open, needFocus) {
|
|
var props = _this.props;
|
|
var state = _this.state;
|
|
|
|
if (state.open === open) {
|
|
_this.maybeFocus(open, !!needFocus);
|
|
|
|
return;
|
|
}
|
|
|
|
if (_this.props.onDropdownVisibleChange) {
|
|
_this.props.onDropdownVisibleChange(open);
|
|
}
|
|
|
|
var nextState = {
|
|
open: open,
|
|
backfillValue: ''
|
|
}; // clear search input value when open is false in singleMode.
|
|
|
|
if (!open && isSingleMode(props) && props.showSearch) {
|
|
_this.setInputValue('', false);
|
|
}
|
|
|
|
if (!open) {
|
|
_this.maybeFocus(open, !!needFocus);
|
|
}
|
|
|
|
_this.setState(_extends({
|
|
open: open
|
|
}, nextState), function () {
|
|
if (open) {
|
|
_this.maybeFocus(open, !!needFocus);
|
|
}
|
|
});
|
|
};
|
|
|
|
_this.setInputValue = function (inputValue) {
|
|
var fireSearch = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
|
|
|
|
if (inputValue !== _this.state.inputValue) {
|
|
_this.setState({
|
|
inputValue: inputValue
|
|
}, _this.forcePopupAlign);
|
|
|
|
if (fireSearch && _this.props.onSearch) {
|
|
_this.props.onSearch(inputValue);
|
|
}
|
|
}
|
|
};
|
|
|
|
_this.getValueByInput = function (str) {
|
|
var _this$props2 = _this.props,
|
|
multiple = _this$props2.multiple,
|
|
tokenSeparators = _this$props2.tokenSeparators;
|
|
var nextValue = _this.state.value;
|
|
var hasNewValue = false;
|
|
splitBySeparators(str, tokenSeparators).forEach(function (label) {
|
|
var selectedValue = [label];
|
|
|
|
if (multiple) {
|
|
var value = _this.getValueByLabel(label);
|
|
|
|
if (value && findIndexInValueBySingleValue(nextValue, value) === -1) {
|
|
nextValue = nextValue.concat(value);
|
|
hasNewValue = true;
|
|
|
|
_this.fireSelect(value);
|
|
}
|
|
} else if (findIndexInValueBySingleValue(nextValue, label) === -1) {
|
|
nextValue = nextValue.concat(selectedValue);
|
|
hasNewValue = true;
|
|
|
|
_this.fireSelect(label);
|
|
}
|
|
});
|
|
return hasNewValue ? nextValue : undefined;
|
|
};
|
|
|
|
_this.getRealOpenState = function (state) {
|
|
// tslint:disable-next-line:variable-name
|
|
var _open = _this.props.open;
|
|
|
|
if (typeof _open === 'boolean') {
|
|
return _open;
|
|
}
|
|
|
|
var open = (state || _this.state).open;
|
|
var options = _this._options || [];
|
|
|
|
if (isMultipleOrTagsOrCombobox(_this.props) || !_this.props.showSearch) {
|
|
if (open && !options.length) {
|
|
open = false;
|
|
}
|
|
}
|
|
|
|
return open;
|
|
};
|
|
|
|
_this.markMouseDown = function () {
|
|
_this._mouseDown = true;
|
|
};
|
|
|
|
_this.markMouseLeave = function () {
|
|
_this._mouseDown = false;
|
|
};
|
|
|
|
_this.handleBackfill = function (item) {
|
|
if (!_this.props.backfill || !(isSingleMode(_this.props) || isCombobox(_this.props))) {
|
|
return;
|
|
}
|
|
|
|
var key = getValuePropValue(item);
|
|
|
|
if (isCombobox(_this.props)) {
|
|
_this.setInputValue(key, false);
|
|
}
|
|
|
|
_this.setState({
|
|
value: [key],
|
|
backfillValue: key
|
|
});
|
|
};
|
|
|
|
_this.filterOption = function (input, child) {
|
|
var defaultFilter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultFilterFn;
|
|
var value = _this.state.value;
|
|
var lastValue = value[value.length - 1];
|
|
|
|
if (!input || lastValue && lastValue === _this.state.backfillValue) {
|
|
return true;
|
|
}
|
|
|
|
var filterFn = _this.props.filterOption;
|
|
|
|
if ('filterOption' in _this.props) {
|
|
if (filterFn === true) {
|
|
filterFn = defaultFilter.bind(_assertThisInitialized(_this));
|
|
}
|
|
} else {
|
|
filterFn = defaultFilter.bind(_assertThisInitialized(_this));
|
|
}
|
|
|
|
if (!filterFn) {
|
|
return true;
|
|
} else if (typeof filterFn === 'function') {
|
|
return filterFn.call(_assertThisInitialized(_this), input, child);
|
|
} else if (child.props.disabled) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
_this.timeoutFocus = function () {
|
|
if (_this.focusTimer) {
|
|
_this.clearFocusTime();
|
|
}
|
|
|
|
_this.focusTimer = window.setTimeout(function () {
|
|
if (_this.props.onFocus) {
|
|
_this.props.onFocus();
|
|
}
|
|
}, 10);
|
|
};
|
|
|
|
_this.clearFocusTime = function () {
|
|
if (_this.focusTimer) {
|
|
clearTimeout(_this.focusTimer);
|
|
_this.focusTimer = null;
|
|
}
|
|
};
|
|
|
|
_this.clearBlurTime = function () {
|
|
if (_this.blurTimer) {
|
|
clearTimeout(_this.blurTimer);
|
|
_this.blurTimer = null;
|
|
}
|
|
};
|
|
|
|
_this.updateFocusClassName = function () {
|
|
var rootRef = _this.rootRef;
|
|
var props = _this.props; // avoid setState and its side effect
|
|
|
|
if (_this._focused) {
|
|
classes(rootRef).add("".concat(props.prefixCls, "-focused"));
|
|
} else {
|
|
classes(rootRef).remove("".concat(props.prefixCls, "-focused"));
|
|
}
|
|
};
|
|
|
|
_this.maybeFocus = function (open, needFocus) {
|
|
if (needFocus || open) {
|
|
var input = _this.getInputDOMNode();
|
|
|
|
var _document = document,
|
|
activeElement = _document.activeElement;
|
|
|
|
if (input && (open || isMultipleOrTagsOrCombobox(_this.props))) {
|
|
if (activeElement !== input) {
|
|
input.focus();
|
|
_this._focused = true;
|
|
}
|
|
} else if (activeElement !== _this.selectionRef && _this.selectionRef) {
|
|
_this.selectionRef.focus();
|
|
|
|
_this._focused = true;
|
|
}
|
|
}
|
|
};
|
|
|
|
_this.removeSelected = function (selectedKey, e) {
|
|
var props = _this.props;
|
|
|
|
if (props.disabled || _this.isChildDisabled(selectedKey)) {
|
|
return;
|
|
} // Do not trigger Trigger popup
|
|
|
|
|
|
if (e && e.stopPropagation) {
|
|
e.stopPropagation();
|
|
}
|
|
|
|
var oldValue = _this.state.value;
|
|
var value = oldValue.filter(function (singleValue) {
|
|
return singleValue !== selectedKey;
|
|
});
|
|
var canMultiple = isMultipleOrTags(props);
|
|
|
|
if (canMultiple) {
|
|
var event = selectedKey;
|
|
|
|
if (props.labelInValue) {
|
|
event = {
|
|
key: selectedKey,
|
|
label: _this.getLabelBySingleValue(selectedKey)
|
|
};
|
|
}
|
|
|
|
if (props.onDeselect) {
|
|
props.onDeselect(event, _this.getOptionBySingleValue(selectedKey));
|
|
}
|
|
}
|
|
|
|
_this.fireChange(value);
|
|
};
|
|
|
|
_this.openIfHasChildren = function () {
|
|
var props = _this.props;
|
|
|
|
if (React.Children.count(props.children) || isSingleMode(props)) {
|
|
_this.setOpenState(true);
|
|
}
|
|
};
|
|
|
|
_this.fireSelect = function (value) {
|
|
if (_this.props.onSelect) {
|
|
_this.props.onSelect(_this.getVLBySingleValue(value), _this.getOptionBySingleValue(value));
|
|
}
|
|
};
|
|
|
|
_this.fireChange = function (value) {
|
|
var props = _this.props;
|
|
|
|
if (!('value' in props)) {
|
|
_this.setState({
|
|
value: value
|
|
}, _this.forcePopupAlign);
|
|
}
|
|
|
|
var vls = _this.getVLForOnChange(value);
|
|
|
|
var options = _this.getOptionsBySingleValue(value);
|
|
|
|
if (props.onChange) {
|
|
props.onChange(vls, isMultipleOrTags(_this.props) ? options : options[0]);
|
|
}
|
|
};
|
|
|
|
_this.isChildDisabled = function (key) {
|
|
return childrenToArray(_this.props.children).some(function (child) {
|
|
var childValue = getValuePropValue(child);
|
|
return childValue === key && child.props && child.props.disabled;
|
|
});
|
|
};
|
|
|
|
_this.forcePopupAlign = function () {
|
|
if (!_this.state.open) {
|
|
return;
|
|
}
|
|
|
|
if (_this.selectTriggerRef && _this.selectTriggerRef.triggerRef) {
|
|
_this.selectTriggerRef.triggerRef.forcePopupAlign();
|
|
}
|
|
};
|
|
|
|
_this.renderFilterOptions = function () {
|
|
var inputValue = _this.state.inputValue;
|
|
var _this$props3 = _this.props,
|
|
children = _this$props3.children,
|
|
tags = _this$props3.tags,
|
|
filterOption = _this$props3.filterOption,
|
|
notFoundContent = _this$props3.notFoundContent;
|
|
var menuItems = [];
|
|
var childrenKeys = [];
|
|
var empty = false;
|
|
|
|
var options = _this.renderFilterOptionsFromChildren(children, childrenKeys, menuItems);
|
|
|
|
if (tags) {
|
|
// tags value must be string
|
|
var value = _this.state.value;
|
|
value = value.filter(function (singleValue) {
|
|
return childrenKeys.indexOf(singleValue) === -1 && (!inputValue || String(singleValue).indexOf(String(inputValue)) > -1);
|
|
}); // sort by length
|
|
|
|
value.sort(function (val1, val2) {
|
|
return val1.length - val2.length;
|
|
});
|
|
value.forEach(function (singleValue) {
|
|
var key = singleValue;
|
|
var menuItem = React.createElement(MenuItem, {
|
|
style: UNSELECTABLE_STYLE,
|
|
role: "option",
|
|
attribute: UNSELECTABLE_ATTRIBUTE,
|
|
value: key,
|
|
key: key
|
|
}, key);
|
|
options.push(menuItem);
|
|
menuItems.push(menuItem);
|
|
});
|
|
|
|
if (inputValue) {
|
|
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 !_this.filterOption.call(_assertThisInitialized(_this), inputValue, option, filterFn);
|
|
}
|
|
|
|
return !filterFn();
|
|
});
|
|
|
|
if (notFindInputItem) {
|
|
options.unshift(React.createElement(MenuItem, {
|
|
style: UNSELECTABLE_STYLE,
|
|
role: "option",
|
|
attribute: UNSELECTABLE_ATTRIBUTE,
|
|
value: inputValue,
|
|
key: inputValue
|
|
}, inputValue));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!options.length && notFoundContent) {
|
|
empty = true;
|
|
options = [React.createElement(MenuItem, {
|
|
style: UNSELECTABLE_STYLE,
|
|
attribute: UNSELECTABLE_ATTRIBUTE,
|
|
disabled: true,
|
|
role: "option",
|
|
value: "NOT_FOUND",
|
|
key: "NOT_FOUND"
|
|
}, notFoundContent)];
|
|
}
|
|
|
|
return {
|
|
empty: empty,
|
|
options: options
|
|
};
|
|
};
|
|
|
|
_this.renderFilterOptionsFromChildren = function (children, childrenKeys, menuItems) {
|
|
var sel = [];
|
|
var props = _this.props;
|
|
var inputValue = _this.state.inputValue;
|
|
var tags = props.tags;
|
|
React.Children.forEach(children, function (child) {
|
|
if (!child) {
|
|
return;
|
|
}
|
|
|
|
var type = child.type;
|
|
|
|
if (type.isSelectOptGroup) {
|
|
var label = child.props.label;
|
|
var key = child.key;
|
|
|
|
if (!key && typeof label === 'string') {
|
|
key = label;
|
|
} else if (!label && key) {
|
|
label = key;
|
|
} // Match option group label
|
|
|
|
|
|
if (inputValue && _this.filterOption(inputValue, child)) {
|
|
var innerItems = childrenToArray(child.props.children).map(function (subChild) {
|
|
var childValueSub = getValuePropValue(subChild) || subChild.key;
|
|
return React.createElement(MenuItem, _extends({
|
|
key: childValueSub,
|
|
value: childValueSub
|
|
}, subChild.props));
|
|
});
|
|
sel.push(React.createElement(MenuItemGroup, {
|
|
key: key,
|
|
title: label
|
|
}, innerItems)); // Not match
|
|
} else {
|
|
var _innerItems = _this.renderFilterOptionsFromChildren(child.props.children, childrenKeys, menuItems);
|
|
|
|
if (_innerItems.length) {
|
|
sel.push(React.createElement(MenuItemGroup, {
|
|
key: key,
|
|
title: label
|
|
}, _innerItems));
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
warning(type.isSelectOption, 'the children of `Select` should be `Select.Option` or `Select.OptGroup`, ' + "instead of `".concat(type.name || type.displayName || child.type, "`."));
|
|
var childValue = getValuePropValue(child);
|
|
validateOptionValue(childValue, _this.props);
|
|
|
|
if (_this.filterOption(inputValue, child)) {
|
|
var menuItem = React.createElement(MenuItem, _extends({
|
|
style: UNSELECTABLE_STYLE,
|
|
attribute: UNSELECTABLE_ATTRIBUTE,
|
|
value: childValue,
|
|
key: childValue,
|
|
role: "option"
|
|
}, child.props));
|
|
sel.push(menuItem);
|
|
menuItems.push(menuItem);
|
|
}
|
|
|
|
if (tags) {
|
|
childrenKeys.push(childValue);
|
|
}
|
|
});
|
|
return sel;
|
|
};
|
|
|
|
_this.renderTopControlNode = function () {
|
|
var _this$state = _this.state,
|
|
open = _this$state.open,
|
|
inputValue = _this$state.inputValue;
|
|
var value = _this.state.value;
|
|
var props = _this.props;
|
|
var choiceTransitionName = props.choiceTransitionName,
|
|
prefixCls = props.prefixCls,
|
|
maxTagTextLength = props.maxTagTextLength,
|
|
maxTagCount = props.maxTagCount,
|
|
showSearch = props.showSearch,
|
|
removeIcon = props.removeIcon;
|
|
var maxTagPlaceholder = props.maxTagPlaceholder;
|
|
var className = "".concat(prefixCls, "-selection__rendered"); // search input is inside topControlNode in single, multiple & combobox. 2016/04/13
|
|
|
|
var innerNode = null;
|
|
|
|
if (isSingleMode(props)) {
|
|
var selectedValue = null;
|
|
|
|
if (value.length) {
|
|
var showSelectedValue = false;
|
|
var opacity = 1;
|
|
|
|
if (!showSearch) {
|
|
showSelectedValue = true;
|
|
} else if (open) {
|
|
showSelectedValue = !inputValue;
|
|
|
|
if (showSelectedValue) {
|
|
opacity = 0.4;
|
|
}
|
|
} else {
|
|
showSelectedValue = true;
|
|
}
|
|
|
|
var singleValue = value[0];
|
|
|
|
var _this$getOptionInfoBy3 = _this.getOptionInfoBySingleValue(singleValue),
|
|
label = _this$getOptionInfoBy3.label,
|
|
title = _this$getOptionInfoBy3.title;
|
|
|
|
selectedValue = React.createElement("div", {
|
|
key: "value",
|
|
className: "".concat(prefixCls, "-selection-selected-value"),
|
|
title: toTitle(title || label),
|
|
style: {
|
|
display: showSelectedValue ? 'block' : 'none',
|
|
opacity: opacity
|
|
}
|
|
}, label);
|
|
}
|
|
|
|
if (!showSearch) {
|
|
innerNode = [selectedValue];
|
|
} else {
|
|
innerNode = [selectedValue, React.createElement("div", {
|
|
className: "".concat(prefixCls, "-search ").concat(prefixCls, "-search--inline"),
|
|
key: "input",
|
|
style: {
|
|
display: open ? 'block' : 'none'
|
|
}
|
|
}, _this.getInputElement())];
|
|
}
|
|
} else {
|
|
var selectedValueNodes = [];
|
|
var limitedCountValue = value;
|
|
var maxTagPlaceholderEl;
|
|
|
|
if (maxTagCount !== undefined && value.length > maxTagCount) {
|
|
limitedCountValue = limitedCountValue.slice(0, maxTagCount);
|
|
|
|
var omittedValues = _this.getVLForOnChange(value.slice(maxTagCount, value.length));
|
|
|
|
var content = "+ ".concat(value.length - maxTagCount, " ...");
|
|
|
|
if (maxTagPlaceholder) {
|
|
content = typeof maxTagPlaceholder === 'function' ? maxTagPlaceholder(omittedValues) : maxTagPlaceholder;
|
|
}
|
|
|
|
maxTagPlaceholderEl = React.createElement("li", _extends({
|
|
style: UNSELECTABLE_STYLE
|
|
}, UNSELECTABLE_ATTRIBUTE, {
|
|
role: "presentation",
|
|
onMouseDown: preventDefaultEvent,
|
|
className: "".concat(prefixCls, "-selection__choice ").concat(prefixCls, "-selection__choice__disabled"),
|
|
key: "maxTagPlaceholder",
|
|
title: toTitle(content)
|
|
}), React.createElement("div", {
|
|
className: "".concat(prefixCls, "-selection__choice__content")
|
|
}, content));
|
|
}
|
|
|
|
if (isMultipleOrTags(props)) {
|
|
selectedValueNodes = limitedCountValue.map(function (singleValue) {
|
|
var info = _this.getOptionInfoBySingleValue(singleValue);
|
|
|
|
var content = info.label;
|
|
var title = info.title || content;
|
|
|
|
if (maxTagTextLength && typeof content === 'string' && content.length > maxTagTextLength) {
|
|
content = "".concat(content.slice(0, maxTagTextLength), "...");
|
|
}
|
|
|
|
var disabled = _this.isChildDisabled(singleValue);
|
|
|
|
var choiceClassName = disabled ? "".concat(prefixCls, "-selection__choice ").concat(prefixCls, "-selection__choice__disabled") : "".concat(prefixCls, "-selection__choice");
|
|
return React.createElement("li", _extends({
|
|
style: UNSELECTABLE_STYLE
|
|
}, UNSELECTABLE_ATTRIBUTE, {
|
|
onMouseDown: preventDefaultEvent,
|
|
className: choiceClassName,
|
|
role: "presentation",
|
|
key: singleValue || SELECT_EMPTY_VALUE_KEY,
|
|
title: toTitle(title)
|
|
}), React.createElement("div", {
|
|
className: "".concat(prefixCls, "-selection__choice__content")
|
|
}, content), disabled ? null : React.createElement("span", {
|
|
onClick: function onClick(event) {
|
|
_this.removeSelected(singleValue, event);
|
|
},
|
|
className: "".concat(prefixCls, "-selection__choice__remove")
|
|
}, removeIcon || React.createElement("i", {
|
|
className: "".concat(prefixCls, "-selection__choice__remove-icon")
|
|
}, "\xD7")));
|
|
});
|
|
}
|
|
|
|
if (maxTagPlaceholderEl) {
|
|
selectedValueNodes.push(maxTagPlaceholderEl);
|
|
}
|
|
|
|
selectedValueNodes.push(React.createElement("li", {
|
|
className: "".concat(prefixCls, "-search ").concat(prefixCls, "-search--inline"),
|
|
key: "__input"
|
|
}, _this.getInputElement()));
|
|
|
|
if (isMultipleOrTags(props) && choiceTransitionName) {
|
|
innerNode = React.createElement(Animate, {
|
|
onLeave: _this.onChoiceAnimationLeave,
|
|
component: "ul",
|
|
transitionName: choiceTransitionName
|
|
}, selectedValueNodes);
|
|
} else {
|
|
innerNode = React.createElement("ul", null, selectedValueNodes);
|
|
}
|
|
}
|
|
|
|
return React.createElement("div", {
|
|
className: className,
|
|
ref: _this.saveTopCtrlRef
|
|
}, _this.getPlaceholderElement(), innerNode);
|
|
};
|
|
|
|
var optionsInfo = Select.getOptionsInfoFromProps(props);
|
|
_this.state = {
|
|
value: Select.getValueFromProps(props, true),
|
|
inputValue: props.combobox ? Select.getInputValueForCombobox(props, optionsInfo, true) : '',
|
|
open: props.defaultOpen,
|
|
optionsInfo: optionsInfo,
|
|
backfillValue: '',
|
|
// a flag for aviod redundant getOptionsInfoFromProps call
|
|
skipBuildOptionsInfo: true,
|
|
ariaId: ''
|
|
};
|
|
_this.saveInputRef = saveRef(_assertThisInitialized(_this), 'inputRef');
|
|
_this.saveInputMirrorRef = saveRef(_assertThisInitialized(_this), 'inputMirrorRef');
|
|
_this.saveTopCtrlRef = saveRef(_assertThisInitialized(_this), 'topCtrlRef');
|
|
_this.saveSelectTriggerRef = saveRef(_assertThisInitialized(_this), 'selectTriggerRef');
|
|
_this.saveRootRef = saveRef(_assertThisInitialized(_this), 'rootRef');
|
|
_this.saveSelectionRef = saveRef(_assertThisInitialized(_this), 'selectionRef');
|
|
return _this;
|
|
}
|
|
|
|
_createClass(Select, [{
|
|
key: "componentDidMount",
|
|
value: function componentDidMount() {
|
|
// when defaultOpen is true, we should auto focus search input
|
|
// https://github.com/ant-design/ant-design/issues/14254
|
|
if (this.props.autoFocus || this.state.open) {
|
|
this.focus();
|
|
}
|
|
|
|
this.setState({
|
|
ariaId: generateUUID()
|
|
});
|
|
}
|
|
}, {
|
|
key: "componentDidUpdate",
|
|
value: function componentDidUpdate() {
|
|
if (isMultipleOrTags(this.props)) {
|
|
var inputNode = this.getInputDOMNode();
|
|
var mirrorNode = this.getInputMirrorDOMNode();
|
|
|
|
if (inputNode && inputNode.value && mirrorNode) {
|
|
inputNode.style.width = '';
|
|
inputNode.style.width = "".concat(mirrorNode.clientWidth, "px");
|
|
} else if (inputNode) {
|
|
inputNode.style.width = '';
|
|
}
|
|
}
|
|
|
|
this.forcePopupAlign();
|
|
}
|
|
}, {
|
|
key: "componentWillUnmount",
|
|
value: function componentWillUnmount() {
|
|
this.clearFocusTime();
|
|
this.clearBlurTime();
|
|
|
|
if (this.dropdownContainer) {
|
|
ReactDOM.unmountComponentAtNode(this.dropdownContainer);
|
|
document.body.removeChild(this.dropdownContainer);
|
|
this.dropdownContainer = null;
|
|
}
|
|
}
|
|
}, {
|
|
key: "focus",
|
|
value: function focus() {
|
|
if (isSingleMode(this.props) && this.selectionRef) {
|
|
this.selectionRef.focus();
|
|
} else if (this.getInputDOMNode()) {
|
|
this.getInputDOMNode().focus();
|
|
}
|
|
}
|
|
}, {
|
|
key: "blur",
|
|
value: function blur() {
|
|
if (isSingleMode(this.props) && this.selectionRef) {
|
|
this.selectionRef.blur();
|
|
} else if (this.getInputDOMNode()) {
|
|
this.getInputDOMNode().blur();
|
|
}
|
|
}
|
|
}, {
|
|
key: "renderArrow",
|
|
value: function renderArrow(multiple) {
|
|
var _this$props4 = this.props,
|
|
showArrow = _this$props4.showArrow,
|
|
loading = _this$props4.loading,
|
|
inputIcon = _this$props4.inputIcon,
|
|
prefixCls = _this$props4.prefixCls;
|
|
|
|
if (!showArrow) {
|
|
return null;
|
|
} // if loading have loading icon
|
|
|
|
|
|
if (multiple && !loading) {
|
|
return null;
|
|
}
|
|
|
|
var defaultIcon = loading ? React.createElement("i", {
|
|
className: "".concat(prefixCls, "-arrow-loading")
|
|
}) : React.createElement("i", {
|
|
className: "".concat(prefixCls, "-arrow-icon")
|
|
});
|
|
return React.createElement("span", _extends({
|
|
key: "arrow",
|
|
className: "".concat(prefixCls, "-arrow"),
|
|
style: UNSELECTABLE_STYLE
|
|
}, UNSELECTABLE_ATTRIBUTE, {
|
|
onClick: this.onArrowClick
|
|
}), inputIcon || defaultIcon);
|
|
}
|
|
}, {
|
|
key: "renderClear",
|
|
value: function renderClear() {
|
|
var _this$props5 = this.props,
|
|
prefixCls = _this$props5.prefixCls,
|
|
allowClear = _this$props5.allowClear,
|
|
clearIcon = _this$props5.clearIcon;
|
|
var inputValue = this.state.inputValue;
|
|
var value = this.state.value;
|
|
var clear = React.createElement("span", _extends({
|
|
key: "clear",
|
|
className: "".concat(prefixCls, "-selection__clear"),
|
|
onMouseDown: preventDefaultEvent,
|
|
style: UNSELECTABLE_STYLE
|
|
}, UNSELECTABLE_ATTRIBUTE, {
|
|
onClick: this.onClearSelection
|
|
}), clearIcon || React.createElement("i", {
|
|
className: "".concat(prefixCls, "-selection__clear-icon")
|
|
}, "\xD7"));
|
|
|
|
if (!allowClear) {
|
|
return null;
|
|
}
|
|
|
|
if (isCombobox(this.props)) {
|
|
if (inputValue) {
|
|
return clear;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
if (inputValue || value.length) {
|
|
return clear;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}, {
|
|
key: "render",
|
|
value: function render() {
|
|
var _rootCls;
|
|
|
|
var props = this.props;
|
|
var multiple = isMultipleOrTags(props);
|
|
var state = this.state;
|
|
var className = props.className,
|
|
disabled = props.disabled,
|
|
prefixCls = props.prefixCls;
|
|
var ctrlNode = this.renderTopControlNode();
|
|
var _this$state2 = this.state,
|
|
open = _this$state2.open,
|
|
ariaId = _this$state2.ariaId;
|
|
|
|
if (open) {
|
|
var filterOptions = this.renderFilterOptions();
|
|
this._empty = filterOptions.empty;
|
|
this._options = filterOptions.options;
|
|
}
|
|
|
|
var realOpen = this.getRealOpenState();
|
|
var empty = this._empty;
|
|
var options = this._options || [];
|
|
var dataOrAriaAttributeProps = {};
|
|
Object.keys(props).forEach(function (key) {
|
|
if (Object.prototype.hasOwnProperty.call(props, key) && (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role')) {
|
|
dataOrAriaAttributeProps[key] = props[key];
|
|
}
|
|
}); // for (const key in props) {
|
|
// if (
|
|
// Object.prototype.hasOwnProperty.call(props, key) &&
|
|
// (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role')
|
|
// ) {
|
|
// dataOrAriaAttributeProps[key] = props[key];
|
|
// }
|
|
// }
|
|
|
|
var extraSelectionProps = _extends({}, dataOrAriaAttributeProps);
|
|
|
|
if (!isMultipleOrTagsOrCombobox(props)) {
|
|
extraSelectionProps = _extends({}, extraSelectionProps, {
|
|
onKeyDown: this.onKeyDown,
|
|
tabIndex: props.disabled ? -1 : props.tabIndex
|
|
});
|
|
}
|
|
|
|
var rootCls = (_rootCls = {}, _defineProperty(_rootCls, className, !!className), _defineProperty(_rootCls, prefixCls, 1), _defineProperty(_rootCls, "".concat(prefixCls, "-open"), open), _defineProperty(_rootCls, "".concat(prefixCls, "-focused"), open || !!this._focused), _defineProperty(_rootCls, "".concat(prefixCls, "-combobox"), isCombobox(props)), _defineProperty(_rootCls, "".concat(prefixCls, "-disabled"), disabled), _defineProperty(_rootCls, "".concat(prefixCls, "-enabled"), !disabled), _defineProperty(_rootCls, "".concat(prefixCls, "-allow-clear"), !!props.allowClear), _defineProperty(_rootCls, "".concat(prefixCls, "-no-arrow"), !props.showArrow), _rootCls);
|
|
return React.createElement(SelectTrigger, {
|
|
onPopupFocus: this.onPopupFocus,
|
|
onMouseEnter: this.props.onMouseEnter,
|
|
onMouseLeave: this.props.onMouseLeave,
|
|
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,
|
|
empty: empty,
|
|
multiple: multiple,
|
|
disabled: disabled,
|
|
visible: realOpen,
|
|
inputValue: state.inputValue,
|
|
value: state.value,
|
|
backfillValue: state.backfillValue,
|
|
firstActiveValue: props.firstActiveValue,
|
|
onDropdownVisibleChange: this.onDropdownVisibleChange,
|
|
getPopupContainer: props.getPopupContainer,
|
|
onMenuSelect: this.onMenuSelect,
|
|
onMenuDeselect: this.onMenuDeselect,
|
|
onPopupScroll: props.onPopupScroll,
|
|
showAction: props.showAction,
|
|
ref: this.saveSelectTriggerRef,
|
|
menuItemSelectedIcon: props.menuItemSelectedIcon,
|
|
dropdownRender: props.dropdownRender,
|
|
ariaId: ariaId
|
|
}, React.createElement("div", {
|
|
id: props.id,
|
|
style: props.style,
|
|
ref: this.saveRootRef,
|
|
onBlur: this.onOuterBlur,
|
|
onFocus: this.onOuterFocus,
|
|
className: classnames(rootCls),
|
|
onMouseDown: this.markMouseDown,
|
|
onMouseUp: this.markMouseLeave,
|
|
onMouseOut: this.markMouseLeave
|
|
}, React.createElement("div", _extends({
|
|
ref: this.saveSelectionRef,
|
|
key: "selection",
|
|
className: "".concat(prefixCls, "-selection\n ").concat(prefixCls, "-selection--").concat(multiple ? 'multiple' : 'single'),
|
|
role: "combobox",
|
|
"aria-autocomplete": "list",
|
|
"aria-haspopup": "true",
|
|
"aria-controls": ariaId,
|
|
"aria-expanded": realOpen
|
|
}, extraSelectionProps), ctrlNode, this.renderClear(), this.renderArrow(!!multiple))));
|
|
}
|
|
}]);
|
|
|
|
return Select;
|
|
}(React.Component);
|
|
|
|
Select.propTypes = SelectPropTypes;
|
|
Select.defaultProps = {
|
|
prefixCls: 'rc-select',
|
|
defaultOpen: false,
|
|
labelInValue: false,
|
|
defaultActiveFirstOption: true,
|
|
showSearch: true,
|
|
allowClear: false,
|
|
placeholder: '',
|
|
onChange: noop,
|
|
onFocus: noop,
|
|
onBlur: noop,
|
|
onSelect: noop,
|
|
onSearch: noop,
|
|
onDeselect: noop,
|
|
onInputKeyDown: noop,
|
|
showArrow: true,
|
|
dropdownMatchSelectWidth: true,
|
|
dropdownStyle: {},
|
|
dropdownMenuStyle: {},
|
|
optionFilterProp: 'value',
|
|
optionLabelProp: 'value',
|
|
notFoundContent: 'Not Found',
|
|
backfill: false,
|
|
showAction: ['click'],
|
|
tokenSeparators: [],
|
|
autoClearSearchValue: true,
|
|
tabIndex: 0,
|
|
dropdownRender: function dropdownRender(menu) {
|
|
return menu;
|
|
}
|
|
};
|
|
|
|
Select.getDerivedStateFromProps = function (nextProps, prevState) {
|
|
var optionsInfo = prevState.skipBuildOptionsInfo ? prevState.optionsInfo : Select.getOptionsInfoFromProps(nextProps, prevState);
|
|
var newState = {
|
|
optionsInfo: optionsInfo,
|
|
skipBuildOptionsInfo: false
|
|
};
|
|
|
|
if ('open' in nextProps) {
|
|
newState.open = nextProps.open;
|
|
}
|
|
|
|
if ('value' in nextProps) {
|
|
var value = Select.getValueFromProps(nextProps);
|
|
newState.value = value;
|
|
|
|
if (nextProps.combobox) {
|
|
newState.inputValue = Select.getInputValueForCombobox(nextProps, optionsInfo);
|
|
}
|
|
}
|
|
|
|
return newState;
|
|
};
|
|
|
|
Select.getOptionsFromChildren = function (children) {
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
|
|
React.Children.forEach(children, function (child) {
|
|
if (!child) {
|
|
return;
|
|
}
|
|
|
|
var type = child.type;
|
|
|
|
if (type.isSelectOptGroup) {
|
|
Select.getOptionsFromChildren(child.props.children, options);
|
|
} else {
|
|
options.push(child);
|
|
}
|
|
});
|
|
return options;
|
|
};
|
|
|
|
Select.getInputValueForCombobox = function (props, optionsInfo, useDefaultValue) {
|
|
var value = [];
|
|
|
|
if ('value' in props && !useDefaultValue) {
|
|
value = toArray(props.value);
|
|
}
|
|
|
|
if ('defaultValue' in props && useDefaultValue) {
|
|
value = toArray(props.defaultValue);
|
|
}
|
|
|
|
if (value.length) {
|
|
value = value[0];
|
|
} else {
|
|
return '';
|
|
}
|
|
|
|
var label = value;
|
|
|
|
if (props.labelInValue) {
|
|
label = value.label;
|
|
} else if (optionsInfo[getMapKey(value)]) {
|
|
label = optionsInfo[getMapKey(value)].label;
|
|
}
|
|
|
|
if (label === undefined) {
|
|
label = '';
|
|
}
|
|
|
|
return label;
|
|
};
|
|
|
|
Select.getLabelFromOption = function (props, option) {
|
|
return getPropValue(option, props.optionLabelProp);
|
|
};
|
|
|
|
Select.getOptionsInfoFromProps = function (props, preState) {
|
|
var options = Select.getOptionsFromChildren(props.children);
|
|
var optionsInfo = {};
|
|
options.forEach(function (option) {
|
|
var singleValue = getValuePropValue(option);
|
|
optionsInfo[getMapKey(singleValue)] = {
|
|
option: option,
|
|
value: singleValue,
|
|
label: Select.getLabelFromOption(props, option),
|
|
title: option.props.title,
|
|
disabled: option.props.disabled
|
|
};
|
|
});
|
|
|
|
if (preState) {
|
|
// keep option info in pre state value.
|
|
var oldOptionsInfo = preState.optionsInfo;
|
|
var value = preState.value;
|
|
|
|
if (value) {
|
|
value.forEach(function (v) {
|
|
var key = getMapKey(v);
|
|
|
|
if (!optionsInfo[key] && oldOptionsInfo[key] !== undefined) {
|
|
optionsInfo[key] = oldOptionsInfo[key];
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
return optionsInfo;
|
|
};
|
|
|
|
Select.getValueFromProps = function (props, useDefaultValue) {
|
|
var value = [];
|
|
|
|
if ('value' in props && !useDefaultValue) {
|
|
value = toArray(props.value);
|
|
}
|
|
|
|
if ('defaultValue' in props && useDefaultValue) {
|
|
value = toArray(props.defaultValue);
|
|
}
|
|
|
|
if (props.labelInValue) {
|
|
value = value.map(function (v) {
|
|
return v.key;
|
|
});
|
|
}
|
|
|
|
return value;
|
|
};
|
|
|
|
Select.displayName = 'Select';
|
|
polyfill(Select);
|
|
export default Select; |