UNPKG

chowa

Version:

UI component library based on React

308 lines (307 loc) 13.5 kB
/** * @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;