{"version":3,"file":"useTree.mjs","names":[],"sources":["../../../../../../../packages/components/tree-v2/src/composables/useTree.ts"],"sourcesContent":["import { computed, ref, shallowRef, watch } from 'vue'\nimport { isObject } from '@element-plus/utils'\nimport {\n  CURRENT_CHANGE,\n  NODE_CLICK,\n  NODE_COLLAPSE,\n  NODE_DROP,\n  NODE_EXPAND,\n  TreeOptionsEnum,\n} from '../virtual-tree'\nimport { useCheck } from './useCheck'\nimport { useFilter } from './useFilter'\n\nimport type {\n  FixedSizeList,\n  Alignment as ScrollStrategy,\n} from '@element-plus/components/virtual-list'\nimport type { SetupContext } from 'vue'\nimport type { treeEmits } from '../virtual-tree'\nimport type { CheckboxValueType } from '@element-plus/components/checkbox'\nimport type {\n  Tree,\n  TreeData,\n  TreeKey,\n  TreeNode,\n  TreeNodeData,\n  TreeProps,\n} from '../types'\n\nexport function useTree(\n  props: TreeProps,\n  emit: SetupContext<typeof treeEmits>['emit']\n) {\n  const expandedKeySet = ref<Set<TreeKey>>(new Set())\n  const currentKey = ref<TreeKey | undefined>()\n  const tree = shallowRef<Tree | undefined>()\n  const listRef = ref<typeof FixedSizeList | undefined>()\n\n  const {\n    isIndeterminate,\n    isChecked,\n    toggleCheckbox,\n    getCheckedKeys,\n    getCheckedNodes,\n    getHalfCheckedKeys,\n    getHalfCheckedNodes,\n    setChecked,\n    setCheckedKeys,\n  } = useCheck(props, tree)\n\n  const { doFilter, hiddenNodeKeySet, isForceHiddenExpandIcon } = useFilter(\n    props,\n    tree\n  )\n\n  const valueKey = computed(() => {\n    return props.props?.value || TreeOptionsEnum.KEY\n  })\n  const childrenKey = computed(() => {\n    return props.props?.children || TreeOptionsEnum.CHILDREN\n  })\n  const disabledKey = computed(() => {\n    return props.props?.disabled || TreeOptionsEnum.DISABLED\n  })\n  const labelKey = computed(() => {\n    return props.props?.label || TreeOptionsEnum.LABEL\n  })\n\n  const flattenTree = computed(() => {\n    const expandedKeys = expandedKeySet.value\n    const hiddenKeys = hiddenNodeKeySet.value\n    const flattenNodes: TreeNode[] = []\n    const nodes = tree.value?.treeNodes || []\n\n    const stack: TreeNode[] = []\n    for (let i = nodes.length - 1; i >= 0; --i) {\n      stack.push(nodes[i])\n    }\n    while (stack.length) {\n      const node = stack.pop()!\n      if (hiddenKeys.has(node.key)) continue\n\n      flattenNodes.push(node)\n      if (node.children && expandedKeys.has(node.key)) {\n        for (let i = node.children.length - 1; i >= 0; --i) {\n          stack.push(node.children[i])\n        }\n      }\n    }\n\n    return flattenNodes\n  })\n\n  const isNotEmpty = computed(() => {\n    return flattenTree.value.length > 0\n  })\n\n  function createTree(data: TreeData): Tree {\n    const treeNodeMap: Map<TreeKey, TreeNode> = new Map()\n    const levelTreeNodeMap: Map<number, TreeNode[]> = new Map()\n    let maxLevel = 1\n    function traverse(\n      nodes: TreeData,\n      level = 1,\n      parent: TreeNode | undefined = undefined\n    ) {\n      const siblings: TreeNode[] = []\n      for (const rawNode of nodes) {\n        const value = getKey(rawNode)\n        const node: TreeNode = {\n          level,\n          key: value,\n          data: rawNode,\n        }\n        node.label = getLabel(rawNode)\n        node.parent = parent\n        const children = getChildren(rawNode)\n        node.disabled = getDisabled(rawNode)\n        node.isLeaf = !children || children.length === 0\n        node.expanded = expandedKeySet.value.has(value)\n        if (children && children.length) {\n          node.children = traverse(children, level + 1, node)\n        }\n        siblings.push(node)\n        treeNodeMap.set(value, node)\n        if (!levelTreeNodeMap.has(level)) {\n          levelTreeNodeMap.set(level, [])\n        }\n        levelTreeNodeMap.get(level)?.push(node)\n      }\n      if (level > maxLevel) {\n        maxLevel = level\n      }\n      return siblings\n    }\n    const treeNodes: TreeNode[] = traverse(data)\n    return {\n      treeNodeMap,\n      levelTreeNodeMap,\n      maxLevel,\n      treeNodes,\n    }\n  }\n\n  function filter(query: string) {\n    const keys = doFilter(query)\n    if (keys) {\n      expandedKeySet.value = keys\n    }\n  }\n\n  function getChildren(node: TreeNodeData): TreeNodeData[] {\n    return node[childrenKey.value]\n  }\n\n  function getKey(node: TreeNodeData): TreeKey {\n    if (!node) {\n      return ''\n    }\n    return node[valueKey.value]\n  }\n\n  function getDisabled(node: TreeNodeData): boolean {\n    return node[disabledKey.value]\n  }\n\n  function getLabel(node: TreeNodeData): string {\n    return node[labelKey.value]\n  }\n\n  function toggleExpand(node: TreeNode) {\n    const expandedKeys = expandedKeySet.value\n    if (expandedKeys.has(node.key)) {\n      collapseNode(node)\n    } else {\n      expandNode(node)\n    }\n  }\n\n  function setExpandedKeys(keys: TreeKey[]) {\n    const expandedKeys = new Set<TreeKey>()\n    const nodeMap = tree.value!.treeNodeMap\n\n    expandedKeySet.value.forEach((key) => {\n      const node = nodeMap.get(key)\n      if (node) node.expanded = false\n    })\n\n    keys.forEach((k) => {\n      let node = nodeMap.get(k)\n      while (node && !expandedKeys.has(node.key)) {\n        expandedKeys.add(node.key)\n        node.expanded = true\n        node = node.parent\n      }\n    })\n\n    expandedKeySet.value = expandedKeys\n  }\n\n  function handleNodeClick(node: TreeNode, e: MouseEvent) {\n    emit(NODE_CLICK, node.data, node, e)\n    handleCurrentChange(node)\n    if (props.expandOnClickNode) {\n      toggleExpand(node)\n    }\n    if (\n      props.showCheckbox &&\n      (props.checkOnClickNode || (node.isLeaf && props.checkOnClickLeaf)) &&\n      !node.disabled\n    ) {\n      toggleCheckbox(node, !isChecked(node), true)\n    }\n  }\n\n  function handleNodeDrop(node: TreeNode, e: DragEvent) {\n    emit(NODE_DROP, node.data, node, e)\n  }\n\n  function handleCurrentChange(node: TreeNode) {\n    if (!isCurrent(node)) {\n      currentKey.value = node.key\n      emit(CURRENT_CHANGE, node.data, node)\n    }\n  }\n\n  function handleNodeCheck(node: TreeNode, checked: CheckboxValueType) {\n    toggleCheckbox(node, checked)\n  }\n\n  function expandNode(node: TreeNode) {\n    const keySet = expandedKeySet.value\n    if (tree.value && props.accordion) {\n      // whether only one node among the same level can be expanded at one time\n      const { treeNodeMap } = tree.value\n      keySet.forEach((key) => {\n        const treeNode = treeNodeMap.get(key)\n        if (node && node.level === treeNode?.level) {\n          keySet.delete(key)\n          treeNode.expanded = false\n        }\n      })\n    }\n    keySet.add(node.key)\n    const _node = getNode(node.key)\n    if (_node) {\n      _node.expanded = true\n      emit(NODE_EXPAND, _node.data, _node)\n    }\n  }\n\n  function collapseNode(node: TreeNode) {\n    expandedKeySet.value.delete(node.key)\n    const _node = getNode(node.key)\n    if (_node) {\n      _node.expanded = false\n      emit(NODE_COLLAPSE, _node.data, _node)\n    }\n  }\n\n  function isDisabled(node: TreeNode): boolean {\n    return !!node.disabled\n  }\n\n  function isCurrent(node: TreeNode): boolean {\n    const current = currentKey.value\n    return current !== undefined && current === node.key\n  }\n\n  function getCurrentNode(): TreeNodeData | undefined {\n    if (!currentKey.value) return undefined\n    return tree.value?.treeNodeMap.get(currentKey.value)?.data\n  }\n\n  function getCurrentKey(): TreeKey | undefined {\n    return currentKey.value\n  }\n\n  function setCurrentKey(key: TreeKey): void {\n    currentKey.value = key\n  }\n\n  function setData(data: TreeData) {\n    tree.value = createTree(data)\n  }\n\n  function getNode(data: TreeKey | TreeNodeData) {\n    const key = isObject(data) ? getKey(data) : data\n    return tree.value?.treeNodeMap.get(key)\n  }\n\n  function scrollToNode(key: TreeKey, strategy: ScrollStrategy = 'auto') {\n    const node = getNode(key)\n    if (node && listRef.value) {\n      listRef.value.scrollToItem(flattenTree.value.indexOf(node), strategy)\n    }\n  }\n\n  function scrollTo(offset: number) {\n    listRef.value?.scrollTo(offset)\n  }\n\n  watch(\n    () => props.currentNodeKey,\n    (key) => {\n      currentKey.value = key\n    },\n    {\n      immediate: true,\n    }\n  )\n\n  watch(\n    () => props.defaultExpandedKeys,\n    (keys) => {\n      setExpandedKeys(keys || [])\n    }\n  )\n\n  watch(\n    () => props.data!,\n    (data: TreeData) => {\n      setData(data)\n      setExpandedKeys(props.defaultExpandedKeys || [])\n    },\n    {\n      immediate: true,\n    }\n  )\n\n  return {\n    tree,\n    flattenTree,\n    isNotEmpty,\n    listRef,\n    getKey,\n    getChildren,\n    toggleExpand,\n    toggleCheckbox,\n    isChecked,\n    isIndeterminate,\n    isDisabled,\n    isCurrent,\n    isForceHiddenExpandIcon,\n    handleNodeClick,\n    handleNodeDrop,\n    handleNodeCheck,\n    // expose\n    getCurrentNode,\n    getCurrentKey,\n    setCurrentKey,\n    getCheckedKeys,\n    getCheckedNodes,\n    getHalfCheckedKeys,\n    getHalfCheckedNodes,\n    setChecked,\n    setCheckedKeys,\n    filter,\n    setData,\n    getNode,\n    expandNode,\n    collapseNode,\n    setExpandedKeys,\n    scrollToNode,\n    scrollTo,\n  }\n}\n"],"mappings":";;;;;;;AA6BA,SAAgB,QACd,OACA,MACA;CACA,MAAM,iBAAiB,oBAAkB,IAAI,KAAK,CAAC;CACnD,MAAM,aAAa,KAA0B;CAC7C,MAAM,OAAO,YAA8B;CAC3C,MAAM,UAAU,KAAuC;CAEvD,MAAM,EACJ,iBACA,WACA,gBACA,gBACA,iBACA,oBACA,qBACA,YACA,mBACE,SAAS,OAAO,KAAK;CAEzB,MAAM,EAAE,UAAU,kBAAkB,4BAA4B,UAC9D,OACA,KACD;CAED,MAAM,WAAW,eAAe;AAC9B,SAAO,MAAM,OAAO,SAAS,gBAAgB;GAC7C;CACF,MAAM,cAAc,eAAe;AACjC,SAAO,MAAM,OAAO,YAAY,gBAAgB;GAChD;CACF,MAAM,cAAc,eAAe;AACjC,SAAO,MAAM,OAAO,YAAY,gBAAgB;GAChD;CACF,MAAM,WAAW,eAAe;AAC9B,SAAO,MAAM,OAAO,SAAS,gBAAgB;GAC7C;CAEF,MAAM,cAAc,eAAe;EACjC,MAAM,eAAe,eAAe;EACpC,MAAM,aAAa,iBAAiB;EACpC,MAAM,eAA2B,EAAE;EACnC,MAAM,QAAQ,KAAK,OAAO,aAAa,EAAE;EAEzC,MAAM,QAAoB,EAAE;AAC5B,OAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,EAAE,EACvC,OAAM,KAAK,MAAM,GAAG;AAEtB,SAAO,MAAM,QAAQ;GACnB,MAAM,OAAO,MAAM,KAAK;AACxB,OAAI,WAAW,IAAI,KAAK,IAAI,CAAE;AAE9B,gBAAa,KAAK,KAAK;AACvB,OAAI,KAAK,YAAY,aAAa,IAAI,KAAK,IAAI,CAC7C,MAAK,IAAI,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK,GAAG,EAAE,EAC/C,OAAM,KAAK,KAAK,SAAS,GAAG;;AAKlC,SAAO;GACP;CAEF,MAAM,aAAa,eAAe;AAChC,SAAO,YAAY,MAAM,SAAS;GAClC;CAEF,SAAS,WAAW,MAAsB;EACxC,MAAM,8BAAsC,IAAI,KAAK;EACrD,MAAM,mCAA4C,IAAI,KAAK;EAC3D,IAAI,WAAW;EACf,SAAS,SACP,OACA,QAAQ,GACR,SAA+B,QAC/B;GACA,MAAM,WAAuB,EAAE;AAC/B,QAAK,MAAM,WAAW,OAAO;IAC3B,MAAM,QAAQ,OAAO,QAAQ;IAC7B,MAAM,OAAiB;KACrB;KACA,KAAK;KACL,MAAM;KACP;AACD,SAAK,QAAQ,SAAS,QAAQ;AAC9B,SAAK,SAAS;IACd,MAAM,WAAW,YAAY,QAAQ;AACrC,SAAK,WAAW,YAAY,QAAQ;AACpC,SAAK,SAAS,CAAC,YAAY,SAAS,WAAW;AAC/C,SAAK,WAAW,eAAe,MAAM,IAAI,MAAM;AAC/C,QAAI,YAAY,SAAS,OACvB,MAAK,WAAW,SAAS,UAAU,QAAQ,GAAG,KAAK;AAErD,aAAS,KAAK,KAAK;AACnB,gBAAY,IAAI,OAAO,KAAK;AAC5B,QAAI,CAAC,iBAAiB,IAAI,MAAM,CAC9B,kBAAiB,IAAI,OAAO,EAAE,CAAC;AAEjC,qBAAiB,IAAI,MAAM,EAAE,KAAK,KAAK;;AAEzC,OAAI,QAAQ,SACV,YAAW;AAEb,UAAO;;EAET,MAAM,YAAwB,SAAS,KAAK;AAC5C,SAAO;GACL;GACA;GACA;GACA;GACD;;CAGH,SAAS,OAAO,OAAe;EAC7B,MAAM,OAAO,SAAS,MAAM;AAC5B,MAAI,KACF,gBAAe,QAAQ;;CAI3B,SAAS,YAAY,MAAoC;AACvD,SAAO,KAAK,YAAY;;CAG1B,SAAS,OAAO,MAA6B;AAC3C,MAAI,CAAC,KACH,QAAO;AAET,SAAO,KAAK,SAAS;;CAGvB,SAAS,YAAY,MAA6B;AAChD,SAAO,KAAK,YAAY;;CAG1B,SAAS,SAAS,MAA4B;AAC5C,SAAO,KAAK,SAAS;;CAGvB,SAAS,aAAa,MAAgB;AAEpC,MADqB,eAAe,MACnB,IAAI,KAAK,IAAI,CAC5B,cAAa,KAAK;MAElB,YAAW,KAAK;;CAIpB,SAAS,gBAAgB,MAAiB;EACxC,MAAM,+BAAe,IAAI,KAAc;EACvC,MAAM,UAAU,KAAK,MAAO;AAE5B,iBAAe,MAAM,SAAS,QAAQ;GACpC,MAAM,OAAO,QAAQ,IAAI,IAAI;AAC7B,OAAI,KAAM,MAAK,WAAW;IAC1B;AAEF,OAAK,SAAS,MAAM;GAClB,IAAI,OAAO,QAAQ,IAAI,EAAE;AACzB,UAAO,QAAQ,CAAC,aAAa,IAAI,KAAK,IAAI,EAAE;AAC1C,iBAAa,IAAI,KAAK,IAAI;AAC1B,SAAK,WAAW;AAChB,WAAO,KAAK;;IAEd;AAEF,iBAAe,QAAQ;;CAGzB,SAAS,gBAAgB,MAAgB,GAAe;AACtD,OAAK,YAAY,KAAK,MAAM,MAAM,EAAE;AACpC,sBAAoB,KAAK;AACzB,MAAI,MAAM,kBACR,cAAa,KAAK;AAEpB,MACE,MAAM,iBACL,MAAM,oBAAqB,KAAK,UAAU,MAAM,qBACjD,CAAC,KAAK,SAEN,gBAAe,MAAM,CAAC,UAAU,KAAK,EAAE,KAAK;;CAIhD,SAAS,eAAe,MAAgB,GAAc;AACpD,OAAK,WAAW,KAAK,MAAM,MAAM,EAAE;;CAGrC,SAAS,oBAAoB,MAAgB;AAC3C,MAAI,CAAC,UAAU,KAAK,EAAE;AACpB,cAAW,QAAQ,KAAK;AACxB,QAAK,gBAAgB,KAAK,MAAM,KAAK;;;CAIzC,SAAS,gBAAgB,MAAgB,SAA4B;AACnE,iBAAe,MAAM,QAAQ;;CAG/B,SAAS,WAAW,MAAgB;EAClC,MAAM,SAAS,eAAe;AAC9B,MAAI,KAAK,SAAS,MAAM,WAAW;GAEjC,MAAM,EAAE,gBAAgB,KAAK;AAC7B,UAAO,SAAS,QAAQ;IACtB,MAAM,WAAW,YAAY,IAAI,IAAI;AACrC,QAAI,QAAQ,KAAK,UAAU,UAAU,OAAO;AAC1C,YAAO,OAAO,IAAI;AAClB,cAAS,WAAW;;KAEtB;;AAEJ,SAAO,IAAI,KAAK,IAAI;EACpB,MAAM,QAAQ,QAAQ,KAAK,IAAI;AAC/B,MAAI,OAAO;AACT,SAAM,WAAW;AACjB,QAAK,aAAa,MAAM,MAAM,MAAM;;;CAIxC,SAAS,aAAa,MAAgB;AACpC,iBAAe,MAAM,OAAO,KAAK,IAAI;EACrC,MAAM,QAAQ,QAAQ,KAAK,IAAI;AAC/B,MAAI,OAAO;AACT,SAAM,WAAW;AACjB,QAAK,eAAe,MAAM,MAAM,MAAM;;;CAI1C,SAAS,WAAW,MAAyB;AAC3C,SAAO,CAAC,CAAC,KAAK;;CAGhB,SAAS,UAAU,MAAyB;EAC1C,MAAM,UAAU,WAAW;AAC3B,SAAO,YAAY,UAAa,YAAY,KAAK;;CAGnD,SAAS,iBAA2C;AAClD,MAAI,CAAC,WAAW,MAAO,QAAO;AAC9B,SAAO,KAAK,OAAO,YAAY,IAAI,WAAW,MAAM,EAAE;;CAGxD,SAAS,gBAAqC;AAC5C,SAAO,WAAW;;CAGpB,SAAS,cAAc,KAAoB;AACzC,aAAW,QAAQ;;CAGrB,SAAS,QAAQ,MAAgB;AAC/B,OAAK,QAAQ,WAAW,KAAK;;CAG/B,SAAS,QAAQ,MAA8B;EAC7C,MAAM,MAAM,SAAS,KAAK,GAAG,OAAO,KAAK,GAAG;AAC5C,SAAO,KAAK,OAAO,YAAY,IAAI,IAAI;;CAGzC,SAAS,aAAa,KAAc,WAA2B,QAAQ;EACrE,MAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,QAAQ,QAAQ,MAClB,SAAQ,MAAM,aAAa,YAAY,MAAM,QAAQ,KAAK,EAAE,SAAS;;CAIzE,SAAS,SAAS,QAAgB;AAChC,UAAQ,OAAO,SAAS,OAAO;;AAGjC,aACQ,MAAM,iBACX,QAAQ;AACP,aAAW,QAAQ;IAErB,EACE,WAAW,MACZ,CACF;AAED,aACQ,MAAM,sBACX,SAAS;AACR,kBAAgB,QAAQ,EAAE,CAAC;GAE9B;AAED,aACQ,MAAM,OACX,SAAmB;AAClB,UAAQ,KAAK;AACb,kBAAgB,MAAM,uBAAuB,EAAE,CAAC;IAElD,EACE,WAAW,MACZ,CACF;AAED,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD"}