UNPKG

zent

Version:

一套前端设计语言和基于React的实现

627 lines (626 loc) 28.8 kB
import { __assign, __extends, __spreadArray } from "tslib"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import cx from 'classnames'; import { Component, createRef } from 'react'; import Popover from '../popover'; import TagList from './TagList'; import Option from './Option'; import Search from './Search'; import { DisabledContext } from '../disabled'; import WindowEventHandler from '../utils/component/WindowEventHandler'; import Icon from '../icon'; import { TextMark } from '../text-mark'; import { InlineLoading } from '../loading/InlineLoading'; import { Pop } from '../pop'; import { I18nReceiver as Receiver } from '../i18n'; import memoize from '../utils/memorize-one'; import uniqueId from '../utils/uniqueId'; import { filterReviver, reviveSelectItem } from './reviver'; var uniqueKey = '__ZENT_SELECT_CREATABLE_KEY__'; var SELECT_CREATABLE_KEY = uniqueId(uniqueKey); function defaultIsEqual(a, b) { return a.key === b.key; } function defaultFilter(keyword, option) { if (typeof option.text !== 'string') { return true; } return option.text.toLowerCase().includes(keyword.toLowerCase()); } function defaultRenderOptionList(options, renderOption) { return options.map(renderOption); } function getExtraOptions(value) { var _a, _b; if (!Array.isArray(value)) { if (((_b = (_a = value === null || value === void 0 ? void 0 : value.key) === null || _a === void 0 ? void 0 : _a.toString()) === null || _b === void 0 ? void 0 : _b.indexOf(uniqueKey)) > -1) { return [value]; } return []; } return value.reduce(function (v, next) { var _a, _b; if (((_b = (_a = next === null || next === void 0 ? void 0 : next.key) === null || _a === void 0 ? void 0 : _a.toString()) === null || _b === void 0 ? void 0 : _b.indexOf(uniqueKey)) > -1) { return __spreadArray(__spreadArray([], v), [next]); } return v; }, []); } function isSelectable(item) { return !!item && !item.disabled && !item.type; } function findNextSelectableOption(options, start) { for (var i = start; i < options.length; i += 1) { if (isSelectable(options[i])) { return i; } } return null; } function findPrevSelectableOption(options, start) { for (var i = start; i >= 0; i -= 1) { if (isSelectable(options[i])) { return i; } } return null; } function defaultHighlight(keyword, option) { if (typeof option.text !== 'string') { return option.text; } return (_jsx(TextMark, { searchWords: [keyword], textToHighlight: option.text, highlightStyle: { backgroundColor: 'initial', color: '#155bd4' }, autoEscape: true }, void 0)); } var DEFAULT_LOADING = (_jsx("div", __assign({ className: "zent-select-v2-popup-loading", "data-zv": '10.0.17' }, { children: _jsx(InlineLoading, { loading: true, icon: "circle", iconSize: 18, iconText: "\u52A0\u8F7D\u4E2D\u2026", textPosition: "right", colorPreset: "grey" }, void 0) }), void 0)); function defaultIsValidNewOption(keyword, options) { return options.every(function (it) { return (typeof it.text === 'string' ? it.text.toLowerCase() : it.text) !== keyword.toLowerCase(); }); } var DEFAULT_TRIGGER_WIDTH = 240; var DEFAULT_SIZE_WIDTH = 116; var DEFAULT_PADDING_WIDTH = 8; var SIZE_MAP = { xs: DEFAULT_SIZE_WIDTH, s: DEFAULT_SIZE_WIDTH * 2 + DEFAULT_PADDING_WIDTH, m: DEFAULT_SIZE_WIDTH * 3 + DEFAULT_PADDING_WIDTH * 2, l: DEFAULT_SIZE_WIDTH * 4 + DEFAULT_PADDING_WIDTH * 3, xl: DEFAULT_SIZE_WIDTH * 5 + DEFAULT_PADDING_WIDTH * 4, }; var Select = (function (_super) { __extends(Select, _super); function Select(props) { var _a, _b; var _this = _super.call(this, props) || this; _this.triggerRef = createRef(); _this.popoverRef = createRef(); _this.inputRef = createRef(); _this.onVisibleChange = function (open) { if (_this.disabled) { return; } var onOpenChange = _this.props.onOpenChange; if (onOpenChange) { onOpenChange(open); } else { _this.setState({ open: open, active: open, activeIndex: null, }); } if (open === false) { _this.resetKeyword('popup-close'); } }; _this.onSelect = function (item) { if (!item || item.disabled || item.type || _this.disabled) { return; } var onCreate = _this.props.onCreate; var isCreate = item.key === SELECT_CREATABLE_KEY; if (isCreate && onCreate) { _this.onCreateClick(); return; } isCreate && _this.resetKeyword('option-create'); var valueItem = isCreate ? __assign(__assign({}, item), { key: uniqueId(uniqueKey) }) : item; if (_this.props.multiple === true) { var _a = _this.props, onChange = _a.onChange, isEqual_1 = _a.isEqual; var value = _this.state.value; var valueIndex_1 = value.findIndex(function (it) { return isEqual_1(it, item); }); _this.focusSearchInput(); var nextValue = valueIndex_1 >= 0 ? value.filter(function (_it, index) { return index !== valueIndex_1; }) : value.concat([valueItem]); if (onChange) { onChange(nextValue); } else { _this.setState({ value: nextValue }); } } else { _this.onVisibleChange(false); var onChange = _this.props.onChange; if (onChange) { onChange(valueItem); } else { _this.setState({ value: valueItem }); } } }; _this.onKeywordChange = function (e) { if (_this.disabled) { return; } _this.setKeyword(e.target.value, 'user-change'); }; _this.onRemove = function (item) { if (_this.disabled) { return; } var value = _this.state.value; var _a = _this.props, onChange = _a.onChange, isEqual = _a.isEqual; var nextValue = value.filter(function (it) { return !isEqual(item, it); }); _this.focusSearchInput(); if (onChange) { onChange(nextValue); } else { _this.setState({ value: nextValue, }); } }; _this.onOptionMouseEnter = function (index) { if (_this.disabled) { return; } _this.setState({ activeIndex: index, }); }; _this.onOptionMouseLeave = function (index) { if (_this.disabled) { return; } _this.setState(function (state) { return state.activeIndex === index ? { activeIndex: null, } : null; }); }; _this.selectCurrentIndex = function () { var _a; if (_this.disabled) { return; } var _b = _this.state, activeIndex = _b.activeIndex, keyword = _b.keyword, value = _b.value; var _c = _this.props, creatable = _c.creatable, _options = _c.options, filter = _c.filter, isValidNewOption = _c.isValidNewOption; var options = _this.filterOptions(keyword, _options, filter, creatable, isValidNewOption, value); if (activeIndex !== null) { _this.onSelect(options[activeIndex]); } else { if (options.length && ((_a = options[0]) === null || _a === void 0 ? void 0 : _a.key) === SELECT_CREATABLE_KEY) { _this.onSelect(options[0]); } } }; _this.renderOption = function (option, index) { var _a = _this.props, isEqual = _a.isEqual, multiple = _a.multiple, renderOptionContent = _a.renderOptionContent, highlight = _a.highlight, filter = _a.filter; var _b = _this.state, value = _b.value, activeIndex = _b.activeIndex, creating = _b.creating; var selected = !!value && (multiple ? value.findIndex(function (it) { return isEqual(it, option); }) >= 0 : isEqual(value, option)); var optionContent = null; var loading = false; if (option.key === SELECT_CREATABLE_KEY) { loading = creating; optionContent = (_jsx(Receiver, __assign({ componentName: "Select" }, { children: function (i18n) { return (_jsxs("span", __assign({ className: "zent-select-v2-option-text-highlight", "data-zv": '10.0.17' }, { children: [i18n.create, option.text] }), void 0)); } }), void 0)); } else if (renderOptionContent) { optionContent = renderOptionContent(option); } else { var keyword = _this.state.keyword.trim(); optionContent = filter !== false && keyword.length > 0 ? highlight === null || highlight === void 0 ? void 0 : highlight(keyword, option) : option.text; } return (_jsx(Option, __assign({ value: option, selected: selected, active: index === activeIndex, onSelect: _this.onSelect, index: index, onMouseEnter: _this.onOptionMouseEnter, onMouseLeave: _this.onOptionMouseLeave, multiple: multiple, loading: loading }, { children: optionContent }), option.key)); }; _this.globalClick = function (e) { var _a; if (_this.disabled || _this.state.open || !_this.state.active || !_this.triggerRef.current || !_this.popoverRef.current) { return; } if (!((_a = _this.triggerRef.current) === null || _a === void 0 ? void 0 : _a.contains(e.target))) { _this.setState({ active: false, }); } }; _this.onIndexChange = function (delta) { if (_this.disabled) { return; } _this.setState(function (state, _a) { var _options = _a.options, creatable = _a.creatable, filter = _a.filter, isValidNewOption = _a.isValidNewOption; var options = _this.filterOptions(state.keyword, _options, filter, creatable, isValidNewOption, state.value); var nextIndex; if (state.activeIndex === null) { if (delta < 0) { nextIndex = options.length - 1; } else { nextIndex = 0; } } else { nextIndex = (state.activeIndex + delta) % options.length; } if (nextIndex >= options.length) { nextIndex = options.length - 1; } if (nextIndex < 0) { nextIndex = 0; } if (!isSelectable(options[nextIndex])) { var enabled = void 0; if (delta > 0) { enabled = findNextSelectableOption(options, nextIndex); } else { enabled = findPrevSelectableOption(options, nextIndex); } if (!enabled) { return null; } nextIndex = enabled; } if (state.activeIndex === nextIndex) { return null; } return { activeIndex: nextIndex, }; }); }; _this.onClear = function (e) { e.stopPropagation(); var keyword = _this.state.keyword; _this.focusSearchInput(); if (keyword) { _this.resetKeyword('user-clear'); return; } if (_this.props.multiple) { var onChange = _this.props.onChange; var value = []; if (onChange) { onChange(value); } else { _this.setState({ value: value, }); } } else { var onChange = _this.props.onChange; var value = null; if (onChange) { onChange(value); } else { _this.setState({ value: value, }); } } }; _this.onCreateClick = function () { var _a = _this.props, onCreate = _a.onCreate, multiple = _a.multiple; var keyword = _this.state.keyword; if (onCreate) { _this.setState({ creating: true }); onCreate(keyword.trim()) .then(function () { if (multiple) { _this.focusSearchInput(); } else { _this.onVisibleChange(false); } _this.resetKeyword('option-create'); }) .finally(function () { _this.setState({ creating: false }); }); } }; _this.filterOptions = memoize(function (keyword, options, filter, creatable, isValidNewOption, value) { if (options === void 0) { options = []; } var extraOptions = creatable ? getExtraOptions(value) : []; var mergedOptions = __spreadArray(__spreadArray([], options), extraOptions); var filtered = filter !== false && keyword ? mergedOptions.filter(function (it) { return filter === null || filter === void 0 ? void 0 : filter(keyword, it); }) : mergedOptions; var pendingCreateOption = creatable && keyword && (isValidNewOption === null || isValidNewOption === void 0 ? void 0 : isValidNewOption(keyword, mergedOptions)) ? [ { key: SELECT_CREATABLE_KEY, text: keyword, }, ] : []; return pendingCreateOption.concat(filtered); }); _this.focusSearchInput = function () { var _a, _b; (_b = (_a = _this.inputRef) === null || _a === void 0 ? void 0 : _a.current) === null || _b === void 0 ? void 0 : _b.focus(); }; var value; if (props.multiple) { value = filterReviver((_a = props.value) !== null && _a !== void 0 ? _a : []); } else { value = filterReviver((_b = props.value) !== null && _b !== void 0 ? _b : null); } var keyword = props.keyword, width = props.width, options = props.options, size = props.size; _this.state = { keyword: keyword !== null && keyword !== void 0 ? keyword : '', value: value, open: false, active: false, activeIndex: null, prevOptions: options, creating: false, triggerWidth: width !== null && width !== void 0 ? width : (SIZE_MAP[size] || DEFAULT_TRIGGER_WIDTH), }; _this.tryReviveOption(props); return _this; } Select.getDerivedStateFromProps = function (props, state) { var _a; var nextState = { prevOptions: props.options, }; if (typeof props.keyword === 'string') { nextState.keyword = props.keyword; } if (typeof props.open === 'boolean') { nextState.open = props.open; nextState.active = props.open; } if (props.multiple) { if (Array.isArray(props.value)) { nextState.value = filterReviver(props.value); } } else { if ('value' in props) { nextState.value = filterReviver((_a = props.value) !== null && _a !== void 0 ? _a : null); } } if (props.options !== state.prevOptions && state.activeIndex !== null) { if (!props.options.length) { nextState.activeIndex = null; } else { if (state.activeIndex >= props.options.length) { nextState.activeIndex = props.options.length - 1; } } } return nextState; }; Select.prototype.componentDidMount = function () { var _a; if ('popupWidth' in this.props) { return; } var _b = this.props, size = _b.size, width = _b.width; var sizeWidth = SIZE_MAP[size] || DEFAULT_TRIGGER_WIDTH; var useWidth = typeof width === 'number' ? width : sizeWidth; var triggerWidth = ((_a = this.triggerRef.current) === null || _a === void 0 ? void 0 : _a.offsetWidth) || useWidth; this.setState({ triggerWidth: triggerWidth, }); }; Select.prototype.componentDidUpdate = function (prevProps) { if (this.props.options !== prevProps.options || this.props.value !== prevProps.value) { this.tryReviveOption(this.props); } }; Object.defineProperty(Select.prototype, "disabled", { get: function () { var _a = this.props.disabled, disabled = _a === void 0 ? this.context.value : _a; return disabled; }, enumerable: false, configurable: true }); Select.prototype.tryReviveOption = function (props) { var _a, _b, _c, _d; var options = props.options; if (props.multiple) { var value = (_a = props.value) !== null && _a !== void 0 ? _a : []; var revived_1 = false; var newValue = value.map(function (v) { var _a; if (v.type === 'reviver') { for (var _i = 0, options_2 = options; _i < options_2.length; _i++) { var opt = options_2[_i]; var revivedOpt = (_a = v.reviver) === null || _a === void 0 ? void 0 : _a.call(v, opt); if (revivedOpt) { revived_1 = true; return revivedOpt; } } } return v; }); if (revived_1) { if (props.onChange) { props.onChange(newValue); } else { this.setState({ value: newValue }); } } } else if (props.multiple === false) { var value = (_b = props.value) !== null && _b !== void 0 ? _b : null; if ((value === null || value === void 0 ? void 0 : value.type) === 'reviver') { var revivedOpt = null; for (var _i = 0, options_1 = options; _i < options_1.length; _i++) { var opt = options_1[_i]; revivedOpt = (_c = value.reviver) === null || _c === void 0 ? void 0 : _c.call(value, opt); if (revivedOpt) { break; } } if (revivedOpt) { if (props.onChange) { (_d = props.onChange) === null || _d === void 0 ? void 0 : _d.call(props, revivedOpt); } else { this.setState({ value: revivedOpt }); } } } } }; Select.prototype.resetKeyword = function (source) { this.setKeyword('', source); }; Select.prototype.setKeyword = function (keyword, source) { var onKeywordChange = this.props.onKeywordChange; if (onKeywordChange) { onKeywordChange(keyword, { source: source }); } else { this.setState({ keyword: keyword, }); } }; Select.prototype.renderValue = function (i18n) { var _a = this.props, placeholder = _a.placeholder, renderValue = _a.renderValue, multiple = _a.multiple; var open = this.state.open; if (multiple) { var value = this.state.value; if ((value === null || value === void 0 ? void 0 : value.length) > 0) { return this.renderTagList(value, i18n); } if (open) { return null; } } else { if (open) { return null; } var value = this.state.value; if (value) { return renderValue ? (renderValue(value)) : (_jsx("span", __assign({ className: "zent-select-v2-text", title: typeof value.text === 'string' ? value.text : '', "data-zv": '10.0.17' }, { children: value.text }), void 0)); } } return _jsx("span", __assign({ className: "zent-select-v2-placeholder", "data-zv": '10.0.17' }, { children: placeholder }), void 0); }; Select.prototype.renderTagCollapsedTrigger = function (value) { return (_jsxs("span", __assign({ className: "zent-select-v2-tag-collapsed-trigger", "data-zv": '10.0.17' }, { children: ["+", value.length] }), void 0)); }; Select.prototype.renderTagList = function (value, i18n) { var _a = this.props, renderValue = _a.renderValue, renderTagList = _a.renderTagList, collapsable = _a.collapsable, hideCollapsePop = _a.hideCollapsePop, _b = _a.collapseAt, collapseAt = _b === void 0 ? 1 : _b, renderCollapsedContent = _a.renderCollapsedContent; var tagsValue = collapsable ? value.slice(0, collapseAt) : value; var collapsedValue = value.slice(collapseAt); return (_jsxs(_Fragment, { children: [typeof renderTagList === 'function' ? (renderTagList({ list: value, onRemove: this.onRemove, renderValue: renderValue, })) : (_jsx(TagList, { list: tagsValue, onRemove: this.onRemove, renderValue: renderValue }, void 0)), collapsable && collapsedValue.length > 0 && (!hideCollapsePop ? (_jsx(Pop, __assign({ trigger: "hover", position: "auto-top-center", cushion: 15, content: _jsx("div", __assign({ className: "zent-select-v2-tag-collapsed-content", "data-zv": '10.0.17' }, { children: _jsx("div", __assign({ "data-zv": '10.0.17' }, { children: typeof renderCollapsedContent === 'function' ? renderCollapsedContent(collapsedValue) : collapsedValue.map(function (item, index) { return (_jsxs("span", __assign({ "data-zv": '10.0.17' }, { children: [renderValue ? renderValue(item) : item.text, index !== collapsedValue.length - 1 && i18n.tagSeparator] }), item.key)); }) }), void 0) }), void 0) }, { children: this.renderTagCollapsedTrigger(collapsedValue) }), void 0)) : (this.renderTagCollapsedTrigger(collapsedValue)))] }, void 0)); }; Select.prototype.getSearchPlaceholder = function () { var placeholder = this.props.placeholder; if (this.props.multiple) { if (this.state.value.length) { return ''; } return placeholder !== null && placeholder !== void 0 ? placeholder : ''; } var value = this.state.value; if (!value || typeof value.text !== 'string') { return placeholder !== null && placeholder !== void 0 ? placeholder : ''; } return value.text; }; Select.prototype.renderPopoverContent = function (i18n) { var _a = this.props, notFoundContent = _a.notFoundContent, renderOptionList = _a.renderOptionList, loading = _a.loading, creatable = _a.creatable, options = _a.options, filter = _a.filter, isValidNewOption = _a.isValidNewOption; var keyword = this.state.keyword.trim(); var value = this.state.value; if (loading) { return DEFAULT_LOADING; } var filtered = this.filterOptions(keyword, options, filter, creatable, isValidNewOption, value); return (filtered === null || filtered === void 0 ? void 0 : filtered.length) ? (renderOptionList(filtered, this.renderOption)) : (_jsx("div", __assign({ className: "zent-select-v2-popup-empty", "data-zv": '10.0.17' }, { children: notFoundContent !== null && notFoundContent !== void 0 ? notFoundContent : i18n.empty }), void 0)); }; Select.prototype.render = function () { var _this = this; var _a = this.state, keyword = _a.keyword, visible = _a.open, active = _a.active, value = _a.value, triggerWidth = _a.triggerWidth; var _b = this.props, inline = _b.inline, width = _b.width, clearable = _b.clearable, multiple = _b.multiple, popupWidth = _b.popupWidth, collapsable = _b.collapsable, className = _b.className, disableSearch = _b.disableSearch, size = _b.size, collapseAt = _b.collapseAt; var notEmpty = multiple ? Array.isArray(value) && value.length > 0 : value; var showClear = clearable && !this.disabled && (keyword || notEmpty); return (_jsxs(_Fragment, { children: [_jsx(Receiver, __assign({ componentName: "Select" }, { children: function (i18n) { return (_jsxs(Popover, __assign({ ref: _this.popoverRef, position: Popover.Position.AutoBottomLeft, visible: visible, onVisibleChange: _this.onVisibleChange, className: "zent-select-v2-popup", style: { width: popupWidth !== null && popupWidth !== void 0 ? popupWidth : triggerWidth }, cushion: 4 }, { children: [_jsx(Popover.Trigger.Click, { children: _jsxs("div", __assign({ ref: _this.triggerRef, className: cx('zent-select-v2', "zent-select-v2-" + size, className, { 'zent-select-v2-inline': inline, 'zent-select-v2-active': active, 'zent-select-v2-visible': visible, 'zent-select-v2-disabled': _this.disabled, 'zent-select-v2-clearable': showClear, 'zent-select-v2-multiple': multiple, 'zent-select-v2-collapsable': collapsable, 'zent-select-v2-collapsable-single': collapseAt === 1, }), style: { width: width }, onClick: _this.focusSearchInput, "data-zv": '10.0.17' }, { children: [_this.renderValue(i18n), showClear && (_jsx(Icon, { type: "close-circle", onClick: _this.onClear }, void 0)), !disableSearch && visible && (_jsx(Search, { placeholder: _this.getSearchPlaceholder(), value: keyword, autoWidth: multiple, onChange: _this.onKeywordChange, onIndexChange: _this.onIndexChange, onEnter: _this.selectCurrentIndex, ref: _this.inputRef }, void 0)), _jsx(Icon, { type: "down" }, void 0)] }), void 0) }, void 0), _jsx(Popover.Content, { children: _this.renderPopoverContent(i18n) }, void 0)] }), void 0)); } }), void 0), _jsx(WindowEventHandler, { eventName: "click", listener: this.globalClick, options: { capture: true } }, void 0)] }, void 0)); }; Select.defaultProps = { isEqual: defaultIsEqual, renderOptionList: defaultRenderOptionList, filter: defaultFilter, isValidNewOption: defaultIsValidNewOption, highlight: defaultHighlight, size: 's', multiple: false, clearable: false, loading: false, creatable: false, }; Select.contextType = DisabledContext; Select.reviveValue = reviveSelectItem; return Select; }(Component)); export { Select }; export default Select;