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.

855 lines (854 loc) 35 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var _exportNames = {}; exports.default = void 0; var _isUndefined2 = _interopRequireDefault(require("lodash/isUndefined")); var _pick2 = _interopRequireDefault(require("lodash/pick")); var _isFunction2 = _interopRequireDefault(require("lodash/isFunction")); var _get2 = _interopRequireDefault(require("lodash/get")); var _isEqual2 = _interopRequireDefault(require("lodash/isEqual")); var _isEmpty2 = _interopRequireDefault(require("lodash/isEmpty")); var _react = _interopRequireDefault(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _propTypes = _interopRequireDefault(require("prop-types")); var _context = _interopRequireDefault(require("../configProvider/context")); var _foundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/tree/foundation")); var _treeUtil = require("@douyinfe/semi-foundation/lib/cjs/tree/treeUtil"); var _constants = require("@douyinfe/semi-foundation/lib/cjs/tree/constants"); var _baseComponent = _interopRequireDefault(require("../_base/baseComponent")); var _treeUtil2 = require("./treeUtil"); var _index = _interopRequireDefault(require("../input/index")); var _reactWindow = require("react-window"); var _autoSizer = _interopRequireDefault(require("./autoSizer")); var _treeContext = _interopRequireDefault(require("./treeContext")); var _treeNode = _interopRequireDefault(require("./treeNode")); var _nodeList = _interopRequireDefault(require("./nodeList")); var _localeConsumer = _interopRequireDefault(require("../locale/localeConsumer")); require("@douyinfe/semi-foundation/lib/cjs/tree/tree.css"); var _semiIcons = require("@douyinfe/semi-icons"); var _checkboxGroup = _interopRequireDefault(require("../checkbox/checkboxGroup")); var _interface = require("./interface"); Object.keys(_interface).forEach(function (key) { if (key === "default" || key === "__esModule") return; if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; if (key in exports && exports[key] === _interface[key]) return; Object.defineProperty(exports, key, { enumerable: true, get: function () { return _interface[key]; } }); }); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } var __rest = void 0 && (void 0).__rest || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; const prefixcls = _constants.cssClasses.PREFIX; const treeDataNodeShape = { key: _propTypes.default.string, value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]), label: _propTypes.default.any, isLeaf: _propTypes.default.bool, children: _propTypes.default.array }; treeDataNodeShape.children = _propTypes.default.arrayOf(_propTypes.default.shape(treeDataNodeShape)); class Tree extends _baseComponent.default { constructor(props) { super(props); this.search = value => { this.foundation.handleInputChange(value); }; this.scrollTo = scrollData => { var _a; const { key, align = 'center' } = scrollData; const { flattenNodes } = this.state; if (key) { const index = flattenNodes === null || flattenNodes === void 0 ? void 0 : flattenNodes.findIndex(node => { return node.key === key; }); index >= 0 && ((_a = this.virtualizedListRef.current) === null || _a === void 0 ? void 0 : _a.scrollToItem(index, align)); } }; this.renderEmpty = () => { const { emptyContent } = this.props; if (emptyContent) { return /*#__PURE__*/_react.default.createElement(_treeNode.default, { empty: true, emptyContent: this.props.emptyContent }); } else { return /*#__PURE__*/_react.default.createElement(_localeConsumer.default, { componentName: "Tree" }, locale => /*#__PURE__*/_react.default.createElement(_treeNode.default, { empty: true, emptyContent: (0, _get2.default)(locale, 'emptyText') })); } }; this.onNodeSelect = (e, treeNode) => { this.foundation.handleNodeSelect(e, treeNode); }; this.onNodeLoad = data => new Promise(resolve => { // We need to get the latest state of loading/loaded keys this.setState(_ref => { let { loadedKeys = new Set([]), loadingKeys = new Set([]) } = _ref; return this.foundation.handleNodeLoad(loadedKeys, loadingKeys, data, resolve); }); }); this.onNodeCheck = (e, treeNode) => { this.foundation.handleNodeSelect(e, treeNode); }; this.onNodeExpand = (e, treeNode) => { this.foundation.handleNodeExpand(e, treeNode); }; this.onNodeRightClick = (e, treeNode) => { this.foundation.handleNodeRightClick(e, treeNode); }; this.onNodeDoubleClick = (e, treeNode) => { this.foundation.handleNodeDoubleClick(e, treeNode); }; this.onNodeDragStart = (e, treeNode) => { this.foundation.handleNodeDragStart(e, treeNode); }; this.onNodeDragEnter = (e, treeNode) => { this.foundation.handleNodeDragEnter(e, treeNode, this.dragNode); }; this.onNodeDragOver = (e, treeNode) => { this.foundation.handleNodeDragOver(e, treeNode, this.dragNode); }; this.onNodeDragLeave = (e, treeNode) => { this.foundation.handleNodeDragLeave(e, treeNode); }; this.onNodeDragEnd = (e, treeNode) => { this.foundation.handleNodeDragEnd(e, treeNode); }; this.onNodeDrop = (e, treeNode) => { this.foundation.handleNodeDrop(e, treeNode, this.dragNode); }; this.getTreeNodeRequiredProps = () => { const { expandedKeys, selectedKeys, checkedKeys, halfCheckedKeys, keyEntities, filteredKeys } = this.state; return { expandedKeys: expandedKeys || new Set(), selectedKeys: selectedKeys || [], checkedKeys: checkedKeys || new Set(), halfCheckedKeys: halfCheckedKeys || new Set(), filteredKeys: filteredKeys || new Set(), keyEntities }; }; this.getTreeNodeKey = treeNode => { const { data } = treeNode; const { key } = data; return key; }; this.renderTreeNode = (treeNode, ind, style) => { const { data, key } = treeNode; const treeNodeProps = this.foundation.getTreeNodeProps(key); if (!treeNodeProps) { return null; } const { keyMaps, showLine, expandIcon } = this.props; const props = (0, _pick2.default)(treeNode, ['key', 'label', 'disabled', 'isLeaf', 'icon', 'isEnd']); const children = data[(0, _get2.default)(keyMaps, 'children', 'children')]; !(0, _isUndefined2.default)(children) && (props.children = children); return /*#__PURE__*/_react.default.createElement(_treeNode.default, Object.assign({}, treeNodeProps, data, props, { showLine: showLine, data: data, expandIcon: expandIcon, style: (0, _isEmpty2.default)(style) ? {} : style })); }; this.itemKey = (index, data) => { // Find the item at the specified index. const item = data[index]; // Return a value that uniquely identifies this item. return item.key; }; this.option = _ref2 => { let { index, style, data } = _ref2; return this.renderTreeNode(data[index], index, style); }; this.state = { inputValue: '', keyEntities: {}, treeData: [], flattenNodes: [], selectedKeys: [], checkedKeys: new Set(), halfCheckedKeys: new Set(), realCheckedKeys: new Set([]), motionKeys: new Set([]), motionType: 'hide', expandedKeys: new Set(props.expandedKeys), filteredKeys: new Set(), filteredExpandedKeys: new Set(), filteredShownKeys: new Set(), prevProps: null, loadedKeys: new Set(), loadingKeys: new Set(), cachedFlattenNodes: undefined, cachedKeyValuePairs: {}, disabledKeys: new Set(), dragging: false, dragNodesKeys: new Set(), dragOverNodeKey: null, dropPosition: null }; this.inputRef = /*#__PURE__*/_react.default.createRef(); this.optionsRef = /*#__PURE__*/_react.default.createRef(); this.foundation = new _foundation.default(this.adapter); this.dragNode = null; this.virtualizedListRef = /*#__PURE__*/_react.default.createRef(); } /** * Process of getDerivedStateFromProps was inspired by rc-tree * https://github.com/react-component/tree */ static getDerivedStateFromProps(props, prevState) { var _a; const { prevProps } = prevState; const { keyMaps } = props; let treeData; let keyEntities = prevState.keyEntities || {}; let valueEntities = prevState.cachedKeyValuePairs || {}; const isSeaching = Boolean(props.filterTreeNode && prevState.inputValue && prevState.inputValue.length); const newState = { prevProps: props }; const isExpandControlled = 'expandedKeys' in props; // Accept a props field as a parameter to determine whether to update the field const needUpdate = name => { const firstInProps = !prevProps && name in props; const nameHasChange = prevProps && !(0, _isEqual2.default)(prevProps[name], props[name]); return firstInProps || nameHasChange; }; /** * Compare treeData structure (key/value) to determine if expandedKeys needs recalculation. * When label is ReactNode, isEqual would return false due to new ReactElement references, * causing unnecessary expandedKeys recalculation that breaks user's expand state. * We only care about structural changes (key/value/children), not label/icon/disabled etc. */ const isTreeDataStructureEqual = (prevTreeData, nextTreeData) => { if (prevTreeData === nextTreeData) { return true; } if (!prevTreeData || !nextTreeData) { return prevTreeData === nextTreeData; } if (prevTreeData.length !== nextTreeData.length) { return false; } const realKeyName = (0, _get2.default)(keyMaps, 'key', 'key'); const realValueName = (0, _get2.default)(keyMaps, 'value', 'value'); const realChildrenName = (0, _get2.default)(keyMaps, 'children', 'children'); const compareNodes = (nodesA, nodesB) => { if (nodesA.length !== nodesB.length) { return false; } for (let i = 0; i < nodesA.length; i++) { const nodeA = nodesA[i]; const nodeB = nodesB[i]; // Compare key and value (structure only, not label/icon/disabled) if (nodeA[realKeyName] !== nodeB[realKeyName] || nodeA[realValueName] !== nodeB[realValueName]) { return false; } // Recursively compare children const childrenA = nodeA[realChildrenName] || []; const childrenB = nodeB[realChildrenName] || []; if (childrenA.length !== childrenB.length) { return false; } if (childrenA.length > 0 && !compareNodes(childrenA, childrenB)) { return false; } } return true; }; return compareNodes(prevTreeData, nextTreeData); }; // Determine whether treeData reference has changed (for UI update and draggable mode) const needUpdateTreeDataRef = () => { const firstInProps = !prevProps && 'treeData' in props; const treeDataHasChange = prevProps && prevProps.treeData !== props.treeData; return firstInProps || treeDataHasChange; }; /** * Determine whether treeData structure has changed (key/value/children). * This is used to decide if expandedKeys needs recalculation. * When label is ReactNode, we use structure comparison instead of isEqual * to avoid false positives that would break user's expand state. */ const needUpdateTreeDataStructure = () => { const firstInProps = !prevProps && 'treeData' in props; if (firstInProps) { return true; } if (prevProps) { const prevTreeData = prevProps.treeData; const nextTreeData = props.treeData; // Use structure comparison instead of isEqual for treeData return !isTreeDataStructureEqual(prevTreeData, nextTreeData); } return false; }; const needUpdateSimpleJson = needUpdate('treeDataSimpleJson'); const treeDataRefUpdated = needUpdateTreeDataRef(); const treeDataStructureUpdated = needUpdateTreeDataStructure(); // Update the data of tree in state // - treeData ref change: always update treeData in state (so UI like label/icon/disabled can update) // - treeData structure change: expandedKeys may need recalculation (handled below) // - entities should be rebuilt whenever treeData ref changes, otherwise derived logic that relies on entity.data // (e.g. disableStrictly/calcDisabledKeys, filterTreeData) may use stale disabled/label/etc // Note: This is more aggressive than original (which used isEqual deep comparison for non-draggable mode), // but necessary to fix ReactNode label false positive issue. Users can use useMemo to stabilize treeData if needed. if (treeDataRefUpdated) { treeData = props.treeData; newState.treeData = treeData; const entitiesMap = (0, _treeUtil.convertDataToEntities)(treeData, keyMaps); newState.keyEntities = Object.assign({}, entitiesMap.keyEntities); keyEntities = newState.keyEntities; newState.cachedKeyValuePairs = Object.assign({}, entitiesMap.valueEntities); valueEntities = newState.cachedKeyValuePairs; } else if (needUpdateSimpleJson) { // Convert treeDataSimpleJson to treeData treeData = (0, _treeUtil.convertJsonToData)(props.treeDataSimpleJson); newState.treeData = treeData; const entitiesMap = (0, _treeUtil.convertDataToEntities)(treeData, keyMaps); newState.keyEntities = Object.assign({}, entitiesMap.keyEntities); keyEntities = newState.keyEntities; newState.cachedKeyValuePairs = Object.assign({}, entitiesMap.valueEntities); valueEntities = newState.cachedKeyValuePairs; } // If treeData structure changes, we won't show animation // (treeData may change by reference only (e.g. label ReactNode), which shouldn't force-disable motion) const dataStructureUpdated = needUpdateSimpleJson || treeDataStructureUpdated; if (dataStructureUpdated && props.motion) { if (prevProps && props.motion) { newState.motionKeys = new Set([]); newState.motionType = null; } } const dataUpdated = dataStructureUpdated; const expandAllWhenDataChange = dataUpdated && props.expandAll; if (!isSeaching) { // Update expandedKeys if (needUpdate('expandedKeys') || prevProps && needUpdate('autoExpandParent')) { newState.expandedKeys = (0, _treeUtil.calcExpandedKeys)(props.expandedKeys, keyEntities, props.autoExpandParent || !prevProps); // only show animation when treeData does not change if (prevProps && props.motion && !treeData) { const { motionKeys, motionType } = (0, _treeUtil.calcMotionKeys)(prevState.expandedKeys, newState.expandedKeys, keyEntities); newState.motionKeys = new Set(motionKeys); newState.motionType = motionType; if (motionType === 'hide') { // cache flatten nodes: expandedKeys changed may not be triggered by interaction newState.cachedFlattenNodes = (0, _treeUtil2.cloneDeep)(prevState.flattenNodes); } } } else if (!prevProps && (props.defaultExpandAll || props.expandAll) || expandAllWhenDataChange) { newState.expandedKeys = new Set(Object.keys(keyEntities)); } else if (!prevProps && props.defaultExpandedKeys) { newState.expandedKeys = (0, _treeUtil.calcExpandedKeys)(props.defaultExpandedKeys, keyEntities); } else if (!prevProps && props.defaultValue) { newState.expandedKeys = (0, _treeUtil.calcExpandedKeysForValues)(props.defaultValue, keyEntities, props.multiple, valueEntities); } else if (!prevProps && props.value) { newState.expandedKeys = (0, _treeUtil.calcExpandedKeysForValues)(props.value, keyEntities, props.multiple, valueEntities); } else if (!isExpandControlled && dataUpdated && props.value) { // 当 treeData 已经设置具体的值,并且设置了 props.loadData ,则认为 treeData 的更新是因为 loadData 导致的 // 如果是因为 loadData 导致 treeData改变, 此时在这里重新计算 key 会导致为未选中的展开项目被收起 // 所以此时不需要重新计算 expandedKeys,因为在点击展开按钮时候已经把被展开的项添加到 expandedKeys 中 // When treeData has a specific value and props.loadData is set, it is considered that the update of treeData is caused by loadData // If the treeData is changed because of loadData, recalculating the key here will cause the unselected expanded items to be collapsed // So there is no need to recalculate expandedKeys at this time, because the expanded item has been added to expandedKeys when the expand button is clicked if (!(prevState.treeData && ((_a = prevState.treeData) === null || _a === void 0 ? void 0 : _a.length) > 0 && props.loadData)) { newState.expandedKeys = (0, _treeUtil.calcExpandedKeysForValues)(props.value, keyEntities, props.multiple, valueEntities); } } if (!newState.expandedKeys) { delete newState.expandedKeys; } // Update flattenNodes if (treeData || newState.expandedKeys) { const flattenNodes = (0, _treeUtil.flattenTreeData)(treeData || prevState.treeData, newState.expandedKeys || prevState.expandedKeys, keyMaps); newState.flattenNodes = flattenNodes; } } else { let filteredState; // treeData changed while searching if (treeData) { // Get filter data filteredState = (0, _treeUtil.filterTreeData)({ treeData, inputValue: prevState.inputValue, filterTreeNode: props.filterTreeNode, filterProps: props.treeNodeFilterProp, showFilteredOnly: props.showFilteredOnly, keyEntities: newState.keyEntities, prevExpandedKeys: [...prevState.filteredExpandedKeys], keyMaps: keyMaps }); newState.flattenNodes = filteredState.flattenNodes; newState.motionKeys = new Set([]); newState.filteredKeys = filteredState.filteredKeys; newState.filteredShownKeys = filteredState.filteredShownKeys; newState.filteredExpandedKeys = filteredState.filteredExpandedKeys; } // expandedKeys changed while searching if (props.expandedKeys) { newState.filteredExpandedKeys = (0, _treeUtil.calcExpandedKeys)(props.expandedKeys, keyEntities, props.autoExpandParent || !prevProps); if (prevProps && props.motion) { const prevKeys = prevState ? prevState.filteredExpandedKeys : new Set([]); // only show animation when treeData does not change if (!treeData) { const motionResult = (0, _treeUtil.calcMotionKeys)(prevKeys, newState.filteredExpandedKeys, keyEntities); let { motionKeys } = motionResult; const { motionType } = motionResult; if (props.showFilteredOnly) { motionKeys = motionKeys.filter(key => prevState.filteredShownKeys.has(key)); } if (motionType === 'hide') { // cache flatten nodes: expandedKeys changed may not be triggered by interaction newState.cachedFlattenNodes = (0, _treeUtil2.cloneDeep)(prevState.flattenNodes); } newState.motionKeys = new Set(motionKeys); newState.motionType = motionType; } } newState.flattenNodes = (0, _treeUtil.flattenTreeData)(treeData || prevState.treeData, newState.filteredExpandedKeys || prevState.filteredExpandedKeys, keyMaps, props.showFilteredOnly && prevState.filteredShownKeys); } } // Handle single selection and multiple selection in controlled mode const withObject = props.onChangeWithObject; const isMultiple = props.multiple; if (!isMultiple) { // When getting single selection, the selected node if (needUpdate('value')) { newState.selectedKeys = (0, _treeUtil.findKeysForValues)( // In both cases whether withObject is turned on, the value is standardized to string (0, _treeUtil.normalizeValue)(props.value, withObject, keyMaps), valueEntities, isMultiple); } else if (!prevProps && props.defaultValue) { newState.selectedKeys = (0, _treeUtil.findKeysForValues)((0, _treeUtil.normalizeValue)(props.defaultValue, withObject, keyMaps), valueEntities, isMultiple); } else if (treeData) { // If `treeData` changed, we also need check it if (props.value) { newState.selectedKeys = (0, _treeUtil.findKeysForValues)((0, _treeUtil.normalizeValue)(props.value, withObject, keyMaps) || '', valueEntities, isMultiple); } } } else { let checkedKeyValues; // Get the selected node during multiple selection if (needUpdate('value')) { checkedKeyValues = (0, _treeUtil.findKeysForValues)((0, _treeUtil.normalizeValue)(props.value, withObject, keyMaps), valueEntities, isMultiple); } else if (!prevProps && props.defaultValue) { checkedKeyValues = (0, _treeUtil.findKeysForValues)((0, _treeUtil.normalizeValue)(props.defaultValue, withObject, keyMaps), valueEntities, isMultiple); } else if (treeData) { // If `treeData` changed, we also need check it if (props.value) { checkedKeyValues = (0, _treeUtil.findKeysForValues)((0, _treeUtil.normalizeValue)(props.value, withObject, keyMaps) || [], valueEntities, isMultiple); } else { checkedKeyValues = (0, _treeUtil.updateKeys)(props.checkRelation === 'related' ? prevState.checkedKeys : prevState.realCheckedKeys, keyEntities); } } if (checkedKeyValues) { if (props.checkRelation === 'unRelated') { newState.realCheckedKeys = new Set(checkedKeyValues); } else if (props.checkRelation === 'related') { const { checkedKeys, halfCheckedKeys } = (0, _treeUtil.calcCheckedKeys)(checkedKeyValues, keyEntities); newState.checkedKeys = checkedKeys; newState.halfCheckedKeys = halfCheckedKeys; } } } // update loadedKeys if (needUpdate('loadedKeys')) { newState.loadedKeys = new Set(props.loadedKeys); } // update disableStrictly if (treeData && props.disableStrictly && props.checkRelation === 'related') { newState.disabledKeys = (0, _treeUtil.calcDisabledKeys)(keyEntities, keyMaps); } return newState; } get adapter() { const filterAdapter = { updateInputValue: value => { this.setState({ inputValue: value }); }, focusInput: () => { const { preventScroll } = this.props; if (this.inputRef && this.inputRef.current) { this.inputRef.current.focus({ preventScroll }); } } }; return Object.assign(Object.assign(Object.assign({}, super.adapter), filterAdapter), { updateState: states => { this.setState(Object.assign({}, states)); }, notifyExpand: (expandedKeys, _ref3) => { let { expanded: bool, node } = _ref3; this.props.onExpand && this.props.onExpand([...expandedKeys], { expanded: bool, node }); if (bool && this.props.loadData) { this.onNodeLoad(node); } }, notifySelect: (selectKey, bool, node) => { this.props.onSelect && this.props.onSelect(selectKey, bool, node); }, notifyChange: value => { this.props.onChange && this.props.onChange(value); }, notifySearch: (input, filteredExpandedKeys) => { this.props.onSearch && this.props.onSearch(input, filteredExpandedKeys); }, notifyRightClick: (e, node) => { this.props.onContextMenu && this.props.onContextMenu(e, node); }, notifyDoubleClick: (e, node) => { this.props.onDoubleClick && this.props.onDoubleClick(e, node); }, cacheFlattenNodes: bool => { this.setState({ cachedFlattenNodes: bool ? (0, _treeUtil2.cloneDeep)(this.state.flattenNodes) : undefined }); }, setDragNode: treeNode => { this.dragNode = treeNode; } }); } renderInput() { const { searchClassName, searchStyle, searchRender, searchPlaceholder, showClear } = this.props; if (searchRender === false) { return null; } const inputcls = (0, _classnames.default)(`${prefixcls}-input`); const { inputValue } = this.state; const inputProps = { value: inputValue, className: inputcls, onChange: value => this.search(value), prefix: /*#__PURE__*/_react.default.createElement(_semiIcons.IconSearch, null), showClear, placeholder: searchPlaceholder }; const wrapperCls = (0, _classnames.default)(`${prefixcls}-search-wrapper`, searchClassName); return /*#__PURE__*/_react.default.createElement("div", { className: wrapperCls, style: searchStyle }, /*#__PURE__*/_react.default.createElement(_localeConsumer.default, { componentName: "Tree" }, locale => { inputProps.placeholder = searchPlaceholder || (0, _get2.default)(locale, 'searchPlaceholder'); if ((0, _isFunction2.default)(searchRender)) { return searchRender(Object.assign({}, inputProps)); } return /*#__PURE__*/_react.default.createElement(_index.default, Object.assign({ "aria-label": 'Filter Tree', ref: this.inputRef }, inputProps)); })); } renderNodeList() { const { flattenNodes, cachedFlattenNodes, motionKeys, motionType } = this.state; const { virtualize, motion } = this.props; const { direction } = this.context; if ((0, _isEmpty2.default)(flattenNodes)) { return undefined; } if (!virtualize || (0, _isEmpty2.default)(virtualize)) { return /*#__PURE__*/_react.default.createElement(_nodeList.default, { flattenNodes: flattenNodes, flattenList: cachedFlattenNodes, motionKeys: motion ? motionKeys : new Set([]), motionType: motionType, onMotionEnd: this.onMotionEnd, renderTreeNode: this.renderTreeNode }); } return /*#__PURE__*/_react.default.createElement(_autoSizer.default, { defaultHeight: virtualize.height, defaultWidth: virtualize.width }, _ref4 => { let { height, width } = _ref4; return /*#__PURE__*/_react.default.createElement(_reactWindow.FixedSizeList, { ref: this.virtualizedListRef, itemCount: flattenNodes.length, itemSize: virtualize.itemSize, height: height, width: width, itemKey: this.itemKey, itemData: flattenNodes, className: `${prefixcls}-virtual-list`, style: { direction } }, this.option); }); } render() { const { keyEntities, motionKeys, motionType, inputValue, filteredKeys, dragOverNodeKey, dropPosition, checkedKeys, realCheckedKeys } = this.state; const _a = this.props, { blockNode, className, style, filterTreeNode, disabled, icon, directory, multiple, showFilteredOnly, showLine, motion, expandAction, loadData, renderLabel, draggable, renderFullLabel, labelEllipsis, virtualize, checkRelation } = _a, rest = __rest(_a, ["blockNode", "className", "style", "filterTreeNode", "disabled", "icon", "directory", "multiple", "showFilteredOnly", "showLine", "motion", "expandAction", "loadData", "renderLabel", "draggable", "renderFullLabel", "labelEllipsis", "virtualize", "checkRelation"]); const wrapperCls = (0, _classnames.default)(`${prefixcls}-wrapper`, className); const listCls = (0, _classnames.default)(`${prefixcls}-option-list`, { [`${prefixcls}-option-list-block`]: blockNode }); const searchNoRes = Boolean(inputValue) && !filteredKeys.size; const noData = (0, _isEmpty2.default)(keyEntities) || showFilteredOnly && searchNoRes; const ariaAttr = { role: noData ? 'none' : 'tree' }; if (ariaAttr.role === 'tree') { ariaAttr['aria-multiselectable'] = multiple ? true : false; } return /*#__PURE__*/_react.default.createElement(_treeContext.default.Provider, { value: { treeDisabled: disabled, treeIcon: icon, motion, motionKeys, motionType, filterTreeNode, keyEntities, onNodeClick: this.onNodeClick, onNodeExpand: this.onNodeExpand, onNodeSelect: this.onNodeSelect, onNodeCheck: this.onNodeCheck, onNodeRightClick: this.onNodeRightClick, onNodeDoubleClick: this.onNodeDoubleClick, renderTreeNode: this.renderTreeNode, onNodeDragStart: this.onNodeDragStart, onNodeDragEnter: this.onNodeDragEnter, onNodeDragOver: this.onNodeDragOver, onNodeDragLeave: this.onNodeDragLeave, onNodeDragEnd: this.onNodeDragEnd, onNodeDrop: this.onNodeDrop, expandAction, directory, multiple, showFilteredOnly, isSearching: Boolean(inputValue), loadData, onNodeLoad: this.onNodeLoad, renderLabel, draggable, renderFullLabel, dragOverNodeKey, dropPosition, labelEllipsis: typeof labelEllipsis === 'undefined' ? virtualize : labelEllipsis } }, /*#__PURE__*/_react.default.createElement("div", Object.assign({ "aria-label": this.props['aria-label'], className: wrapperCls, style: style }, this.getDataAttr(rest)), filterTreeNode ? this.renderInput() : null, /*#__PURE__*/_react.default.createElement("div", Object.assign({ className: listCls }, ariaAttr), noData ? this.renderEmpty() : multiple ? (/*#__PURE__*/_react.default.createElement(_checkboxGroup.default, { value: Array.from(checkRelation === 'related' ? checkedKeys : realCheckedKeys) }, this.renderNodeList())) : this.renderNodeList()))); } } Tree.contextType = _context.default; Tree.propTypes = { autoMergeValue: _propTypes.default.bool, blockNode: _propTypes.default.bool, className: _propTypes.default.string, showClear: _propTypes.default.bool, defaultExpandAll: _propTypes.default.bool, defaultExpandedKeys: _propTypes.default.array, defaultValue: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.array]), directory: _propTypes.default.bool, disabled: _propTypes.default.bool, emptyContent: _propTypes.default.node, expandAll: _propTypes.default.bool, expandedKeys: _propTypes.default.array, filterTreeNode: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.bool]), icon: _propTypes.default.node, onChangeWithObject: _propTypes.default.bool, motion: _propTypes.default.bool, multiple: _propTypes.default.bool, onChange: _propTypes.default.func, onExpand: _propTypes.default.func, onSearch: _propTypes.default.func, onSelect: _propTypes.default.func, onContextMenu: _propTypes.default.func, onDoubleClick: _propTypes.default.func, searchClassName: _propTypes.default.string, searchPlaceholder: _propTypes.default.string, searchStyle: _propTypes.default.object, selectedKey: _propTypes.default.string, showFilteredOnly: _propTypes.default.bool, showLine: _propTypes.default.bool, style: _propTypes.default.object, treeData: _propTypes.default.arrayOf(_propTypes.default.shape(treeDataNodeShape)), keyMaps: _propTypes.default.object, treeDataSimpleJson: _propTypes.default.object, treeNodeFilterProp: _propTypes.default.string, value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number, _propTypes.default.array, _propTypes.default.object]), virtualize: _propTypes.default.object, autoExpandParent: _propTypes.default.bool, expandAction: _propTypes.default.oneOf(_constants.strings.EXPAND_ACTION), searchRender: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.bool]), renderLabel: _propTypes.default.func, renderFullLabel: _propTypes.default.func, leafOnly: _propTypes.default.bool, loadedKeys: _propTypes.default.array, loadData: _propTypes.default.func, onLoad: _propTypes.default.func, disableStrictly: _propTypes.default.bool, draggable: _propTypes.default.bool, autoExpandWhenDragEnter: _propTypes.default.bool, hideDraggingNode: _propTypes.default.bool, renderDraggingNode: _propTypes.default.func, onDragEnd: _propTypes.default.func, onDragEnter: _propTypes.default.func, onDragLeave: _propTypes.default.func, onDragOver: _propTypes.default.func, onDragStart: _propTypes.default.func, onDrop: _propTypes.default.func, labelEllipsis: _propTypes.default.bool, checkRelation: _propTypes.default.string, 'aria-label': _propTypes.default.string, preventScroll: _propTypes.default.bool }; Tree.defaultProps = { showClear: true, disabled: false, blockNode: true, multiple: false, filterTreeNode: false, autoExpandParent: false, treeNodeFilterProp: 'label', defaultExpandAll: false, expandAll: false, onChangeWithObject: false, motion: true, leafOnly: false, showFilteredOnly: false, showLine: false, expandAction: false, disableStrictly: false, draggable: false, autoExpandWhenDragEnter: true, checkRelation: 'related', autoMergeValue: true }; Tree.TreeNode = _treeNode.default; var _default = exports.default = Tree;