{"version":3,"file":"use-cascader.cjs","names":["getCascaderPathOptions","cascaderOptionHasChildren","getCascaderColumns"],"sources":["../../../src/components/Cascader/use-cascader.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { useUncontrolled } from '@mantine/hooks';\nimport type { CascaderOption } from './Cascader';\nimport { cascaderOptionHasChildren, getCascaderColumns } from './get-cascader-columns';\nimport { getCascaderPathOptions } from './get-cascader-path-options';\n\nexport interface UseCascaderInput {\n  data: CascaderOption[];\n  value: string[] | null | undefined;\n  defaultValue: string[] | null | undefined;\n  onChange: ((value: string[] | null, options: CascaderOption[]) => void) | undefined;\n  changeOnSelect: boolean | undefined;\n  allowDeselect: boolean | undefined;\n  expandTrigger: 'click' | 'hover' | undefined;\n  onLeafSelect?: () => void;\n}\n\nfunction pathsEqual(a: string[] | null, b: string[]): boolean {\n  return !!a && a.length === b.length && a.every((item, index) => item === b[index]);\n}\n\nfunction findEnabledIndex(options: CascaderOption[], from: number, direction: 1 | -1): number {\n  let index = from + direction;\n\n  while (index >= 0 && index < options.length) {\n    if (!options[index].disabled) {\n      return index;\n    }\n    index += direction;\n  }\n\n  return -1;\n}\n\nexport function useCascader({\n  data,\n  value,\n  defaultValue,\n  onChange,\n  changeOnSelect,\n  allowDeselect,\n  expandTrigger,\n  onLeafSelect,\n}: UseCascaderInput) {\n  const [keyboardNav, setKeyboardNav] = useState(false);\n\n  const [_value, setValue] = useUncontrolled<string[] | null>({\n    value: value as any,\n    defaultValue: defaultValue as any,\n    finalValue: null,\n    onChange: (val) => onChange?.(val, getCascaderPathOptions(data, val)),\n  });\n\n  const [activePath, setActivePath] = useState<string[]>(() => _value ?? []);\n  const activePathRef = useRef(activePath);\n  activePathRef.current = activePath;\n\n  const resetActivePath = useCallback(() => {\n    setActivePath(_value ?? []);\n  }, [_value]);\n\n  const selectPath = useCallback(\n    (path: string[]) => {\n      setValue(allowDeselect && pathsEqual(_value, path) ? null : path);\n    },\n    [allowDeselect, _value, setValue]\n  );\n\n  const expandOption = useCallback((level: number, option: CascaderOption) => {\n    const optionPath = [...activePathRef.current.slice(0, level), option.value];\n    const children = option.children;\n\n    if (Array.isArray(children) && children.length > 0) {\n      const first = findEnabledIndex(children, -1, 1);\n      setActivePath(first >= 0 ? [...optionPath, children[first].value] : optionPath);\n    } else {\n      setActivePath(optionPath);\n    }\n  }, []);\n\n  const handleOptionClick = useCallback(\n    (level: number, option: CascaderOption) => {\n      setKeyboardNav(false);\n      const path = [...activePath.slice(0, level), option.value];\n\n      if (cascaderOptionHasChildren(option)) {\n        if (changeOnSelect) {\n          selectPath(path);\n        }\n        expandOption(level, option);\n        if (changeOnSelect) {\n          onLeafSelect?.();\n        }\n      } else {\n        selectPath(path);\n        onLeafSelect?.();\n      }\n    },\n    [activePath, changeOnSelect, selectPath, expandOption, onLeafSelect]\n  );\n\n  const handleOptionMouseEnter = useCallback(\n    (level: number, option: CascaderOption) => {\n      setKeyboardNav(false);\n\n      if (expandTrigger !== 'hover') {\n        return;\n      }\n\n      if (cascaderOptionHasChildren(option)) {\n        expandOption(level, option);\n      } else {\n        setActivePath([...activePath.slice(0, level), option.value]);\n      }\n    },\n    [expandTrigger, activePath, expandOption]\n  );\n\n  const handleColumnsKeyDown = useCallback(\n    (event: React.KeyboardEvent): boolean => {\n      setKeyboardNav(true);\n      const columns = getCascaderColumns(data, activePath);\n      const focusedLevel = Math.max(0, activePath.length - 1);\n      const currentColumn = columns[focusedLevel] ?? columns[0] ?? [];\n      const focusedIndex = currentColumn.findIndex(\n        (item) => item.value === activePath[focusedLevel]\n      );\n      const focusedOption = focusedIndex >= 0 ? currentColumn[focusedIndex] : undefined;\n\n      switch (event.key) {\n        case 'ArrowDown': {\n          const next = findEnabledIndex(currentColumn, focusedIndex, 1);\n          if (next >= 0) {\n            setActivePath([...activePath.slice(0, focusedLevel), currentColumn[next].value]);\n          }\n          return true;\n        }\n        case 'ArrowUp': {\n          const from = focusedIndex < 0 ? currentColumn.length : focusedIndex;\n          const prev = findEnabledIndex(currentColumn, from, -1);\n          if (prev >= 0) {\n            setActivePath([...activePath.slice(0, focusedLevel), currentColumn[prev].value]);\n          }\n          return true;\n        }\n        case 'ArrowRight': {\n          if (focusedOption && cascaderOptionHasChildren(focusedOption)) {\n            expandOption(focusedLevel, focusedOption);\n          }\n          return true;\n        }\n        case 'ArrowLeft': {\n          if (activePath.length > 1) {\n            setActivePath(activePath.slice(0, -1));\n          }\n          return true;\n        }\n        case 'Enter': {\n          if (!focusedOption) {\n            return false;\n          }\n\n          if (cascaderOptionHasChildren(focusedOption)) {\n            if (changeOnSelect) {\n              selectPath([...activePath.slice(0, focusedLevel), focusedOption.value]);\n            }\n            expandOption(focusedLevel, focusedOption);\n            if (changeOnSelect) {\n              onLeafSelect?.();\n            }\n          } else {\n            selectPath([...activePath.slice(0, focusedLevel), focusedOption.value]);\n            onLeafSelect?.();\n          }\n          return true;\n        }\n        default:\n          return false;\n      }\n    },\n    [data, activePath, changeOnSelect, selectPath, expandOption, onLeafSelect]\n  );\n\n  const pathOptions = useMemo(() => getCascaderPathOptions(data, _value), [data, _value]);\n\n  return {\n    value: _value,\n    setValue,\n    selectPath,\n    activePath,\n    setActivePath,\n    resetActivePath,\n    keyboardNav,\n    setKeyboardNav,\n    handleOptionClick,\n    handleOptionMouseEnter,\n    handleColumnsKeyDown,\n    pathOptions,\n  };\n}\n"],"mappings":"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"}