perf: tree, close #5551
							parent
							
								
									53b4c5d8b2
								
							
						
					
					
						commit
						9aeadaf877
					
				|  | @ -16,8 +16,8 @@ import PropTypes from '../_util/vue-types'; | |||
| import useConfigInject from '../_util/hooks/useConfigInject'; | ||||
| import devWarning from '../vc-util/devWarning'; | ||||
| import getIcons from '../select/utils/iconUtil'; | ||||
| import type { SwitcherIconProps } from '../tree/utils/iconUtil'; | ||||
| import renderSwitcherIcon from '../tree/utils/iconUtil'; | ||||
| import type { AntTreeNodeProps } from '../tree/Tree'; | ||||
| import { warning } from '../vc-util/warning'; | ||||
| import { flattenChildren } from '../_util/props-util'; | ||||
| import { useInjectFormItemContext } from '../form/FormItemContext'; | ||||
|  | @ -239,7 +239,7 @@ const TreeSelect = defineComponent({ | |||
|           multiple={multiple} | ||||
|           removeIcon={removeIcon} | ||||
|           clearIcon={clearIcon} | ||||
|           switcherIcon={(nodeProps: AntTreeNodeProps) => | ||||
|           switcherIcon={(nodeProps: SwitcherIconProps) => | ||||
|             renderSwitcherIcon(treePrefixCls.value, switcherIcon, treeLine, nodeProps) | ||||
|           } | ||||
|           showTreeIcon={treeIcon as any} | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import type { DataNode, EventDataNode, FieldNames, Key } from '../vc-tree/interf | |||
| import type { TreeNodeProps } from '../vc-tree/props'; | ||||
| import { treeProps as vcTreeProps } from '../vc-tree/props'; | ||||
| import useConfigInject from '../_util/hooks/useConfigInject'; | ||||
| import type { SwitcherIconProps } from './utils/iconUtil'; | ||||
| import renderSwitcherIcon from './utils/iconUtil'; | ||||
| import dropIndicatorRender from './utils/dropIndicator'; | ||||
| import devWarning from '../vc-util/devWarning'; | ||||
|  | @ -229,7 +230,7 @@ export default defineComponent({ | |||
|         icon, | ||||
|         itemHeight, | ||||
|       }; | ||||
| 
 | ||||
|       const children = slots.default ? filterEmpty(slots.default()) : undefined; | ||||
|       return ( | ||||
|         <VcTree | ||||
|           {...newProps} | ||||
|  | @ -249,7 +250,7 @@ export default defineComponent({ | |||
|           direction={direction.value} | ||||
|           checkable={checkable} | ||||
|           selectable={selectable} | ||||
|           switcherIcon={(nodeProps: AntTreeNodeProps) => | ||||
|           switcherIcon={(nodeProps: SwitcherIconProps) => | ||||
|             renderSwitcherIcon(prefixCls.value, switcherIcon, showLine, nodeProps) | ||||
|           } | ||||
|           onCheck={handleCheck} | ||||
|  | @ -260,7 +261,7 @@ export default defineComponent({ | |||
|             ...slots, | ||||
|             checkable: () => <span class={`${prefixCls.value}-checkbox-inner`} />, | ||||
|           }} | ||||
|           children={filterEmpty(slots.default?.())} | ||||
|           children={children} | ||||
|         ></VcTree> | ||||
|       ); | ||||
|     }; | ||||
|  |  | |||
|  | @ -7,12 +7,15 @@ import type { AntTreeNodeProps } from '../Tree'; | |||
| import { isValidElement } from '../../_util/props-util'; | ||||
| 
 | ||||
| import { cloneVNode } from 'vue'; | ||||
| 
 | ||||
| export interface SwitcherIconProps extends AntTreeNodeProps { | ||||
|   expanded: boolean; | ||||
|   loading: boolean; | ||||
| } | ||||
| export default function renderSwitcherIcon( | ||||
|   prefixCls: string, | ||||
|   switcherIcon: any, | ||||
|   showLine: boolean | { showLeafIcon: boolean } | undefined, | ||||
|   props: AntTreeNodeProps, | ||||
|   props: SwitcherIconProps, | ||||
| ) { | ||||
|   const { isLeaf, expanded, loading } = props; | ||||
|   let icon = switcherIcon; | ||||
|  |  | |||
|  | @ -1,7 +1,5 @@ | |||
| import TreeNode from './TreeNode'; | ||||
| import type { FlattenNode } from './interface'; | ||||
| import type { TreeNodeRequiredProps } from './utils/treeUtil'; | ||||
| import { getTreeNodeProps } from './utils/treeUtil'; | ||||
| import { useInjectTreeContext } from './contextTypes'; | ||||
| import type { PropType } from 'vue'; | ||||
| import { | ||||
|  | @ -28,7 +26,7 @@ export default defineComponent({ | |||
|     onMotionStart: Function, | ||||
|     onMotionEnd: Function, | ||||
|     motionType: String, | ||||
|     treeNodeRequiredProps: { type: Object as PropType<TreeNodeRequiredProps> }, | ||||
|     // treeNodeRequiredProps: { type: Object as PropType<TreeNodeRequiredProps> }, | ||||
|   }, | ||||
|   slots: ['title', 'icon', 'switcherIcon', 'checkable'], | ||||
|   setup(props, { attrs, slots }) { | ||||
|  | @ -73,8 +71,7 @@ export default defineComponent({ | |||
|     }); | ||||
| 
 | ||||
|     return () => { | ||||
|       const { motion, motionNodes, motionType, active, treeNodeRequiredProps, ...otherProps } = | ||||
|         props; | ||||
|       const { motion, motionNodes, motionType, active, eventKey, ...otherProps } = props; | ||||
|       if (motionNodes) { | ||||
|         return ( | ||||
|           <Transition | ||||
|  | @ -94,17 +91,15 @@ export default defineComponent({ | |||
|                 } = treeNode; | ||||
|                 delete restProps.children; | ||||
| 
 | ||||
|                 const treeNodeProps = getTreeNodeProps(key, treeNodeRequiredProps); | ||||
| 
 | ||||
|                 return ( | ||||
|                   <TreeNode | ||||
|                     v-slots={slots} | ||||
|                     {...restProps} | ||||
|                     {...treeNodeProps} | ||||
|                     title={title} | ||||
|                     active={active} | ||||
|                     data={treeNode.data} | ||||
|                     key={key} | ||||
|                     eventKey={key} | ||||
|                     isStart={isStart} | ||||
|                     isEnd={isEnd} | ||||
|                   /> | ||||
|  | @ -122,6 +117,7 @@ export default defineComponent({ | |||
|           style={attrs.style} | ||||
|           {...otherProps} | ||||
|           active={active} | ||||
|           eventKey={eventKey} | ||||
|         /> | ||||
|       ); | ||||
|     }; | ||||
|  |  | |||
|  | @ -4,12 +4,14 @@ | |||
| 
 | ||||
| import { computed, defineComponent, ref, shallowRef, watch } from 'vue'; | ||||
| import VirtualList from '../vc-virtual-list'; | ||||
| import omit from '../_util/omit'; | ||||
| import { useInjectKeysState, useInjectTreeContext } from './contextTypes'; | ||||
| import type { FlattenNode, DataEntity, DataNode, ScrollTo } from './interface'; | ||||
| import MotionTreeNode from './MotionTreeNode'; | ||||
| import type { NodeListProps } from './props'; | ||||
| import { nodeListProps } from './props'; | ||||
| import { findExpandedKeys, getExpandRange } from './utils/diffUtil'; | ||||
| import { getTreeNodeProps, getKey } from './utils/treeUtil'; | ||||
| import { getKey } from './utils/treeUtil'; | ||||
| 
 | ||||
| const HIDDEN_STYLE = { | ||||
|   width: 0, | ||||
|  | @ -97,6 +99,7 @@ export default defineComponent({ | |||
|     // =============================== Ref ================================ | ||||
|     const listRef = ref(); | ||||
|     const indentMeasurerRef = ref(); | ||||
|     const { expandedKeys, flattenNodes } = useInjectKeysState(); | ||||
|     expose({ | ||||
|       scrollTo: scroll => { | ||||
|         listRef.value.scrollTo(scroll); | ||||
|  | @ -104,19 +107,21 @@ export default defineComponent({ | |||
|       getIndentWidth: () => indentMeasurerRef.value.offsetWidth, | ||||
|     }); | ||||
|     // ============================== Motion ============================== | ||||
|     const transitionData = shallowRef<FlattenNode[]>(props.data); | ||||
|     const transitionData = shallowRef<FlattenNode[]>(flattenNodes.value); | ||||
|     const transitionRange = shallowRef([]); | ||||
|     const motionType = ref<'show' | 'hide' | null>(null); | ||||
| 
 | ||||
|     function onMotionEnd() { | ||||
|       transitionData.value = props.data; | ||||
|       transitionData.value = flattenNodes.value; | ||||
|       transitionRange.value = []; | ||||
|       motionType.value = null; | ||||
| 
 | ||||
|       props.onListChangeEnd(); | ||||
|     } | ||||
| 
 | ||||
|     const context = useInjectTreeContext(); | ||||
|     watch( | ||||
|       [() => [...props.expandedKeys], () => props.data], | ||||
|       [() => expandedKeys.value.slice(), flattenNodes], | ||||
|       ([expandedKeys, data], [prevExpandedKeys, prevData]) => { | ||||
|         const diffExpanded = findExpandedKeys(prevExpandedKeys, expandedKeys); | ||||
|         if (diffExpanded.key !== null) { | ||||
|  | @ -160,7 +165,7 @@ export default defineComponent({ | |||
|     ); | ||||
|     // We should clean up motion if is changed by dragging | ||||
|     watch( | ||||
|       () => props.dragging, | ||||
|       () => context.value.dragging, | ||||
|       dragging => { | ||||
|         if (!dragging) { | ||||
|           onMotionEnd(); | ||||
|  | @ -169,27 +174,18 @@ export default defineComponent({ | |||
|     ); | ||||
| 
 | ||||
|     const mergedData = computed(() => | ||||
|       props.motion === undefined ? transitionData.value : props.data, | ||||
|       props.motion === undefined ? transitionData.value : flattenNodes.value, | ||||
|     ); | ||||
| 
 | ||||
|     const onActiveChange = () => { | ||||
|       props.onActiveChange(null); | ||||
|     }; | ||||
|     return () => { | ||||
|       const { | ||||
|         prefixCls, | ||||
|         data, | ||||
|         selectable, | ||||
|         checkable, | ||||
|         expandedKeys, | ||||
|         selectedKeys, | ||||
|         checkedKeys, | ||||
|         loadedKeys, | ||||
|         loadingKeys, | ||||
|         halfCheckedKeys, | ||||
|         keyEntities, | ||||
|         disabled, | ||||
| 
 | ||||
|         dragging, | ||||
|         dragOverNodeKey, | ||||
|         dropPosition, | ||||
|         motion, | ||||
| 
 | ||||
|         height, | ||||
|  | @ -204,25 +200,12 @@ export default defineComponent({ | |||
|         onKeydown, | ||||
|         onFocus, | ||||
|         onBlur, | ||||
|         onActiveChange, | ||||
| 
 | ||||
|         onListChangeStart, | ||||
|         onListChangeEnd, | ||||
| 
 | ||||
|         ...domProps | ||||
|       } = { ...props, ...attrs } as NodeListProps; | ||||
| 
 | ||||
|       const treeNodeRequiredProps = { | ||||
|         expandedKeys, | ||||
|         selectedKeys, | ||||
|         loadedKeys, | ||||
|         loadingKeys, | ||||
|         checkedKeys, | ||||
|         halfCheckedKeys, | ||||
|         dragOverNodeKey, | ||||
|         dropPosition, | ||||
|         keyEntities, | ||||
|       }; | ||||
|       return ( | ||||
|         <> | ||||
|           {focused && activeItem && ( | ||||
|  | @ -262,7 +245,7 @@ export default defineComponent({ | |||
|           </div> | ||||
| 
 | ||||
|           <VirtualList | ||||
|             {...domProps} | ||||
|             {...omit(domProps, ['onActiveChange'])} | ||||
|             data={mergedData.value} | ||||
|             itemKey={itemKey as any} | ||||
|             height={height} | ||||
|  | @ -293,15 +276,12 @@ export default defineComponent({ | |||
|                 const mergedKey = getKey(key, pos); | ||||
|                 delete restProps.key; | ||||
|                 delete restProps.children; | ||||
| 
 | ||||
|                 const treeNodeProps = getTreeNodeProps(mergedKey, treeNodeRequiredProps); | ||||
|                 return ( | ||||
|                   <MotionTreeNode | ||||
|                     {...restProps} | ||||
|                     {...treeNodeProps} | ||||
|                     eventKey={mergedKey} | ||||
|                     title={title} | ||||
|                     active={!!activeItem && key === activeItem.key} | ||||
|                     pos={pos} | ||||
|                     data={treeNode.data} | ||||
|                     isStart={isStart} | ||||
|                     isEnd={isEnd} | ||||
|  | @ -310,10 +290,7 @@ export default defineComponent({ | |||
|                     motionType={motionType.value} | ||||
|                     onMotionStart={onListChangeStart} | ||||
|                     onMotionEnd={onMotionEnd} | ||||
|                     treeNodeRequiredProps={treeNodeRequiredProps} | ||||
|                     onMousemove={() => { | ||||
|                       onActiveChange(null); | ||||
|                     }} | ||||
|                     onMousemove={onActiveChange} | ||||
|                   /> | ||||
|                 ); | ||||
|               }, | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| import type { NodeMouseEventHandler, NodeDragEventHandler } from './contextTypes'; | ||||
| import { TreeContext } from './contextTypes'; | ||||
| import { useProvideKeysState, TreeContext } from './contextTypes'; | ||||
| import { | ||||
|   getDragChildrenKeys, | ||||
|   parseCheckedKeys, | ||||
|  | @ -11,6 +11,7 @@ import { | |||
|   posToArr, | ||||
| } from './util'; | ||||
| import type { Key, FlattenNode, EventDataNode, ScrollTo, DragNodeEvent } from './interface'; | ||||
| import type { TreeNodeRequiredProps } from './utils/treeUtil'; | ||||
| import { | ||||
|   flattenTreeData, | ||||
|   convertTreeToData, | ||||
|  | @ -78,12 +79,12 @@ export default defineComponent({ | |||
|     const destroyed = ref(false); | ||||
|     let delayedDragEnterLogic: Record<Key, number> = {}; | ||||
|     const indent = ref(); | ||||
|     const selectedKeys = shallowRef([]); | ||||
|     const checkedKeys = shallowRef([]); | ||||
|     const halfCheckedKeys = shallowRef([]); | ||||
|     const loadedKeys = shallowRef([]); | ||||
|     const loadingKeys = shallowRef([]); | ||||
|     const expandedKeys = shallowRef([]); | ||||
|     const selectedKeys = shallowRef<Key[]>([]); | ||||
|     const checkedKeys = shallowRef<Key[]>([]); | ||||
|     const halfCheckedKeys = shallowRef<Key[]>([]); | ||||
|     const loadedKeys = shallowRef<Key[]>([]); | ||||
|     const loadingKeys = shallowRef<Key[]>([]); | ||||
|     const expandedKeys = shallowRef<Key[]>([]); | ||||
|     const loadingRetryTimes: Record<Key, number> = {}; | ||||
|     const dragState = reactive({ | ||||
|       draggingNodeKey: null, | ||||
|  | @ -112,7 +113,10 @@ export default defineComponent({ | |||
|             ? toRaw(props.treeData).slice() | ||||
|             : convertTreeToData(toRaw(props.children)); | ||||
|       }, | ||||
|       { immediate: true, deep: true }, | ||||
|       { | ||||
|         immediate: true, | ||||
|         deep: true, | ||||
|       }, | ||||
|     ); | ||||
|     const keyEntities = shallowRef({}); | ||||
| 
 | ||||
|  | @ -131,19 +135,37 @@ export default defineComponent({ | |||
| 
 | ||||
|     let currentMouseOverDroppableNodeKey = null; | ||||
| 
 | ||||
|     const treeNodeRequiredProps = computed(() => { | ||||
|     const treeNodeRequiredProps = computed<TreeNodeRequiredProps>(() => { | ||||
|       return { | ||||
|         expandedKeys: expandedKeys.value || [], | ||||
|         selectedKeys: selectedKeys.value || [], | ||||
|         loadedKeys: loadedKeys.value || [], | ||||
|         loadingKeys: loadingKeys.value || [], | ||||
|         checkedKeys: checkedKeys.value || [], | ||||
|         halfCheckedKeys: halfCheckedKeys.value || [], | ||||
|         expandedKeysSet: expandedKeysSet.value, | ||||
|         selectedKeysSet: selectedKeysSet.value, | ||||
|         loadedKeysSet: loadedKeysSet.value, | ||||
|         loadingKeysSet: loadingKeysSet.value, | ||||
|         checkedKeysSet: checkedKeysSet.value, | ||||
|         halfCheckedKeysSet: halfCheckedKeysSet.value, | ||||
|         dragOverNodeKey: dragState.dragOverNodeKey, | ||||
|         dropPosition: dragState.dropPosition, | ||||
|         keyEntities: keyEntities.value, | ||||
|       }; | ||||
|     }); | ||||
|     const expandedKeysSet = computed(() => { | ||||
|       return new Set(expandedKeys.value); | ||||
|     }); | ||||
|     const selectedKeysSet = computed(() => { | ||||
|       return new Set(selectedKeys.value); | ||||
|     }); | ||||
|     const loadedKeysSet = computed(() => { | ||||
|       return new Set(loadedKeys.value); | ||||
|     }); | ||||
|     const loadingKeysSet = computed(() => { | ||||
|       return new Set(loadingKeys.value); | ||||
|     }); | ||||
|     const checkedKeysSet = computed(() => { | ||||
|       return new Set(checkedKeys.value); | ||||
|     }); | ||||
|     const halfCheckedKeysSet = computed(() => { | ||||
|       return new Set(halfCheckedKeys.value); | ||||
|     }); | ||||
| 
 | ||||
|     watchEffect(() => { | ||||
|       if (treeData.value) { | ||||
|  | @ -388,7 +410,7 @@ export default defineComponent({ | |||
|         allowDrop, | ||||
|         flattenNodes.value, | ||||
|         keyEntities.value, | ||||
|         expandedKeys.value, | ||||
|         expandedKeysSet.value, | ||||
|         direction, | ||||
|       ); | ||||
| 
 | ||||
|  | @ -485,7 +507,7 @@ export default defineComponent({ | |||
|         allowDrop, | ||||
|         flattenNodes.value, | ||||
|         keyEntities.value, | ||||
|         expandedKeys.value, | ||||
|         expandedKeysSet.value, | ||||
|         direction, | ||||
|       ); | ||||
| 
 | ||||
|  | @ -558,7 +580,6 @@ export default defineComponent({ | |||
|     const onNodeDrop = (event: DragEvent, _node, outsideTree = false) => { | ||||
|       const { dragChildrenKeys, dropPosition, dropTargetKey, dropTargetPos, dropAllowed } = | ||||
|         dragState; | ||||
| 
 | ||||
|       if (!dropAllowed) return; | ||||
| 
 | ||||
|       const { onDrop } = props; | ||||
|  | @ -735,11 +756,7 @@ export default defineComponent({ | |||
|         // We need to get the latest state of loading/loaded keys | ||||
|         const { loadData, onLoad } = props; | ||||
| 
 | ||||
|         if ( | ||||
|           !loadData || | ||||
|           loadedKeys.value.indexOf(key) !== -1 || | ||||
|           loadingKeys.value.indexOf(key) !== -1 | ||||
|         ) { | ||||
|         if (!loadData || loadedKeysSet.value.has(key) || loadingKeysSet.value.has(key)) { | ||||
|           return null; | ||||
|         } | ||||
| 
 | ||||
|  | @ -977,7 +994,7 @@ export default defineComponent({ | |||
|           // >>> Expand | ||||
|           case KeyCode.LEFT: { | ||||
|             // Collapse if possible | ||||
|             if (expandable && expandedKeys.value.includes(activeKey.value)) { | ||||
|             if (expandable && expandedKeysSet.value.has(activeKey.value)) { | ||||
|               onNodeExpand({} as MouseEvent, eventNode); | ||||
|             } else if (item.parent) { | ||||
|               onActiveChange(item.parent.key); | ||||
|  | @ -987,7 +1004,7 @@ export default defineComponent({ | |||
|           } | ||||
|           case KeyCode.RIGHT: { | ||||
|             // Expand if possible | ||||
|             if (expandable && !expandedKeys.value.includes(activeKey.value)) { | ||||
|             if (expandable && !expandedKeysSet.value.has(activeKey.value)) { | ||||
|               onNodeExpand({} as MouseEvent, eventNode); | ||||
|             } else if (item.children && item.children.length) { | ||||
|               onActiveChange(item.children[0].key); | ||||
|  | @ -1005,11 +1022,7 @@ export default defineComponent({ | |||
|               eventNode.checkable !== false && | ||||
|               !eventNode.disableCheckbox | ||||
|             ) { | ||||
|               onNodeCheck( | ||||
|                 {} as MouseEvent, | ||||
|                 eventNode, | ||||
|                 !checkedKeys.value.includes(activeKey.value), | ||||
|               ); | ||||
|               onNodeCheck({} as MouseEvent, eventNode, !checkedKeysSet.value.has(activeKey.value)); | ||||
|             } else if ( | ||||
|               !checkable && | ||||
|               selectable && | ||||
|  | @ -1042,6 +1055,21 @@ export default defineComponent({ | |||
|       window.removeEventListener('dragend', onWindowDragEnd); | ||||
|       destroyed.value = true; | ||||
|     }); | ||||
|     useProvideKeysState({ | ||||
|       expandedKeys, | ||||
|       selectedKeys, | ||||
|       loadedKeys, | ||||
|       loadingKeys, | ||||
|       checkedKeys, | ||||
|       halfCheckedKeys, | ||||
|       expandedKeysSet, | ||||
|       selectedKeysSet, | ||||
|       loadedKeysSet, | ||||
|       loadingKeysSet, | ||||
|       checkedKeysSet, | ||||
|       halfCheckedKeysSet, | ||||
|       flattenNodes, | ||||
|     }); | ||||
|     return () => { | ||||
|       const { | ||||
|         // focused, | ||||
|  | @ -1123,6 +1151,7 @@ export default defineComponent({ | |||
|             dropTargetKey, | ||||
|             dropPosition, | ||||
|             dragOverNodeKey, | ||||
|             dragging: draggingNodeKey !== null, | ||||
|             indent: indent.value, | ||||
|             direction, | ||||
|             dropIndicatorRender, | ||||
|  | @ -1160,12 +1189,10 @@ export default defineComponent({ | |||
|               ref={listRef} | ||||
|               prefixCls={prefixCls} | ||||
|               style={style} | ||||
|               data={flattenNodes.value} | ||||
|               disabled={disabled} | ||||
|               selectable={selectable} | ||||
|               checkable={!!checkable} | ||||
|               motion={motion} | ||||
|               dragging={draggingNodeKey !== null} | ||||
|               height={height} | ||||
|               itemHeight={itemHeight} | ||||
|               virtual={virtual} | ||||
|  | @ -1181,7 +1208,6 @@ export default defineComponent({ | |||
|               onListChangeEnd={onListChangeEnd} | ||||
|               onContextmenu={onContextmenu} | ||||
|               onScroll={onScroll} | ||||
|               {...treeNodeRequiredProps.value} | ||||
|               {...domProps} | ||||
|             /> | ||||
|           </div> | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { useInjectTreeContext } from './contextTypes'; | ||||
| import { useInjectKeysState, useInjectTreeContext } from './contextTypes'; | ||||
| import Indent from './Indent'; | ||||
| import { convertNodePropsToEventData } from './utils/treeUtil'; | ||||
| import { convertNodePropsToEventData, getTreeNodeProps } from './utils/treeUtil'; | ||||
| import { | ||||
|   computed, | ||||
|   defineComponent, | ||||
|  | @ -14,8 +14,8 @@ import { treeNodeProps } from './props'; | |||
| import classNames from '../_util/classNames'; | ||||
| import { warning } from '../vc-util/warning'; | ||||
| import type { DragNodeEvent, Key } from './interface'; | ||||
| import pick from 'lodash-es/pick'; | ||||
| import pickAttrs from '../_util/pickAttrs'; | ||||
| import eagerComputed from '../_util/eagerComputed'; | ||||
| 
 | ||||
| const ICON_OPEN = 'open'; | ||||
| const ICON_CLOSE = 'close'; | ||||
|  | @ -35,8 +35,43 @@ export default defineComponent({ | |||
|         key => '`v-slot:' + key + '` ', | ||||
|       )}instead`, | ||||
|     ); | ||||
| 
 | ||||
|     const dragNodeHighlight = ref(false); | ||||
|     const context = useInjectTreeContext(); | ||||
|     const { | ||||
|       expandedKeysSet, | ||||
|       selectedKeysSet, | ||||
|       loadedKeysSet, | ||||
|       loadingKeysSet, | ||||
|       checkedKeysSet, | ||||
|       halfCheckedKeysSet, | ||||
|     } = useInjectKeysState(); | ||||
|     const { dragOverNodeKey, dropPosition, keyEntities } = context.value; | ||||
|     const mergedTreeNodeProps = computed(() => { | ||||
|       return getTreeNodeProps(props.eventKey, { | ||||
|         expandedKeysSet: expandedKeysSet.value, | ||||
|         selectedKeysSet: selectedKeysSet.value, | ||||
|         loadedKeysSet: loadedKeysSet.value, | ||||
|         loadingKeysSet: loadingKeysSet.value, | ||||
|         checkedKeysSet: checkedKeysSet.value, | ||||
|         halfCheckedKeysSet: halfCheckedKeysSet.value, | ||||
|         dragOverNodeKey, | ||||
|         dropPosition, | ||||
|         keyEntities, | ||||
|       }); | ||||
|     }); | ||||
| 
 | ||||
|     const expanded = eagerComputed(() => mergedTreeNodeProps.value.expanded); | ||||
|     const selected = eagerComputed(() => mergedTreeNodeProps.value.selected); | ||||
|     const checked = eagerComputed(() => mergedTreeNodeProps.value.checked); | ||||
|     const loaded = eagerComputed(() => mergedTreeNodeProps.value.loaded); | ||||
|     const loading = eagerComputed(() => mergedTreeNodeProps.value.loading); | ||||
|     const halfChecked = eagerComputed(() => mergedTreeNodeProps.value.halfChecked); | ||||
|     const dragOver = eagerComputed(() => mergedTreeNodeProps.value.dragOver); | ||||
|     const dragOverGapTop = eagerComputed(() => mergedTreeNodeProps.value.dragOverGapTop); | ||||
|     const dragOverGapBottom = eagerComputed(() => mergedTreeNodeProps.value.dragOverGapBottom); | ||||
|     const pos = eagerComputed(() => mergedTreeNodeProps.value.pos); | ||||
| 
 | ||||
|     const selectHandle = ref(); | ||||
| 
 | ||||
|     const hasChildren = computed(() => { | ||||
|  | @ -48,7 +83,7 @@ export default defineComponent({ | |||
|     }); | ||||
| 
 | ||||
|     const isLeaf = computed(() => { | ||||
|       const { isLeaf, loaded } = props; | ||||
|       const { isLeaf } = props; | ||||
|       const { loadData } = context.value; | ||||
| 
 | ||||
|       const has = hasChildren.value; | ||||
|  | @ -57,16 +92,14 @@ export default defineComponent({ | |||
|         return false; | ||||
|       } | ||||
| 
 | ||||
|       return isLeaf || (!loadData && !has) || (loadData && loaded && !has); | ||||
|       return isLeaf || (!loadData && !has) || (loadData && loaded.value && !has); | ||||
|     }); | ||||
|     const nodeState = computed(() => { | ||||
|       const { expanded } = props; | ||||
| 
 | ||||
|       if (isLeaf.value) { | ||||
|         return null; | ||||
|       } | ||||
| 
 | ||||
|       return expanded ? ICON_OPEN : ICON_CLOSE; | ||||
|       return expanded.value ? ICON_OPEN : ICON_CLOSE; | ||||
|     }); | ||||
| 
 | ||||
|     const isDisabled = computed(() => { | ||||
|  | @ -97,24 +130,22 @@ export default defineComponent({ | |||
|       return treeSelectable; | ||||
|     }); | ||||
|     const renderArgsData = computed(() => { | ||||
|       const { data, active, checkable, disableCheckbox, disabled, selectable } = props; | ||||
|       return { | ||||
|         ...pick(props, [ | ||||
|           'active', | ||||
|           'checkable', | ||||
|           'checked', | ||||
|           'disableCheckbox', | ||||
|           'disabled', | ||||
|           'expanded', | ||||
|           'isLeaf', | ||||
|           'loading', | ||||
|           'selectable', | ||||
|           'selected', | ||||
|           'halfChecked', | ||||
|         ]), | ||||
|         ...props.data, | ||||
|         dataRef: props.data, | ||||
|         data: props.data, | ||||
|         active, | ||||
|         checkable, | ||||
|         disableCheckbox, | ||||
|         disabled, | ||||
|         selectable, | ||||
|         ...data, | ||||
|         dataRef: data, | ||||
|         data, | ||||
|         isLeaf: isLeaf.value, | ||||
|         checked: checked.value, | ||||
|         expanded: expanded.value, | ||||
|         loading: loading.value, | ||||
|         selected: selected.value, | ||||
|         halfChecked: halfChecked.value, | ||||
|       }; | ||||
|     }); | ||||
|     const instance = getCurrentInstance(); | ||||
|  | @ -122,13 +153,16 @@ export default defineComponent({ | |||
|       const { eventKey } = props; | ||||
|       const { keyEntities } = context.value; | ||||
|       const { parent } = keyEntities[eventKey] || {}; | ||||
|       return { ...convertNodePropsToEventData(props), parent }; | ||||
|       return { | ||||
|         ...convertNodePropsToEventData(Object.assign({}, props, mergedTreeNodeProps.value)), | ||||
|         parent, | ||||
|       }; | ||||
|     }); | ||||
|     const dragNodeEvent: DragNodeEvent = reactive({ | ||||
|       eventData, | ||||
|       eventKey: computed(() => props.eventKey), | ||||
|       selectHandle, | ||||
|       pos: computed(() => props.pos), | ||||
|       pos, | ||||
|       key: instance.vnode.key as Key, | ||||
|     }); | ||||
|     expose(dragNodeEvent); | ||||
|  | @ -148,13 +182,13 @@ export default defineComponent({ | |||
|     const onCheck = (e: MouseEvent) => { | ||||
|       if (isDisabled.value) return; | ||||
| 
 | ||||
|       const { disableCheckbox, checked } = props; | ||||
|       const { disableCheckbox } = props; | ||||
|       const { onNodeCheck } = context.value; | ||||
| 
 | ||||
|       if (!isCheckable.value || disableCheckbox) return; | ||||
| 
 | ||||
|       e.preventDefault(); | ||||
|       const targetChecked = !checked; | ||||
|       const targetChecked = !checked.value; | ||||
|       onNodeCheck(e, eventData.value, targetChecked); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -244,7 +278,7 @@ export default defineComponent({ | |||
|     // Disabled item still can be switch | ||||
|     const onExpand = e => { | ||||
|       const { onNodeExpand } = context.value; | ||||
|       if (props.loading) return; | ||||
|       if (loading.value) return; | ||||
|       onNodeExpand(e, eventData.value); | ||||
|     }; | ||||
| 
 | ||||
|  | @ -279,18 +313,18 @@ export default defineComponent({ | |||
| 
 | ||||
|     // Load data to avoid default expanded tree without data | ||||
|     const syncLoadData = () => { | ||||
|       const { expanded, loading, loaded } = props; | ||||
|       //const { expanded, loading, loaded } = props; | ||||
|       const { loadData, onNodeLoad } = context.value; | ||||
| 
 | ||||
|       if (loading) { | ||||
|       if (loading.value) { | ||||
|         return; | ||||
|       } | ||||
| 
 | ||||
|       // read from state to avoid loadData at same time | ||||
|       if (loadData && expanded && !isLeaf.value) { | ||||
|       if (loadData && expanded.value && !isLeaf.value) { | ||||
|         // We needn't reload data when has children in sync logic | ||||
|         // It's only needed in node expanded | ||||
|         if (!hasChildren.value && !loaded) { | ||||
|         if (!hasChildren.value && !loaded.value) { | ||||
|           onNodeLoad(eventData.value); | ||||
|         } | ||||
|       } | ||||
|  | @ -306,7 +340,6 @@ export default defineComponent({ | |||
| 
 | ||||
|     // Switcher | ||||
|     const renderSwitcher = () => { | ||||
|       const { expanded } = props; | ||||
|       const { prefixCls } = context.value; | ||||
|       // if switcherIconDom is null, no render switcher span | ||||
|       const switcherIconDom = renderSwitcherIconDom(); | ||||
|  | @ -320,7 +353,7 @@ export default defineComponent({ | |||
| 
 | ||||
|       const switcherCls = classNames( | ||||
|         `${prefixCls}-switcher`, | ||||
|         `${prefixCls}-switcher_${expanded ? ICON_OPEN : ICON_CLOSE}`, | ||||
|         `${prefixCls}-switcher_${expanded.value ? ICON_OPEN : ICON_CLOSE}`, | ||||
|       ); | ||||
| 
 | ||||
|       return switcherIconDom !== false ? ( | ||||
|  | @ -332,7 +365,7 @@ export default defineComponent({ | |||
| 
 | ||||
|     // Checkbox | ||||
|     const renderCheckbox = () => { | ||||
|       const { checked, halfChecked, disableCheckbox } = props; | ||||
|       const { disableCheckbox } = props; | ||||
|       const { prefixCls } = context.value; | ||||
| 
 | ||||
|       const disabled = isDisabled.value; | ||||
|  | @ -344,8 +377,8 @@ export default defineComponent({ | |||
|         <span | ||||
|           class={classNames( | ||||
|             `${prefixCls}-checkbox`, | ||||
|             checked && `${prefixCls}-checkbox-checked`, | ||||
|             !checked && halfChecked && `${prefixCls}-checkbox-indeterminate`, | ||||
|             checked.value && `${prefixCls}-checkbox-checked`, | ||||
|             !checked.value && halfChecked.value && `${prefixCls}-checkbox-indeterminate`, | ||||
|             (disabled || disableCheckbox) && `${prefixCls}-checkbox-disabled`, | ||||
|           )} | ||||
|           onClick={onCheck} | ||||
|  | @ -356,7 +389,6 @@ export default defineComponent({ | |||
|     }; | ||||
| 
 | ||||
|     const renderIcon = () => { | ||||
|       const { loading } = props; | ||||
|       const { prefixCls } = context.value; | ||||
| 
 | ||||
|       return ( | ||||
|  | @ -364,7 +396,7 @@ export default defineComponent({ | |||
|           class={classNames( | ||||
|             `${prefixCls}-iconEle`, | ||||
|             `${prefixCls}-icon__${nodeState.value || 'docu'}`, | ||||
|             loading && `${prefixCls}-icon_loading`, | ||||
|             loading.value && `${prefixCls}-icon_loading`, | ||||
|           )} | ||||
|         /> | ||||
|       ); | ||||
|  | @ -396,9 +428,9 @@ export default defineComponent({ | |||
|         // title = slots.title || | ||||
|         //   context.value.slots?.[props.data?.slots?.title] || | ||||
|         //   context.value.slots?.title, | ||||
|         selected, | ||||
|         // selected, | ||||
|         icon = slots.icon, | ||||
|         loading, | ||||
|         // loading, | ||||
|         data, | ||||
|       } = props; | ||||
|       const title = | ||||
|  | @ -430,7 +462,7 @@ export default defineComponent({ | |||
|         ) : ( | ||||
|           renderIcon() | ||||
|         ); | ||||
|       } else if (loadData && loading) { | ||||
|       } else if (loadData && loading.value) { | ||||
|         $icon = renderIcon(); | ||||
|       } | ||||
| 
 | ||||
|  | @ -454,7 +486,9 @@ export default defineComponent({ | |||
|           class={classNames( | ||||
|             `${wrapClass}`, | ||||
|             `${wrapClass}-${nodeState.value || 'normal'}`, | ||||
|             !disabled && (selected || dragNodeHighlight.value) && `${prefixCls}-node-selected`, | ||||
|             !disabled && | ||||
|               (selected.value || dragNodeHighlight.value) && | ||||
|               `${prefixCls}-node-selected`, | ||||
|           )} | ||||
|           onMouseenter={onMouseEnter} | ||||
|           onMouseleave={onMouseLeave} | ||||
|  | @ -471,17 +505,9 @@ export default defineComponent({ | |||
|     return () => { | ||||
|       const { | ||||
|         eventKey, | ||||
|         dragOver, | ||||
|         dragOverGapTop, | ||||
|         dragOverGapBottom, | ||||
|         isLeaf, | ||||
|         isStart, | ||||
|         isEnd, | ||||
|         expanded, | ||||
|         selected, | ||||
|         checked, | ||||
|         halfChecked, | ||||
|         loading, | ||||
|         domRef, | ||||
|         active, | ||||
|         data, | ||||
|  | @ -507,17 +533,17 @@ export default defineComponent({ | |||
| 
 | ||||
|       const dragging = draggingNodeKey === eventKey; | ||||
|       const ariaSelected = selectable !== undefined ? { 'aria-selected': !!selectable } : undefined; | ||||
| 
 | ||||
|       // console.log(1); | ||||
|       return ( | ||||
|         <div | ||||
|           ref={domRef} | ||||
|           class={classNames(attrs.class, `${prefixCls}-treenode`, { | ||||
|             [`${prefixCls}-treenode-disabled`]: disabled, | ||||
|             [`${prefixCls}-treenode-switcher-${expanded ? 'open' : 'close'}`]: !isLeaf, | ||||
|             [`${prefixCls}-treenode-checkbox-checked`]: checked, | ||||
|             [`${prefixCls}-treenode-checkbox-indeterminate`]: halfChecked, | ||||
|             [`${prefixCls}-treenode-selected`]: selected, | ||||
|             [`${prefixCls}-treenode-loading`]: loading, | ||||
|             [`${prefixCls}-treenode-switcher-${expanded.value ? 'open' : 'close'}`]: !isLeaf, | ||||
|             [`${prefixCls}-treenode-checkbox-checked`]: checked.value, | ||||
|             [`${prefixCls}-treenode-checkbox-indeterminate`]: halfChecked.value, | ||||
|             [`${prefixCls}-treenode-selected`]: selected.value, | ||||
|             [`${prefixCls}-treenode-loading`]: loading.value, | ||||
|             [`${prefixCls}-treenode-active`]: active, | ||||
|             [`${prefixCls}-treenode-leaf-last`]: isEndNode, | ||||
|             [`${prefixCls}-treenode-draggable`]: draggableWithoutDisabled, | ||||
|  | @ -525,9 +551,9 @@ export default defineComponent({ | |||
|             dragging, | ||||
|             'drop-target': dropTargetKey === eventKey, | ||||
|             'drop-container': dropContainerKey === eventKey, | ||||
|             'drag-over': !disabled && dragOver, | ||||
|             'drag-over-gap-top': !disabled && dragOverGapTop, | ||||
|             'drag-over-gap-bottom': !disabled && dragOverGapBottom, | ||||
|             'drag-over': !disabled && dragOver.value, | ||||
|             'drag-over-gap-top': !disabled && dragOverGapTop.value, | ||||
|             'drag-over-gap-bottom': !disabled && dragOverGapBottom.value, | ||||
|             'filter-node': filterTreeNode && filterTreeNode(eventData.value), | ||||
|           })} | ||||
|           style={attrs.style} | ||||
|  |  | |||
|  | @ -3,8 +3,8 @@ | |||
|  * When util.js imports the TreeNode for tree generate will cause treeContextTypes be empty. | ||||
|  */ | ||||
| 
 | ||||
| import type { ComputedRef, InjectionKey, PropType } from 'vue'; | ||||
| import { inject, computed, defineComponent, provide } from 'vue'; | ||||
| import type { ComputedRef, InjectionKey, PropType, ShallowRef } from 'vue'; | ||||
| import { shallowRef, inject, computed, defineComponent, provide } from 'vue'; | ||||
| import type { VueNode } from '../_util/type'; | ||||
| import type { | ||||
|   IconType, | ||||
|  | @ -13,6 +13,7 @@ import type { | |||
|   EventDataNode, | ||||
|   DragNodeEvent, | ||||
|   Direction, | ||||
|   FlattenNode, | ||||
| } from './interface'; | ||||
| 
 | ||||
| import type { DraggableConfig } from './Tree'; | ||||
|  | @ -60,6 +61,7 @@ export interface TreeContextProps { | |||
|     direction: Direction; | ||||
|   }) => VueNode; | ||||
|   dragOverNodeKey: Key | null; | ||||
|   dragging: boolean; | ||||
|   direction: Direction; | ||||
| 
 | ||||
|   loadData: (treeNode: EventDataNode) => Promise<void>; | ||||
|  | @ -108,3 +110,40 @@ export const useInjectTreeContext = () => { | |||
|     computed(() => ({} as TreeContextProps)), | ||||
|   ); | ||||
| }; | ||||
| type KeysStateKeyType = { | ||||
|   expandedKeysSet: ComputedRef<Set<Key>>; | ||||
|   selectedKeysSet: ComputedRef<Set<Key>>; | ||||
|   loadedKeysSet: ComputedRef<Set<Key>>; | ||||
|   loadingKeysSet: ComputedRef<Set<Key>>; | ||||
|   checkedKeysSet: ComputedRef<Set<Key>>; | ||||
|   halfCheckedKeysSet: ComputedRef<Set<Key>>; | ||||
|   expandedKeys: ShallowRef<Key[]>; | ||||
|   selectedKeys: ShallowRef<Key[]>; | ||||
|   loadedKeys: ShallowRef<Key[]>; | ||||
|   loadingKeys: ShallowRef<Key[]>; | ||||
|   checkedKeys: ShallowRef<Key[]>; | ||||
|   halfCheckedKeys: ShallowRef<Key[]>; | ||||
|   flattenNodes: ShallowRef<FlattenNode[]>; | ||||
| }; | ||||
| const KeysStateKey: InjectionKey<KeysStateKeyType> = Symbol('KeysStateKey'); | ||||
| export const useProvideKeysState = (state: KeysStateKeyType) => { | ||||
|   provide(KeysStateKey, state); | ||||
| }; | ||||
| 
 | ||||
| export const useInjectKeysState = () => { | ||||
|   return inject(KeysStateKey, { | ||||
|     expandedKeys: shallowRef<Key[]>([]), | ||||
|     selectedKeys: shallowRef<Key[]>([]), | ||||
|     loadedKeys: shallowRef<Key[]>([]), | ||||
|     loadingKeys: shallowRef<Key[]>([]), | ||||
|     checkedKeys: shallowRef<Key[]>([]), | ||||
|     halfCheckedKeys: shallowRef<Key[]>([]), | ||||
|     expandedKeysSet: computed<Set<Key>>(() => new Set()), | ||||
|     selectedKeysSet: computed<Set<Key>>(() => new Set()), | ||||
|     loadedKeysSet: computed<Set<Key>>(() => new Set()), | ||||
|     loadingKeysSet: computed<Set<Key>>(() => new Set()), | ||||
|     checkedKeysSet: computed<Set<Key>>(() => new Set()), | ||||
|     halfCheckedKeysSet: computed<Set<Key>>(() => new Set()), | ||||
|     flattenNodes: shallowRef<FlattenNode[]>([]), | ||||
|   }); | ||||
| }; | ||||
|  |  | |||
|  | @ -7,15 +7,7 @@ import type { | |||
|   NodeMouseEventHandler, | ||||
|   NodeMouseEventParams, | ||||
| } from './contextTypes'; | ||||
| import type { | ||||
|   DataNode, | ||||
|   Key, | ||||
|   FlattenNode, | ||||
|   EventDataNode, | ||||
|   Direction, | ||||
|   FieldNames, | ||||
|   DataEntity, | ||||
| } from './interface'; | ||||
| import type { DataNode, Key, FlattenNode, EventDataNode, Direction, FieldNames } from './interface'; | ||||
| 
 | ||||
| export interface CheckInfo { | ||||
|   event: 'check'; | ||||
|  | @ -32,18 +24,18 @@ export const treeNodeProps = { | |||
|   prefixCls: String, | ||||
| 
 | ||||
|   // By parent
 | ||||
|   expanded: { type: Boolean, default: undefined }, | ||||
|   selected: { type: Boolean, default: undefined }, | ||||
|   checked: { type: Boolean, default: undefined }, | ||||
|   loaded: { type: Boolean, default: undefined }, | ||||
|   loading: { type: Boolean, default: undefined }, | ||||
|   halfChecked: { type: Boolean, default: undefined }, | ||||
|   title: PropTypes.any, | ||||
|   dragOver: { type: Boolean, default: undefined }, | ||||
|   dragOverGapTop: { type: Boolean, default: undefined }, | ||||
|   dragOverGapBottom: { type: Boolean, default: undefined }, | ||||
|   pos: String, | ||||
|   // expanded: { type: Boolean, default: undefined },
 | ||||
|   // selected: { type: Boolean, default: undefined },
 | ||||
|   // checked: { type: Boolean, default: undefined },
 | ||||
|   // loaded: { type: Boolean, default: undefined },
 | ||||
|   // loading: { type: Boolean, default: undefined },
 | ||||
|   // halfChecked: { type: Boolean, default: undefined },
 | ||||
|   // dragOver: { type: Boolean, default: undefined },
 | ||||
|   // dragOverGapTop: { type: Boolean, default: undefined },
 | ||||
|   // dragOverGapBottom: { type: Boolean, default: undefined },
 | ||||
|   // pos: String,
 | ||||
| 
 | ||||
|   title: PropTypes.any, | ||||
|   /** New added in Tree for easy data access */ | ||||
|   data: { type: Object as PropType<DataNode>, default: undefined as DataNode }, | ||||
|   parent: { type: Object as PropType<DataNode>, default: undefined as DataNode }, | ||||
|  | @ -68,7 +60,7 @@ export type TreeNodeProps = Partial<ExtractPropTypes<typeof treeNodeProps>>; | |||
| 
 | ||||
| export const nodeListProps = { | ||||
|   prefixCls: { type: String as PropType<string> }, | ||||
|   data: { type: Array as PropType<FlattenNode[]> }, | ||||
|   // data: { type: Array as PropType<FlattenNode[]> },
 | ||||
|   motion: { type: Object as PropType<any> }, | ||||
|   focusable: { type: Boolean as PropType<boolean> }, | ||||
|   activeItem: { type: Object as PropType<FlattenNode> }, | ||||
|  | @ -78,17 +70,17 @@ export const nodeListProps = { | |||
|   selectable: { type: Boolean as PropType<boolean> }, | ||||
|   disabled: { type: Boolean as PropType<boolean> }, | ||||
| 
 | ||||
|   expandedKeys: { type: Array as PropType<Key[]> }, | ||||
|   selectedKeys: { type: Array as PropType<Key[]> }, | ||||
|   checkedKeys: { type: Array as PropType<Key[]> }, | ||||
|   loadedKeys: { type: Array as PropType<Key[]> }, | ||||
|   loadingKeys: { type: Array as PropType<Key[]> }, | ||||
|   halfCheckedKeys: { type: Array as PropType<Key[]> }, | ||||
|   keyEntities: { type: Object as PropType<Record<Key, DataEntity<DataNode>>> }, | ||||
|   // expandedKeys: { type: Array as PropType<Key[]> },
 | ||||
|   // selectedKeys: { type: Array as PropType<Key[]> },
 | ||||
|   // checkedKeys: { type: Array as PropType<Key[]> },
 | ||||
|   // loadedKeys: { type: Array as PropType<Key[]> },
 | ||||
|   // loadingKeys: { type: Array as PropType<Key[]> },
 | ||||
|   // halfCheckedKeys: { type: Array as PropType<Key[]> },
 | ||||
|   // keyEntities: { type: Object as PropType<Record<Key, DataEntity<DataNode>>> },
 | ||||
| 
 | ||||
|   dragging: { type: Boolean as PropType<boolean> }, | ||||
|   dragOverNodeKey: { type: [String, Number] as PropType<Key> }, | ||||
|   dropPosition: { type: Number as PropType<number> }, | ||||
|   // dragging: { type: Boolean as PropType<boolean> },
 | ||||
|   // dragOverNodeKey: { type: [String, Number] as PropType<Key> },
 | ||||
|   // dropPosition: { type: Number as PropType<number> },
 | ||||
| 
 | ||||
|   // Virtual list
 | ||||
|   height: { type: Number as PropType<number> }, | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ export function calcDropPosition<TreeDataType extends BasicDataNode = DataNode>( | |||
|   allowDrop: AllowDrop<TreeDataType>, | ||||
|   flattenedNodes: FlattenNode[], | ||||
|   keyEntities: Record<Key, DataEntity<TreeDataType>>, | ||||
|   expandKeys: Key[], | ||||
|   expandKeysSet: Set<Key>, | ||||
|   direction: Direction, | ||||
| ): { | ||||
|   dropPosition: -1 | 0 | 1; | ||||
|  | @ -138,7 +138,7 @@ export function calcDropPosition<TreeDataType extends BasicDataNode = DataNode>( | |||
|   let dropLevelOffset = 0; | ||||
| 
 | ||||
|   // Only allow cross level drop when dragging on a non-expanded node | ||||
|   if (!expandKeys.includes(initialAbstractDropNodeKey)) { | ||||
|   if (!expandKeysSet.has(initialAbstractDropNodeKey)) { | ||||
|     for (let i = 0; i < rawDropLevelOffset; i += 1) { | ||||
|       if (isLastChild(abstractDropNodeEntity)) { | ||||
|         abstractDropNodeEntity = abstractDropNodeEntity.parent; | ||||
|  | @ -164,10 +164,7 @@ export function calcDropPosition<TreeDataType extends BasicDataNode = DataNode>( | |||
|   ) { | ||||
|     // first half of first node in first level | ||||
|     dropPosition = -1; | ||||
|   } else if ( | ||||
|     (abstractDragOverEntity.children || []).length && | ||||
|     expandKeys.includes(dragOverNodeKey) | ||||
|   ) { | ||||
|   } else if ((abstractDragOverEntity.children || []).length && expandKeysSet.has(dragOverNodeKey)) { | ||||
|     // drop on expanded node | ||||
|     // only allow drop inside | ||||
|     if ( | ||||
|  |  | |||
|  | @ -361,12 +361,12 @@ export function convertDataToEntities( | |||
| } | ||||
| 
 | ||||
| export interface TreeNodeRequiredProps<TreeDataType extends BasicDataNode = DataNode> { | ||||
|   expandedKeys: Key[]; | ||||
|   selectedKeys: Key[]; | ||||
|   loadedKeys: Key[]; | ||||
|   loadingKeys: Key[]; | ||||
|   checkedKeys: Key[]; | ||||
|   halfCheckedKeys: Key[]; | ||||
|   expandedKeysSet: Set<Key>; | ||||
|   selectedKeysSet: Set<Key>; | ||||
|   loadedKeysSet: Set<Key>; | ||||
|   loadingKeysSet: Set<Key>; | ||||
|   checkedKeysSet: Set<Key>; | ||||
|   halfCheckedKeysSet: Set<Key>; | ||||
|   dragOverNodeKey: Key; | ||||
|   dropPosition: number; | ||||
|   keyEntities: Record<Key, DataEntity<TreeDataType>>; | ||||
|  | @ -378,12 +378,12 @@ export interface TreeNodeRequiredProps<TreeDataType extends BasicDataNode = Data | |||
| export function getTreeNodeProps<TreeDataType extends BasicDataNode = DataNode>( | ||||
|   key: Key, | ||||
|   { | ||||
|     expandedKeys, | ||||
|     selectedKeys, | ||||
|     loadedKeys, | ||||
|     loadingKeys, | ||||
|     checkedKeys, | ||||
|     halfCheckedKeys, | ||||
|     expandedKeysSet, | ||||
|     selectedKeysSet, | ||||
|     loadedKeysSet, | ||||
|     loadingKeysSet, | ||||
|     checkedKeysSet, | ||||
|     halfCheckedKeysSet, | ||||
|     dragOverNodeKey, | ||||
|     dropPosition, | ||||
|     keyEntities, | ||||
|  | @ -393,12 +393,12 @@ export function getTreeNodeProps<TreeDataType extends BasicDataNode = DataNode>( | |||
| 
 | ||||
|   const treeNodeProps = { | ||||
|     eventKey: key, | ||||
|     expanded: expandedKeys.indexOf(key) !== -1, | ||||
|     selected: selectedKeys.indexOf(key) !== -1, | ||||
|     loaded: loadedKeys.indexOf(key) !== -1, | ||||
|     loading: loadingKeys.indexOf(key) !== -1, | ||||
|     checked: checkedKeys.indexOf(key) !== -1, | ||||
|     halfChecked: halfCheckedKeys.indexOf(key) !== -1, | ||||
|     expanded: expandedKeysSet.has(key), | ||||
|     selected: selectedKeysSet.has(key), | ||||
|     loaded: loadedKeysSet.has(key), | ||||
|     loading: loadingKeysSet.has(key), | ||||
|     checked: checkedKeysSet.has(key), | ||||
|     halfChecked: halfCheckedKeysSet.has(key), | ||||
|     pos: String(entity ? entity.pos : ''), | ||||
|     parent: entity.parent, | ||||
|     // [Legacy] Drag props
 | ||||
|  | @ -412,7 +412,9 @@ export function getTreeNodeProps<TreeDataType extends BasicDataNode = DataNode>( | |||
|   return treeNodeProps; | ||||
| } | ||||
| 
 | ||||
| export function convertNodePropsToEventData(props: TreeNodeProps): EventDataNode { | ||||
| export function convertNodePropsToEventData( | ||||
|   props: TreeNodeProps & ReturnType<typeof getTreeNodeProps>, | ||||
| ): EventDataNode { | ||||
|   const { | ||||
|     data, | ||||
|     expanded, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 tangjinzhou
						tangjinzhou