@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
149 lines (146 loc) • 4.8 kB
JavaScript
'use client';
import { useState, useCallback } from 'react';
import { getAllCheckedNodes } from './get-all-checked-nodes/get-all-checked-nodes.mjs';
import { getChildrenNodesValues } from './get-children-nodes-values/get-children-nodes-values.mjs';
import { memoizedIsNodeChecked } from './is-node-checked/is-node-checked.mjs';
import { memoizedIsNodeIndeterminate } from './is-node-indeterminate/is-node-indeterminate.mjs';
function getInitialExpandedState(initialState, data, value, acc = {}) {
data.forEach((node) => {
acc[node.value] = node.value in initialState ? initialState[node.value] : node.value === value;
if (Array.isArray(node.children)) {
getInitialExpandedState(initialState, node.children, value, acc);
}
});
return acc;
}
function getInitialCheckedState(initialState, data) {
const acc = [];
initialState.forEach((node) => acc.push(...getChildrenNodesValues(node, data)));
return acc;
}
function useTree({
initialSelectedState = [],
initialCheckedState = [],
initialExpandedState = {},
multiple = false
} = {}) {
const [data, setData] = useState([]);
const [expandedState, setExpandedState] = useState(initialExpandedState);
const [selectedState, setSelectedState] = useState(initialSelectedState);
const [checkedState, setCheckedState] = useState(initialCheckedState);
const [anchorNode, setAnchorNode] = useState(null);
const [hoveredNode, setHoveredNode] = useState(null);
const initialize = useCallback(
(_data) => {
setExpandedState((current) => getInitialExpandedState(current, _data, selectedState));
setCheckedState((current) => getInitialCheckedState(current, _data));
setData(_data);
},
[selectedState, checkedState]
);
const toggleExpanded = useCallback((value) => {
setExpandedState((current) => ({ ...current, [value]: !current[value] }));
}, []);
const collapse = useCallback((value) => {
setExpandedState((current) => ({ ...current, [value]: false }));
}, []);
const expand = useCallback((value) => {
setExpandedState((current) => ({ ...current, [value]: true }));
}, []);
const expandAllNodes = useCallback(() => {
setExpandedState((current) => {
const next = { ...current };
Object.keys(next).forEach((key) => {
next[key] = true;
});
return next;
});
}, []);
const collapseAllNodes = useCallback(() => {
setExpandedState((current) => {
const next = { ...current };
Object.keys(next).forEach((key) => {
next[key] = false;
});
return next;
});
}, []);
const toggleSelected = useCallback(
(value) => setSelectedState((current) => {
if (!multiple) {
if (current.includes(value)) {
setAnchorNode(null);
return [];
}
setAnchorNode(value);
return [value];
}
if (current.includes(value)) {
setAnchorNode(null);
return current.filter((item) => item !== value);
}
setAnchorNode(value);
return [...current, value];
}),
[]
);
const select = useCallback((value) => {
setAnchorNode(value);
setSelectedState(
(current) => multiple ? current.includes(value) ? current : [...current, value] : [value]
);
}, []);
const deselect = useCallback((value) => {
anchorNode === value && setAnchorNode(null);
setSelectedState((current) => current.filter((item) => item !== value));
}, []);
const clearSelected = useCallback(() => {
setSelectedState([]);
setAnchorNode(null);
}, []);
const checkNode = useCallback(
(value) => {
const checkedNodes = getChildrenNodesValues(value, data);
setCheckedState((current) => Array.from(/* @__PURE__ */ new Set([...current, ...checkedNodes])));
},
[data]
);
const uncheckNode = useCallback(
(value) => {
const checkedNodes = getChildrenNodesValues(value, data);
setCheckedState((current) => current.filter((item) => !checkedNodes.includes(item)));
},
[data]
);
const getCheckedNodes = () => getAllCheckedNodes(data, checkedState).result;
const isNodeChecked = (value) => memoizedIsNodeChecked(value, data, checkedState);
const isNodeIndeterminate = (value) => memoizedIsNodeIndeterminate(value, data, checkedState);
return {
multiple,
expandedState,
selectedState,
checkedState,
anchorNode,
initialize,
toggleExpanded,
collapse,
expand,
expandAllNodes,
collapseAllNodes,
setExpandedState,
checkNode,
uncheckNode,
toggleSelected,
select,
deselect,
clearSelected,
setSelectedState,
hoveredNode,
setHoveredNode,
getCheckedNodes,
isNodeChecked,
isNodeIndeterminate
};
}
export { useTree };
//# sourceMappingURL=use-tree.mjs.map