UNPKG

@mantine/core

Version:

React components library focused on usability, accessibility and developer experience

1 lines 14.8 kB
{"version":3,"file":"use-tree.cjs","names":["getChildrenNodesValues","getAllChildrenNodes","getAllCheckedNodes","memoizedIsNodeChecked","memoizedIsNodeIndeterminate"],"sources":["../../../src/components/Tree/use-tree.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { useUncontrolled } from '@mantine/hooks';\nimport {\n CheckedNodeStatus,\n getAllCheckedNodes,\n} from './get-all-checked-nodes/get-all-checked-nodes';\nimport {\n getAllChildrenNodes,\n getChildrenNodesValues,\n} from './get-children-nodes-values/get-children-nodes-values';\nimport { memoizedIsNodeChecked } from './is-node-checked/is-node-checked';\nimport { memoizedIsNodeIndeterminate } from './is-node-indeterminate/is-node-indeterminate';\nimport type { TreeNodeData } from './Tree';\n\nexport type TreeExpandedState = Record<string, boolean>;\n\nfunction getInitialTreeExpandedState(\n initialState: TreeExpandedState,\n data: TreeNodeData[],\n value: string | string[] | undefined,\n acc: TreeExpandedState = {}\n) {\n data.forEach((node) => {\n acc[node.value] = node.value in initialState ? initialState[node.value] : node.value === value;\n\n if (Array.isArray(node.children)) {\n getInitialTreeExpandedState(initialState, node.children, value, acc);\n }\n });\n\n return acc;\n}\n\nexport function getTreeExpandedState(\n data: TreeNodeData[],\n expandedNodesValues: string[] | '*'\n): Record<string, boolean> {\n const state = getInitialTreeExpandedState({}, data, []);\n\n if (expandedNodesValues === '*') {\n return Object.keys(state).reduce((acc, key) => ({ ...acc, [key]: true }), {});\n }\n\n expandedNodesValues.forEach((node) => {\n state[node] = true;\n });\n\n return state;\n}\n\nfunction getInitialCheckedState(initialState: string[], data: TreeNodeData[]) {\n const acc: string[] = [];\n\n initialState.forEach((node) => acc.push(...getChildrenNodesValues(node, data)));\n\n return Array.from(new Set(acc));\n}\n\nexport interface UseTreeInput {\n /** Initial expanded state of all nodes, uncontrolled state */\n initialExpandedState?: TreeExpandedState;\n\n /** Expanded state of all nodes, controlled state */\n expandedState?: TreeExpandedState;\n\n /** Called when the tree expanded state changes */\n onExpandedStateChange?: (expandedState: TreeExpandedState) => void;\n\n /** Initial selected state of nodes */\n initialSelectedState?: string[];\n\n /** Selected state of all nodes, controlled state */\n selectedState?: string[];\n\n /** Called when the tree selected state changes */\n onSelectedStateChange?: (selectedState: string[]) => void;\n\n /** Initial checked state of nodes */\n initialCheckedState?: string[];\n\n /** Checked state of all nodes, controlled state */\n checkedState?: string[];\n\n /** Called when the tree checked state changes */\n onCheckedStateChange?: (checkedState: string[]) => void;\n\n /** Determines whether multiple node can be selected at a time */\n multiple?: boolean;\n\n /** Called with the node value when it is expanded */\n onNodeExpand?: (value: string) => void;\n\n /** Called with the node value when it is collapsed */\n onNodeCollapse?: (value: string) => void;\n}\n\nexport interface UseTreeReturnType {\n /** Determines whether multiple node can be selected at a time */\n multiple: boolean;\n\n /** A record of `node.value` and boolean values that represent nodes expanded state */\n expandedState: TreeExpandedState;\n\n /** An array of selected nodes values */\n selectedState: string[];\n\n /** An array of checked nodes values */\n checkedState: string[];\n\n /** A value of the node that was last clicked\n * Anchor node is used to determine range of selected nodes for multiple selection\n */\n anchorNode: string | null;\n\n /** Initializes tree state based on provided data, called automatically by the Tree component */\n initialize: (data: TreeNodeData[]) => void;\n\n /** Toggles expanded state of the node with provided value */\n toggleExpanded: (value: string) => void;\n\n /** Collapses node with provided value */\n collapse: (value: string) => void;\n\n /** Expands node with provided value */\n expand: (value: string) => void;\n\n /** Expands all nodes */\n expandAllNodes: () => void;\n\n /** Collapses all nodes */\n collapseAllNodes: () => void;\n\n /** Sets expanded state */\n setExpandedState: (value: TreeExpandedState) => void;\n\n /** Toggles selected state of the node with provided value */\n toggleSelected: (value: string) => void;\n\n /** Selects node with provided value */\n select: (value: string) => void;\n\n /** Deselects node with provided value */\n deselect: (value: string) => void;\n\n /** Clears selected state */\n clearSelected: () => void;\n\n /** Sets selected state */\n setSelectedState: (value: string[]) => void;\n\n /** Checks node with provided value */\n checkNode: (value: string) => void;\n\n /** Unchecks node with provided value */\n uncheckNode: (value: string) => void;\n\n /** Checks all nodes */\n checkAllNodes: () => void;\n\n /** Unchecks all nodes */\n uncheckAllNodes: () => void;\n\n /** Sets checked state */\n setCheckedState: (value: string[]) => void;\n\n /** Returns all checked nodes with status */\n getCheckedNodes: () => CheckedNodeStatus[];\n\n /** Returns `true` if node with provided value is checked */\n isNodeChecked: (value: string) => boolean;\n\n /** Returns `true` if node with provided value is indeterminate */\n isNodeIndeterminate: (value: string) => boolean;\n}\n\nexport function useTree({\n initialSelectedState = [],\n expandedState,\n initialCheckedState = [],\n checkedState,\n initialExpandedState = {},\n selectedState,\n multiple = false,\n onNodeCollapse,\n onNodeExpand,\n onCheckedStateChange,\n onSelectedStateChange,\n onExpandedStateChange,\n}: UseTreeInput = {}): UseTreeReturnType {\n const [data, setData] = useState<TreeNodeData[]>([]);\n const [_expandedState, setExpandedState] = useUncontrolled({\n value: expandedState,\n defaultValue: initialExpandedState,\n finalValue: {},\n onChange: onExpandedStateChange,\n });\n\n const [_selectedState, setSelectedState] = useUncontrolled({\n value: selectedState,\n defaultValue: initialSelectedState,\n finalValue: [],\n onChange: onSelectedStateChange,\n });\n\n const [_checkedState, setCheckedState] = useUncontrolled({\n value: checkedState,\n defaultValue: initialCheckedState,\n finalValue: [],\n onChange: onCheckedStateChange,\n });\n\n const [anchorNode, setAnchorNode] = useState<string | null>(null);\n\n const initialize = useCallback(\n (_data: TreeNodeData[]) => {\n setExpandedState(getInitialTreeExpandedState(_expandedState, _data, _selectedState));\n setCheckedState(getInitialCheckedState(_checkedState, _data));\n setData(_data);\n },\n [_selectedState, _checkedState, _expandedState]\n );\n\n const toggleExpanded = useCallback(\n (value: string) => {\n const nextState = { ..._expandedState, [value]: !_expandedState[value] };\n nextState[value] ? onNodeExpand?.(value) : onNodeCollapse?.(value);\n setExpandedState(nextState);\n },\n [onNodeCollapse, onNodeExpand, _expandedState]\n );\n\n const collapse = useCallback(\n (value: string) => {\n if (_expandedState[value] !== false) {\n onNodeCollapse?.(value);\n }\n\n setExpandedState({ ..._expandedState, [value]: false });\n },\n [onNodeCollapse, _expandedState]\n );\n\n const expand = useCallback(\n (value: string) => {\n if (_expandedState[value] !== true) {\n onNodeExpand?.(value);\n }\n\n setExpandedState({ ..._expandedState, [value]: true });\n },\n [onNodeExpand, _expandedState]\n );\n\n const expandAllNodes = useCallback(() => {\n const nextState = { ..._expandedState };\n Object.keys(nextState).forEach((key) => {\n nextState[key] = true;\n });\n\n setExpandedState(nextState);\n }, [_expandedState]);\n\n const collapseAllNodes = useCallback(() => {\n const nextState = { ..._expandedState };\n Object.keys(nextState).forEach((key) => {\n nextState[key] = false;\n });\n\n setExpandedState(nextState);\n }, [_expandedState]);\n\n const toggleSelected = useCallback(\n (value: string) => {\n if (!multiple) {\n if (_selectedState.includes(value)) {\n setAnchorNode(null);\n return [];\n }\n\n setAnchorNode(value);\n return [value];\n }\n\n if (_selectedState.includes(value)) {\n setAnchorNode(null);\n return _selectedState.filter((item) => item !== value);\n }\n\n setAnchorNode(value);\n setSelectedState([..._selectedState, value]);\n },\n [_selectedState]\n );\n\n const select = useCallback(\n (value: string) => {\n setAnchorNode(value);\n setSelectedState(\n multiple\n ? _selectedState.includes(value)\n ? _selectedState\n : [..._selectedState, value]\n : [value]\n );\n },\n [_selectedState]\n );\n\n const deselect = useCallback(\n (value: string) => {\n anchorNode === value && setAnchorNode(null);\n setSelectedState(_selectedState.filter((item) => item !== value));\n },\n [_selectedState]\n );\n\n const clearSelected = useCallback(() => {\n setSelectedState([]);\n setAnchorNode(null);\n }, []);\n\n const checkNode = useCallback(\n (value: string) => {\n const checkedNodes = getChildrenNodesValues(value, data);\n setCheckedState(Array.from(new Set([..._checkedState, ...checkedNodes])));\n },\n [data, _checkedState]\n );\n\n const uncheckNode = useCallback(\n (value: string) => {\n const checkedNodes = getChildrenNodesValues(value, data);\n setCheckedState(_checkedState.filter((item) => !checkedNodes.includes(item)));\n },\n [data, _checkedState]\n );\n\n const checkAllNodes = useCallback(() => {\n setCheckedState(getAllChildrenNodes(data));\n }, [data]);\n\n const uncheckAllNodes = useCallback(() => {\n setCheckedState([]);\n }, []);\n\n const getCheckedNodes = () => getAllCheckedNodes(data, _checkedState).result;\n const isNodeChecked = (value: string) => memoizedIsNodeChecked(value, data, _checkedState);\n const isNodeIndeterminate = (value: string) =>\n memoizedIsNodeIndeterminate(value, data, _checkedState);\n\n return {\n multiple,\n expandedState: _expandedState,\n selectedState: _selectedState,\n checkedState: _checkedState,\n anchorNode,\n initialize,\n\n toggleExpanded,\n collapse,\n expand,\n expandAllNodes,\n collapseAllNodes,\n setExpandedState,\n\n checkNode,\n uncheckNode,\n checkAllNodes,\n uncheckAllNodes,\n setCheckedState,\n\n toggleSelected,\n select,\n deselect,\n clearSelected,\n setSelectedState,\n\n getCheckedNodes,\n isNodeChecked,\n isNodeIndeterminate,\n };\n}\n\nexport type TreeController = ReturnType<typeof useTree>;\n"],"mappings":"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"}