@mantine/core
Version:
React components library focused on usability, accessibility and developer experience
330 lines (329 loc) • 10.6 kB
JavaScript
"use client";
require("../../_virtual/_rolldown/runtime.cjs");
const require_get_children_nodes_values = require("./get-children-nodes-values/get-children-nodes-values.cjs");
const require_get_all_checked_nodes = require("./get-all-checked-nodes/get-all-checked-nodes.cjs");
const require_is_node_checked = require("./is-node-checked/is-node-checked.cjs");
const require_is_node_indeterminate = require("./is-node-indeterminate/is-node-indeterminate.cjs");
let react = require("react");
let _mantine_hooks = require("@mantine/hooks");
//#region packages/@mantine/core/src/components/Tree/use-tree.ts
function getInitialTreeExpandedState(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)) getInitialTreeExpandedState(initialState, node.children, value, acc);
});
return acc;
}
function getTreeExpandedState(data, expandedNodesValues) {
const state = getInitialTreeExpandedState({}, data, []);
if (expandedNodesValues === "*") {
const result = {};
const keys = Object.keys(state);
for (let i = 0; i < keys.length; i++) result[keys[i]] = true;
return result;
}
expandedNodesValues.forEach((node) => {
state[node] = true;
});
return state;
}
function getInitialCheckedState(initialState, data, checkStrictly) {
if (checkStrictly) return initialState;
const acc = [];
initialState.forEach((node) => acc.push(...require_get_children_nodes_values.getChildrenNodesValues(node, data)));
return Array.from(new Set(acc));
}
function getAllNodeValues(data) {
const acc = [];
for (const node of data) {
acc.push(node.value);
if (Array.isArray(node.children) && node.children.length > 0) acc.push(...getAllNodeValues(node.children));
}
return acc;
}
function useTree({ initialSelectedState = [], expandedState, initialCheckedState = [], checkedState, initialExpandedState = {}, selectedState, multiple = false, onNodeCollapse, onNodeExpand, onCheckedStateChange, onSelectedStateChange, onExpandedStateChange, onLoadChildren, checkStrictly = false } = {}) {
const [data, setData] = (0, react.useState)([]);
const [_expandedState, setExpandedState] = (0, _mantine_hooks.useUncontrolled)({
value: expandedState,
defaultValue: initialExpandedState,
finalValue: {},
onChange: onExpandedStateChange
});
const [_selectedState, setSelectedState] = (0, _mantine_hooks.useUncontrolled)({
value: selectedState,
defaultValue: initialSelectedState,
finalValue: [],
onChange: onSelectedStateChange
});
const [_checkedState, setCheckedState] = (0, _mantine_hooks.useUncontrolled)({
value: checkedState,
defaultValue: initialCheckedState,
finalValue: [],
onChange: onCheckedStateChange
});
const [anchorNode, setAnchorNode] = (0, react.useState)(null);
const loadingNodesRef = (0, react.useRef)(/* @__PURE__ */ new Set());
const loadedNodesRef = (0, react.useRef)(/* @__PURE__ */ new Set());
const [loadingNodes, setLoadingNodes] = (0, react.useState)([]);
const [loadErrors, setLoadErrors] = (0, react.useState)({});
const initialize = (0, react.useCallback)((_data) => {
setExpandedState(getInitialTreeExpandedState(_expandedState, _data, _selectedState));
setCheckedState(getInitialCheckedState(_checkedState, _data, checkStrictly));
setData(_data);
}, [
_selectedState,
_checkedState,
_expandedState,
checkStrictly
]);
const loadNodeImpl = (0, react.useCallback)(async (value) => {
if (!onLoadChildren) return;
if (loadingNodesRef.current.has(value) || loadedNodesRef.current.has(value)) return;
loadingNodesRef.current.add(value);
setLoadingNodes(Array.from(loadingNodesRef.current));
setLoadErrors((prev) => {
if (!(value in prev)) return prev;
const next = { ...prev };
delete next[value];
return next;
});
try {
await onLoadChildren(value);
loadedNodesRef.current.add(value);
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
setLoadErrors((prev) => ({
...prev,
[value]: err
}));
} finally {
loadingNodesRef.current.delete(value);
setLoadingNodes(Array.from(loadingNodesRef.current));
}
}, [onLoadChildren]);
const tryLoadAsync = (0, react.useCallback)((value) => {
if (!onLoadChildren) return;
const node = require_get_children_nodes_values.findTreeNode(value, data);
if (node && node.hasChildren && !Array.isArray(node.children)) loadNodeImpl(value);
}, [
onLoadChildren,
data,
loadNodeImpl
]);
const toggleExpanded = (0, react.useCallback)((value) => {
const nextState = {
..._expandedState,
[value]: !_expandedState[value]
};
nextState[value] ? onNodeExpand?.(value) : onNodeCollapse?.(value);
if (nextState[value]) tryLoadAsync(value);
setExpandedState(nextState);
}, [
onNodeCollapse,
onNodeExpand,
_expandedState,
tryLoadAsync
]);
const collapse = (0, react.useCallback)((value) => {
if (_expandedState[value] !== false) onNodeCollapse?.(value);
setExpandedState({
..._expandedState,
[value]: false
});
}, [onNodeCollapse, _expandedState]);
const expand = (0, react.useCallback)((value) => {
if (_expandedState[value] !== true) onNodeExpand?.(value);
tryLoadAsync(value);
setExpandedState({
..._expandedState,
[value]: true
});
}, [
onNodeExpand,
_expandedState,
tryLoadAsync
]);
const expandAllNodes = (0, react.useCallback)(() => {
const nextState = { ..._expandedState };
Object.keys(nextState).forEach((key) => {
nextState[key] = true;
tryLoadAsync(key);
});
setExpandedState(nextState);
}, [_expandedState, tryLoadAsync]);
const collapseAllNodes = (0, react.useCallback)(() => {
const nextState = { ..._expandedState };
Object.keys(nextState).forEach((key) => {
nextState[key] = false;
});
setExpandedState(nextState);
}, [_expandedState]);
const toggleSelected = (0, react.useCallback)((value) => {
if (!multiple) {
if (_selectedState.includes(value)) {
setAnchorNode(null);
return [];
}
setAnchorNode(value);
return [value];
}
if (_selectedState.includes(value)) {
setAnchorNode(null);
return _selectedState.filter((item) => item !== value);
}
setAnchorNode(value);
setSelectedState([..._selectedState, value]);
}, [_selectedState]);
const select = (0, react.useCallback)((value) => {
setAnchorNode(value);
setSelectedState(multiple ? _selectedState.includes(value) ? _selectedState : [..._selectedState, value] : [value]);
}, [_selectedState]);
const deselect = (0, react.useCallback)((value) => {
anchorNode === value && setAnchorNode(null);
setSelectedState(_selectedState.filter((item) => item !== value));
}, [_selectedState]);
const clearSelected = (0, react.useCallback)(() => {
setSelectedState([]);
setAnchorNode(null);
}, []);
const checkNode = (0, react.useCallback)((value) => {
if (checkStrictly) {
if (!_checkedState.includes(value)) setCheckedState([..._checkedState, value]);
} else {
const checkedNodes = require_get_children_nodes_values.getChildrenNodesValues(value, data);
setCheckedState(Array.from(new Set([..._checkedState, ...checkedNodes])));
}
}, [
data,
_checkedState,
checkStrictly
]);
const uncheckNode = (0, react.useCallback)((value) => {
if (checkStrictly) setCheckedState(_checkedState.filter((item) => item !== value));
else {
const checkedNodes = require_get_children_nodes_values.getChildrenNodesValues(value, data);
setCheckedState(_checkedState.filter((item) => !checkedNodes.includes(item)));
}
}, [
data,
_checkedState,
checkStrictly
]);
const checkAllNodes = (0, react.useCallback)(() => {
if (checkStrictly) setCheckedState(getAllNodeValues(data));
else setCheckedState(require_get_children_nodes_values.getAllChildrenNodes(data));
}, [data, checkStrictly]);
const uncheckAllNodes = (0, react.useCallback)(() => {
setCheckedState([]);
}, []);
const getCheckedNodes = (0, react.useCallback)(() => {
if (checkStrictly) return _checkedState.map((value) => {
const node = require_get_children_nodes_values.findTreeNode(value, data);
return {
checked: true,
indeterminate: false,
value,
hasChildren: node ? Array.isArray(node.children) && node.children.length > 0 || !!node.hasChildren : false
};
});
return require_get_all_checked_nodes.getAllCheckedNodes(data, _checkedState).result;
}, [
checkStrictly,
_checkedState,
data
]);
const isNodeChecked = (0, react.useCallback)((value) => {
if (checkStrictly) return _checkedState.includes(value);
return require_is_node_checked.memoizedIsNodeChecked(value, data, _checkedState);
}, [
checkStrictly,
_checkedState,
data
]);
const isNodeIndeterminate = (0, react.useCallback)((value) => {
if (checkStrictly) return false;
return require_is_node_indeterminate.memoizedIsNodeIndeterminate(value, data, _checkedState);
}, [
checkStrictly,
_checkedState,
data
]);
const isNodeLoading = (0, react.useCallback)((value) => loadingNodes.includes(value), [loadingNodes]);
const getNodeLoadError = (0, react.useCallback)((value) => loadErrors[value] || null, [loadErrors]);
const invalidateNode = (0, react.useCallback)((value) => {
loadedNodesRef.current.delete(value);
setLoadErrors((prev) => {
if (!(value in prev)) return prev;
const next = { ...prev };
delete next[value];
return next;
});
}, []);
return (0, react.useMemo)(() => ({
checkStrictly,
multiple,
expandedState: _expandedState,
selectedState: _selectedState,
checkedState: _checkedState,
anchorNode,
initialize,
toggleExpanded,
collapse,
expand,
expandAllNodes,
collapseAllNodes,
setExpandedState,
checkNode,
uncheckNode,
checkAllNodes,
uncheckAllNodes,
setCheckedState,
toggleSelected,
select,
deselect,
clearSelected,
setSelectedState,
getCheckedNodes,
isNodeChecked,
isNodeIndeterminate,
isNodeLoading,
getNodeLoadError,
loadNode: loadNodeImpl,
invalidateNode
}), [
checkStrictly,
multiple,
_expandedState,
_selectedState,
_checkedState,
anchorNode,
initialize,
toggleExpanded,
collapse,
expand,
expandAllNodes,
collapseAllNodes,
setExpandedState,
checkNode,
uncheckNode,
checkAllNodes,
uncheckAllNodes,
setCheckedState,
toggleSelected,
select,
deselect,
clearSelected,
setSelectedState,
getCheckedNodes,
isNodeChecked,
isNodeIndeterminate,
isNodeLoading,
getNodeLoadError,
loadNodeImpl,
invalidateNode
]);
}
//#endregion
exports.getTreeExpandedState = getTreeExpandedState;
exports.useTree = useTree;
//# sourceMappingURL=use-tree.cjs.map