chowa
Version:
UI component library based on React
308 lines (307 loc) • 13.5 kB
JavaScript
/**
* @license chowa v1.1.3
*
* Copyright (c) Chowa Techonlogies Co.,Ltd.(http://www.chowa.cn).
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const React = require("react");
const PropTypes = require("prop-types");
const classnames_1 = require("classnames");
const utils_1 = require("../utils");
const select_option_1 = require("./select-option");
const select_option_group_1 = require("./select-option-group");
const tool_1 = require("./tool");
const select_selector_1 = require("./select-selector");
const dropdown_1 = require("../dropdown");
const icon_1 = require("../icon");
const tag_1 = require("../tag");
const i18n_1 = require("../i18n");
class Select extends React.PureComponent {
constructor(props) {
super(props);
const values = tool_1.compileValue(props.value || props.defaultValue);
const renderOptions = Array.isArray(props.options)
? props.options
: tool_1.transformReactNodeToOptions(props.children);
this.state = {
renderOptions,
selectedOptions: tool_1.compileSelectedOptions(values, renderOptions),
selectorVisible: props.visible || props.defaultVisible,
clearBtnVisible: false,
searching: false,
searchValue: '',
activeOption: undefined
};
[
'onSelectHandler',
'onDeSelectHandler',
'onVisibleChange',
'clearSelected',
'onKeyboardOperation',
'onTriggerMouseEnterHandler',
'onTriggerMouseLeaveHandler',
'onSearchChangeHandler',
'onSearchFocusHandler',
'onSearchBlurHandler',
'onOptionMouseEnter',
'onOptionMouseLeave'
].forEach((fn) => {
this[fn] = this[fn].bind(this);
});
}
componentDidUpdate(preProps, preState) {
if (!utils_1.isEqual(preProps.value, this.props.value)) {
const values = tool_1.compileValue(this.props.value);
this.setState({
selectedOptions: tool_1.compileSelectedOptions(values, this.state.renderOptions)
});
}
if (!Array.isArray(this.props.options)
&& !utils_1.isEqual(preProps.children, this.props.children)) {
this.setState({
renderOptions: tool_1.transformReactNodeToOptions(this.props.children)
});
}
if (!utils_1.isEqual(preProps.options, this.props.options) && !utils_1.isEqual(this.state.renderOptions, this.props.options)) {
this.setState({
renderOptions: this.props.options
});
}
if (this.props.searchable
&& this.state.selectorVisible
&& (preState.selectorVisible !== this.state.selectorVisible
|| !utils_1.isEqual(preState.selectedOptions, this.state.selectedOptions))) {
this.inputElement.focus();
}
if (preProps.visible !== this.props.visible && this.props.visible !== this.state.selectorVisible) {
this.setState({
selectorVisible: this.props.visible
});
}
}
onKeyboardOperation(e) {
const { multiple } = this.props;
const { selectorVisible, renderOptions, searchValue, activeOption, selectedOptions } = this.state;
if (e.keyCode === 9) {
return this.setState({ selectorVisible: false });
}
if (!selectorVisible) {
if (e.keyCode === 13 || e.keyCode === 40) {
this.setState({ selectorVisible: true });
e.preventDefault();
}
}
else {
switch (e.keyCode) {
case 40:
this.setState({
activeOption: tool_1.getNextOption(renderOptions, searchValue, activeOption)
});
e.preventDefault();
break;
case 38:
this.setState({
activeOption: tool_1.getPreOption(renderOptions, searchValue, activeOption)
});
e.preventDefault();
break;
case 13:
if (activeOption === undefined) {
return;
}
if (multiple) {
if (selectedOptions.some((item) => item.value === activeOption.value)) {
this.onDeSelectHandler(activeOption);
}
else {
this.onSelectHandler(activeOption);
}
}
else {
this.onSelectHandler(activeOption);
this.setState({ selectorVisible: false });
}
e.preventDefault();
break;
case 27:
this.setState({ selectorVisible: false });
e.preventDefault();
break;
case 8:
if (!searchValue && multiple && selectedOptions.length > 0) {
this.onDeSelectHandler(selectedOptions[selectedOptions.length - 1], e);
}
e.preventDefault();
break;
}
}
utils_1.stopReactPropagation(e);
}
onTriggerMouseEnterHandler() {
this.setState({ clearBtnVisible: true });
}
onTriggerMouseLeaveHandler() {
this.setState({ clearBtnVisible: false });
}
onSearchChangeHandler(e) {
const searchValue = e.target.value;
this.setState({
searchValue,
activeOption: undefined
}, () => {
if (this.props.onSearch) {
this.props.onSearch(searchValue);
}
});
utils_1.stopReactPropagation(e);
}
onSearchFocusHandler(e) {
this.setState({ searching: true });
utils_1.stopReactPropagation(e);
}
onSearchBlurHandler(e) {
this.setState({ searching: false });
utils_1.stopReactPropagation(e);
}
clearSelected(e) {
this.setState({
selectedOptions: []
});
if (this.props.onChange) {
this.props.onChange(this.props.multiple ? [] : '');
}
utils_1.stopReactPropagation(e);
}
onVisibleChange(v) {
this.setState({
selectorVisible: v,
searchValue: ''
});
}
onDeSelectHandler(option, e) {
const selectedOptions = [].concat(this.state.selectedOptions);
const index = selectedOptions.findIndex((item) => item.value === option.value);
selectedOptions.splice(index, 1);
this.setState({ selectedOptions });
if (this.props.onDeselect) {
this.props.onDeselect(option.value);
}
if (e) {
utils_1.stopReactPropagation(e);
}
}
onSelectHandler(option) {
const { multiple, onChange, onSelect } = this.props;
const selectedOptions = multiple ? [].concat(this.state.selectedOptions) : [];
selectedOptions.push(option);
this.setState({ selectedOptions });
if (onSelect) {
onSelect(option.value);
}
if (onChange) {
onChange(multiple
? selectedOptions.map((item) => item.value)
: selectedOptions[0].value);
}
if (!multiple) {
this.setState({ selectorVisible: false });
}
}
onOptionMouseEnter(option) {
this.setState({ activeOption: option });
}
onOptionMouseLeave() {
this.setState({ activeOption: undefined });
}
renderContent() {
const { multiple, noDataDescription, noDataImg, noDataImgStyle, searchable, onFilter } = this.props;
const { searchValue, renderOptions, activeOption, selectedOptions } = this.state;
return (React.createElement(select_selector_1.default, { multiple: multiple, noDataDescription: noDataDescription, noDataImg: noDataImg, noDataImgStyle: noDataImgStyle, searchable: searchable, searchValue: searchValue, options: renderOptions, onFilter: onFilter, onKeyDown: this.onKeyboardOperation, activeOption: activeOption, selectedOptions: selectedOptions, selectHandler: this.onSelectHandler, deSelectHandler: this.onDeSelectHandler, onOptionMouseEnter: this.onOptionMouseEnter, onOptionMouseLeave: this.onOptionMouseLeave }));
}
render() {
const { className, style, showArrow, disabled, externalWheelHide, clearable, tabIndex, searchable, multiple, placeholder } = this.props;
const { selectorVisible, selectedOptions, searching, searchValue, clearBtnVisible } = this.state;
const triggerClass = classnames_1.default({
[utils_1.preClass('select')]: true,
[utils_1.preClass('select-disabled')]: disabled,
[utils_1.preClass('select-focused')]: selectorVisible,
[className]: utils_1.isExist(className)
});
const arrowClass = classnames_1.default({
[utils_1.preClass('select-arrow')]: true,
[utils_1.preClass('select-arrow-active')]: selectorVisible
});
const valueClass = classnames_1.default({
[utils_1.preClass('select-value')]: true,
[utils_1.preClass('select-searching')]: searching
});
const inputClass = classnames_1.default({
[utils_1.preClass('select-search-input')]: true,
[utils_1.preClass('select-search-multiple-input')]: multiple && selectedOptions.length > 0
});
const searchInputStyle = Object.assign(Object.assign({}, (multiple && searchValue ? { width: searchValue.length * 20 } : {})), { display: (selectorVisible ? 'inline-block' : 'none') });
return (React.createElement(dropdown_1.default, { visible: selectorVisible, onVisibleChange: this.onVisibleChange, externalWheelHide: externalWheelHide, content: this.renderContent(), matchTriggerWidth: true, disabled: disabled, role: 'select', trigger: 'click' },
React.createElement("div", { tabIndex: disabled ? -1 : tabIndex, className: triggerClass, style: style, onKeyDown: disabled ? null : this.onKeyboardOperation, onMouseEnter: clearable ? this.onTriggerMouseEnterHandler : null, onMouseLeave: clearable ? this.onTriggerMouseLeaveHandler : null },
React.createElement("div", { className: utils_1.preClass('select-selection') },
!searchValue && selectedOptions.length === 0 &&
React.createElement("span", { className: utils_1.preClass('select-placeholder') },
React.createElement(i18n_1.I18nReceiver, { module: 'Select' }, (i18n) => placeholder || i18n.placeholder)),
!searchValue && !multiple && selectedOptions.length > 0 &&
React.createElement("span", { className: valueClass }, tool_1.getOptionLabel(selectedOptions[0])),
multiple &&
selectedOptions.map((option, key) => {
return (React.createElement(tag_1.default, { key: key, disabled: disabled, closable: true, onClose: this.onDeSelectHandler.bind(this, option) }, tool_1.getOptionLabel(option)));
}),
searchable &&
React.createElement("input", { type: 'text', tabIndex: -1, value: searchValue, className: inputClass, style: searchInputStyle, onFocus: this.onSearchFocusHandler, onBlur: this.onSearchBlurHandler, onChange: this.onSearchChangeHandler, onKeyDown: this.onKeyboardOperation, ref: (ele) => {
this.inputElement = ele;
} })),
showArrow &&
React.createElement("span", { className: arrowClass },
React.createElement(icon_1.default, { type: 'arrow-down' })),
clearable &&
React.createElement(utils_1.ClearButton, { visible: clearBtnVisible && selectedOptions.length > 0, onClick: this.clearSelected }))));
}
}
Select.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
visible: PropTypes.bool,
defaultVisible: PropTypes.bool,
externalWheelHide: PropTypes.bool,
tabIndex: PropTypes.number,
multiple: PropTypes.bool,
disabled: PropTypes.bool,
showArrow: PropTypes.bool,
searchable: PropTypes.bool,
defaultValue: PropTypes.any,
value: PropTypes.any,
placeholder: PropTypes.string,
onChange: PropTypes.func,
onDeselect: PropTypes.func,
onSelect: PropTypes.func,
onSearch: PropTypes.func,
onFilter: PropTypes.func,
noDataDescription: PropTypes.node,
noDataImg: PropTypes.string,
noDataImgStyle: PropTypes.object,
clearable: PropTypes.bool
};
Select.defaultProps = {
visible: false,
defaultVisible: false,
externalWheelHide: true,
tabIndex: 0,
multiple: false,
disabled: false,
showArrow: true,
searchable: false,
clearable: false
};
Select.Option = select_option_1.default;
Select.OptionGroup = select_option_group_1.default;
exports.default = Select;