vexip-ui
Version:
A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good
1 lines • 70.3 kB
Source Map (JSON)
{"version":3,"file":"tree.vue2.mjs","sources":["../../../components/tree/tree.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { CollapseTransition } from '@/components/collapse-transition'\nimport { Renderer } from '@/components/renderer'\nimport { VirtualList } from '@/components/virtual-list'\n\nimport {\n computed,\n nextTick,\n onMounted,\n provide,\n reactive,\n ref,\n toRef,\n watch,\n watchEffect,\n} from 'vue'\n\nimport TreeNode from './tree-node.vue'\nimport { createIconProp, emitEvent, useLocale, useNameHelper, useProps } from '@vexip-ui/config'\nimport { useMounted, useSetTimeout } from '@vexip-ui/hooks'\nimport {\n debounce,\n filterTree,\n flatTree,\n getGlobalCount,\n getLast,\n isNull,\n isPromise,\n mapTree,\n queryAll,\n removeArrayItem,\n transformTree,\n walkTree,\n} from '@vexip-ui/utils'\nimport { treeProps } from './props'\nimport { useCascadedChecked } from './hooks'\nimport { DropType, TREE_NODE_STATE, TREE_STATE, defaultKeyConfig } from './symbol'\n\nimport type { VirtualListExposed } from '@/components/virtual-list'\nimport type {\n Data,\n FilterFn,\n Key,\n TreeCollapseProps,\n TreeNodeInstance,\n TreeNodeProps,\n TreeNodeState,\n TreeSlots,\n} from './symbol'\n\ndefineOptions({ name: 'Tree' })\n\nconst _props = defineProps(treeProps)\nconst props = useProps('tree', _props, {\n arrow: {\n default: 'auto',\n validator: value => typeof value === 'boolean' || value === 'auto',\n },\n data: {\n default: () => [],\n static: true,\n },\n noBuildTree: false,\n emptyText: null,\n disabled: false,\n readonly: false,\n checkbox: false,\n suffixCheckbox: false,\n renderer: {\n default: null,\n isFunc: true,\n },\n prefixRenderer: {\n default: null,\n isFunc: true,\n },\n suffixRenderer: {\n default: null,\n isFunc: true,\n },\n multiple: false,\n indent: '16px',\n accordion: false,\n draggable: false,\n appear: false,\n floorSelect: false,\n onAsyncLoad: {\n default: null,\n isFunc: true,\n },\n cacheNode: false,\n rootId: null,\n keyConfig: () => ({}),\n noCascaded: false,\n filter: '',\n ignoreCase: false,\n nodeProps: null,\n linkLine: false,\n postCreate: {\n default: null,\n isFunc: true,\n },\n virtual: false,\n nodeMinHeight: {\n default: 26,\n validator: value => value > 0,\n },\n useYBar: false,\n noTransition: false,\n arrowIcon: createIconProp(),\n blockEffect: false,\n filterLeaf: false,\n keepSelected: false,\n slots: () => ({}),\n})\n\nconst slots = defineSlots<TreeSlots>()\n\nconst nh = useNameHelper('tree')\nconst locale = useLocale('tree', toRef(props, 'locale'))\n\nconst nodeMap = new Map<Key, TreeNodeProps>()\nconst nodeDataMap = new Map<Data, TreeNodeProps>()\nconst treeNodes = ref<TreeNodeProps[]>([])\nconst flattedNodes = ref<TreeNodeProps[]>([])\nconst dragging = ref(false)\nconst indicatorShow = ref(false)\nconst keyConfig = reactive({ ...defaultKeyConfig })\nconst nodeStates = reactive(new Map<Key, TreeNodeState>())\nconst expanding = ref(false)\nconst expandingNodes = ref<TreeNodeProps[]>([])\nconst expandedNodeIds = ref(new Set<Key>())\n\nconst { timer } = useSetTimeout()\nconst { isMounted } = useMounted()\n\nconst virtualList = ref<VirtualListExposed>()\nconst trap = ref<HTMLElement>()\nconst indicator = ref<HTMLElement>()\n\nconst wrapper = computed(() => virtualList.value?.wrapper)\n\nlet visibleNodeEls: HTMLElement[] = []\n\nconst defaultNodeProperties = {\n visible: true,\n selected: false,\n expanded: false,\n disabled: false,\n checked: false,\n loading: false,\n loaded: false,\n loadFail: false,\n readonly: false,\n arrow: 'auto' as boolean | 'auto',\n // will follow checkbox prop of tree when not set (be null)\n checkbox: null! as boolean,\n selectDisabled: false,\n expandDisabled: false,\n checkDisabled: false,\n isLeaf: 'auto' as boolean | 'auto',\n}\n\nconst boundAsyncLoad = computed(() => typeof props.onAsyncLoad === 'function')\nconst linkLine = computed(() => {\n return props.linkLine === true ? 'dashed' : props.linkLine === 'none' ? false : props.linkLine\n})\nconst style = computed(() => {\n return {\n [nh.cv('indent-width')]: typeof props.indent === 'number' ? `${props.indent}px` : props.indent,\n [nh.cv('link-line-type')]: linkLine.value || undefined,\n }\n})\nconst visibleNodes = computed(() => flatNodes(treeNodes.value))\nconst renderedNodes = computed(() => {\n return expanding.value ? expandingNodes.value : visibleNodes.value\n})\nconst toNodeProps = computed(() => {\n return typeof props.nodeProps === 'function' ? props.nodeProps : () => props.nodeProps\n})\n\nfunction createDefaultFilter(value: string) {\n const pattern = props.ignoreCase ? String(value).toLocaleLowerCase() : value\n const defaultFilter: FilterFn = data => {\n const label = data[keyConfig.label]\n\n return props.ignoreCase\n ? String(label).toLocaleLowerCase().includes(pattern)\n : String(label).includes(pattern)\n }\n\n return defaultFilter\n}\n\nconst updateVisibleNodeEls = debounce(() => {\n if (wrapper.value) {\n visibleNodeEls = queryAll(`.${nh.be('node')}`, wrapper.value)\n }\n}, 300)\n\nlet disableExpand = false\n\nfunction disableExpandTick() {\n disableExpand = true\n\n nextTick(() => {\n disableExpand = false\n })\n}\nwatchEffect(() => {\n const nodes = flattedNodes.value\n\n disableExpandTick()\n\n if (!props.filter) {\n for (let i = 0, len = nodes.length; i < len; ++i) {\n const node = nodes[i]\n\n node.matched = true\n node.childMatched = false\n node.upperMatched = false\n }\n } else {\n const filter =\n typeof props.filter === 'function' ? props.filter : createDefaultFilter(props.filter)\n const leafOnly = props.filterLeaf\n\n for (let i = 0, len = nodes.length; i < len; ++i) {\n const node = nodes[i]\n\n if (leafOnly && !isLeafNode(node)) {\n node.matched = false\n node.childMatched = false\n node.upperMatched = false\n\n continue\n }\n\n const parent = node.parent ? nodeMap.get(node.parent) : undefined\n\n node.matched = filter(node.data, node)\n node.childMatched = false\n node.upperMatched = !!parent && (parent.matched || parent.upperMatched)\n\n if (node.matched) {\n let upper = parent\n\n while (upper && !upper.childMatched) {\n upper.childMatched = true\n upper.expanded = true\n upper = upper.parent ? nodeMap.get(upper.parent) : undefined\n }\n }\n }\n }\n\n resetExpanded()\n})\nwatchEffect(() => Object.assign(keyConfig, props.keyConfig))\nwatchEffect(() => {\n const oldIds = expandedNodeIds.value\n const ids = new Set<Key>()\n\n let changed = false\n\n for (const node of flattedNodes.value) {\n if (node.expanded) {\n ids.add(node.id)\n\n if (!changed && !oldIds.has(node.id)) {\n changed = true\n }\n }\n }\n\n if (changed || ids.size !== oldIds.size) {\n expandedNodeIds.value = ids\n }\n})\nwatch(\n [\n () => props.data,\n () => props.data.length,\n () => keyConfig.id,\n () => keyConfig.children,\n () => keyConfig.parent,\n () => props.rootId,\n ],\n parseAndTransformData,\n { immediate: true },\n)\nwatch(\n [treeNodes, () => props.rootId],\n () => {\n flattedNodes.value = flatTree(treeNodes.value, {\n keyField: 'id',\n parentField: 'parent',\n childField: 'children',\n rootId: props.rootId,\n injectId: false,\n depthFirst: true,\n })\n },\n { immediate: true },\n)\nwatch(expandedNodeIds, (value, prev) => {\n if (props.noTransition) {\n updateVisibleNodeEls()\n }\n\n if (props.noTransition || disableExpand || !wrapper.value) return\n\n let addedId: Key | undefined\n let removedId: Key | undefined\n\n for (const id of value) {\n if (!prev.has(id)) {\n if (addedId != null) return\n\n addedId = id\n }\n }\n\n for (const id of prev) {\n if (!value.has(id)) {\n if (removedId != null) return\n\n removedId = id\n }\n }\n\n if (addedId == null && removedId == null) return\n if (\n (addedId && !nodeMap.get(addedId)?.children?.length) ||\n (removedId && !nodeMap.get(removedId)?.children?.length)\n )\n return\n\n clearTimeout(timer.expand)\n\n transferring.value = false\n expanding.value = true\n\n let baseExpandedIds: Set<Key> | undefined\n\n if (addedId != null) {\n baseExpandedIds = prev\n }\n\n if (removedId != null) {\n if (!baseExpandedIds) {\n baseExpandedIds = value\n } else {\n baseExpandedIds = new Set(baseExpandedIds)\n baseExpandedIds.delete(removedId)\n }\n }\n\n const baseNodes = flatNodes(treeNodes.value, baseExpandedIds!)\n\n const virtual = props.virtual\n const viewHeight = wrapper.value.offsetHeight\n const nodeHeight = props.nodeMinHeight || 1\n const viewCount = Math.ceil(viewHeight / nodeHeight) + 1\n\n const loop = [\n addedId != null && { id: addedId, type: 'expand' },\n removedId != null && { id: removedId, type: 'reduce' },\n ]\n\n for (const meta of loop) {\n if (!meta) continue\n\n const { id, type } = meta\n const index = baseNodes.findIndex(node => node.id === id)\n\n if (~index) {\n const children = baseNodes[index].children\n\n if (children?.length) {\n const addedNodes = flatNodes(children, value)\n\n baseNodes.splice(index + 1, 0, {\n id: Symbol('TreeNodePlaceholder'),\n collapse: true,\n type,\n height: virtual ? addedNodes.length * nodeHeight : undefined,\n nodes: virtual ? addedNodes.slice(0, viewCount) : addedNodes,\n } as any)\n }\n }\n }\n\n expandingNodes.value = baseNodes\n})\n\nprovide(\n TREE_STATE,\n reactive({\n arrow: toRef(props, 'arrow'),\n checkbox: toRef(props, 'checkbox'),\n suffixCheckbox: toRef(props, 'suffixCheckbox'),\n noCascaded: toRef(props, 'noCascaded'),\n linkLine,\n virtual: toRef(props, 'virtual'),\n labelKey: toRef(keyConfig, 'label'),\n draggable: toRef(props, 'draggable'),\n floorSelect: toRef(props, 'floorSelect'),\n renderer: toRef(props, 'renderer'),\n prefixRenderer: toRef(props, 'prefixRenderer'),\n suffixRenderer: toRef(props, 'suffixRenderer'),\n arrowIcon: toRef(props, 'arrowIcon'),\n blockEffect: toRef(props, 'blockEffect'),\n dragging,\n boundAsyncLoad,\n nodeStates,\n expanding,\n keepSelected: toRef(props, 'keepSelected'),\n multiple: toRef(props, 'multiple'),\n getParentNode,\n updateVisibleNodeEls,\n computeCheckedState,\n handleNodeClick,\n handleNodeSelect,\n handleNodeCancel,\n handleNodeExpand,\n handleNodeReduce,\n handleNodeContextmenu,\n handleAsyncLoad,\n handleNodeDragStart,\n handleNodeDragOver,\n handleNodeDrop,\n handleNodeDragEnd,\n handleHittingChange,\n handleNodeHitting,\n handleLabelClick,\n }),\n)\nprovide(\n TREE_NODE_STATE,\n reactive({\n depth: -1,\n disabled: toRef(props, 'disabled'),\n readonly: toRef(props, 'readonly'),\n }),\n)\n\ndefineExpose({\n treeNodes,\n flattedNodes,\n dragging,\n expanding,\n\n virtualList,\n trap,\n indicator,\n\n refreshScroll,\n isLeafNode,\n parseAndTransformData,\n forceUpdateData,\n syncNodeStateIntoData,\n getCheckedNodes,\n getCheckedNodeData,\n getSelectedNodes,\n getSelectedNodeData,\n getExpandedNodes,\n getDisabledNodes,\n getParentNode,\n getNodeChildren,\n getSiblingNodes,\n getPrevSiblingNode,\n getNextSiblingNode,\n getNodeByData,\n expandNodeByData,\n selectNodeByData,\n checkNodeByData,\n toggleNodeLoadingByData,\n toggleAllExpanded,\n getTreeData,\n getFlattedData,\n updateVisibleNodeEls,\n})\n\nonMounted(updateVisibleNodeEls)\n\nconst { updateCheckedUpward, updateCheckedDown } = useCascadedChecked({\n getNode: key => nodeMap.get(key),\n disableNode: node => node.disabled,\n})\n\nfunction getIndexId() {\n return `__vxp-tree-key-${getGlobalCount()}`\n}\n\nfunction isLeafNode(node: TreeNodeProps) {\n const isLeaf = node.isLeaf\n\n let leafSign: boolean | 'auto' = 'auto'\n let asyncLoad = false\n\n if (isNull(isLeaf) || isLeaf === 'auto') {\n leafSign = 'auto'\n asyncLoad = boundAsyncLoad.value\n } else {\n leafSign = isLeaf\n }\n\n return leafSign === 'auto' ? !(node.children?.length || (asyncLoad && !node.loaded)) : !!leafSign\n}\n\nfunction flatNodes(nodes: TreeNodeProps[], expandedIds?: Set<Key>) {\n const rootNodes = new Set(nodes)\n\n return flatTree(nodes, {\n keyField: 'id',\n parentField: 'parent',\n childField: 'children',\n injectId: false,\n depthFirst: true,\n cascaded: true,\n filter: node => {\n if (rootNodes.has(node)) {\n return node.matched || node.childMatched || node.upperMatched\n }\n\n const parentNode = getParentNode(node)\n\n return (\n node.visible &&\n (node.matched || node.childMatched || node.upperMatched) &&\n (!parentNode || (expandedIds ? expandedIds.has(parentNode.id) : parentNode.expanded))\n )\n },\n })\n}\n\nfunction isCollapse(node: any): node is TreeCollapseProps {\n return node.collapse\n}\n\nfunction refreshNodesDepth() {\n walkTree(treeNodes.value, (node, depth) => {\n node.depth = depth\n node.lineIndexes = [0]\n\n if (node.parent && nodeMap.has(node.parent)) {\n const parent = nodeMap.get(node.parent)!\n\n node.last = getLast(parent.children) === node\n node.upstreamLast = [parent.last, ...parent.upstreamLast]\n } else {\n node.last = getLast(treeNodes.value) === node\n node.upstreamLast = []\n }\n\n for (let i = 1; i < depth; ++i) {\n if (!node.upstreamLast[i - 1]) {\n node.lineIndexes.push(i)\n }\n }\n })\n}\n\nfunction buildTreeNodes(nodes: TreeNodeProps[]) {\n treeNodes.value = transformTree(nodes, {\n keyField: 'id',\n parentField: 'parent',\n childField: 'children',\n rootId: props.rootId,\n })\n\n refreshNodesDepth()\n}\n\nfunction parseAndTransformData() {\n const idKey = keyConfig.id\n const oldDataMap = new Map<Data, TreeNodeProps>()\n const oldIdMap = new Map<any, TreeNodeProps>()\n\n for (const node of nodeMap.values()) {\n oldDataMap.set(node.data, node)\n oldIdMap.set(node.data[idKey], node)\n }\n\n nodeMap.clear()\n nodeDataMap.clear()\n\n const nodes: TreeNodeProps[] = []\n\n if (props.noBuildTree) {\n walkTree(\n props.data,\n (item, _, parent) => {\n const oldNode = oldDataMap.get(item)\n const id = oldNode?.id ?? getIndexId()\n const node = props.cacheNode\n ? (oldNode ?? createNodeItem(item))\n : createNodeItem(item, oldNode)\n\n node.id = id\n node.parent = parent ? nodeDataMap.get(parent)?.id : undefined\n\n nodeMap.set(node.id, node)\n nodes.push(node)\n nodeDataMap.set(item, node)\n },\n { childField: keyConfig.children, depthFirst: true },\n )\n } else {\n const data = props.data\n\n for (let i = 0, len = data.length; i < len; ++i) {\n const item = data[i]\n const oldNode = oldDataMap.get(item) ?? oldIdMap.get(item[idKey])\n const node = props.cacheNode\n ? (oldNode ?? createNodeItem(item))\n : createNodeItem(item, oldNode)\n\n nodeMap.set(node.id, node)\n nodes.push(node)\n nodeDataMap.set(item, node)\n }\n }\n\n buildTreeNodes(nodes)\n\n if (!props.noCascaded) {\n const checkedNodes = flattedNodes.value.filter(item => item.checked)\n\n for (let i = 0, len = checkedNodes.length; i < len; ++i) {\n const item = checkedNodes[i]\n const parentKey = item.parent\n\n updateCheckedDown(item.id)\n\n if (parentKey && nodeMap.has(parentKey)) {\n const parent = nodeMap.get(parentKey)!\n\n if (!parent.checked) {\n updateCheckedUpward(item.id)\n }\n }\n }\n }\n\n resetExpanded()\n}\n\nfunction forceUpdateData() {\n const nodes: TreeNodeProps[] = []\n\n const {\n id: idKey,\n visible: visibleKey,\n selected: selectedKey,\n expanded: expandedKey,\n disabled: disabledKey,\n checked: checkedKey,\n loading: loadingKey,\n loaded: loadedKey,\n loadFail: loadFailKey,\n readonly: readonlyKey,\n arrow: arrowKey,\n checkbox: checkboxKey,\n selectDisabled: selectDisabledKey,\n expandDisabled: expandDisabledKey,\n checkDisabled: checkDisabledKey,\n isLeaf: isLeafKey,\n } = keyConfig\n\n const refresh = (node: TreeNodeProps, item: Data) => {\n const {\n [visibleKey]: visible = node.visible,\n [selectedKey]: selected = node.selected,\n [expandedKey]: expanded = node.expanded,\n [disabledKey]: disabled = node.disabled,\n [checkedKey]: checked = node.checked,\n [loadingKey]: loading = node.loading,\n [loadedKey]: loaded = node.loaded,\n [loadFailKey]: loadFail = node.loadFail,\n [readonlyKey]: readonly = node.readonly,\n [arrowKey]: arrow = node.arrow,\n [checkboxKey]: checkbox = node.checkbox,\n [selectDisabledKey]: selectDisabled = node.selectDisabled,\n [expandDisabledKey]: expandDisabled = node.expandDisabled,\n [checkDisabledKey]: checkDisabled = node.checkDisabled,\n [isLeafKey]: isLeaf = node.isLeaf,\n } = item\n\n node.visible = visible\n node.selected = selected\n node.expanded = expanded\n node.disabled = disabled\n node.checked = checked\n node.loading = loading\n node.loaded = loaded\n node.loadFail = loadFail\n node.readonly = readonly\n node.arrow = arrow\n node.checkbox = checkbox\n node.selectDisabled = selectDisabled\n node.expandDisabled = expandDisabled\n node.checkDisabled = checkDisabled\n node.isLeaf = isLeaf\n }\n\n if (props.noBuildTree) {\n walkTree(\n props.data,\n (item, _, parent) => {\n let node = nodeDataMap.get(item)\n\n if (node) {\n refresh(node, item)\n } else {\n node = createNodeItem(item)\n node.id = getIndexId()\n node.parent = parent ? nodeDataMap.get(parent)?.id : undefined\n\n nodeMap.set(node.id, node)\n nodeDataMap.set(item, node)\n }\n\n nodes.push(node)\n },\n { childField: keyConfig.children, depthFirst: true },\n )\n } else {\n const data = props.data\n\n for (let i = 0, len = data.length; i < len; ++i) {\n const item = data[i]\n const id = item[idKey] as Key\n\n let node = nodeMap.get(id)\n\n if (node) {\n refresh(node, item)\n } else {\n node = createNodeItem(item)\n nodeMap.set(id, node)\n }\n\n nodes.push(node)\n }\n }\n\n buildTreeNodes(nodes)\n resetExpanded()\n}\n\nfunction syncNodeStateIntoData() {\n flattedNodes.value.forEach(node => {\n if (!node.data) return\n\n const { data, visible, selected, expanded, disabled, checked, loading, readonly } = node\n\n data.visible = visible\n data.selected = selected\n data.expanded = expanded\n data.disabled = disabled\n data.checked = checked\n data.loading = loading\n data.readonly = readonly\n })\n\n resetExpanded()\n}\n\nfunction createNodeItem(data: Data, defaults = defaultNodeProperties): TreeNodeProps {\n const {\n id: idKey,\n parent: parentKey,\n visible: visibleKey,\n selected: selectedKey,\n expanded: expandedKey,\n disabled: disabledKey,\n checked: checkedKey,\n loading: loadingKey,\n loaded: loadedKey,\n loadFail: loadFailKey,\n readonly: readonlyKey,\n arrow: arrowKey,\n checkbox: checkboxKey,\n selectDisabled: selectDisabledKey,\n expandDisabled: expandDisabledKey,\n checkDisabled: checkDisabledKey,\n isLeaf: isLeafKey,\n } = keyConfig\n\n const {\n [visibleKey]: visible = defaults.visible,\n [selectedKey]: selected = defaults.selected,\n [expandedKey]: expanded = defaults.expanded,\n [disabledKey]: disabled = defaults.disabled,\n [checkedKey]: checked = defaults.checked,\n [loadingKey]: loading = defaults.loading,\n [loadedKey]: loaded = defaults.loaded,\n [loadFailKey]: loadFail = defaults.loadFail,\n [readonlyKey]: readonly = defaults.readonly,\n [arrowKey]: arrow = defaults.arrow,\n [checkboxKey]: checkbox = defaults.checkbox,\n [selectDisabledKey]: selectDisabled = defaults.selectDisabled,\n [expandDisabledKey]: expandDisabled = defaults.expandDisabled,\n [checkDisabledKey]: checkDisabled = defaults.checkDisabled,\n [isLeafKey]: isLeaf = defaults.isLeaf,\n } = data\n const id = props.noBuildTree ? null : data[idKey]\n const parent = props.noBuildTree ? null : data[parentKey]\n\n const node = {\n id,\n parent,\n data,\n visible,\n selected,\n expanded,\n disabled,\n checked,\n loading,\n loaded,\n loadFail,\n readonly,\n arrow,\n checkbox,\n selectDisabled,\n expandDisabled,\n checkDisabled,\n isLeaf,\n }\n\n if (typeof props.postCreate === 'function') {\n props.postCreate(node as TreeNodeProps)\n }\n\n return reactive({\n ...node,\n id,\n parent,\n children: [],\n partial: false,\n matched: false,\n childMatched: false,\n upperMatched: false,\n depth: -1,\n last: false,\n // inLastCount: 0,\n upstreamLast: [],\n lineIndexes: [],\n })\n}\n\nfunction computeCheckedState(originNode: TreeNodeProps, able: boolean) {\n if (!props.noCascaded) {\n const nodeList = [originNode].concat(\n // 需要包含被禁用且被勾选的节点\n flattedNodes.value.filter(item => (item.disabled || item.checkDisabled) && item.checked),\n )\n\n for (let i = 0, len = nodeList.length; i < len; ++i) {\n const item = nodeList[i]\n\n updateCheckedUpward(item.id)\n updateCheckedDown(item.id)\n }\n }\n\n emitEvent(props.onNodeChange, originNode.data, originNode, able)\n}\n\nfunction handleNodeClick(node: TreeNodeProps) {\n emitEvent(props.onNodeClick, node.data, node)\n}\n\nfunction handleLabelClick(node: TreeNodeProps) {\n emitEvent(props.onLabelClick, node.data, node)\n}\n\nfunction handleNodeSelect(node: TreeNodeProps) {\n const selectedNodes = flattedNodes.value.filter(item => item.selected)\n\n if (props.multiple) {\n emitEvent(\n props.onNodeSelect,\n selectedNodes.map(item => item.data),\n selectedNodes,\n )\n } else {\n const currentId = node.id\n\n for (let i = 0, len = selectedNodes.length; i < len; ++i) {\n const item = selectedNodes[i]\n\n item.selected = item.id === currentId\n }\n\n emitEvent(props.onNodeSelect, node.data, node)\n }\n}\n\nfunction handleNodeCancel(node: TreeNodeProps) {\n emitEvent(props.onNodeCancel, node.data, node)\n}\n\nfunction handleNodeExpand(node: TreeNodeProps) {\n if (props.accordion) {\n const siblingNodes = getSiblingNodes(node)\n\n for (let i = 0, len = siblingNodes.length; i < len; ++i) {\n siblingNodes[i].expanded = false\n }\n }\n\n emitEvent(props.onNodeExpand, node.data, node)\n}\n\nfunction handleNodeReduce(node: TreeNodeProps) {\n emitEvent(props.onNodeReduce, node.data, node)\n}\n\nfunction handleNodeContextmenu(event: MouseEvent, node: TreeNodeProps) {\n emitEvent(props.onNodeContextmenu, event, node.data, node)\n}\n\nasync function handleAsyncLoad(node: TreeNodeProps) {\n if (!boundAsyncLoad.value) return false\n\n let result = props.onAsyncLoad(node.data, node)\n\n if (isPromise(result)) {\n result = await result\n }\n\n return result !== false\n}\n\nlet dragState: {\n draggingNode: TreeNodeProps,\n treeRect: DOMRect,\n willDropNode: TreeNodeProps | null,\n dropType: DropType,\n} | null = null\n\nfunction handleNodeDragStart(nodeInstance: TreeNodeInstance) {\n if (!wrapper.value) return\n\n dragState = {\n draggingNode: nodeInstance.node,\n treeRect: wrapper.value.getBoundingClientRect(),\n willDropNode: null,\n dropType: DropType.BEFORE,\n }\n\n dragging.value = true\n emitEvent(props.onDragStart, nodeInstance.node.data, nodeInstance.node)\n}\n\nfunction handleNodeDragOver(nodeInstance: TreeNodeInstance, event: DragEvent) {\n if (!dragState || !nodeInstance.el || !nodeInstance.arrow) return\n\n const dropNodeRect = nodeInstance.el.getBoundingClientRect()\n const treeRect = dragState.treeRect\n const dropArrowRect = nodeInstance.arrow.getBoundingClientRect()\n const prevPercent = 0.25\n const nextPercent = 0.75\n const distance = event.clientY - dropNodeRect.top\n const dropNodeHeight = dropArrowRect.height\n\n let dropType: DropType\n let indicatorTop = -9999\n let isIndicatorShow = true\n\n if (distance < dropNodeHeight * prevPercent) {\n dropType = DropType.BEFORE\n indicatorTop = dropArrowRect.top - treeRect.top\n } else if (distance > dropNodeHeight * nextPercent) {\n dropType = DropType.AFTER\n indicatorTop = dropArrowRect.bottom - treeRect.top\n } else {\n dropType = DropType.INNER\n isIndicatorShow = false\n }\n\n if (indicator.value) {\n indicator.value.style.top = `${indicatorTop}px`\n indicator.value.style.insetInlineStart = `${dropArrowRect.right - treeRect.left}px`\n }\n\n dragState.willDropNode = nodeInstance.node\n dragState.dropType = dropType\n\n indicatorShow.value = isIndicatorShow\n emitEvent(props.onDragOver, nodeInstance.node.data, nodeInstance.node)\n}\n\nfunction isLeftInsideRight(left: TreeNodeProps, right: TreeNodeProps) {\n if (!left || !right) return true\n\n while (left) {\n if (left === right || left.id === right.id) {\n return true\n }\n\n left = getParentNode(left)!\n }\n\n return false\n}\n\nfunction handleNodeDrop(nodeInstance: TreeNodeInstance) {\n if (!dragState) return\n\n const { draggingNode, willDropNode, dropType } = dragState\n\n if (!willDropNode || isLeftInsideRight(willDropNode, draggingNode)) return\n\n let currentId: Key\n let parent: TreeNodeProps | null\n\n if (draggingNode) {\n parent = getParentNode(draggingNode)\n\n if (!parent) {\n parent = {\n children: treeNodes.value,\n } as TreeNodeProps\n }\n\n currentId = draggingNode.id as Key\n removeArrayItem(parent.children, item => item.id === currentId)\n }\n\n if (dropType === DropType.INNER) {\n if (!Array.isArray(willDropNode.children)) {\n willDropNode.children = []\n }\n\n const children = Array.from(willDropNode.children as TreeNodeProps[])\n\n children.push(draggingNode)\n\n willDropNode.children = children\n draggingNode.parent = willDropNode.id\n } else {\n parent = getParentNode(willDropNode)\n\n if (!parent) {\n parent = {\n parent: undefined! as Key,\n children: treeNodes.value,\n } as TreeNodeProps\n }\n\n currentId = willDropNode.id\n const index = parent.children.findIndex(item => item.id === currentId)\n\n if (~index) {\n parent.children.splice(+(dropType === DropType.AFTER) + index, 0, draggingNode)\n\n draggingNode.parent = parent.id\n }\n }\n\n refreshNodesDepth()\n emitEvent(props.onDrop, nodeInstance.node.data, nodeInstance.node, dropType)\n}\n\nfunction handleNodeDragEnd(nodeInstance: TreeNodeInstance) {\n dragging.value = true\n indicatorShow.value = false\n dragState = null\n emitEvent(props.onDragEnd, nodeInstance.node.data, nodeInstance.node)\n}\n\nfunction handleHittingChange(type: 'up' | 'down') {\n const activeEl = document.activeElement\n\n if (!visibleNodeEls.length || !activeEl) return\n\n const index = visibleNodeEls.findIndex(nodeEl => nodeEl === activeEl)\n\n if (~index) {\n visibleNodeEls[\n (index + (type === 'up' ? -1 : 1) + visibleNodeEls.length) % visibleNodeEls.length\n ]?.focus()\n }\n}\n\nfunction handleNodeHitting(nodeEl?: HTMLElement | null) {\n if (!nodeEl || !visibleNodeEls.length) return\n\n if (visibleNodeEls.includes(nodeEl)) {\n nodeEl.focus()\n }\n}\n\nfunction handleScroll() {\n // onScroll()\n updateVisibleNodeEls()\n}\n\nfunction handleTreeFocus(event: FocusEvent) {\n const target = event.target as HTMLElement\n\n if (!visibleNodeEls.length || !target || !trap.value) {\n return\n }\n\n if (target === trap.value) {\n visibleNodeEls[0].focus()\n }\n}\n\nfunction refreshScroll() {\n virtualList.value?.refresh()\n}\n\nfunction resetExpanded() {\n expanding.value = false\n isMounted.value && updateVisibleNodeEls()\n}\n\nfunction afterExpand() {\n if (props.virtual) {\n resetExpanded()\n return\n }\n\n transferring.value = true\n\n requestAnimationFrame(() => {\n resetExpanded()\n timer.expand = setTimeout(() => {\n transferring.value = false\n }, 300)\n })\n}\n\nfunction getCheckedNodes(includePartial = false): TreeNodeProps[] {\n return flattedNodes.value.filter(item => item.checked || (includePartial && item.partial))\n}\n\nfunction getCheckedNodeData(includePartial = false) {\n return getCheckedNodes(includePartial).map(node => node.data)\n}\n\nfunction getSelectedNodes(): TreeNodeProps[] {\n return flattedNodes.value.filter(item => item.selected)\n}\n\nfunction getSelectedNodeData() {\n return getSelectedNodes().map(node => node.data)\n}\n\nfunction getExpandedNodes(): TreeNodeProps[] {\n return flattedNodes.value.filter(item => item.expanded)\n}\n\nfunction getDisabledNodes(): TreeNodeProps[] {\n return flattedNodes.value.filter(item => item.disabled)\n}\n\nfunction getParentNode(node: TreeNodeProps): TreeNodeProps | null {\n if (node.parent) {\n return nodeMap.get(node.parent) ?? null\n }\n\n return null\n}\n\nfunction getNodeChildren(node: TreeNodeProps) {\n return node.children\n}\n\nfunction getSiblingNodes(node: TreeNodeProps, includeSelf = false): TreeNodeProps[] {\n const parent = getParentNode(node)\n\n const currentId = node.id as Key\n const parentId = parent ? (parent.id as Key) : null\n\n return flattedNodes.value.filter(item => {\n const isChild = parentId === null ? !item.parent : item.parent === parentId\n\n if (isChild && !includeSelf) {\n return item.id !== currentId\n }\n\n return isChild\n })\n}\n\nfunction getPrevSiblingNode(node: TreeNodeProps): TreeNodeProps | null {\n const parent = getParentNode(node)\n\n if (!parent) return null\n\n const currentId = node.id\n const parentId = parent.id\n const children = flattedNodes.value.filter(item => item.parent === parentId)\n\n if (children && children.length) {\n const index = children.findIndex(item => item.id === currentId)\n\n if (index > 0) {\n return children[index - 1]\n }\n }\n\n return null\n}\n\nfunction getNextSiblingNode(node: TreeNodeProps): TreeNodeProps | null {\n const parent = getParentNode(node)\n\n if (!parent) return null\n\n const currentId = node.id\n const parentId = parent.id\n const children = flattedNodes.value.filter(item => item.parent === parentId)\n\n if (children && children.length) {\n const index = children.findIndex(item => item.id === currentId)\n\n if (!~index && index < children.length - 1) {\n return children[index + 1]\n }\n }\n\n return null\n}\n\nfunction getNodeByData<T extends Data>(data: T): TreeNodeProps | null {\n if (props.noBuildTree) {\n return flattedNodes.value.find(item => item.data === data) ?? null\n }\n\n const idKey = keyConfig.id\n\n return (\n flattedNodes.value.find(\n item => item.data === data || item.data[idKey] === data[idKey as keyof T],\n ) ?? null\n )\n}\n\nfunction expandNodeByData<T extends Data>(data: T, expanded?: boolean, upstream = false) {\n const node = getNodeByData(data)\n\n if (node) {\n node.expanded = isNull(expanded) ? !node.expanded : !!expanded\n\n if (upstream) {\n let parentNode = getParentNode(node)\n\n while (parentNode) {\n parentNode.expanded = node.expanded\n parentNode = getParentNode(parentNode)\n }\n }\n }\n}\n\nfunction selectNodeByData<T extends Data>(data: T, selected?: boolean) {\n const node = getNodeByData(data)\n\n if (node) {\n node.selected = isNull(selected) ? !node.selected : !!selected\n }\n}\n\nfunction checkNodeByData<T extends Data>(data: T, checked?: boolean) {\n const node = getNodeByData(data)\n\n if (node) {\n node.checked = isNull(checked) ? !node.checked : !!checked\n\n if (!props.noCascaded) {\n const nodeList = [node].concat(\n flattedNodes.value.filter(item => item.disabled && item.checked),\n )\n\n for (let i = 0, len = nodeList.length; i < len; ++i) {\n const item = nodeList[i]\n\n updateCheckedUpward(item.id)\n updateCheckedDown(item.id)\n }\n }\n }\n}\n\nfunction toggleNodeLoadingByData<T extends Data>(data: T, loading?: boolean) {\n const node = getNodeByData(data)\n\n if (node) {\n node.checked = isNull(loading) ? !node.loading : !!loading\n }\n}\n\nfunction toggleAllExpanded(expanded: boolean) {\n for (const node of flattedNodes.value) {\n if (!node.disabled && !node.expandDisabled && !node.loading && node.children?.length) {\n node.expanded = expanded\n }\n }\n}\n\nfunction getTreeData(withFilter = false) {\n return mapTree(\n withFilter\n ? filterTree(treeNodes.value, node => node.matched, {\n childField: 'children',\n leafOnly: props.filterLeaf,\n isLeaf: isLeafNode,\n })\n : treeNodes.value,\n node => ({ ...node.data }),\n )\n}\n\nfunction getFlattedData(withFilter = false) {\n return (\n withFilter\n ? flattedNodes.value.filter(node => node.matched || node.childMatched || node.upperMatched)\n : flattedNodes.value\n ).map(node => ({ ...node.data }))\n}\n\nconst transferring = ref(false)\n</script>\n\n<template>\n <VirtualList\n ref=\"virtualList\"\n :class=\"[nh.b(), nh.bs('vars'), props.inherit && nh.bm('inherit')]\"\n :inherit=\"props.inherit\"\n :items=\"renderedNodes\"\n :item-size=\"props.nodeMinHeight\"\n items-tag=\"ul\"\n :items-attrs=\"{ class: nh.be('list') }\"\n :hide-bar=\"!props.useYBar\"\n :ignore-resize=\"transferring\"\n :disabled=\"!props.virtual\"\n role=\"tree\"\n tabindex=\"-1\"\n :aria-disabled=\"props.disabled\"\n :aria-readonly=\"props.readonly\"\n :style=\"style\"\n @scroll=\"handleScroll\"\n >\n <template #prefix-trap>\n <div\n ref=\"trap\"\n tabindex=\"0\"\n role=\"none\"\n style=\"width: 0; height: 0; overflow: hidden; outline: none\"\n @focus=\"handleTreeFocus\"\n ></div>\n </template>\n <template #default=\"{ item: node }: { item: TreeNodeProps }\">\n <CollapseTransition\n v-if=\"isCollapse(node)\"\n appear\n :reverse=\"node.type === 'reduce'\"\n @after-enter=\"afterExpand\"\n >\n <div :class=\"nh.be('collapse')\" :style=\"{ height: `${node.height}px` }\">\n <TreeNode\n v-for=\"(innerNode, index) in node.nodes\"\n :key=\"innerNode.id ?? index\"\n v-bind=\"toNodeProps(innerNode.data, innerNode)\"\n :node=\"innerNode\"\n >\n <template v-if=\"slots.node || props.slots.node\" #default=\"payload\">\n <slot name=\"node\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.node\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.arrow || props.slots.arrow\" #arrow=\"payload\">\n <slot name=\"arrow\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.arrow\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.label || props.slots.label\" #label=\"payload\">\n <slot name=\"label\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.label\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.prefix || props.slots.prefix\" #prefix=\"payload\">\n <slot name=\"prefix\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.prefix\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.suffix || props.slots.suffix\" #suffix=\"payload\">\n <slot name=\"suffix\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.suffix\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n </TreeNode>\n </div>\n </CollapseTransition>\n <TreeNode v-else v-bind=\"toNodeProps(node.data, node)\" :node=\"node\">\n <template v-if=\"slots.node || props.slots.node\" #default=\"payload\">\n <slot name=\"node\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.node\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.arrow || props.slots.arrow\" #arrow=\"payload\">\n <slot name=\"arrow\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.arrow\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.label || props.slots.label\" #label=\"payload\">\n <slot name=\"label\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.label\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.prefix || props.slots.prefix\" #prefix=\"payload\">\n <slot name=\"prefix\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.prefix\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n <template v-if=\"slots.suffix || props.slots.suffix\" #suffix=\"payload\">\n <slot name=\"suffix\" v-bind=\"payload\">\n <Renderer :renderer=\"props.slots.suffix\" :data=\"payload\"></Renderer>\n </slot>\n </template>\n </TreeNode>\n </template>\n <template #empty>\n <div :class=\"nh.be('empty-tip')\">\n <slot name=\"empty\">\n <Renderer :renderer=\"props.slots.empty\">\n {{ props.emptyText ?? locale.empty }}\n </Renderer>\n </slot>\n </div>\n </template>\n <template #suffix-trap>\n <div\n v-if=\"props.draggable\"\n v-show=\"indicatorShow\"\n ref=\"indicator\"\n :class=\"nh.be('indicator')\"\n ></div>\n </template>\n </VirtualList>\n</template>\n"],"names":["props","useProps","__props","value","createIconProp","slots","_useSlots","nh","useNameHelper","locale","useLocale","toRef","nodeMap","nodeDataMap","treeNodes","ref","flattedNodes","dragging","indicatorShow","keyConfig","reactive","defaultKeyConfig","nodeStates","expanding","expandingNodes","expandedNodeIds","timer","useSetTimeout","isMounted","useMounted","virtualList","trap","indicator","wrapper","computed","_a","visibleNodeEls","defaultNodeProperties","boundAsyncLoad","linkLine","style","visibleNodes","flatNodes","renderedNodes","toNodeProps","createDefaultFilter","pattern","data","label","updateVisibleNodeEls","debounce","queryAll","disableExpand","disableExpandTick","nextTick","watchEffect","nodes","filter","leafOnly","i","len","node","isLeafNode","parent","upper","resetExpanded","oldIds","ids","changed","watch","parseAndTransformData","flatTree","prev","addedId","removedId","id","_b","_d","_c","transferring","baseExpandedIds","baseNodes","virtual","viewHeight","nodeHeight","viewCount","loop","meta","type","index","children","addedNodes","provide","TREE_STATE","getParentNode","computeCheckedState","handleNodeClick","handleNodeSelect","handleNodeCancel","handleNodeExpand","handleNodeReduce","handleNodeContextmenu","handleAsyncLoad","handleNodeDragStart","handleNodeDragOver","handleNodeDrop","handleNodeDragEnd","handleHittingChange","handleNodeHitting","handleLabelClick","TREE_NODE_STATE","__expose","refreshScroll","forceUpdateData","syncNodeStateIntoData","getCheckedNodes","getCheckedNodeData","getSelectedNodes","getSelectedNodeData","getExpandedNodes","getDisabledNodes","getNodeChildren","getSiblingNodes","getPrevSiblingNode","getNextSiblingNode","getNodeByData","expandNodeByData","selectNodeByData","checkNodeByData","toggleNodeLoadingByData","toggleAllExpanded","getTreeData","getFlattedData","onMounted","updateCheckedUpward","updateCheckedDown","useCascadedChecked","key","getIndexId","getGlobalCount","isLeaf","leafSign","asyncLoad","isNull","expandedIds","rootNodes","parentNode","isCollapse","refreshNodesDepth","walkTree","depth","getLast","buildTreeNodes","transformTree","idKey","oldDataMap","oldIdMap","item","_","oldNode","createNodeItem","checkedNodes","parentKey","visibleKey","selectedKey","expandedKey","disabledKey","checkedKey","loadingKey","loadedKey","loadFailKey","readonlyKey","arrowKey","checkboxKey","selectDisabledKey","expandDisabledKey","checkDisabledKey","isLeafKey","refresh","visible","selected","expanded","disabled","checked","loading","loaded","loadFail","readonly","arrow","checkbox","selectDisabled","expandDisabled","checkDisabled","defaults","originNode","able","nodeList","emitEvent","selectedNodes","currentId","siblingNodes","event","result","isPromise","dragState","nodeInstance","DropType","dropNodeRect","treeRect","dropArrowRect","prevPercent","nextPercent","distance","dropNodeHeight","dropType","indicatorTop","isIndicatorShow","isLeftInsideRight","left","right","draggingNode","willDropNode","removeArrayItem","activeEl","nodeEl","handleScroll","handleTreeFocus","target","afterExpand","includePartial","includeSelf","parentId","isChild","upstream","withFilter","mapTree","filterTree","_createBlock","_unref","VirtualList","_normalizeClass","_createElementVNode","_withCtx","CollapseTransition","_normalizeStyle","_openBlock","_createElementBlock","_Fragment","innerNode","TreeNode","_mergeProps","_createSlots","payload","_renderSlot","_ctx","_createVNode","Renderer","_normalizeProps","_guardReactiveProps","_createTextVNode","_toDisplayString"],"mappings":"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