UNPKG

amis

Version:

一种MIS页面生成工具

414 lines (413 loc) 20.4 kB
"use strict"; /** * @file Select * @description * @author fex * @date 2017-11-07 */ Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var uncontrollable = require("uncontrollable"); var react_1 = tslib_1.__importDefault(require("react")); /*@require react-datetime/css/react-datetime.css*/; var Overlay_1 = tslib_1.__importDefault(require("./Overlay")); var PopOver_1 = tslib_1.__importDefault(require("./PopOver")); var downshift_1 = tslib_1.__importDefault(require("downshift")); var icons_1 = require("./icons"); var match_sorter_1 = tslib_1.__importDefault(require("match-sorter")); var helper_1 = require("../utils/helper"); var find = require("lodash/find"); var isPlainObject = require("lodash/isPlainObject"); var union = require("lodash/union"); var Options_1 = require("../renderers/Form/Options"); var react_dom_1 = require("react-dom"); var theme_1 = require("../theme"); var Checkbox_1 = tslib_1.__importDefault(require("./Checkbox")); function value2array(value, props) { if (props.multi || props.multiple) { if (typeof value === 'string') { value = value.split(props.delimiter || ','); } if (!Array.isArray(value)) { if (value === null || value === undefined) { return []; } value = [value]; } return value.map(function (value) { return expandValue(value, props); }).filter(function (item) { return item; }); } else if (Array.isArray(value)) { value = value[0]; } var expandedValue = expandValue(value, props); return expandedValue ? [expandedValue] : []; } exports.value2array = value2array; function expandValue(value, props) { var valueType = typeof value; if (valueType !== 'string' && valueType !== 'number' && valueType !== 'boolean') { return value; } var options = props.options; if (!options) { return null; } return find(options, function (item) { return String(item[props.valueField || 'value']) === String(value); }); } exports.expandValue = expandValue; function normalizeOptions(options) { if (typeof options === 'string') { return options.split(',').map(function (item) { return ({ label: item, value: item }); }); } else if (Array.isArray(options) && typeof options[0] === 'string') { return options.map(function (item) { return ({ label: item, value: item }); }); } else if (Array.isArray(options)) { return options.map(function (item) { var option = tslib_1.__assign(tslib_1.__assign({}, item), { value: item && item.value }); if (typeof option.children !== 'undefined') { option.children = normalizeOptions(option.children); } return option; }); } else if (isPlainObject(options)) { return Object.keys(options).map(function (key) { return ({ label: options[key], value: key }); }); } return []; } exports.normalizeOptions = normalizeOptions; var Select = /** @class */ (function (_super) { tslib_1.__extends(Select, _super); function Select(props) { var _this = _super.call(this, props) || this; _this.menu = react_1.default.createRef(); _this.open = _this.open.bind(_this); _this.close = _this.close.bind(_this); _this.toggle = _this.toggle.bind(_this); _this.onBlur = _this.onBlur.bind(_this); _this.onFocus = _this.onFocus.bind(_this); _this.focus = _this.focus.bind(_this); _this.inputRef = _this.inputRef.bind(_this); _this.handleChange = _this.handleChange.bind(_this); _this.handleInputChange = _this.handleInputChange.bind(_this); _this.clearValue = _this.clearValue.bind(_this); _this.handleStateChange = _this.handleStateChange.bind(_this); _this.handleKeyPress = _this.handleKeyPress.bind(_this); _this.getTarget = _this.getTarget.bind(_this); _this.toggleCheckAll = _this.toggleCheckAll.bind(_this); _this.state = { isOpen: false, isFocused: false, inputValue: '', highlightedIndex: -1, selection: value2array(props.value, props) }; return _this; } Select.prototype.componentDidMount = function () { var _a = this.props, loadOptions = _a.loadOptions, options = _a.options, multiple = _a.multiple, checkAll = _a.checkAll, defaultCheckAll = _a.defaultCheckAll, onChange = _a.onChange, simpleValue = _a.simpleValue; var selection = this.state.selection; if (multiple && checkAll && defaultCheckAll && options.length) { selection = union(options, selection); this.setState({ selection: selection }, function () { return onChange(simpleValue ? selection.map(function (item) { return item.value; }) : selection); }); } loadOptions && loadOptions(''); }; Select.prototype.componentWillReceiveProps = function (nextProps) { var props = this.props; if (props.value !== nextProps.value || JSON.stringify(props.options) !== JSON.stringify(nextProps.options)) { this.setState({ selection: value2array(nextProps.value, nextProps) }); } }; Select.prototype.open = function () { this.props.disabled || this.setState({ isOpen: true }); }; Select.prototype.close = function () { this.setState({ isOpen: false }); }; Select.prototype.toggle = function (e) { if (e && this.menu.current && this.menu.current.contains(e.target)) { return; } this.props.disabled || this.setState({ isOpen: !this.state.isOpen }); }; Select.prototype.onFocus = function (e) { this.props.disabled || this.setState({ isFocused: true }, this.focus); this.props.onFocus && this.props.onFocus(e); }; Select.prototype.onBlur = function (e) { this.setState({ isFocused: false, inputValue: '' }); this.props.onBlur && this.props.onBlur(e); }; Select.prototype.focus = function () { this.input ? this.input.focus() : this.getTarget() && this.getTarget().focus(); }; Select.prototype.blur = function () { this.input ? this.input.blur() : this.getTarget() && this.getTarget().blur(); }; Select.prototype.getTarget = function () { if (!this.target) { this.target = react_dom_1.findDOMNode(this); } return this.target; }; Select.prototype.inputRef = function (ref) { this.input = ref; }; Select.prototype.toggleCheckAll = function () { var _a = this.props, options = _a.options, onChange = _a.onChange, simpleValue = _a.simpleValue; var selection = this.state.selection; var optionsValues = options.map(function (option) { return option.value; }); var selectionValues = selection.map(function (select) { return select.value; }); var checkedAll = optionsValues.every(function (option) { return selectionValues.indexOf(option) > -1; }); selection = checkedAll ? [] : options; onChange(simpleValue ? selection.map(function (item) { return item.value; }) : selection); }; Select.prototype.removeItem = function (index, e) { var _a = this.props, onChange = _a.onChange, simpleValue = _a.simpleValue; var value = this.state.selection; e && e.stopPropagation(); value = Array.isArray(value) ? value.concat() : [value]; value.splice(index, 1); onChange(simpleValue ? value.map(function (item) { return item.value; }) : value); }; Select.prototype.handleInputChange = function (evt) { var _this = this; var loadOptions = this.props.loadOptions; this.setState({ inputValue: evt.currentTarget.value }, function () { return loadOptions && loadOptions(_this.state.inputValue); }); }; Select.prototype.handleChange = function (selectItem) { var _a = this.props, onChange = _a.onChange, multiple = _a.multiple, onNewOptionClick = _a.onNewOptionClick, simpleValue = _a.simpleValue; var selection = this.state.selection; if (selectItem.isNew) { delete selectItem.isNew; onNewOptionClick(selectItem); } if (multiple) { selection = selection.concat(); var idx = selection.indexOf(selectItem); if (~idx) { selection.splice(idx, 1); } else { selection.push(selectItem); } onChange(simpleValue ? selection.map(function (item) { return item.value; }) : selection); } else { onChange(simpleValue ? selectItem.value : selectItem); } }; Select.prototype.handleStateChange = function (changes) { var _a = this.props, multiple = _a.multiple, checkAll = _a.checkAll; var update = {}; var loadOptions = this.props.loadOptions; var doLoad = false; if (changes.isOpen !== void 0) { update.isOpen = changes.isOpen; } if (changes.highlightedIndex !== void 0) { update.highlightedIndex = changes.highlightedIndex; } switch (changes.type) { case downshift_1.default.stateChangeTypes.keyDownEnter: case downshift_1.default.stateChangeTypes.clickItem: update = tslib_1.__assign(tslib_1.__assign({}, update), { inputValue: '', isOpen: multiple && checkAll ? true : false, isFocused: multiple && checkAll ? true : false }); doLoad = true; break; case downshift_1.default.stateChangeTypes.changeInput: update.highlightedIndex = 0; break; } if (Object.keys(update).length) { this.setState(update, doLoad && loadOptions ? function () { return loadOptions(''); } : undefined); } }; Select.prototype.handleKeyPress = function (e) { if (e.key === ' ') { this.toggle(); } }; Select.prototype.clearValue = function (e) { var onChange = this.props.onChange; e.preventDefault(); e.stopPropagation(); onChange(''); }; Select.prototype.renderValue = function (_a) { var _this = this; var inputValue = _a.inputValue, isOpen = _a.isOpen; var _b = this.props, multiple = _b.multiple, placeholder = _b.placeholder, ns = _b.classPrefix, labelField = _b.labelField, searchable = _b.searchable, creatable = _b.creatable; var selection = this.state.selection; if (searchable && !creatable && inputValue && (multiple ? !selection.length : true)) { return null; } if (!selection.length) { return creatable && inputValue ? null : (react_1.default.createElement("div", { key: "placeholder", className: ns + "Select-placeholder" }, placeholder)); } return selection.map(function (item, index) { return multiple ? (react_1.default.createElement("div", { className: ns + "Select-value", key: index }, react_1.default.createElement("span", { className: ns + "Select-valueIcon", onClick: _this.removeItem.bind(_this, index) }, "\u00D7"), react_1.default.createElement("span", { className: ns + "Select-valueLabel" }, item[labelField || 'label']))) : inputValue && isOpen ? null : (react_1.default.createElement("div", { className: ns + "Select-value", key: index }, item.label)); }); }; Select.prototype.renderOuter = function (_a) { var _b; var _this = this; var selectedItem = _a.selectedItem, getItemProps = _a.getItemProps, highlightedIndex = _a.highlightedIndex, inputValue = _a.inputValue, isOpen = _a.isOpen; var _c = this.props, popOverContainer = _c.popOverContainer, options = _c.options, valueField = _c.valueField, labelField = _c.labelField, noResultsText = _c.noResultsText, loadOptions = _c.loadOptions, creatable = _c.creatable, promptTextCreator = _c.promptTextCreator, multiple = _c.multiple, cx = _c.classnames, checkAll = _c.checkAll, checkAllLabel = _c.checkAllLabel; var selection = this.state.selection; var checkedAll = false; var checkedPartial = false; var filtedOptions = inputValue && isOpen && !loadOptions ? match_sorter_1.default(options, inputValue, { keys: [labelField || 'label', valueField || 'value'] }) : options.concat(); if (multiple) { if (checkAll) { var optionsValues = options.map(function (option) { return option.value; }); var selectionValues_1 = selection.map(function (select) { return select.value; }); checkedAll = optionsValues.every(function (option) { return selectionValues_1.indexOf(option) > -1; }); checkedPartial = optionsValues.some(function (option) { return selectionValues_1.indexOf(option) > -1; }); } else { filtedOptions = filtedOptions.filter(function (option) { return !~selectedItem.indexOf(option); }); } } if (inputValue && creatable && !find(options, function (item) { return item[labelField || 'label'] == inputValue; })) { filtedOptions.unshift((_b = {}, _b[labelField] = inputValue, _b[valueField] = inputValue, _b.isNew = true, _b)); } var menu = (react_1.default.createElement("div", { ref: this.menu, className: cx('Select-menu') }, multiple && checkAll ? (react_1.default.createElement("div", { className: cx('Select-checkAll') }, react_1.default.createElement(Checkbox_1.default, { checked: checkedPartial, partial: checkedPartial && !checkedAll, onChange: this.toggleCheckAll }, checkAllLabel))) : null, filtedOptions.length ? (filtedOptions.map(function (item, index) { var checked = checkAll ? selection.some(function (o) { return o.value == item.value; }) : false; return (react_1.default.createElement("div", tslib_1.__assign({}, getItemProps({ key: index, index: index, item: item, disabled: item.disabled }), { className: cx("Select-option", { 'is-disabled': item.disabled, 'is-highlight': highlightedIndex === index, 'is-active': selectedItem === item || (Array.isArray(selectedItem) && ~selectedItem.indexOf(item)) }) }), checkAll ? (react_1.default.createElement(Checkbox_1.default, { checked: checked, trueValue: item.value, onChange: function () { return _this.handleChange(item); } }, item.isNew ? promptTextCreator(item.label) : item.disabled ? item[labelField] : Options_1.highlight(item[labelField], inputValue, cx('Select-option-hl')))) : item.isNew ? (promptTextCreator(item.label)) : (react_1.default.createElement("span", null, item.disabled ? item.label : Options_1.highlight(item[labelField], inputValue, cx('Select-option-hl')), item.tip)))); })) : (react_1.default.createElement("div", { className: cx('Select-option Select-option--placeholder') }, noResultsText)))); if (popOverContainer) { return (react_1.default.createElement(Overlay_1.default, { container: popOverContainer, placement: "left-bottom-left-top", target: this.getTarget, show: true }, react_1.default.createElement(PopOver_1.default, { className: cx('Select-popover'), style: { width: this.target ? this.target.offsetWidth : 'auto' } }, menu))); } else { return react_1.default.createElement("div", { className: cx('Select-menuOuter') }, menu); } }; Select.prototype.render = function () { var _this = this; var _a = this.props, cx = _a.classnames, multiple = _a.multiple, searchable = _a.searchable, inline = _a.inline, className = _a.className, value = _a.value, loading = _a.loading, spinnerClassName = _a.spinnerClassName, clearable = _a.clearable, labelField = _a.labelField, disabled = _a.disabled; var selection = this.state.selection; var inputValue = this.state.inputValue; return (react_1.default.createElement(downshift_1.default, { selectedItem: selection, highlightedIndex: this.state.highlightedIndex, isOpen: this.state.isOpen, inputValue: inputValue, onChange: this.handleChange, onStateChange: this.handleStateChange, onOuterClick: this.close, itemToString: function (item) { return (item ? item[labelField] : ''); } }, function (options) { var _a; var isOpen = options.isOpen, getInputProps = options.getInputProps; return (react_1.default.createElement("div", { tabIndex: searchable || disabled ? -1 : 0, onKeyPress: _this.handleKeyPress, onClick: _this.toggle, onFocus: _this.onFocus, onBlur: _this.onBlur, className: cx("Select", (_a = {}, _a["Select--multi"] = multiple, _a["Select--inline"] = inline, _a["Select--searchable"] = searchable, _a['is-opened'] = isOpen, _a['is-focused'] = _this.state.isFocused, _a['is-disabled'] = disabled, _a), className) }, react_1.default.createElement("div", { className: cx("Select-valueWrap") }, _this.renderValue(options), searchable && !disabled ? (react_1.default.createElement("input", tslib_1.__assign({}, getInputProps({ className: cx("Select-input"), onFocus: _this.onFocus, onBlur: _this.onBlur, onKeyDown: function (event) { if (event.key === 'Backspace' && !inputValue) { _this.removeItem(value.length - 1); } }, onChange: _this.handleInputChange, ref: _this.inputRef })))) : null), clearable && !disabled && value && value.length ? (react_1.default.createElement("a", { onClick: _this.clearValue, className: cx('Select-clear') }, react_1.default.createElement(icons_1.Icon, { icon: "close", className: "icon" }))) : null, loading ? (react_1.default.createElement("span", { className: cx('Select-spinner') }, react_1.default.createElement("i", { className: spinnerClassName }))) : null, react_1.default.createElement("span", { className: cx('Select-arrow') }), isOpen ? _this.renderOuter(options) : null)); })); }; Select.defaultProps = { multiple: false, clearable: true, creatable: false, searchPromptText: '输入内容进行检索', loadingPlaceholder: '加载中..', noResultsText: '没有结果', clearAllText: '移除所有', clearValueText: '移除', placeholder: '请选择', valueField: 'value', labelField: 'label', spinnerClassName: 'fa fa-spinner fa-spin fa-1x fa-fw', promptTextCreator: function (label) { return "\u65B0\u589E\uFF1A" + label; }, onNewOptionClick: helper_1.noop, inline: false, disabled: false, checkAll: false, checkAllLabel: '全选', defaultCheckAll: false }; return Select; }(react_1.default.Component)); exports.Select = Select; exports.default = theme_1.themeable(uncontrollable(Select, { value: 'onChange' })); //# sourceMappingURL=./components/Select.js.map