UNPKG

vexip-ui

Version:

A Vue 3 UI library, Highly customizability, full TypeScript, performance pretty good

1 lines 67.7 kB
{"version":3,"file":"tree.vue2.cjs","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","__props","props","useProps","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","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","_a","_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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