UNPKG

acud

Version:

acg react 组件库

369 lines • 14.6 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import _extends from "@babel/runtime/helpers/esm/extends"; import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import * as React from 'react'; import KeyCode from "rc-util/es/KeyCode"; import useMemo from "rc-util/es/hooks/useMemo"; import { useBaseProps } from 'rc-select'; import Tree from 'rc-tree'; import OutlinedLoading from "acud-icon/es/icons/OutlinedLoading"; import Checkbox from '../../checkbox'; import LegacyContext from './LegacyContext'; import TreeSelectContext from './TreeSelectContext'; import { getAllKeys, isCheckDisabled } from './utils/valueUtil'; var HIDDEN_STYLE = { width: 0, height: 0, display: 'flex', overflow: 'hidden', opacity: 0, border: 0, padding: 0, margin: 0 }; var OptionList = function OptionList(_, ref) { var _useBaseProps = useBaseProps(), prefixCls = _useBaseProps.prefixCls, multiple = _useBaseProps.multiple, searchValue = _useBaseProps.searchValue, toggleOpen = _useBaseProps.toggleOpen, open = _useBaseProps.open, notFoundContent = _useBaseProps.notFoundContent; var _React$useContext = React.useContext(TreeSelectContext), virtual = _React$useContext.virtual, listHeight = _React$useContext.listHeight, listItemHeight = _React$useContext.listItemHeight, treeData = _React$useContext.treeData, fieldNames = _React$useContext.fieldNames, onSelect = _React$useContext.onSelect, triggerChange = _React$useContext.triggerChange, dropdownMatchSelectWidth = _React$useContext.dropdownMatchSelectWidth, treeExpandAction = _React$useContext.treeExpandAction; var _React$useContext2 = React.useContext(LegacyContext), checkable = _React$useContext2.checkable, checkedKeys = _React$useContext2.checkedKeys, halfCheckedKeys = _React$useContext2.halfCheckedKeys, treeExpandedKeys = _React$useContext2.treeExpandedKeys, treeDefaultExpandAll = _React$useContext2.treeDefaultExpandAll, treeDefaultExpandedKeys = _React$useContext2.treeDefaultExpandedKeys, onTreeExpand = _React$useContext2.onTreeExpand, treeIcon = _React$useContext2.treeIcon, showTreeIcon = _React$useContext2.showTreeIcon, showSelectAll = _React$useContext2.showSelectAll, switcherIcon = _React$useContext2.switcherIcon, treeLine = _React$useContext2.treeLine, treeNodeFilterProp = _React$useContext2.treeNodeFilterProp, loadData = _React$useContext2.loadData, treeLoadedKeys = _React$useContext2.treeLoadedKeys, treeMotion = _React$useContext2.treeMotion, onTreeLoad = _React$useContext2.onTreeLoad, keyEntities = _React$useContext2.keyEntities; var treeRef = React.useRef(); var memoTreeData = useMemo(function () { return treeData; }, [open, treeData], function (prev, next) { return next[0] && prev[1] !== next[1]; }); // ========================== Values ========================== var mergedCheckedKeys = React.useMemo(function () { if (!checkable) { return null; } return { checked: checkedKeys, halfChecked: halfCheckedKeys }; }, [checkable, checkedKeys, halfCheckedKeys]); // ========================== Scroll ========================== React.useEffect(function () { var _a; // Single mode should scroll to current key if (open && !multiple && checkedKeys.length) { (_a = treeRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({ key: checkedKeys[0] }); } }, [open]); // ========================== Search ========================== var lowerSearchValue = String(searchValue).toLowerCase(); var filterTreeNode = function filterTreeNode(treeNode) { if (!lowerSearchValue) { return false; } return String(treeNode[treeNodeFilterProp]).toLowerCase().includes(lowerSearchValue); }; // =========================== Keys =========================== var _React$useState = React.useState(treeDefaultExpandedKeys), _React$useState2 = _slicedToArray(_React$useState, 2), expandedKeys = _React$useState2[0], setExpandedKeys = _React$useState2[1]; var _React$useState3 = React.useState(null), _React$useState4 = _slicedToArray(_React$useState3, 2), searchExpandedKeys = _React$useState4[0], setSearchExpandedKeys = _React$useState4[1]; var mergedExpandedKeys = React.useMemo(function () { if (treeExpandedKeys) { return _toConsumableArray(treeExpandedKeys); } return searchValue ? searchExpandedKeys : expandedKeys; }, [expandedKeys, searchExpandedKeys, treeExpandedKeys, searchValue]); var allKeys = React.useMemo(function () { return getAllKeys(treeData, fieldNames); }, [treeData, fieldNames]); React.useEffect(function () { if (searchValue) { setSearchExpandedKeys(allKeys); } }, [searchValue]); var onInternalExpand = function onInternalExpand(keys) { setExpandedKeys(keys); setSearchExpandedKeys(keys); if (onTreeExpand) { onTreeExpand(keys); } }; // ========================== Events ========================== var onListMouseDown = function onListMouseDown(event) { event.preventDefault(); }; var onInternalSelect = function onInternalSelect(__, info) { var node = info.node; if (checkable && isCheckDisabled(node)) { return; } onSelect(node.key, { selected: !checkedKeys.includes(node.key) }); if (!multiple) { toggleOpen(false); } }; // ========================= Keyboard ========================= var _React$useState5 = React.useState(null), _React$useState6 = _slicedToArray(_React$useState5, 2), activeKey = _React$useState6[0], setActiveKey = _React$useState6[1]; var activeEntity = keyEntities[activeKey]; React.useImperativeHandle(ref, function () { var _a; return { scrollTo: (_a = treeRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo, onKeyDown: function onKeyDown(event) { var _a; var which = event.which; switch (which) { // >>> Arrow keys case KeyCode.UP: case KeyCode.DOWN: case KeyCode.LEFT: case KeyCode.RIGHT: (_a = treeRef.current) === null || _a === void 0 ? void 0 : _a.onKeyDown(event); break; // >>> Select item case KeyCode.ENTER: { if (activeEntity) { var _ref = (activeEntity === null || activeEntity === void 0 ? void 0 : activeEntity.node) || {}, selectable = _ref.selectable, value = _ref.value; if (selectable !== false) { onInternalSelect(null, { node: { key: activeKey }, selected: !checkedKeys.includes(value) }); } } break; } // >>> Close case KeyCode.ESC: { toggleOpen(false); } } }, onKeyUp: function onKeyUp() {} }; }); var treeProps = { fieldNames: fieldNames }; if (treeLoadedKeys) { treeProps.loadedKeys = treeLoadedKeys; } if (mergedExpandedKeys) { treeProps.expandedKeys = mergedExpandedKeys; } var allDisabledCheckedKeys = React.useMemo(function () { var adcKeys = []; var _loopTreeData = function loopTreeData(arr) { arr.forEach(function (data) { if (data.disabled && checkedKeys.includes(data.key)) { adcKeys.push(data.key); } if (data.children && Array.isArray(data.children)) { _loopTreeData(data.children); } }); }; _loopTreeData(treeData); return adcKeys; }, [treeData, checkedKeys]); var allAbleKeys = React.useMemo(function () { var abKeys = []; var _loopTreeData2 = function loopTreeData(arr) { arr.forEach(function (data) { if (!data.disabled) { abKeys.push(data.key); } if (data.children && Array.isArray(data.children)) { _loopTreeData2(data.children); } }); }; _loopTreeData2(treeData); return abKeys; }, [treeData]); var allAbleCheckedKeys = React.useMemo(function () { return checkedKeys.filter(function (key) { return allAbleKeys.includes(key); }); }, [allAbleKeys, checkedKeys]); var selectAllStatus = React.useMemo(function () { var hasCheckedValue = allAbleCheckedKeys.length > 0; return { all: hasCheckedValue && allAbleKeys.length === allAbleCheckedKeys.length, indeterminate: hasCheckedValue && allAbleCheckedKeys.length !== allAbleKeys.length, disabled: allAbleKeys.length === 0 }; }, [allAbleCheckedKeys, allAbleKeys]); var handleCheckAll = React.useCallback(function () { if (selectAllStatus.all) { triggerChange(_toConsumableArray(allDisabledCheckedKeys)); } else { triggerChange([].concat(_toConsumableArray(allDisabledCheckedKeys), _toConsumableArray(allAbleKeys))); } }, [selectAllStatus, allAbleKeys, allDisabledCheckedKeys, triggerChange]); var formatContent = React.useCallback(function (content, searchValue, prefixCls) { if (typeof content !== 'string' && typeof content !== 'number') { return /*#__PURE__*/React.createElement(React.Fragment, null, content); } var contentStr = content.toString(); var lowerContent = contentStr.toLowerCase(); var lowerSearch = searchValue.toLowerCase().trim(); var searchStartIndex = lowerContent.indexOf(lowerSearch); var len = lowerSearch.length; // 存在搜索值不在content的情况,比如key与children不一致时 if (searchStartIndex === -1) { return /*#__PURE__*/React.createElement(React.Fragment, null, content); } return /*#__PURE__*/React.createElement(React.Fragment, null, contentStr.slice(0, searchStartIndex), /*#__PURE__*/React.createElement("span", { className: "".concat(prefixCls, "-search-highlight") }, contentStr.slice(searchStartIndex, searchStartIndex + len)), contentStr.slice(searchStartIndex + len)); }, []); // 处理搜索高亮匹配,当显示字段与过滤字段相同时高亮显示”匹配片段“,反之高亮显示 "当前选项" var handleHighlightContent = React.useCallback(function (item, searchValue, prefixCls) { var filterContent = item[treeNodeFilterProp]; if (fieldNames._title.includes(treeNodeFilterProp)) { return _extends(_extends({}, item), _defineProperty({}, treeNodeFilterProp, formatContent(filterContent, searchValue, prefixCls))); } if (typeof filterContent !== 'string' && typeof filterContent !== 'number') { return item; } var lowerContent = filterContent.toString().toLowerCase(); var lowerSearch = searchValue.toLowerCase().trim(); var searchStartIndex = lowerContent.indexOf(lowerSearch); // 根据_title获取当前显示的字段名称,_title默认值为['title', 'label'],搜索值不匹配时,直接返回,反之高亮当前选项 var fieldName = fieldNames._title.find(function (field) { return item.hasOwnProperty(field); }); return searchStartIndex === -1 ? item : _extends(_extends({}, item), _defineProperty({}, fieldName, /*#__PURE__*/React.createElement("span", { className: "".concat(prefixCls, "-search-highlight") }, item[fieldName]))); }, [treeNodeFilterProp, fieldNames, formatContent]); var formatTreeData = React.useMemo(function () { if ((searchValue === null || searchValue === void 0 ? void 0 : searchValue.toString().trim()) === '') { return memoTreeData; } var _loopTree = function loopTree(arr) { return arr.map(function (item) { var newItem = handleHighlightContent(item, searchValue, prefixCls); if (newItem.children && newItem.children.length) { newItem.children = _loopTree(newItem.children); } return newItem; }); }; return _loopTree(memoTreeData); }, [memoTreeData, searchValue, prefixCls, formatContent]); // ========================== Render ========================== if (memoTreeData.length === 0) { return /*#__PURE__*/React.createElement("div", { role: "listbox", className: "".concat(prefixCls, "-empty"), onMouseDown: onListMouseDown }, notFoundContent); } // 渲染TreeSelect的icon var renderSwitcherIcon = function renderSwitcherIcon(nodeProps) { var loading = nodeProps.loading; if (loading) { return /*#__PURE__*/React.createElement(OutlinedLoading, { width: 16, animation: "spin" }); } return typeof switcherIcon === 'function' ? switcherIcon(nodeProps) : switcherIcon; }; return /*#__PURE__*/React.createElement("div", { onMouseDown: onListMouseDown }, activeEntity && open && /*#__PURE__*/React.createElement("span", { style: HIDDEN_STYLE, "aria-live": "assertive" }, activeEntity.node.value), multiple && showSelectAll && /*#__PURE__*/React.createElement("div", { className: "".concat(prefixCls, "-tree-select-all") }, /*#__PURE__*/React.createElement(Checkbox, { checked: selectAllStatus.all, indeterminate: selectAllStatus.indeterminate, disabled: selectAllStatus.disabled, onClick: handleCheckAll }, "\u5168\u9009")), /*#__PURE__*/React.createElement(Tree, _extends({ ref: treeRef, focusable: false, prefixCls: "".concat(prefixCls, "-tree"), treeData: formatTreeData, height: listHeight, itemHeight: listItemHeight, virtual: virtual !== false && dropdownMatchSelectWidth !== false, multiple: multiple, icon: treeIcon, showIcon: showTreeIcon, switcherIcon: renderSwitcherIcon, showLine: treeLine, loadData: searchValue ? null : loadData, motion: treeMotion, activeKey: activeKey // We handle keys by out instead tree self , checkable: checkable, checkStrictly: true, checkedKeys: mergedCheckedKeys, selectedKeys: checkedKeys, defaultExpandAll: treeDefaultExpandAll }, treeProps, { // Proxy event out onActiveChange: setActiveKey, onSelect: onInternalSelect, onCheck: onInternalSelect, onExpand: onInternalExpand, onLoad: onTreeLoad, filterTreeNode: filterTreeNode, expandAction: treeExpandAction }))); }; var RefOptionList = /*#__PURE__*/React.forwardRef(OptionList); RefOptionList.displayName = 'OptionList'; export default RefOptionList;