UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

389 lines (388 loc) 13.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _includes2 = _interopRequireDefault(require("lodash/includes")); var _react = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _propTypes = _interopRequireDefault(require("prop-types")); var _constants = require("@douyinfe/semi-foundation/lib/cjs/cascader/constants"); var _isEnterPress = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/utils/isEnterPress")); var _context = _interopRequireDefault(require("../configProvider/context")); var _localeConsumer = _interopRequireDefault(require("../locale/localeConsumer")); var _semiIcons = require("@douyinfe/semi-icons"); var _spin = _interopRequireDefault(require("../spin")); var _checkbox = _interopRequireDefault(require("../checkbox")); var _reactWindow = require("react-window"); var _virtualRow = _interopRequireDefault(require("./virtualRow")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const prefixcls = _constants.cssClasses.PREFIX_OPTION; class Item extends _react.PureComponent { constructor() { var _this; super(...arguments); _this = this; this.onClick = (e, item) => { const { onItemClick } = this.props; if (item.data.disabled || 'disabled' in item && item.disabled) { return; } onItemClick(e, item); }; /** * A11y: simulate item click */ this.handleItemEnterPress = (keyboardEvent, item) => { if ((0, _isEnterPress.default)(keyboardEvent)) { this.onClick(keyboardEvent, item); } }; this.onHover = (e, item) => { const { showNext, onItemHover } = this.props; if (item.data.disabled) { return; } if (showNext === _constants.strings.SHOW_NEXT_BY_HOVER) { onItemHover(e, item); } }; this.onCheckboxChange = (e, item) => { const { onItemCheckboxClick } = this.props; // Prevent Checkbox's click event bubbling to trigger the li click event e.stopPropagation(); if (e.nativeEvent && typeof e.nativeEvent.stopImmediatePropagation === 'function') { e.nativeEvent.stopImmediatePropagation(); } onItemCheckboxClick(item); }; this.getItemStatus = key => { const { activeKeys, selectedKeys, loadedKeys, loadingKeys } = this.props; const state = { active: false, selected: false, loading: false }; if (activeKeys.has(key)) { state.active = true; } if (selectedKeys.has(key)) { state.selected = true; } if (loadingKeys.has(key) && !loadedKeys.has(key)) { state.loading = true; } return state; }; this.renderIcon = function (type) { let haveMarginLeft = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; const finalCls = style => { return style + (haveMarginLeft ? ` ${prefixcls}-icon-left` : ''); }; switch (type) { case 'child': const { expandIcon } = _this.props; if (expandIcon) { return expandIcon; } return /*#__PURE__*/_react.default.createElement(_semiIcons.IconChevronRight, { className: finalCls(`${prefixcls}-icon ${prefixcls}-icon-expand`) }); case 'tick': return /*#__PURE__*/_react.default.createElement(_semiIcons.IconTick, { className: finalCls(`${prefixcls}-icon ${prefixcls}-icon-active`) }); case 'loading': return /*#__PURE__*/_react.default.createElement(_spin.default, { wrapperClassName: finalCls(`${prefixcls}-spin-icon`) }); case 'empty': return /*#__PURE__*/_react.default.createElement("span", { "aria-hidden": true, className: finalCls(`${prefixcls}-icon ${prefixcls}-icon-empty`) }); default: return null; } }; this.highlight = searchText => { const content = []; const { keyword, separator } = this.props; searchText.forEach((item, idx) => { if (typeof item === 'string' && (0, _includes2.default)(item, keyword)) { item.split(keyword).forEach((node, index) => { if (index > 0) { content.push(/*#__PURE__*/_react.default.createElement("span", { className: `${prefixcls}-label-highlight`, key: `${index}-${idx}` }, keyword)); } content.push(node); }); } else { content.push(item); } if (idx !== searchText.length - 1) { content.push(separator); } }); return content; }; this.renderFlattenOptionItem = (data, index, style) => { var _a; const { multiple, selectedKeys, checkedKeys, halfCheckedKeys, keyword, filterRender, virtualize } = this.props; const { searchText, key, disabled, pathData } = data; const selected = selectedKeys.has(key); const className = (0, _classnames.default)(prefixcls, { [`${prefixcls}-flatten`]: true && !filterRender, [`${prefixcls}-disabled`]: disabled, [`${prefixcls}-select`]: selected && !multiple }); const onClick = e => { this.onClick(e, data); }; const onKeyPress = e => this.handleItemEnterPress(e, data); const onCheck = e => this.onCheckboxChange(e, data); if (filterRender) { const props = { className, inputValue: keyword, disabled, data: pathData, checkStatus: { checked: checkedKeys.has(data.key), halfChecked: halfCheckedKeys.has(data.key) }, selected, onClick, onCheck }; const item = filterRender(props); const otherProps = virtualize ? { key, style: Object.assign(Object.assign({}, (_a = item.props.style) !== null && _a !== void 0 ? _a : {}), style) } : { key }; return /*#__PURE__*/_react.default.cloneElement(item, otherProps); } return /*#__PURE__*/_react.default.createElement("li", { role: 'menuitem', className: className, style: style, key: key, onClick: onClick, onKeyPress: onKeyPress }, /*#__PURE__*/_react.default.createElement("span", { className: `${prefixcls}-label` }, !multiple && this.renderIcon('empty'), multiple && (/*#__PURE__*/_react.default.createElement(_checkbox.default, { onChange: onCheck, disabled: disabled, indeterminate: halfCheckedKeys.has(data.key), checked: checkedKeys.has(data.key), className: `${prefixcls}-label-checkbox` })), this.highlight(searchText))); }; this.renderFlattenOption = data => { const { virtualize } = this.props; const content = /*#__PURE__*/_react.default.createElement("ul", { className: `${prefixcls}-list`, key: 'flatten-list' }, virtualize ? this.renderVirtualizeList(data) : data.map(item => this.renderFlattenOptionItem(item))); return content; }; this.renderVirtualizeList = visibleOptions => { var _a; const { direction } = this.context; const { virtualize } = this.props; return /*#__PURE__*/_react.default.createElement(_reactWindow.FixedSizeList, { height: virtualize.height, itemCount: visibleOptions.length, itemSize: virtualize.itemSize, itemData: { visibleOptions, renderOption: this.renderFlattenOptionItem }, width: (_a = virtualize.width) !== null && _a !== void 0 ? _a : '100%', style: { direction } }, _virtualRow.default); }; } renderItem(renderData) { let content = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; const { multiple, checkedKeys, halfCheckedKeys } = this.props; let showChildItem; const ind = content.length; content.push(/*#__PURE__*/_react.default.createElement("ul", { role: 'menu', className: `${prefixcls}-list`, key: renderData[0].key, onScroll: e => this.props.onListScroll(e, ind) }, renderData.map(item => { const { data, key, parentKey } = item; const { children, label, disabled, isLeaf } = data; const { active, selected, loading } = this.getItemStatus(key); const hasChild = Boolean(children) && children.length; const showExpand = hasChild || this.props.loadData && !isLeaf; if (active && hasChild) { showChildItem = item; } const className = (0, _classnames.default)(prefixcls, { [`${prefixcls}-active`]: active && !selected, [`${prefixcls}-select`]: selected && !multiple, [`${prefixcls}-disabled`]: disabled }); const otherAriaProps = parentKey ? { ['aria-owns']: `cascaderItem-${parentKey}` } : {}; return /*#__PURE__*/_react.default.createElement("li", Object.assign({ role: 'menuitem', id: `cascaderItem-${key}`, "aria-expanded": active, "aria-haspopup": Boolean(showExpand), "aria-disabled": disabled }, otherAriaProps, { className: className, key: key, onClick: e => { this.onClick(e, item); }, onKeyPress: e => this.handleItemEnterPress(e, item), onMouseEnter: e => { this.onHover(e, item); } }), /*#__PURE__*/_react.default.createElement("span", { className: `${prefixcls}-label` }, selected && !multiple && this.renderIcon('tick'), !selected && !multiple && this.renderIcon('empty'), multiple && (/*#__PURE__*/_react.default.createElement(_checkbox.default, { onChange: e => this.onCheckboxChange(e, item), disabled: disabled, indeterminate: halfCheckedKeys.has(item.key), checked: checkedKeys.has(item.key), className: `${prefixcls}-label-checkbox` })), /*#__PURE__*/_react.default.createElement("span", null, label)), showExpand ? this.renderIcon(loading ? 'loading' : 'child', true) : null); }))); if (showChildItem) { content.concat(this.renderItem(showChildItem.children, content)); } return content; } renderEmpty() { const { emptyContent } = this.props; if (emptyContent === null) { return null; } return /*#__PURE__*/_react.default.createElement(_localeConsumer.default, { componentName: "Cascader" }, locale => (/*#__PURE__*/_react.default.createElement("ul", { className: `${prefixcls} ${prefixcls}-empty`, key: 'empty-list' }, /*#__PURE__*/_react.default.createElement("span", { className: `${prefixcls}-label`, "x-semi-prop": "emptyContent" }, emptyContent || locale.emptyText)))); } render() { const { data, searchable } = this.props; const { direction } = this.context; const isEmpty = !data || !data.length; let content; const listsCls = (0, _classnames.default)({ [`${prefixcls}-lists`]: true, [`${prefixcls}-lists-rtl`]: direction === 'rtl', [`${prefixcls}-lists-empty`]: isEmpty }); if (isEmpty) { content = this.renderEmpty(); } else { content = searchable ? this.renderFlattenOption(data) : this.renderItem(data); } return /*#__PURE__*/_react.default.createElement("div", { className: listsCls }, content); } } exports.default = Item; Item.contextType = _context.default; Item.propTypes = { data: _propTypes.default.array, emptyContent: _propTypes.default.node, searchable: _propTypes.default.bool, onItemClick: _propTypes.default.func, onItemHover: _propTypes.default.func, multiple: _propTypes.default.bool, showNext: _propTypes.default.oneOf([_constants.strings.SHOW_NEXT_BY_CLICK, _constants.strings.SHOW_NEXT_BY_HOVER]), checkedKeys: _propTypes.default.object, halfCheckedKeys: _propTypes.default.object, onItemCheckboxClick: _propTypes.default.func, separator: _propTypes.default.string, keyword: _propTypes.default.string, virtualize: _propTypes.default.object, expandIcon: _propTypes.default.node }; Item.defaultProps = { empty: false };