{"version":3,"file":"Tree.mjs","names":["useControlledState"],"sources":["../../../src/base-ui/Tree/Tree.tsx"],"sourcesContent":["'use client';\n\nimport { cx } from 'antd-style';\nimport { memo, useId, useMemo, useRef, useState } from 'react';\nimport useControlledState from 'use-merge-value';\n\nimport { FocusScope, focusScopeItem, useScopeArrowNav } from '@/base-ui/FocusScope';\n\nimport { TreeContext, type TreeContextValue } from './context';\nimport { styles } from './style';\nimport TreeNode from './TreeNode';\nimport type { TreeDataNode, TreeProps } from './type';\nimport { conductCheck, flattenVisible, getAllKeys, getAncestorKeys, getSubtreeKeys } from './utils';\n\nconst EMPTY: string[] = [];\n\nconst Tree = memo<TreeProps>(\n  ({\n    blockNode = false,\n    checkStrictly = false,\n    checkable = false,\n    checkedKeys: checkedKeysProp,\n    className,\n    classNames = {},\n    defaultCheckedKeys = EMPTY,\n    defaultExpandAll = false,\n    defaultExpandedKeys = EMPTY,\n    defaultSelectedKeys = EMPTY,\n    disabled = false,\n    expandedKeys: expandedKeysProp,\n    indent = 20,\n    multiple = false,\n    onCheck,\n    onExpand,\n    onRightClick,\n    onSelect,\n    scopeId: scopeIdProp,\n    selectedKeys: selectedKeysProp,\n    showIcon = false,\n    showLine = false,\n    size = 'middle',\n    style,\n    styles: customStyles = {},\n    switcherIcon,\n    titleRender,\n    treeData,\n    vimKeys = false,\n  }) => {\n    const generatedId = useId();\n    const scopeId = scopeIdProp ?? generatedId;\n    const [expandedKeys, setExpandedKeys] = useControlledState<string[]>(\n      defaultExpandAll ? getAllKeys(treeData) : defaultExpandedKeys,\n      { value: expandedKeysProp },\n    );\n    const [selectedKeys, setSelectedKeys] = useControlledState<string[]>(defaultSelectedKeys, {\n      value: selectedKeysProp,\n    });\n    const [checkedKeys, setCheckedKeys] = useControlledState<string[]>(defaultCheckedKeys, {\n      value: checkedKeysProp,\n    });\n\n    const expanded = useMemo(() => new Set(expandedKeys), [expandedKeys]);\n    const selected = useMemo(() => new Set(selectedKeys), [selectedKeys]);\n    const flat = useMemo(() => flattenVisible(treeData, expanded), [treeData, expanded]);\n    const { checked, halfChecked } = useMemo(\n      () =>\n        checkStrictly\n          ? { checked: new Set(checkedKeys), halfChecked: new Set<string>() }\n          : conductCheck(treeData, checkedKeys),\n      [checkStrictly, treeData, checkedKeys],\n    );\n\n    const [activeKeyState, setActiveKeyState] = useState<string | null>(null);\n    const setActiveKey = setActiveKeyState;\n    const activeKey =\n      activeKeyState && flat.some((row) => row.node.key === activeKeyState)\n        ? activeKeyState\n        : (selectedKeys.find((key) => flat.some((row) => row.node.key === key)) ??\n          flat[0]?.node.key ??\n          null);\n\n    const anchorRef = useRef<string | null>(null);\n\n    const rowOf = (key: string) =>\n      document.querySelector<HTMLElement>(`[data-focus-scope=\"${scopeId}\"] [data-id=\"${key}\"]`);\n    const focusRow = (key: string) => {\n      setActiveKey(key);\n      const row = rowOf(key);\n      if (row) focusScopeItem(scopeId, row);\n    };\n\n    const isDisabled = (node: TreeDataNode) => disabled || !!node.disabled;\n\n    const toggleExpand = (node: TreeDataNode) => {\n      const willExpand = !expanded.has(node.key);\n      const next = willExpand\n        ? [...expandedKeys, node.key]\n        : expandedKeys.filter((key) => key !== node.key);\n      setExpandedKeys(next);\n      onExpand?.(next, { expanded: willExpand, node });\n    };\n\n    const toggleSelect: TreeContextValue['toggleSelect'] = (node, event) => {\n      if (isDisabled(node) || node.selectable === false) return;\n      let next: string[];\n      if (multiple && event?.shiftKey && anchorRef.current) {\n        const a = flat.findIndex((row) => row.node.key === anchorRef.current);\n        const b = flat.findIndex((row) => row.node.key === node.key);\n        next = flat\n          .slice(Math.min(a, b), Math.max(a, b) + 1)\n          .filter((row) => !isDisabled(row.node) && row.node.selectable !== false)\n          .map((row) => row.node.key);\n      } else if (multiple && (event?.metaKey || event?.ctrlKey)) {\n        next = selected.has(node.key)\n          ? selectedKeys.filter((key) => key !== node.key)\n          : [...selectedKeys, node.key];\n        anchorRef.current = node.key;\n      } else {\n        next = [node.key];\n        anchorRef.current = node.key;\n      }\n      setSelectedKeys(next);\n      setActiveKey(node.key);\n      onSelect?.(next, { node, selected: next.includes(node.key) });\n    };\n\n    const toggleCheck = (node: TreeDataNode) => {\n      if (isDisabled(node) || node.checkable === false) return;\n      const willCheck = !checked.has(node.key);\n      const keys = checkStrictly ? [node.key] : getSubtreeKeys(node);\n      const base = new Set(checkStrictly ? checkedKeys : checked);\n      keys.forEach((key) => (willCheck ? base.add(key) : base.delete(key)));\n      if (!willCheck && !checkStrictly) getAncestorKeys(treeData, node.key).forEach((key) => base.delete(key));\n      const next = checkStrictly ? [...base] : [...conductCheck(treeData, base).checked];\n      setCheckedKeys(next);\n      setActiveKey(node.key);\n      onCheck?.(next, { checked: willCheck, node });\n    };\n\n    const currentRow = () => {\n      const focused = document.activeElement?.closest<HTMLElement>('[role=\"treeitem\"]');\n      const key = focused?.dataset.id ?? activeKey;\n      return flat.find((row) => row.node.key === key);\n    };\n\n    const withRow = (fn: (row: (typeof flat)[number], event: KeyboardEvent) => void) =>\n      (event: KeyboardEvent) => {\n        const row = currentRow();\n        if (row) fn(row, event);\n      };\n\n    useScopeArrowNav({\n      extra: {\n        ' ': withRow((row, event) => {\n          if (checkable && row.node.checkable !== false) toggleCheck(row.node);\n          else toggleSelect(row.node, event);\n        }),\n        '*': withRow((row) => {\n          const siblings = flat.filter(\n            (r) => r.parentKey === row.parentKey && r.hasChildren && !expanded.has(r.node.key),\n          );\n          if (siblings.length === 0) return;\n          const next = [...expandedKeys, ...siblings.map((r) => r.node.key)];\n          setExpandedKeys(next);\n          onExpand?.(next, { expanded: true, node: row.node });\n        }),\n        ArrowLeft: withRow((row) => {\n          if (row.hasChildren && expanded.has(row.node.key)) toggleExpand(row.node);\n          else if (row.parentKey) focusRow(row.parentKey);\n        }),\n        ArrowRight: withRow((row) => {\n          if (!row.hasChildren) return;\n          if (expanded.has(row.node.key)) focusRow(flat[row.index + 1].node.key);\n          else toggleExpand(row.node);\n        }),\n        Enter: withRow((row, event) => toggleSelect(row.node, event)),\n      },\n      itemSelector: '[role=\"treeitem\"]',\n      onItemFocus: (el) => el.dataset.id && setActiveKey(el.dataset.id),\n      scopeId,\n      vimKeys,\n    });\n\n    const ctx: TreeContextValue = {\n      activeKey,\n      blockNode,\n      checkable,\n      checked,\n      classNames,\n      disabled,\n      expanded,\n      halfChecked,\n      indent,\n      onRightClick: (event, node) => onRightClick?.({ event, node }),\n      selected,\n      setActiveKey,\n      showIcon,\n      showLine,\n      size,\n      styles: customStyles,\n      switcherIcon,\n      titleRender,\n      toggleCheck,\n      toggleExpand,\n      toggleSelect,\n    };\n\n    return (\n      <TreeContext value={ctx}>\n        <FocusScope\n          className={cx(styles.root, classNames.root, className)}\n          id={scopeId}\n          role=\"tree\"\n          style={{ ...customStyles.root, ...style }}\n        >\n          {treeData.map((node, i) => (\n            <TreeNode\n              depth={0}\n              isLast={i === treeData.length - 1}\n              key={node.key}\n              node={node}\n              trail={[]}\n            />\n          ))}\n        </FocusScope>\n      </TreeContext>\n    );\n  },\n);\n\nTree.displayName = 'Tree';\n\nexport default Tree;\n"],"mappings":"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"}