@mantine/core 9.0.1 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/components/Blockquote/Blockquote.cjs +5 -6
- package/cjs/components/Blockquote/Blockquote.cjs.map +1 -1
- package/cjs/components/Flex/Flex.cjs +7 -2
- package/cjs/components/Flex/Flex.cjs.map +1 -1
- package/cjs/components/FloatingIndicator/FloatingIndicator.cjs +1 -2
- package/cjs/components/FloatingIndicator/FloatingIndicator.cjs.map +1 -1
- package/cjs/components/MaskInput/MaskInput.cjs +24 -0
- package/cjs/components/MaskInput/MaskInput.cjs.map +1 -0
- package/cjs/components/MaskInput/use-mask-input-props.cjs +29 -0
- package/cjs/components/MaskInput/use-mask-input-props.cjs.map +1 -0
- package/cjs/components/Rating/Rating.cjs +1 -2
- package/cjs/components/Rating/Rating.cjs.map +1 -1
- package/cjs/components/SemiCircleProgress/SemiCircleProgress.cjs +2 -0
- package/cjs/components/SemiCircleProgress/SemiCircleProgress.cjs.map +1 -1
- package/cjs/components/Slider/Marks/Marks.cjs +3 -2
- package/cjs/components/Slider/Marks/Marks.cjs.map +1 -1
- package/cjs/components/Slider/Marks/is-mark-filled.cjs +2 -1
- package/cjs/components/Slider/Marks/is-mark-filled.cjs.map +1 -1
- package/cjs/components/Slider/Slider/Slider.cjs +12 -3
- package/cjs/components/Slider/Slider/Slider.cjs.map +1 -1
- package/cjs/components/Slider/Track/Track.cjs +3 -2
- package/cjs/components/Slider/Track/Track.cjs.map +1 -1
- package/cjs/components/Tabs/Tabs.cjs +3 -1
- package/cjs/components/Tabs/Tabs.cjs.map +1 -1
- package/cjs/components/Tabs/Tabs.context.cjs.map +1 -1
- package/cjs/components/Tabs/TabsPanel/TabsPanel.cjs +2 -1
- package/cjs/components/Tabs/TabsPanel/TabsPanel.cjs.map +1 -1
- package/cjs/components/Textarea/Autosize.cjs +1 -0
- package/cjs/components/Textarea/Autosize.cjs.map +1 -1
- package/cjs/components/Tree/FlatTreeNode.cjs +102 -0
- package/cjs/components/Tree/FlatTreeNode.cjs.map +1 -0
- package/cjs/components/Tree/Tree.cjs +10 -2
- package/cjs/components/Tree/Tree.cjs.map +1 -1
- package/cjs/components/Tree/Tree.module.cjs.map +1 -1
- package/cjs/components/Tree/TreeNode.cjs +65 -27
- package/cjs/components/Tree/TreeNode.cjs.map +1 -1
- package/cjs/components/Tree/filter-tree-data/filter-tree-data.cjs +23 -0
- package/cjs/components/Tree/filter-tree-data/filter-tree-data.cjs.map +1 -0
- package/cjs/components/Tree/flatten-tree-data/flatten-tree-data.cjs +28 -0
- package/cjs/components/Tree/flatten-tree-data/flatten-tree-data.cjs.map +1 -0
- package/cjs/components/Tree/get-children-nodes-values/get-children-nodes-values.cjs +1 -0
- package/cjs/components/Tree/merge-async-children/merge-async-children.cjs +32 -0
- package/cjs/components/Tree/merge-async-children/merge-async-children.cjs.map +1 -0
- package/cjs/components/Tree/move-tree-node/move-tree-node.cjs +78 -0
- package/cjs/components/Tree/move-tree-node/move-tree-node.cjs.map +1 -0
- package/cjs/components/Tree/use-tree-node-drag-drop.cjs +96 -0
- package/cjs/components/Tree/use-tree-node-drag-drop.cjs.map +1 -0
- package/cjs/components/Tree/use-tree.cjs +176 -26
- package/cjs/components/Tree/use-tree.cjs.map +1 -1
- package/cjs/core/Box/Box.cjs +6 -2
- package/cjs/core/Box/Box.cjs.map +1 -1
- package/cjs/core/InlineStyles/InlineStyles.cjs +14 -2
- package/cjs/core/InlineStyles/InlineStyles.cjs.map +1 -1
- package/cjs/core/InlineStyles/hash-styles.cjs +15 -0
- package/cjs/core/InlineStyles/hash-styles.cjs.map +1 -0
- package/cjs/core/MantineProvider/Mantine.context.cjs +4 -0
- package/cjs/core/MantineProvider/Mantine.context.cjs.map +1 -1
- package/cjs/core/MantineProvider/MantineProvider.cjs +3 -2
- package/cjs/core/MantineProvider/MantineProvider.cjs.map +1 -1
- package/cjs/core/MantineProvider/color-functions/default-variant-colors-resolver/default-variant-colors-resolver.cjs +3 -4
- package/cjs/core/MantineProvider/color-functions/default-variant-colors-resolver/default-variant-colors-resolver.cjs.map +1 -1
- package/cjs/index.cjs +16 -0
- package/esm/components/Blockquote/Blockquote.mjs +5 -6
- package/esm/components/Blockquote/Blockquote.mjs.map +1 -1
- package/esm/components/Flex/Flex.mjs +7 -2
- package/esm/components/Flex/Flex.mjs.map +1 -1
- package/esm/components/FloatingIndicator/FloatingIndicator.mjs +1 -2
- package/esm/components/FloatingIndicator/FloatingIndicator.mjs.map +1 -1
- package/esm/components/MaskInput/MaskInput.mjs +23 -0
- package/esm/components/MaskInput/MaskInput.mjs.map +1 -0
- package/esm/components/MaskInput/use-mask-input-props.mjs +28 -0
- package/esm/components/MaskInput/use-mask-input-props.mjs.map +1 -0
- package/esm/components/Rating/Rating.mjs +1 -2
- package/esm/components/Rating/Rating.mjs.map +1 -1
- package/esm/components/SemiCircleProgress/SemiCircleProgress.mjs +2 -0
- package/esm/components/SemiCircleProgress/SemiCircleProgress.mjs.map +1 -1
- package/esm/components/Slider/Marks/Marks.mjs +3 -2
- package/esm/components/Slider/Marks/Marks.mjs.map +1 -1
- package/esm/components/Slider/Marks/is-mark-filled.mjs +2 -1
- package/esm/components/Slider/Marks/is-mark-filled.mjs.map +1 -1
- package/esm/components/Slider/Slider/Slider.mjs +12 -3
- package/esm/components/Slider/Slider/Slider.mjs.map +1 -1
- package/esm/components/Slider/Track/Track.mjs +3 -2
- package/esm/components/Slider/Track/Track.mjs.map +1 -1
- package/esm/components/Tabs/Tabs.context.mjs.map +1 -1
- package/esm/components/Tabs/Tabs.mjs +3 -1
- package/esm/components/Tabs/Tabs.mjs.map +1 -1
- package/esm/components/Tabs/TabsPanel/TabsPanel.mjs +2 -1
- package/esm/components/Tabs/TabsPanel/TabsPanel.mjs.map +1 -1
- package/esm/components/Textarea/Autosize.mjs +1 -0
- package/esm/components/Textarea/Autosize.mjs.map +1 -1
- package/esm/components/Tree/FlatTreeNode.mjs +101 -0
- package/esm/components/Tree/FlatTreeNode.mjs.map +1 -0
- package/esm/components/Tree/Tree.mjs +11 -3
- package/esm/components/Tree/Tree.mjs.map +1 -1
- package/esm/components/Tree/Tree.module.mjs.map +1 -1
- package/esm/components/Tree/TreeNode.mjs +65 -27
- package/esm/components/Tree/TreeNode.mjs.map +1 -1
- package/esm/components/Tree/filter-tree-data/filter-tree-data.mjs +22 -0
- package/esm/components/Tree/filter-tree-data/filter-tree-data.mjs.map +1 -0
- package/esm/components/Tree/flatten-tree-data/flatten-tree-data.mjs +28 -0
- package/esm/components/Tree/flatten-tree-data/flatten-tree-data.mjs.map +1 -0
- package/esm/components/Tree/get-children-nodes-values/get-children-nodes-values.mjs +1 -1
- package/esm/components/Tree/merge-async-children/merge-async-children.mjs +32 -0
- package/esm/components/Tree/merge-async-children/merge-async-children.mjs.map +1 -0
- package/esm/components/Tree/move-tree-node/move-tree-node.mjs +78 -0
- package/esm/components/Tree/move-tree-node/move-tree-node.mjs.map +1 -0
- package/esm/components/Tree/use-tree-node-drag-drop.mjs +96 -0
- package/esm/components/Tree/use-tree-node-drag-drop.mjs.map +1 -0
- package/esm/components/Tree/use-tree.mjs +177 -27
- package/esm/components/Tree/use-tree.mjs.map +1 -1
- package/esm/core/Box/Box.mjs +7 -3
- package/esm/core/Box/Box.mjs.map +1 -1
- package/esm/core/InlineStyles/InlineStyles.mjs +14 -2
- package/esm/core/InlineStyles/InlineStyles.mjs.map +1 -1
- package/esm/core/InlineStyles/hash-styles.mjs +15 -0
- package/esm/core/InlineStyles/hash-styles.mjs.map +1 -0
- package/esm/core/MantineProvider/Mantine.context.mjs +4 -1
- package/esm/core/MantineProvider/Mantine.context.mjs.map +1 -1
- package/esm/core/MantineProvider/MantineProvider.mjs +3 -2
- package/esm/core/MantineProvider/MantineProvider.mjs.map +1 -1
- package/esm/core/MantineProvider/color-functions/default-variant-colors-resolver/default-variant-colors-resolver.mjs +3 -4
- package/esm/core/MantineProvider/color-functions/default-variant-colors-resolver/default-variant-colors-resolver.mjs.map +1 -1
- package/esm/index.mjs +9 -2
- package/lib/components/MaskInput/MaskInput.d.ts +68 -0
- package/lib/components/MaskInput/index.d.ts +7 -0
- package/lib/components/MaskInput/use-mask-input-props.d.ts +428 -0
- package/lib/components/Slider/Marks/Marks.d.ts +2 -1
- package/lib/components/Slider/Marks/is-mark-filled.d.ts +2 -1
- package/lib/components/Slider/Slider/Slider.d.ts +2 -0
- package/lib/components/Slider/Track/Track.d.ts +2 -1
- package/lib/components/Tabs/Tabs.context.d.ts +1 -0
- package/lib/components/Tabs/Tabs.d.ts +2 -0
- package/lib/components/Tree/FlatTreeNode.d.ts +31 -0
- package/lib/components/Tree/Tree.d.ts +21 -1
- package/lib/components/Tree/TreeNode.d.ts +6 -2
- package/lib/components/Tree/filter-tree-data/filter-tree-data.d.ts +4 -0
- package/lib/components/Tree/flatten-tree-data/flatten-tree-data.d.ts +15 -0
- package/lib/components/Tree/index.d.ts +9 -0
- package/lib/components/Tree/merge-async-children/merge-async-children.d.ts +2 -0
- package/lib/components/Tree/move-tree-node/move-tree-node.d.ts +11 -0
- package/lib/components/Tree/use-tree-node-drag-drop.d.ts +18 -0
- package/lib/components/Tree/use-tree.d.ts +19 -1
- package/lib/components/index.d.ts +1 -0
- package/lib/core/InlineStyles/InlineStyles.d.ts +2 -1
- package/lib/core/InlineStyles/hash-styles.d.ts +2 -0
- package/lib/core/InlineStyles/index.d.ts +1 -0
- package/lib/core/MantineProvider/Mantine.context.d.ts +2 -0
- package/lib/core/MantineProvider/MantineProvider.d.ts +3 -1
- package/lib/core/MantineProvider/index.d.ts +1 -1
- package/package.json +5 -5
- package/styles/Tree.css +66 -0
- package/styles/Tree.layer.css +66 -0
- package/styles.css +66 -0
- package/styles.layer.css +66 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { findTreeNode } from "../get-children-nodes-values/get-children-nodes-values.mjs";
|
|
3
|
+
//#region packages/@mantine/core/src/components/Tree/move-tree-node/move-tree-node.ts
|
|
4
|
+
function isDescendant(data, ancestorValue, value) {
|
|
5
|
+
const ancestor = findTreeNode(ancestorValue, data);
|
|
6
|
+
if (!ancestor || !ancestor.children) return false;
|
|
7
|
+
function check(nodes) {
|
|
8
|
+
for (const node of nodes) {
|
|
9
|
+
if (node.value === value) return true;
|
|
10
|
+
if (node.children && check(node.children)) return true;
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return check(ancestor.children);
|
|
15
|
+
}
|
|
16
|
+
function removeNode(data, value) {
|
|
17
|
+
let removed = null;
|
|
18
|
+
return {
|
|
19
|
+
data: data.reduce((acc, node) => {
|
|
20
|
+
if (node.value === value) {
|
|
21
|
+
removed = { ...node };
|
|
22
|
+
return acc;
|
|
23
|
+
}
|
|
24
|
+
if (node.children) {
|
|
25
|
+
const result = removeNode(node.children, value);
|
|
26
|
+
if (result.removed) {
|
|
27
|
+
removed = result.removed;
|
|
28
|
+
acc.push({
|
|
29
|
+
...node,
|
|
30
|
+
children: result.data
|
|
31
|
+
});
|
|
32
|
+
} else acc.push(node);
|
|
33
|
+
} else acc.push(node);
|
|
34
|
+
return acc;
|
|
35
|
+
}, []),
|
|
36
|
+
removed
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function insertNode(data, node, targetValue, position) {
|
|
40
|
+
if (position === "inside") return data.map((item) => {
|
|
41
|
+
if (item.value === targetValue) return {
|
|
42
|
+
...item,
|
|
43
|
+
children: [...item.children || [], node]
|
|
44
|
+
};
|
|
45
|
+
if (item.children) return {
|
|
46
|
+
...item,
|
|
47
|
+
children: insertNode(item.children, node, targetValue, position)
|
|
48
|
+
};
|
|
49
|
+
return item;
|
|
50
|
+
});
|
|
51
|
+
const targetIndex = data.findIndex((item) => item.value === targetValue);
|
|
52
|
+
if (targetIndex !== -1) {
|
|
53
|
+
const result = [...data];
|
|
54
|
+
const insertIndex = position === "before" ? targetIndex : targetIndex + 1;
|
|
55
|
+
result.splice(insertIndex, 0, node);
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
return data.map((item) => {
|
|
59
|
+
if (item.children) return {
|
|
60
|
+
...item,
|
|
61
|
+
children: insertNode(item.children, node, targetValue, position)
|
|
62
|
+
};
|
|
63
|
+
return item;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function moveTreeNode(data, payload) {
|
|
67
|
+
const { draggedNode, targetNode, position } = payload;
|
|
68
|
+
if (draggedNode === targetNode) return data;
|
|
69
|
+
if (!findTreeNode(targetNode, data)) return data;
|
|
70
|
+
if (isDescendant(data, draggedNode, targetNode)) return data;
|
|
71
|
+
const { data: dataWithout, removed } = removeNode(data, draggedNode);
|
|
72
|
+
if (!removed) return data;
|
|
73
|
+
return insertNode(dataWithout, removed, targetNode, position);
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { moveTreeNode };
|
|
77
|
+
|
|
78
|
+
//# sourceMappingURL=move-tree-node.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"move-tree-node.mjs","names":[],"sources":["../../../../src/components/Tree/move-tree-node/move-tree-node.ts"],"sourcesContent":["import { findTreeNode } from '../get-children-nodes-values/get-children-nodes-values';\nimport type { TreeNodeData } from '../Tree';\n\nexport type TreeDragDropPosition = 'before' | 'after' | 'inside';\n\nexport interface TreeDragDropPayload {\n /** Value of the dragged node */\n draggedNode: string;\n\n /** Value of the target node */\n targetNode: string;\n\n /** Position relative to the target node */\n position: TreeDragDropPosition;\n}\n\nfunction isDescendant(data: TreeNodeData[], ancestorValue: string, value: string): boolean {\n const ancestor = findTreeNode(ancestorValue, data);\n if (!ancestor || !ancestor.children) {\n return false;\n }\n\n function check(nodes: TreeNodeData[]): boolean {\n for (const node of nodes) {\n if (node.value === value) {\n return true;\n }\n\n if (node.children && check(node.children)) {\n return true;\n }\n }\n\n return false;\n }\n\n return check(ancestor.children);\n}\n\nfunction removeNode(\n data: TreeNodeData[],\n value: string\n): { data: TreeNodeData[]; removed: TreeNodeData | null } {\n let removed: TreeNodeData | null = null;\n\n const newData = data.reduce<TreeNodeData[]>((acc, node) => {\n if (node.value === value) {\n removed = { ...node };\n return acc;\n }\n\n if (node.children) {\n const result = removeNode(node.children, value);\n if (result.removed) {\n removed = result.removed;\n acc.push({ ...node, children: result.data });\n } else {\n acc.push(node);\n }\n } else {\n acc.push(node);\n }\n\n return acc;\n }, []);\n\n return { data: newData, removed };\n}\n\nfunction insertNode(\n data: TreeNodeData[],\n node: TreeNodeData,\n targetValue: string,\n position: TreeDragDropPosition\n): TreeNodeData[] {\n if (position === 'inside') {\n return data.map((item) => {\n if (item.value === targetValue) {\n return { ...item, children: [...(item.children || []), node] };\n }\n\n if (item.children) {\n return { ...item, children: insertNode(item.children, node, targetValue, position) };\n }\n\n return item;\n });\n }\n\n const targetIndex = data.findIndex((item) => item.value === targetValue);\n\n if (targetIndex !== -1) {\n const result = [...data];\n const insertIndex = position === 'before' ? targetIndex : targetIndex + 1;\n result.splice(insertIndex, 0, node);\n return result;\n }\n\n return data.map((item) => {\n if (item.children) {\n return { ...item, children: insertNode(item.children, node, targetValue, position) };\n }\n\n return item;\n });\n}\n\nexport function moveTreeNode(data: TreeNodeData[], payload: TreeDragDropPayload): TreeNodeData[] {\n const { draggedNode, targetNode, position } = payload;\n\n if (draggedNode === targetNode) {\n return data;\n }\n\n if (!findTreeNode(targetNode, data)) {\n return data;\n }\n\n if (isDescendant(data, draggedNode, targetNode)) {\n return data;\n }\n\n const { data: dataWithout, removed } = removeNode(data, draggedNode);\n\n if (!removed) {\n return data;\n }\n\n return insertNode(dataWithout, removed, targetNode, position);\n}\n"],"mappings":";;;AAgBA,SAAS,aAAa,MAAsB,eAAuB,OAAwB;CACzF,MAAM,WAAW,aAAa,eAAe,KAAK;AAClD,KAAI,CAAC,YAAY,CAAC,SAAS,SACzB,QAAO;CAGT,SAAS,MAAM,OAAgC;AAC7C,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,UAAU,MACjB,QAAO;AAGT,OAAI,KAAK,YAAY,MAAM,KAAK,SAAS,CACvC,QAAO;;AAIX,SAAO;;AAGT,QAAO,MAAM,SAAS,SAAS;;AAGjC,SAAS,WACP,MACA,OACwD;CACxD,IAAI,UAA+B;AAuBnC,QAAO;EAAE,MArBO,KAAK,QAAwB,KAAK,SAAS;AACzD,OAAI,KAAK,UAAU,OAAO;AACxB,cAAU,EAAE,GAAG,MAAM;AACrB,WAAO;;AAGT,OAAI,KAAK,UAAU;IACjB,MAAM,SAAS,WAAW,KAAK,UAAU,MAAM;AAC/C,QAAI,OAAO,SAAS;AAClB,eAAU,OAAO;AACjB,SAAI,KAAK;MAAE,GAAG;MAAM,UAAU,OAAO;MAAM,CAAC;UAE5C,KAAI,KAAK,KAAK;SAGhB,KAAI,KAAK,KAAK;AAGhB,UAAO;KACN,EAAE,CAAC;EAEkB;EAAS;;AAGnC,SAAS,WACP,MACA,MACA,aACA,UACgB;AAChB,KAAI,aAAa,SACf,QAAO,KAAK,KAAK,SAAS;AACxB,MAAI,KAAK,UAAU,YACjB,QAAO;GAAE,GAAG;GAAM,UAAU,CAAC,GAAI,KAAK,YAAY,EAAE,EAAG,KAAK;GAAE;AAGhE,MAAI,KAAK,SACP,QAAO;GAAE,GAAG;GAAM,UAAU,WAAW,KAAK,UAAU,MAAM,aAAa,SAAS;GAAE;AAGtF,SAAO;GACP;CAGJ,MAAM,cAAc,KAAK,WAAW,SAAS,KAAK,UAAU,YAAY;AAExE,KAAI,gBAAgB,IAAI;EACtB,MAAM,SAAS,CAAC,GAAG,KAAK;EACxB,MAAM,cAAc,aAAa,WAAW,cAAc,cAAc;AACxE,SAAO,OAAO,aAAa,GAAG,KAAK;AACnC,SAAO;;AAGT,QAAO,KAAK,KAAK,SAAS;AACxB,MAAI,KAAK,SACP,QAAO;GAAE,GAAG;GAAM,UAAU,WAAW,KAAK,UAAU,MAAM,aAAa,SAAS;GAAE;AAGtF,SAAO;GACP;;AAGJ,SAAgB,aAAa,MAAsB,SAA8C;CAC/F,MAAM,EAAE,aAAa,YAAY,aAAa;AAE9C,KAAI,gBAAgB,WAClB,QAAO;AAGT,KAAI,CAAC,aAAa,YAAY,KAAK,CACjC,QAAO;AAGT,KAAI,aAAa,MAAM,aAAa,WAAW,CAC7C,QAAO;CAGT,MAAM,EAAE,MAAM,aAAa,YAAY,WAAW,MAAM,YAAY;AAEpE,KAAI,CAAC,QACH,QAAO;AAGT,QAAO,WAAW,aAAa,SAAS,YAAY,SAAS"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { findTreeNode } from "./get-children-nodes-values/get-children-nodes-values.mjs";
|
|
3
|
+
//#region packages/@mantine/core/src/components/Tree/use-tree-node-drag-drop.ts
|
|
4
|
+
function isDescendantOf(data, ancestorValue, descendantValue) {
|
|
5
|
+
const ancestor = findTreeNode(ancestorValue, data);
|
|
6
|
+
if (!ancestor || !ancestor.children) return false;
|
|
7
|
+
function check(nodes) {
|
|
8
|
+
for (const node of nodes) {
|
|
9
|
+
if (node.value === descendantValue) return true;
|
|
10
|
+
if (node.children && check(node.children)) return true;
|
|
11
|
+
}
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
return check(ancestor.children);
|
|
15
|
+
}
|
|
16
|
+
function getDragDropPosition(event, element, hasChildren) {
|
|
17
|
+
const rect = element.getBoundingClientRect();
|
|
18
|
+
const y = event.clientY - rect.top;
|
|
19
|
+
const height = rect.height;
|
|
20
|
+
if (hasChildren) {
|
|
21
|
+
if (y < height * .25) return "before";
|
|
22
|
+
if (y > height * .75) return "after";
|
|
23
|
+
return "inside";
|
|
24
|
+
}
|
|
25
|
+
if (y < height * .5) return "before";
|
|
26
|
+
return "after";
|
|
27
|
+
}
|
|
28
|
+
const EMPTY_DRAG_PROPS = {};
|
|
29
|
+
function useTreeNodeDragDrop({ nodeValue, hasChildren, data, onDragDrop, dragStateRef }) {
|
|
30
|
+
if (!onDragDrop) return EMPTY_DRAG_PROPS;
|
|
31
|
+
const handleDragStart = (event) => {
|
|
32
|
+
event.stopPropagation();
|
|
33
|
+
event.dataTransfer.effectAllowed = "move";
|
|
34
|
+
event.dataTransfer.setData("text/plain", nodeValue);
|
|
35
|
+
dragStateRef.current.draggedValue = nodeValue;
|
|
36
|
+
const target = event.currentTarget;
|
|
37
|
+
requestAnimationFrame(() => {
|
|
38
|
+
target.setAttribute("data-dragging", "true");
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const handleDragOver = (event) => {
|
|
42
|
+
const draggedValue = dragStateRef.current.draggedValue;
|
|
43
|
+
if (!draggedValue || draggedValue === nodeValue) return;
|
|
44
|
+
if (isDescendantOf(data, draggedValue, nodeValue)) return;
|
|
45
|
+
event.preventDefault();
|
|
46
|
+
event.stopPropagation();
|
|
47
|
+
event.dataTransfer.dropEffect = "move";
|
|
48
|
+
const target = event.currentTarget;
|
|
49
|
+
const position = getDragDropPosition(event, target, hasChildren);
|
|
50
|
+
const prevTarget = dragStateRef.current.currentDropTarget;
|
|
51
|
+
if (prevTarget && prevTarget !== target) prevTarget.removeAttribute("data-drag-over");
|
|
52
|
+
target.setAttribute("data-drag-over", position);
|
|
53
|
+
dragStateRef.current.currentDropTarget = target;
|
|
54
|
+
};
|
|
55
|
+
const handleDragLeave = (event) => {
|
|
56
|
+
const target = event.currentTarget;
|
|
57
|
+
const related = event.relatedTarget;
|
|
58
|
+
if (related && target.contains(related)) return;
|
|
59
|
+
target.removeAttribute("data-drag-over");
|
|
60
|
+
if (dragStateRef.current.currentDropTarget === target) dragStateRef.current.currentDropTarget = null;
|
|
61
|
+
};
|
|
62
|
+
const handleDrop = (event) => {
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
event.stopPropagation();
|
|
65
|
+
const target = event.currentTarget;
|
|
66
|
+
const position = target.getAttribute("data-drag-over");
|
|
67
|
+
target.removeAttribute("data-drag-over");
|
|
68
|
+
const draggedValue = dragStateRef.current.draggedValue;
|
|
69
|
+
if (draggedValue && position && draggedValue !== nodeValue) onDragDrop({
|
|
70
|
+
draggedNode: draggedValue,
|
|
71
|
+
targetNode: nodeValue,
|
|
72
|
+
position
|
|
73
|
+
});
|
|
74
|
+
dragStateRef.current.draggedValue = null;
|
|
75
|
+
dragStateRef.current.currentDropTarget = null;
|
|
76
|
+
};
|
|
77
|
+
const handleDragEnd = (event) => {
|
|
78
|
+
event.currentTarget.removeAttribute("data-dragging");
|
|
79
|
+
const prevTarget = dragStateRef.current.currentDropTarget;
|
|
80
|
+
if (prevTarget) prevTarget.removeAttribute("data-drag-over");
|
|
81
|
+
dragStateRef.current.draggedValue = null;
|
|
82
|
+
dragStateRef.current.currentDropTarget = null;
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
draggable: true,
|
|
86
|
+
onDragStart: handleDragStart,
|
|
87
|
+
onDragOver: handleDragOver,
|
|
88
|
+
onDragLeave: handleDragLeave,
|
|
89
|
+
onDrop: handleDrop,
|
|
90
|
+
onDragEnd: handleDragEnd
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
94
|
+
export { useTreeNodeDragDrop };
|
|
95
|
+
|
|
96
|
+
//# sourceMappingURL=use-tree-node-drag-drop.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-tree-node-drag-drop.mjs","names":[],"sources":["../../../src/components/Tree/use-tree-node-drag-drop.ts"],"sourcesContent":["import { findTreeNode } from './get-children-nodes-values/get-children-nodes-values';\nimport type { TreeDragDropPayload, TreeDragDropPosition } from './move-tree-node/move-tree-node';\nimport type { TreeDragState, TreeNodeData } from './Tree';\n\ninterface UseTreeNodeDragDropInput {\n nodeValue: string;\n hasChildren: boolean;\n data: TreeNodeData[];\n onDragDrop: ((payload: TreeDragDropPayload) => void) | undefined;\n dragStateRef: React.RefObject<TreeDragState>;\n}\n\nfunction isDescendantOf(\n data: TreeNodeData[],\n ancestorValue: string,\n descendantValue: string\n): boolean {\n const ancestor = findTreeNode(ancestorValue, data);\n if (!ancestor || !ancestor.children) {\n return false;\n }\n\n function check(nodes: TreeNodeData[]): boolean {\n for (const node of nodes) {\n if (node.value === descendantValue) {\n return true;\n }\n\n if (node.children && check(node.children)) {\n return true;\n }\n }\n\n return false;\n }\n\n return check(ancestor.children);\n}\n\nfunction getDragDropPosition(\n event: React.DragEvent,\n element: HTMLElement,\n hasChildren: boolean\n): TreeDragDropPosition {\n const rect = element.getBoundingClientRect();\n const y = event.clientY - rect.top;\n const height = rect.height;\n\n if (hasChildren) {\n if (y < height * 0.25) {\n return 'before';\n }\n\n if (y > height * 0.75) {\n return 'after';\n }\n\n return 'inside';\n }\n\n if (y < height * 0.5) {\n return 'before';\n }\n\n return 'after';\n}\n\nconst EMPTY_DRAG_PROPS: Record<string, never> = {};\n\nexport function useTreeNodeDragDrop({\n nodeValue,\n hasChildren,\n data,\n onDragDrop,\n dragStateRef,\n}: UseTreeNodeDragDropInput) {\n if (!onDragDrop) {\n return EMPTY_DRAG_PROPS;\n }\n\n const handleDragStart = (event: React.DragEvent) => {\n event.stopPropagation();\n event.dataTransfer.effectAllowed = 'move';\n event.dataTransfer.setData('text/plain', nodeValue);\n dragStateRef.current.draggedValue = nodeValue;\n\n const target = event.currentTarget as HTMLElement;\n requestAnimationFrame(() => {\n target.setAttribute('data-dragging', 'true');\n });\n };\n\n const handleDragOver = (event: React.DragEvent) => {\n const draggedValue = dragStateRef.current.draggedValue;\n if (!draggedValue || draggedValue === nodeValue) {\n return;\n }\n\n if (isDescendantOf(data, draggedValue, nodeValue)) {\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n event.dataTransfer.dropEffect = 'move';\n\n const target = event.currentTarget as HTMLElement;\n const position = getDragDropPosition(event, target, hasChildren);\n\n const prevTarget = dragStateRef.current.currentDropTarget;\n if (prevTarget && prevTarget !== target) {\n prevTarget.removeAttribute('data-drag-over');\n }\n\n target.setAttribute('data-drag-over', position);\n dragStateRef.current.currentDropTarget = target;\n };\n\n const handleDragLeave = (event: React.DragEvent) => {\n const target = event.currentTarget as HTMLElement;\n const related = event.relatedTarget as HTMLElement | null;\n\n if (related && target.contains(related)) {\n return;\n }\n\n target.removeAttribute('data-drag-over');\n\n if (dragStateRef.current.currentDropTarget === target) {\n dragStateRef.current.currentDropTarget = null;\n }\n };\n\n const handleDrop = (event: React.DragEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n const target = event.currentTarget as HTMLElement;\n const position = target.getAttribute('data-drag-over') as TreeDragDropPosition | null;\n target.removeAttribute('data-drag-over');\n\n const draggedValue = dragStateRef.current.draggedValue;\n if (draggedValue && position && draggedValue !== nodeValue) {\n onDragDrop({ draggedNode: draggedValue, targetNode: nodeValue, position });\n }\n\n dragStateRef.current.draggedValue = null;\n dragStateRef.current.currentDropTarget = null;\n };\n\n const handleDragEnd = (event: React.DragEvent) => {\n const target = event.currentTarget as HTMLElement;\n target.removeAttribute('data-dragging');\n\n const prevTarget = dragStateRef.current.currentDropTarget;\n if (prevTarget) {\n prevTarget.removeAttribute('data-drag-over');\n }\n\n dragStateRef.current.draggedValue = null;\n dragStateRef.current.currentDropTarget = null;\n };\n\n return {\n draggable: true as const,\n onDragStart: handleDragStart,\n onDragOver: handleDragOver,\n onDragLeave: handleDragLeave,\n onDrop: handleDrop,\n onDragEnd: handleDragEnd,\n };\n}\n"],"mappings":";;;AAYA,SAAS,eACP,MACA,eACA,iBACS;CACT,MAAM,WAAW,aAAa,eAAe,KAAK;AAClD,KAAI,CAAC,YAAY,CAAC,SAAS,SACzB,QAAO;CAGT,SAAS,MAAM,OAAgC;AAC7C,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,KAAK,UAAU,gBACjB,QAAO;AAGT,OAAI,KAAK,YAAY,MAAM,KAAK,SAAS,CACvC,QAAO;;AAIX,SAAO;;AAGT,QAAO,MAAM,SAAS,SAAS;;AAGjC,SAAS,oBACP,OACA,SACA,aACsB;CACtB,MAAM,OAAO,QAAQ,uBAAuB;CAC5C,MAAM,IAAI,MAAM,UAAU,KAAK;CAC/B,MAAM,SAAS,KAAK;AAEpB,KAAI,aAAa;AACf,MAAI,IAAI,SAAS,IACf,QAAO;AAGT,MAAI,IAAI,SAAS,IACf,QAAO;AAGT,SAAO;;AAGT,KAAI,IAAI,SAAS,GACf,QAAO;AAGT,QAAO;;AAGT,MAAM,mBAA0C,EAAE;AAElD,SAAgB,oBAAoB,EAClC,WACA,aACA,MACA,YACA,gBAC2B;AAC3B,KAAI,CAAC,WACH,QAAO;CAGT,MAAM,mBAAmB,UAA2B;AAClD,QAAM,iBAAiB;AACvB,QAAM,aAAa,gBAAgB;AACnC,QAAM,aAAa,QAAQ,cAAc,UAAU;AACnD,eAAa,QAAQ,eAAe;EAEpC,MAAM,SAAS,MAAM;AACrB,8BAA4B;AAC1B,UAAO,aAAa,iBAAiB,OAAO;IAC5C;;CAGJ,MAAM,kBAAkB,UAA2B;EACjD,MAAM,eAAe,aAAa,QAAQ;AAC1C,MAAI,CAAC,gBAAgB,iBAAiB,UACpC;AAGF,MAAI,eAAe,MAAM,cAAc,UAAU,CAC/C;AAGF,QAAM,gBAAgB;AACtB,QAAM,iBAAiB;AACvB,QAAM,aAAa,aAAa;EAEhC,MAAM,SAAS,MAAM;EACrB,MAAM,WAAW,oBAAoB,OAAO,QAAQ,YAAY;EAEhE,MAAM,aAAa,aAAa,QAAQ;AACxC,MAAI,cAAc,eAAe,OAC/B,YAAW,gBAAgB,iBAAiB;AAG9C,SAAO,aAAa,kBAAkB,SAAS;AAC/C,eAAa,QAAQ,oBAAoB;;CAG3C,MAAM,mBAAmB,UAA2B;EAClD,MAAM,SAAS,MAAM;EACrB,MAAM,UAAU,MAAM;AAEtB,MAAI,WAAW,OAAO,SAAS,QAAQ,CACrC;AAGF,SAAO,gBAAgB,iBAAiB;AAExC,MAAI,aAAa,QAAQ,sBAAsB,OAC7C,cAAa,QAAQ,oBAAoB;;CAI7C,MAAM,cAAc,UAA2B;AAC7C,QAAM,gBAAgB;AACtB,QAAM,iBAAiB;EAEvB,MAAM,SAAS,MAAM;EACrB,MAAM,WAAW,OAAO,aAAa,iBAAiB;AACtD,SAAO,gBAAgB,iBAAiB;EAExC,MAAM,eAAe,aAAa,QAAQ;AAC1C,MAAI,gBAAgB,YAAY,iBAAiB,UAC/C,YAAW;GAAE,aAAa;GAAc,YAAY;GAAW;GAAU,CAAC;AAG5E,eAAa,QAAQ,eAAe;AACpC,eAAa,QAAQ,oBAAoB;;CAG3C,MAAM,iBAAiB,UAA2B;AACjC,QAAM,cACd,gBAAgB,gBAAgB;EAEvC,MAAM,aAAa,aAAa,QAAQ;AACxC,MAAI,WACF,YAAW,gBAAgB,iBAAiB;AAG9C,eAAa,QAAQ,eAAe;AACpC,eAAa,QAAQ,oBAAoB;;AAG3C,QAAO;EACL,WAAW;EACX,aAAa;EACb,YAAY;EACZ,aAAa;EACb,QAAQ;EACR,WAAW;EACZ"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { findTreeNode, getAllChildrenNodes, getChildrenNodesValues } from "./get-children-nodes-values/get-children-nodes-values.mjs";
|
|
2
3
|
import { getAllCheckedNodes } from "./get-all-checked-nodes/get-all-checked-nodes.mjs";
|
|
3
|
-
import { getAllChildrenNodes, getChildrenNodesValues } from "./get-children-nodes-values/get-children-nodes-values.mjs";
|
|
4
4
|
import { memoizedIsNodeChecked } from "./is-node-checked/is-node-checked.mjs";
|
|
5
5
|
import { memoizedIsNodeIndeterminate } from "./is-node-indeterminate/is-node-indeterminate.mjs";
|
|
6
|
-
import { useCallback, useState } from "react";
|
|
6
|
+
import { useCallback, useMemo, useRef, useState } from "react";
|
|
7
7
|
import { useUncontrolled } from "@mantine/hooks";
|
|
8
8
|
//#region packages/@mantine/core/src/components/Tree/use-tree.ts
|
|
9
9
|
function getInitialTreeExpandedState(initialState, data, value, acc = {}) {
|
|
@@ -15,21 +15,32 @@ function getInitialTreeExpandedState(initialState, data, value, acc = {}) {
|
|
|
15
15
|
}
|
|
16
16
|
function getTreeExpandedState(data, expandedNodesValues) {
|
|
17
17
|
const state = getInitialTreeExpandedState({}, data, []);
|
|
18
|
-
if (expandedNodesValues === "*")
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
if (expandedNodesValues === "*") {
|
|
19
|
+
const result = {};
|
|
20
|
+
const keys = Object.keys(state);
|
|
21
|
+
for (let i = 0; i < keys.length; i++) result[keys[i]] = true;
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
22
24
|
expandedNodesValues.forEach((node) => {
|
|
23
25
|
state[node] = true;
|
|
24
26
|
});
|
|
25
27
|
return state;
|
|
26
28
|
}
|
|
27
|
-
function getInitialCheckedState(initialState, data) {
|
|
29
|
+
function getInitialCheckedState(initialState, data, checkStrictly) {
|
|
30
|
+
if (checkStrictly) return initialState;
|
|
28
31
|
const acc = [];
|
|
29
32
|
initialState.forEach((node) => acc.push(...getChildrenNodesValues(node, data)));
|
|
30
33
|
return Array.from(new Set(acc));
|
|
31
34
|
}
|
|
32
|
-
function
|
|
35
|
+
function getAllNodeValues(data) {
|
|
36
|
+
const acc = [];
|
|
37
|
+
for (const node of data) {
|
|
38
|
+
acc.push(node.value);
|
|
39
|
+
if (Array.isArray(node.children) && node.children.length > 0) acc.push(...getAllNodeValues(node.children));
|
|
40
|
+
}
|
|
41
|
+
return acc;
|
|
42
|
+
}
|
|
43
|
+
function useTree({ initialSelectedState = [], expandedState, initialCheckedState = [], checkedState, initialExpandedState = {}, selectedState, multiple = false, onNodeCollapse, onNodeExpand, onCheckedStateChange, onSelectedStateChange, onExpandedStateChange, onLoadChildren, checkStrictly = false } = {}) {
|
|
33
44
|
const [data, setData] = useState([]);
|
|
34
45
|
const [_expandedState, setExpandedState] = useUncontrolled({
|
|
35
46
|
value: expandedState,
|
|
@@ -50,14 +61,53 @@ function useTree({ initialSelectedState = [], expandedState, initialCheckedState
|
|
|
50
61
|
onChange: onCheckedStateChange
|
|
51
62
|
});
|
|
52
63
|
const [anchorNode, setAnchorNode] = useState(null);
|
|
64
|
+
const loadingNodesRef = useRef(/* @__PURE__ */ new Set());
|
|
65
|
+
const loadedNodesRef = useRef(/* @__PURE__ */ new Set());
|
|
66
|
+
const [loadingNodes, setLoadingNodes] = useState([]);
|
|
67
|
+
const [loadErrors, setLoadErrors] = useState({});
|
|
53
68
|
const initialize = useCallback((_data) => {
|
|
54
69
|
setExpandedState(getInitialTreeExpandedState(_expandedState, _data, _selectedState));
|
|
55
|
-
setCheckedState(getInitialCheckedState(_checkedState, _data));
|
|
70
|
+
setCheckedState(getInitialCheckedState(_checkedState, _data, checkStrictly));
|
|
56
71
|
setData(_data);
|
|
57
72
|
}, [
|
|
58
73
|
_selectedState,
|
|
59
74
|
_checkedState,
|
|
60
|
-
_expandedState
|
|
75
|
+
_expandedState,
|
|
76
|
+
checkStrictly
|
|
77
|
+
]);
|
|
78
|
+
const loadNodeImpl = useCallback(async (value) => {
|
|
79
|
+
if (!onLoadChildren) return;
|
|
80
|
+
if (loadingNodesRef.current.has(value) || loadedNodesRef.current.has(value)) return;
|
|
81
|
+
loadingNodesRef.current.add(value);
|
|
82
|
+
setLoadingNodes(Array.from(loadingNodesRef.current));
|
|
83
|
+
setLoadErrors((prev) => {
|
|
84
|
+
if (!(value in prev)) return prev;
|
|
85
|
+
const next = { ...prev };
|
|
86
|
+
delete next[value];
|
|
87
|
+
return next;
|
|
88
|
+
});
|
|
89
|
+
try {
|
|
90
|
+
await onLoadChildren(value);
|
|
91
|
+
loadedNodesRef.current.add(value);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
94
|
+
setLoadErrors((prev) => ({
|
|
95
|
+
...prev,
|
|
96
|
+
[value]: err
|
|
97
|
+
}));
|
|
98
|
+
} finally {
|
|
99
|
+
loadingNodesRef.current.delete(value);
|
|
100
|
+
setLoadingNodes(Array.from(loadingNodesRef.current));
|
|
101
|
+
}
|
|
102
|
+
}, [onLoadChildren]);
|
|
103
|
+
const tryLoadAsync = useCallback((value) => {
|
|
104
|
+
if (!onLoadChildren) return;
|
|
105
|
+
const node = findTreeNode(value, data);
|
|
106
|
+
if (node && node.hasChildren && !Array.isArray(node.children)) loadNodeImpl(value);
|
|
107
|
+
}, [
|
|
108
|
+
onLoadChildren,
|
|
109
|
+
data,
|
|
110
|
+
loadNodeImpl
|
|
61
111
|
]);
|
|
62
112
|
const toggleExpanded = useCallback((value) => {
|
|
63
113
|
const nextState = {
|
|
@@ -65,11 +115,13 @@ function useTree({ initialSelectedState = [], expandedState, initialCheckedState
|
|
|
65
115
|
[value]: !_expandedState[value]
|
|
66
116
|
};
|
|
67
117
|
nextState[value] ? onNodeExpand?.(value) : onNodeCollapse?.(value);
|
|
118
|
+
if (nextState[value]) tryLoadAsync(value);
|
|
68
119
|
setExpandedState(nextState);
|
|
69
120
|
}, [
|
|
70
121
|
onNodeCollapse,
|
|
71
122
|
onNodeExpand,
|
|
72
|
-
_expandedState
|
|
123
|
+
_expandedState,
|
|
124
|
+
tryLoadAsync
|
|
73
125
|
]);
|
|
74
126
|
const collapse = useCallback((value) => {
|
|
75
127
|
if (_expandedState[value] !== false) onNodeCollapse?.(value);
|
|
@@ -80,18 +132,24 @@ function useTree({ initialSelectedState = [], expandedState, initialCheckedState
|
|
|
80
132
|
}, [onNodeCollapse, _expandedState]);
|
|
81
133
|
const expand = useCallback((value) => {
|
|
82
134
|
if (_expandedState[value] !== true) onNodeExpand?.(value);
|
|
135
|
+
tryLoadAsync(value);
|
|
83
136
|
setExpandedState({
|
|
84
137
|
..._expandedState,
|
|
85
138
|
[value]: true
|
|
86
139
|
});
|
|
87
|
-
}, [
|
|
140
|
+
}, [
|
|
141
|
+
onNodeExpand,
|
|
142
|
+
_expandedState,
|
|
143
|
+
tryLoadAsync
|
|
144
|
+
]);
|
|
88
145
|
const expandAllNodes = useCallback(() => {
|
|
89
146
|
const nextState = { ..._expandedState };
|
|
90
147
|
Object.keys(nextState).forEach((key) => {
|
|
91
148
|
nextState[key] = true;
|
|
149
|
+
tryLoadAsync(key);
|
|
92
150
|
});
|
|
93
151
|
setExpandedState(nextState);
|
|
94
|
-
}, [_expandedState]);
|
|
152
|
+
}, [_expandedState, tryLoadAsync]);
|
|
95
153
|
const collapseAllNodes = useCallback(() => {
|
|
96
154
|
const nextState = { ..._expandedState };
|
|
97
155
|
Object.keys(nextState).forEach((key) => {
|
|
@@ -128,23 +186,80 @@ function useTree({ initialSelectedState = [], expandedState, initialCheckedState
|
|
|
128
186
|
setAnchorNode(null);
|
|
129
187
|
}, []);
|
|
130
188
|
const checkNode = useCallback((value) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
189
|
+
if (checkStrictly) {
|
|
190
|
+
if (!_checkedState.includes(value)) setCheckedState([..._checkedState, value]);
|
|
191
|
+
} else {
|
|
192
|
+
const checkedNodes = getChildrenNodesValues(value, data);
|
|
193
|
+
setCheckedState(Array.from(new Set([..._checkedState, ...checkedNodes])));
|
|
194
|
+
}
|
|
195
|
+
}, [
|
|
196
|
+
data,
|
|
197
|
+
_checkedState,
|
|
198
|
+
checkStrictly
|
|
199
|
+
]);
|
|
134
200
|
const uncheckNode = useCallback((value) => {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
201
|
+
if (checkStrictly) setCheckedState(_checkedState.filter((item) => item !== value));
|
|
202
|
+
else {
|
|
203
|
+
const checkedNodes = getChildrenNodesValues(value, data);
|
|
204
|
+
setCheckedState(_checkedState.filter((item) => !checkedNodes.includes(item)));
|
|
205
|
+
}
|
|
206
|
+
}, [
|
|
207
|
+
data,
|
|
208
|
+
_checkedState,
|
|
209
|
+
checkStrictly
|
|
210
|
+
]);
|
|
138
211
|
const checkAllNodes = useCallback(() => {
|
|
139
|
-
setCheckedState(
|
|
140
|
-
|
|
212
|
+
if (checkStrictly) setCheckedState(getAllNodeValues(data));
|
|
213
|
+
else setCheckedState(getAllChildrenNodes(data));
|
|
214
|
+
}, [data, checkStrictly]);
|
|
141
215
|
const uncheckAllNodes = useCallback(() => {
|
|
142
216
|
setCheckedState([]);
|
|
143
217
|
}, []);
|
|
144
|
-
const getCheckedNodes = () =>
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
218
|
+
const getCheckedNodes = useCallback(() => {
|
|
219
|
+
if (checkStrictly) return _checkedState.map((value) => {
|
|
220
|
+
const node = findTreeNode(value, data);
|
|
221
|
+
return {
|
|
222
|
+
checked: true,
|
|
223
|
+
indeterminate: false,
|
|
224
|
+
value,
|
|
225
|
+
hasChildren: node ? Array.isArray(node.children) && node.children.length > 0 || !!node.hasChildren : false
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
return getAllCheckedNodes(data, _checkedState).result;
|
|
229
|
+
}, [
|
|
230
|
+
checkStrictly,
|
|
231
|
+
_checkedState,
|
|
232
|
+
data
|
|
233
|
+
]);
|
|
234
|
+
const isNodeChecked = useCallback((value) => {
|
|
235
|
+
if (checkStrictly) return _checkedState.includes(value);
|
|
236
|
+
return memoizedIsNodeChecked(value, data, _checkedState);
|
|
237
|
+
}, [
|
|
238
|
+
checkStrictly,
|
|
239
|
+
_checkedState,
|
|
240
|
+
data
|
|
241
|
+
]);
|
|
242
|
+
const isNodeIndeterminate = useCallback((value) => {
|
|
243
|
+
if (checkStrictly) return false;
|
|
244
|
+
return memoizedIsNodeIndeterminate(value, data, _checkedState);
|
|
245
|
+
}, [
|
|
246
|
+
checkStrictly,
|
|
247
|
+
_checkedState,
|
|
248
|
+
data
|
|
249
|
+
]);
|
|
250
|
+
const isNodeLoading = useCallback((value) => loadingNodes.includes(value), [loadingNodes]);
|
|
251
|
+
const getNodeLoadError = useCallback((value) => loadErrors[value] || null, [loadErrors]);
|
|
252
|
+
const invalidateNode = useCallback((value) => {
|
|
253
|
+
loadedNodesRef.current.delete(value);
|
|
254
|
+
setLoadErrors((prev) => {
|
|
255
|
+
if (!(value in prev)) return prev;
|
|
256
|
+
const next = { ...prev };
|
|
257
|
+
delete next[value];
|
|
258
|
+
return next;
|
|
259
|
+
});
|
|
260
|
+
}, []);
|
|
261
|
+
return useMemo(() => ({
|
|
262
|
+
checkStrictly,
|
|
148
263
|
multiple,
|
|
149
264
|
expandedState: _expandedState,
|
|
150
265
|
selectedState: _selectedState,
|
|
@@ -169,8 +284,43 @@ function useTree({ initialSelectedState = [], expandedState, initialCheckedState
|
|
|
169
284
|
setSelectedState,
|
|
170
285
|
getCheckedNodes,
|
|
171
286
|
isNodeChecked,
|
|
172
|
-
isNodeIndeterminate
|
|
173
|
-
|
|
287
|
+
isNodeIndeterminate,
|
|
288
|
+
isNodeLoading,
|
|
289
|
+
getNodeLoadError,
|
|
290
|
+
loadNode: loadNodeImpl,
|
|
291
|
+
invalidateNode
|
|
292
|
+
}), [
|
|
293
|
+
checkStrictly,
|
|
294
|
+
multiple,
|
|
295
|
+
_expandedState,
|
|
296
|
+
_selectedState,
|
|
297
|
+
_checkedState,
|
|
298
|
+
anchorNode,
|
|
299
|
+
initialize,
|
|
300
|
+
toggleExpanded,
|
|
301
|
+
collapse,
|
|
302
|
+
expand,
|
|
303
|
+
expandAllNodes,
|
|
304
|
+
collapseAllNodes,
|
|
305
|
+
setExpandedState,
|
|
306
|
+
checkNode,
|
|
307
|
+
uncheckNode,
|
|
308
|
+
checkAllNodes,
|
|
309
|
+
uncheckAllNodes,
|
|
310
|
+
setCheckedState,
|
|
311
|
+
toggleSelected,
|
|
312
|
+
select,
|
|
313
|
+
deselect,
|
|
314
|
+
clearSelected,
|
|
315
|
+
setSelectedState,
|
|
316
|
+
getCheckedNodes,
|
|
317
|
+
isNodeChecked,
|
|
318
|
+
isNodeIndeterminate,
|
|
319
|
+
isNodeLoading,
|
|
320
|
+
getNodeLoadError,
|
|
321
|
+
loadNodeImpl,
|
|
322
|
+
invalidateNode
|
|
323
|
+
]);
|
|
174
324
|
}
|
|
175
325
|
//#endregion
|
|
176
326
|
export { getTreeExpandedState, useTree };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-tree.mjs","names":[],"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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"}
|
|
1
|
+
{"version":3,"file":"use-tree.mjs","names":[],"sources":["../../../src/components/Tree/use-tree.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, 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 findTreeNode,\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 const result: Record<string, boolean> = {};\n const keys = Object.keys(state);\n for (let i = 0; i < keys.length; i++) {\n result[keys[i]] = true;\n }\n return result;\n }\n\n expandedNodesValues.forEach((node) => {\n state[node] = true;\n });\n\n return state;\n}\n\nfunction getInitialCheckedState(\n initialState: string[],\n data: TreeNodeData[],\n checkStrictly: boolean\n) {\n if (checkStrictly) {\n return initialState;\n }\n\n const acc: string[] = [];\n\n initialState.forEach((node) => acc.push(...getChildrenNodesValues(node, data)));\n\n return Array.from(new Set(acc));\n}\n\nfunction getAllNodeValues(data: TreeNodeData[]): string[] {\n const acc: string[] = [];\n for (const node of data) {\n acc.push(node.value);\n if (Array.isArray(node.children) && node.children.length > 0) {\n acc.push(...getAllNodeValues(node.children));\n }\n }\n return 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 /** Called when a node with `hasChildren: true` is expanded for the first time.\n * The callback should update the tree data with loaded children.\n */\n onLoadChildren?: (nodeValue: string) => Promise<void>;\n\n /** When `true`, checking a parent does not affect children and vice versa.\n * Each node's checked state is fully independent. @default false\n */\n checkStrictly?: boolean;\n}\n\nexport interface UseTreeReturnType {\n /** When `true`, each node's checked state is independent (no parent-child cascading) */\n checkStrictly: boolean;\n\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 /** Returns `true` if the node's children are currently being loaded */\n isNodeLoading: (value: string) => boolean;\n\n /** Returns the error from the last failed load attempt for the given node, or `null` */\n getNodeLoadError: (value: string) => Error | null;\n\n /** Programmatically triggers loading of a node's children */\n loadNode: (value: string) => Promise<void>;\n\n /** Clears the loaded cache for a node, causing it to re-fetch on next expand */\n invalidateNode: (value: string) => void;\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 onLoadChildren,\n checkStrictly = false,\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 loadingNodesRef = useRef(new Set<string>());\n const loadedNodesRef = useRef(new Set<string>());\n const [loadingNodes, setLoadingNodes] = useState<string[]>([]);\n const [loadErrors, setLoadErrors] = useState<Record<string, Error>>({});\n\n const initialize = useCallback(\n (_data: TreeNodeData[]) => {\n setExpandedState(getInitialTreeExpandedState(_expandedState, _data, _selectedState));\n setCheckedState(getInitialCheckedState(_checkedState, _data, checkStrictly));\n setData(_data);\n },\n [_selectedState, _checkedState, _expandedState, checkStrictly]\n );\n\n const loadNodeImpl = useCallback(\n async (value: string) => {\n if (!onLoadChildren) {\n return;\n }\n\n if (loadingNodesRef.current.has(value) || loadedNodesRef.current.has(value)) {\n return;\n }\n\n loadingNodesRef.current.add(value);\n setLoadingNodes(Array.from(loadingNodesRef.current));\n setLoadErrors((prev) => {\n if (!(value in prev)) {\n return prev;\n }\n\n const next = { ...prev };\n delete next[value];\n return next;\n });\n\n try {\n await onLoadChildren(value);\n loadedNodesRef.current.add(value);\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n setLoadErrors((prev) => ({ ...prev, [value]: err }));\n } finally {\n loadingNodesRef.current.delete(value);\n setLoadingNodes(Array.from(loadingNodesRef.current));\n }\n },\n [onLoadChildren]\n );\n\n const tryLoadAsync = useCallback(\n (value: string) => {\n if (!onLoadChildren) {\n return;\n }\n\n const node = findTreeNode(value, data);\n if (node && node.hasChildren && !Array.isArray(node.children)) {\n loadNodeImpl(value);\n }\n },\n [onLoadChildren, data, loadNodeImpl]\n );\n\n const toggleExpanded = useCallback(\n (value: string) => {\n const nextState = { ..._expandedState, [value]: !_expandedState[value] };\n nextState[value] ? onNodeExpand?.(value) : onNodeCollapse?.(value);\n if (nextState[value]) {\n tryLoadAsync(value);\n }\n setExpandedState(nextState);\n },\n [onNodeCollapse, onNodeExpand, _expandedState, tryLoadAsync]\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 tryLoadAsync(value);\n setExpandedState({ ..._expandedState, [value]: true });\n },\n [onNodeExpand, _expandedState, tryLoadAsync]\n );\n\n const expandAllNodes = useCallback(() => {\n const nextState = { ..._expandedState };\n Object.keys(nextState).forEach((key) => {\n nextState[key] = true;\n tryLoadAsync(key);\n });\n\n setExpandedState(nextState);\n }, [_expandedState, tryLoadAsync]);\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 if (checkStrictly) {\n if (!_checkedState.includes(value)) {\n setCheckedState([..._checkedState, value]);\n }\n } else {\n const checkedNodes = getChildrenNodesValues(value, data);\n setCheckedState(Array.from(new Set([..._checkedState, ...checkedNodes])));\n }\n },\n [data, _checkedState, checkStrictly]\n );\n\n const uncheckNode = useCallback(\n (value: string) => {\n if (checkStrictly) {\n setCheckedState(_checkedState.filter((item) => item !== value));\n } else {\n const checkedNodes = getChildrenNodesValues(value, data);\n setCheckedState(_checkedState.filter((item) => !checkedNodes.includes(item)));\n }\n },\n [data, _checkedState, checkStrictly]\n );\n\n const checkAllNodes = useCallback(() => {\n if (checkStrictly) {\n setCheckedState(getAllNodeValues(data));\n } else {\n setCheckedState(getAllChildrenNodes(data));\n }\n }, [data, checkStrictly]);\n\n const uncheckAllNodes = useCallback(() => {\n setCheckedState([]);\n }, []);\n\n const getCheckedNodes = useCallback((): CheckedNodeStatus[] => {\n if (checkStrictly) {\n return _checkedState.map((value) => {\n const node = findTreeNode(value, data);\n return {\n checked: true,\n indeterminate: false,\n value,\n hasChildren: node\n ? (Array.isArray(node.children) && node.children.length > 0) || !!node.hasChildren\n : false,\n };\n });\n }\n return getAllCheckedNodes(data, _checkedState).result;\n }, [checkStrictly, _checkedState, data]);\n\n const isNodeChecked = useCallback(\n (value: string) => {\n if (checkStrictly) {\n return _checkedState.includes(value);\n }\n return memoizedIsNodeChecked(value, data, _checkedState);\n },\n [checkStrictly, _checkedState, data]\n );\n\n const isNodeIndeterminate = useCallback(\n (value: string) => {\n if (checkStrictly) {\n return false;\n }\n return memoizedIsNodeIndeterminate(value, data, _checkedState);\n },\n [checkStrictly, _checkedState, data]\n );\n\n const isNodeLoading = useCallback(\n (value: string) => loadingNodes.includes(value),\n [loadingNodes]\n );\n\n const getNodeLoadError = useCallback((value: string) => loadErrors[value] || null, [loadErrors]);\n\n const invalidateNode = useCallback((value: string) => {\n loadedNodesRef.current.delete(value);\n setLoadErrors((prev) => {\n if (!(value in prev)) {\n return prev;\n }\n\n const next = { ...prev };\n delete next[value];\n return next;\n });\n }, []);\n\n return useMemo(\n () => ({\n checkStrictly,\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 isNodeLoading,\n getNodeLoadError,\n loadNode: loadNodeImpl,\n invalidateNode,\n }),\n [\n checkStrictly,\n multiple,\n _expandedState,\n _selectedState,\n _checkedState,\n anchorNode,\n initialize,\n toggleExpanded,\n collapse,\n expand,\n expandAllNodes,\n collapseAllNodes,\n setExpandedState,\n checkNode,\n uncheckNode,\n checkAllNodes,\n uncheckAllNodes,\n setCheckedState,\n toggleSelected,\n select,\n deselect,\n clearSelected,\n setSelectedState,\n getCheckedNodes,\n isNodeChecked,\n isNodeIndeterminate,\n isNodeLoading,\n getNodeLoadError,\n loadNodeImpl,\n invalidateNode,\n ]\n );\n}\n\nexport type TreeController = ReturnType<typeof useTree>;\n"],"mappings":"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"}
|
package/esm/core/Box/Box.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { isNumberLike } from "../utils/is-number-like/is-number-like.mjs";
|
|
3
|
-
import { useMantineSxTransform } from "../MantineProvider/Mantine.context.mjs";
|
|
3
|
+
import { useMantineDeduplicateInlineStyles, useMantineSxTransform } from "../MantineProvider/Mantine.context.mjs";
|
|
4
4
|
import { useMantineTheme } from "../MantineProvider/MantineThemeProvider/MantineThemeProvider.mjs";
|
|
5
5
|
import { InlineStyles } from "../InlineStyles/InlineStyles.mjs";
|
|
6
|
+
import { hashStyleProps } from "../InlineStyles/hash-styles.mjs";
|
|
6
7
|
import { extractStyleProps } from "./style-props/extract-style-props/extract-style-props.mjs";
|
|
7
8
|
import { STYlE_PROPS_DATA } from "./style-props/style-props-data.mjs";
|
|
8
9
|
import { parseStyleProps } from "./style-props/parse-style-props/parse-style-props.mjs";
|
|
@@ -18,12 +19,14 @@ function _Box({ component, style, __vars, className, variant, mod, size, hiddenF
|
|
|
18
19
|
const Element = component || "div";
|
|
19
20
|
const { styleProps, rest } = extractStyleProps(others);
|
|
20
21
|
const transformedSx = useMantineSxTransform()?.()?.(styleProps.sx);
|
|
21
|
-
const
|
|
22
|
+
const randomClassName = useRandomClassName();
|
|
22
23
|
const parsedStyleProps = parseStyleProps({
|
|
23
24
|
styleProps,
|
|
24
25
|
theme,
|
|
25
26
|
data: STYlE_PROPS_DATA
|
|
26
27
|
});
|
|
28
|
+
const deduplicateInlineStyles = useMantineDeduplicateInlineStyles();
|
|
29
|
+
const responsiveClassName = deduplicateInlineStyles && parsedStyleProps.hasResponsiveStyles ? hashStyleProps(parsedStyleProps.styles, parsedStyleProps.media) : randomClassName;
|
|
27
30
|
const props = {
|
|
28
31
|
ref,
|
|
29
32
|
style: getBoxStyle({
|
|
@@ -48,7 +51,8 @@ function _Box({ component, style, __vars, className, variant, mod, size, hiddenF
|
|
|
48
51
|
return /* @__PURE__ */ jsxs(Fragment, { children: [parsedStyleProps.hasResponsiveStyles && /* @__PURE__ */ jsx(InlineStyles, {
|
|
49
52
|
selector: `.${responsiveClassName}`,
|
|
50
53
|
styles: parsedStyleProps.styles,
|
|
51
|
-
media: parsedStyleProps.media
|
|
54
|
+
media: parsedStyleProps.media,
|
|
55
|
+
deduplicate: deduplicateInlineStyles
|
|
52
56
|
}), typeof renderRoot === "function" ? renderRoot(props) : /* @__PURE__ */ jsx(Element, { ...props })] });
|
|
53
57
|
}
|
|
54
58
|
_Box.displayName = "@mantine/core/Box";
|
package/esm/core/Box/Box.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Box.mjs","names":[],"sources":["../../../src/core/Box/Box.tsx"],"sourcesContent":["import cx from 'clsx';\nimport { polymorphic } from '../factory';\nimport { InlineStyles } from '../InlineStyles';\nimport {
|
|
1
|
+
{"version":3,"file":"Box.mjs","names":[],"sources":["../../../src/core/Box/Box.tsx"],"sourcesContent":["import cx from 'clsx';\nimport { polymorphic } from '../factory';\nimport { hashStyleProps, InlineStyles } from '../InlineStyles';\nimport {\n MantineBreakpoint,\n useMantineDeduplicateInlineStyles,\n useMantineSxTransform,\n useMantineTheme,\n} from '../MantineProvider';\nimport { isNumberLike } from '../utils';\nimport type { CssVarsProp, MantineStyleProp } from './Box.types';\nimport { getBoxMod } from './get-box-mod/get-box-mod';\nimport { getBoxStyle } from './get-box-style/get-box-style';\nimport {\n extractStyleProps,\n MantineStyleProps,\n parseStyleProps,\n STYlE_PROPS_DATA,\n} from './style-props';\nimport { useRandomClassName } from './use-random-classname/use-random-classname';\n\nexport type Mod = Record<string, any> | string;\nexport type BoxMod = Mod | Mod[] | BoxMod[];\n\nexport interface BoxProps extends MantineStyleProps {\n /** Class added to the root element, if applicable */\n className?: string;\n\n /** Inline style added to root component element, can subscribe to theme defined on MantineProvider */\n style?: MantineStyleProp;\n\n /** CSS variables defined on root component element */\n __vars?: CssVarsProp;\n\n /** `size` property passed down the HTML element */\n __size?: string;\n\n /** Breakpoint above which the component is hidden with `display: none` */\n hiddenFrom?: MantineBreakpoint;\n\n /** Breakpoint below which the component is hidden with `display: none` */\n visibleFrom?: MantineBreakpoint;\n\n /** Determines whether component should be hidden in light color scheme with `display: none` */\n lightHidden?: boolean;\n\n /** Determines whether component should be hidden in dark color scheme with `display: none` */\n darkHidden?: boolean;\n\n /** Element modifiers transformed into `data-` attributes, for example, `{ 'data-size': 'xl' }`, falsy values are removed */\n mod?: BoxMod;\n}\n\nexport type ElementProps<\n ElementType extends React.ElementType,\n PropsToOmit extends string = never,\n> = Omit<React.ComponentProps<ElementType>, 'style' | PropsToOmit>;\n\nexport interface BoxComponentProps extends BoxProps {\n /** Variant passed from parent component, sets `data-variant` */\n variant?: string;\n\n /** Size passed from parent component, sets `data-size` if value is not number like */\n size?: string | number;\n}\n\nfunction _Box({\n component,\n style,\n __vars,\n className,\n variant,\n mod,\n size,\n hiddenFrom,\n visibleFrom,\n lightHidden,\n darkHidden,\n renderRoot,\n __size,\n ref,\n ...others\n}: BoxComponentProps & { component: any; className: string; renderRoot: any; ref: any }) {\n const theme = useMantineTheme();\n const Element = component || 'div';\n const { styleProps, rest } = extractStyleProps(others);\n const useSxTransform = useMantineSxTransform();\n const transformedSx = useSxTransform?.()?.(styleProps.sx);\n const randomClassName = useRandomClassName();\n const parsedStyleProps = parseStyleProps({\n styleProps,\n theme,\n data: STYlE_PROPS_DATA,\n });\n\n const deduplicateInlineStyles = useMantineDeduplicateInlineStyles();\n const responsiveClassName =\n deduplicateInlineStyles && parsedStyleProps.hasResponsiveStyles\n ? hashStyleProps(parsedStyleProps.styles, parsedStyleProps.media)\n : randomClassName;\n\n const props = {\n ref,\n style: getBoxStyle({\n theme,\n style,\n vars: __vars,\n styleProps: parsedStyleProps.inlineStyles,\n }),\n className: cx(className, transformedSx, {\n [responsiveClassName]: parsedStyleProps.hasResponsiveStyles,\n 'mantine-light-hidden': lightHidden,\n 'mantine-dark-hidden': darkHidden,\n [`mantine-hidden-from-${hiddenFrom}`]: hiddenFrom,\n [`mantine-visible-from-${visibleFrom}`]: visibleFrom,\n }),\n 'data-variant': variant,\n 'data-size': isNumberLike(size) ? undefined : size || undefined,\n size: __size,\n ...getBoxMod(mod),\n ...rest,\n };\n\n return (\n <>\n {parsedStyleProps.hasResponsiveStyles && (\n <InlineStyles\n selector={`.${responsiveClassName}`}\n styles={parsedStyleProps.styles}\n media={parsedStyleProps.media}\n deduplicate={deduplicateInlineStyles}\n />\n )}\n\n {typeof renderRoot === 'function' ? renderRoot(props) : <Element {...props} />}\n </>\n );\n}\n\n_Box.displayName = '@mantine/core/Box';\n\nexport const Box = polymorphic<'div', BoxComponentProps>(_Box);\n"],"mappings":";;;;;;;;;;;;;;;;AAkEA,SAAS,KAAK,EACZ,WACA,OACA,QACA,WACA,SACA,KACA,MACA,YACA,aACA,aACA,YACA,YACA,QACA,KACA,GAAG,UACoF;CACvF,MAAM,QAAQ,iBAAiB;CAC/B,MAAM,UAAU,aAAa;CAC7B,MAAM,EAAE,YAAY,SAAS,kBAAkB,OAAO;CAEtD,MAAM,gBADiB,uBAAuB,IACN,GAAG,WAAW,GAAG;CACzD,MAAM,kBAAkB,oBAAoB;CAC5C,MAAM,mBAAmB,gBAAgB;EACvC;EACA;EACA,MAAM;EACP,CAAC;CAEF,MAAM,0BAA0B,mCAAmC;CACnE,MAAM,sBACJ,2BAA2B,iBAAiB,sBACxC,eAAe,iBAAiB,QAAQ,iBAAiB,MAAM,GAC/D;CAEN,MAAM,QAAQ;EACZ;EACA,OAAO,YAAY;GACjB;GACA;GACA,MAAM;GACN,YAAY,iBAAiB;GAC9B,CAAC;EACF,WAAW,GAAG,WAAW,eAAe;IACrC,sBAAsB,iBAAiB;GACxC,wBAAwB;GACxB,uBAAuB;IACtB,uBAAuB,eAAe;IACtC,wBAAwB,gBAAgB;GAC1C,CAAC;EACF,gBAAgB;EAChB,aAAa,aAAa,KAAK,GAAG,KAAA,IAAY,QAAQ,KAAA;EACtD,MAAM;EACN,GAAG,UAAU,IAAI;EACjB,GAAG;EACJ;AAED,QACE,qBAAA,UAAA,EAAA,UAAA,CACG,iBAAiB,uBAChB,oBAAC,cAAD;EACE,UAAU,IAAI;EACd,QAAQ,iBAAiB;EACzB,OAAO,iBAAiB;EACxB,aAAa;EACb,CAAA,EAGH,OAAO,eAAe,aAAa,WAAW,MAAM,GAAG,oBAAC,SAAD,EAAS,GAAI,OAAS,CAAA,CAC7E,EAAA,CAAA;;AAIP,KAAK,cAAc;AAEnB,MAAa,MAAM,YAAsC,KAAK"}
|