@mantine/core 9.0.2 → 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.
Files changed (147) hide show
  1. package/cjs/components/Blockquote/Blockquote.cjs +5 -6
  2. package/cjs/components/Blockquote/Blockquote.cjs.map +1 -1
  3. package/cjs/components/Flex/Flex.cjs +7 -2
  4. package/cjs/components/Flex/Flex.cjs.map +1 -1
  5. package/cjs/components/FloatingIndicator/FloatingIndicator.cjs +1 -2
  6. package/cjs/components/FloatingIndicator/FloatingIndicator.cjs.map +1 -1
  7. package/cjs/components/MaskInput/MaskInput.cjs +24 -0
  8. package/cjs/components/MaskInput/MaskInput.cjs.map +1 -0
  9. package/cjs/components/MaskInput/use-mask-input-props.cjs +29 -0
  10. package/cjs/components/MaskInput/use-mask-input-props.cjs.map +1 -0
  11. package/cjs/components/Rating/Rating.cjs +1 -2
  12. package/cjs/components/Rating/Rating.cjs.map +1 -1
  13. package/cjs/components/SemiCircleProgress/SemiCircleProgress.cjs +2 -0
  14. package/cjs/components/SemiCircleProgress/SemiCircleProgress.cjs.map +1 -1
  15. package/cjs/components/Slider/Marks/Marks.cjs +3 -2
  16. package/cjs/components/Slider/Marks/Marks.cjs.map +1 -1
  17. package/cjs/components/Slider/Marks/is-mark-filled.cjs +2 -1
  18. package/cjs/components/Slider/Marks/is-mark-filled.cjs.map +1 -1
  19. package/cjs/components/Slider/Slider/Slider.cjs +12 -3
  20. package/cjs/components/Slider/Slider/Slider.cjs.map +1 -1
  21. package/cjs/components/Slider/Track/Track.cjs +3 -2
  22. package/cjs/components/Slider/Track/Track.cjs.map +1 -1
  23. package/cjs/components/Tabs/Tabs.cjs +3 -1
  24. package/cjs/components/Tabs/Tabs.cjs.map +1 -1
  25. package/cjs/components/Tabs/Tabs.context.cjs.map +1 -1
  26. package/cjs/components/Tabs/TabsPanel/TabsPanel.cjs +2 -1
  27. package/cjs/components/Tabs/TabsPanel/TabsPanel.cjs.map +1 -1
  28. package/cjs/components/Tree/FlatTreeNode.cjs +102 -0
  29. package/cjs/components/Tree/FlatTreeNode.cjs.map +1 -0
  30. package/cjs/components/Tree/Tree.cjs +10 -2
  31. package/cjs/components/Tree/Tree.cjs.map +1 -1
  32. package/cjs/components/Tree/Tree.module.cjs.map +1 -1
  33. package/cjs/components/Tree/TreeNode.cjs +65 -27
  34. package/cjs/components/Tree/TreeNode.cjs.map +1 -1
  35. package/cjs/components/Tree/filter-tree-data/filter-tree-data.cjs +23 -0
  36. package/cjs/components/Tree/filter-tree-data/filter-tree-data.cjs.map +1 -0
  37. package/cjs/components/Tree/flatten-tree-data/flatten-tree-data.cjs +28 -0
  38. package/cjs/components/Tree/flatten-tree-data/flatten-tree-data.cjs.map +1 -0
  39. package/cjs/components/Tree/get-children-nodes-values/get-children-nodes-values.cjs +1 -0
  40. package/cjs/components/Tree/merge-async-children/merge-async-children.cjs +32 -0
  41. package/cjs/components/Tree/merge-async-children/merge-async-children.cjs.map +1 -0
  42. package/cjs/components/Tree/move-tree-node/move-tree-node.cjs +78 -0
  43. package/cjs/components/Tree/move-tree-node/move-tree-node.cjs.map +1 -0
  44. package/cjs/components/Tree/use-tree-node-drag-drop.cjs +96 -0
  45. package/cjs/components/Tree/use-tree-node-drag-drop.cjs.map +1 -0
  46. package/cjs/components/Tree/use-tree.cjs +176 -26
  47. package/cjs/components/Tree/use-tree.cjs.map +1 -1
  48. package/cjs/core/Box/Box.cjs +6 -2
  49. package/cjs/core/Box/Box.cjs.map +1 -1
  50. package/cjs/core/InlineStyles/InlineStyles.cjs +14 -2
  51. package/cjs/core/InlineStyles/InlineStyles.cjs.map +1 -1
  52. package/cjs/core/InlineStyles/hash-styles.cjs +15 -0
  53. package/cjs/core/InlineStyles/hash-styles.cjs.map +1 -0
  54. package/cjs/core/MantineProvider/Mantine.context.cjs +4 -0
  55. package/cjs/core/MantineProvider/Mantine.context.cjs.map +1 -1
  56. package/cjs/core/MantineProvider/MantineProvider.cjs +3 -2
  57. package/cjs/core/MantineProvider/MantineProvider.cjs.map +1 -1
  58. package/cjs/index.cjs +16 -0
  59. package/esm/components/Blockquote/Blockquote.mjs +5 -6
  60. package/esm/components/Blockquote/Blockquote.mjs.map +1 -1
  61. package/esm/components/Flex/Flex.mjs +7 -2
  62. package/esm/components/Flex/Flex.mjs.map +1 -1
  63. package/esm/components/FloatingIndicator/FloatingIndicator.mjs +1 -2
  64. package/esm/components/FloatingIndicator/FloatingIndicator.mjs.map +1 -1
  65. package/esm/components/MaskInput/MaskInput.mjs +23 -0
  66. package/esm/components/MaskInput/MaskInput.mjs.map +1 -0
  67. package/esm/components/MaskInput/use-mask-input-props.mjs +28 -0
  68. package/esm/components/MaskInput/use-mask-input-props.mjs.map +1 -0
  69. package/esm/components/Rating/Rating.mjs +1 -2
  70. package/esm/components/Rating/Rating.mjs.map +1 -1
  71. package/esm/components/SemiCircleProgress/SemiCircleProgress.mjs +2 -0
  72. package/esm/components/SemiCircleProgress/SemiCircleProgress.mjs.map +1 -1
  73. package/esm/components/Slider/Marks/Marks.mjs +3 -2
  74. package/esm/components/Slider/Marks/Marks.mjs.map +1 -1
  75. package/esm/components/Slider/Marks/is-mark-filled.mjs +2 -1
  76. package/esm/components/Slider/Marks/is-mark-filled.mjs.map +1 -1
  77. package/esm/components/Slider/Slider/Slider.mjs +12 -3
  78. package/esm/components/Slider/Slider/Slider.mjs.map +1 -1
  79. package/esm/components/Slider/Track/Track.mjs +3 -2
  80. package/esm/components/Slider/Track/Track.mjs.map +1 -1
  81. package/esm/components/Tabs/Tabs.context.mjs.map +1 -1
  82. package/esm/components/Tabs/Tabs.mjs +3 -1
  83. package/esm/components/Tabs/Tabs.mjs.map +1 -1
  84. package/esm/components/Tabs/TabsPanel/TabsPanel.mjs +2 -1
  85. package/esm/components/Tabs/TabsPanel/TabsPanel.mjs.map +1 -1
  86. package/esm/components/Tree/FlatTreeNode.mjs +101 -0
  87. package/esm/components/Tree/FlatTreeNode.mjs.map +1 -0
  88. package/esm/components/Tree/Tree.mjs +11 -3
  89. package/esm/components/Tree/Tree.mjs.map +1 -1
  90. package/esm/components/Tree/Tree.module.mjs.map +1 -1
  91. package/esm/components/Tree/TreeNode.mjs +65 -27
  92. package/esm/components/Tree/TreeNode.mjs.map +1 -1
  93. package/esm/components/Tree/filter-tree-data/filter-tree-data.mjs +22 -0
  94. package/esm/components/Tree/filter-tree-data/filter-tree-data.mjs.map +1 -0
  95. package/esm/components/Tree/flatten-tree-data/flatten-tree-data.mjs +28 -0
  96. package/esm/components/Tree/flatten-tree-data/flatten-tree-data.mjs.map +1 -0
  97. package/esm/components/Tree/get-children-nodes-values/get-children-nodes-values.mjs +1 -1
  98. package/esm/components/Tree/merge-async-children/merge-async-children.mjs +32 -0
  99. package/esm/components/Tree/merge-async-children/merge-async-children.mjs.map +1 -0
  100. package/esm/components/Tree/move-tree-node/move-tree-node.mjs +78 -0
  101. package/esm/components/Tree/move-tree-node/move-tree-node.mjs.map +1 -0
  102. package/esm/components/Tree/use-tree-node-drag-drop.mjs +96 -0
  103. package/esm/components/Tree/use-tree-node-drag-drop.mjs.map +1 -0
  104. package/esm/components/Tree/use-tree.mjs +177 -27
  105. package/esm/components/Tree/use-tree.mjs.map +1 -1
  106. package/esm/core/Box/Box.mjs +7 -3
  107. package/esm/core/Box/Box.mjs.map +1 -1
  108. package/esm/core/InlineStyles/InlineStyles.mjs +14 -2
  109. package/esm/core/InlineStyles/InlineStyles.mjs.map +1 -1
  110. package/esm/core/InlineStyles/hash-styles.mjs +15 -0
  111. package/esm/core/InlineStyles/hash-styles.mjs.map +1 -0
  112. package/esm/core/MantineProvider/Mantine.context.mjs +4 -1
  113. package/esm/core/MantineProvider/Mantine.context.mjs.map +1 -1
  114. package/esm/core/MantineProvider/MantineProvider.mjs +3 -2
  115. package/esm/core/MantineProvider/MantineProvider.mjs.map +1 -1
  116. package/esm/index.mjs +9 -2
  117. package/lib/components/MaskInput/MaskInput.d.ts +68 -0
  118. package/lib/components/MaskInput/index.d.ts +7 -0
  119. package/lib/components/MaskInput/use-mask-input-props.d.ts +428 -0
  120. package/lib/components/Slider/Marks/Marks.d.ts +2 -1
  121. package/lib/components/Slider/Marks/is-mark-filled.d.ts +2 -1
  122. package/lib/components/Slider/Slider/Slider.d.ts +2 -0
  123. package/lib/components/Slider/Track/Track.d.ts +2 -1
  124. package/lib/components/Tabs/Tabs.context.d.ts +1 -0
  125. package/lib/components/Tabs/Tabs.d.ts +2 -0
  126. package/lib/components/Tree/FlatTreeNode.d.ts +31 -0
  127. package/lib/components/Tree/Tree.d.ts +21 -1
  128. package/lib/components/Tree/TreeNode.d.ts +6 -2
  129. package/lib/components/Tree/filter-tree-data/filter-tree-data.d.ts +4 -0
  130. package/lib/components/Tree/flatten-tree-data/flatten-tree-data.d.ts +15 -0
  131. package/lib/components/Tree/index.d.ts +9 -0
  132. package/lib/components/Tree/merge-async-children/merge-async-children.d.ts +2 -0
  133. package/lib/components/Tree/move-tree-node/move-tree-node.d.ts +11 -0
  134. package/lib/components/Tree/use-tree-node-drag-drop.d.ts +18 -0
  135. package/lib/components/Tree/use-tree.d.ts +19 -1
  136. package/lib/components/index.d.ts +1 -0
  137. package/lib/core/InlineStyles/InlineStyles.d.ts +2 -1
  138. package/lib/core/InlineStyles/hash-styles.d.ts +2 -0
  139. package/lib/core/InlineStyles/index.d.ts +1 -0
  140. package/lib/core/MantineProvider/Mantine.context.d.ts +2 -0
  141. package/lib/core/MantineProvider/MantineProvider.d.ts +3 -1
  142. package/lib/core/MantineProvider/index.d.ts +1 -1
  143. package/package.json +5 -5
  144. package/styles/Tree.css +66 -0
  145. package/styles/Tree.layer.css +66 -0
  146. package/styles.css +66 -0
  147. package/styles.layer.css +66 -0
@@ -1,6 +1,8 @@
1
1
  "use client";
2
2
  import { findElementAncestor } from "../../core/utils/find-element-ancestor/find-element-ancestor.mjs";
3
3
  import { Box } from "../../core/Box/Box.mjs";
4
+ import { Loader } from "../Loader/Loader.mjs";
5
+ import { useTreeNodeDragDrop } from "./use-tree-node-drag-drop.mjs";
4
6
  import { Activity, useRef } from "react";
5
7
  import { jsx, jsxs } from "react/jsx-runtime";
6
8
  //#region packages/@mantine/core/src/components/Tree/TreeNode.tsx
@@ -12,8 +14,14 @@ function getValuesRange(anchor, value, flatValues) {
12
14
  const end = Math.max(anchorIndex, valueIndex);
13
15
  return flatValues.slice(start, end + 1);
14
16
  }
15
- function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selectOnClick, isSubtree, level = 1, renderNode, flatValues, allowRangeSelection, expandOnSpace, checkOnSpace, keepMounted }) {
17
+ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selectOnClick, isSubtree, level = 1, renderNode, flatValues, allowRangeSelection, expandOnSpace, checkOnSpace, keepMounted, onDragDrop, dragStateRef, data }) {
16
18
  const ref = useRef(null);
19
+ const hasLoadedChildren = Array.isArray(node.children);
20
+ const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;
21
+ const hasChildren = hasLoadedChildren || hasAsyncChildren;
22
+ const isLoading = controller.isNodeLoading(node.value);
23
+ const loadError = controller.getNodeLoadError(node.value);
24
+ const isExpanded = controller.expandedState[node.value] || false;
17
25
  const nested = (node.children || []).map((child) => /* @__PURE__ */ jsx(TreeNode, {
18
26
  node: child,
19
27
  flatValues,
@@ -28,19 +36,29 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
28
36
  allowRangeSelection,
29
37
  expandOnSpace,
30
38
  checkOnSpace,
31
- keepMounted
39
+ keepMounted,
40
+ onDragDrop,
41
+ dragStateRef,
42
+ data
32
43
  }, child.value));
44
+ const dragProps = useTreeNodeDragDrop({
45
+ nodeValue: node.value,
46
+ hasChildren,
47
+ data,
48
+ onDragDrop,
49
+ dragStateRef
50
+ });
33
51
  const handleKeyDown = (event) => {
34
52
  if (event.nativeEvent.code === "ArrowRight") {
35
53
  event.stopPropagation();
36
54
  event.preventDefault();
37
- if (controller.expandedState[node.value]) event.currentTarget.querySelector("[role=treeitem]")?.focus();
55
+ if (isExpanded) event.currentTarget.querySelector("[role=treeitem]")?.focus();
38
56
  else controller.expand(node.value);
39
57
  }
40
58
  if (event.nativeEvent.code === "ArrowLeft") {
41
59
  event.stopPropagation();
42
60
  event.preventDefault();
43
- if (controller.expandedState[node.value] && (node.children || []).length > 0) controller.collapse(node.value);
61
+ if (isExpanded && hasChildren) controller.collapse(node.value);
44
62
  else if (isSubtree) findElementAncestor(event.currentTarget, "[role=treeitem]")?.focus();
45
63
  }
46
64
  if (event.nativeEvent.code === "ArrowDown" || event.nativeEvent.code === "ArrowUp") {
@@ -77,7 +95,7 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
77
95
  controller.setSelectedState(getValuesRange(controller.anchorNode, node.value, flatValues));
78
96
  ref.current?.focus();
79
97
  } else {
80
- expandOnClick && controller.toggleExpanded(node.value);
98
+ if (expandOnClick) controller.toggleExpanded(node.value);
81
99
  selectOnClick && controller.select(node.value);
82
100
  ref.current?.focus();
83
101
  }
@@ -87,8 +105,10 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
87
105
  ...getStyles("label"),
88
106
  onClick: handleNodeClick,
89
107
  "data-selected": selected || void 0,
90
- "data-value": node.value
108
+ "data-value": node.value,
109
+ ...dragProps
91
110
  };
111
+ const withLoadingIndicator = isExpanded && isLoading && nested.length === 0;
92
112
  return /* @__PURE__ */ jsxs("li", {
93
113
  ...getStyles("node", { style: { "--label-offset": `calc(var(--level-offset) * ${level - 1})` } }),
94
114
  role: "treeitem",
@@ -99,33 +119,51 @@ function TreeNode({ node, getStyles, rootIndex, controller, expandOnClick, selec
99
119
  tabIndex: rootIndex === 0 ? 0 : -1,
100
120
  onKeyDown: handleKeyDown,
101
121
  ref,
102
- children: [typeof renderNode === "function" ? renderNode({
103
- node,
104
- level,
105
- selected,
106
- tree: controller,
107
- expanded: controller.expandedState[node.value] || false,
108
- hasChildren: Array.isArray(node.children) && node.children.length > 0,
109
- elementProps
110
- }) : /* @__PURE__ */ jsx("div", {
111
- ...elementProps,
112
- children: node.label
113
- }), keepMounted && nested.length > 0 ? /* @__PURE__ */ jsx(Activity, {
114
- mode: controller.expandedState[node.value] ? "visible" : "hidden",
115
- children: /* @__PURE__ */ jsx(Box, {
122
+ children: [
123
+ typeof renderNode === "function" ? renderNode({
124
+ node,
125
+ level,
126
+ selected,
127
+ tree: controller,
128
+ expanded: isExpanded,
129
+ hasChildren,
130
+ isLoading,
131
+ loadError,
132
+ elementProps
133
+ }) : /* @__PURE__ */ jsx("div", {
134
+ ...elementProps,
135
+ children: node.label
136
+ }),
137
+ withLoadingIndicator && /* @__PURE__ */ jsx(Box, {
138
+ component: "ul",
139
+ role: "group",
140
+ ...getStyles("subtree"),
141
+ "data-level": level,
142
+ children: /* @__PURE__ */ jsx("li", {
143
+ ...getStyles("node", { style: { "--label-offset": `calc(var(--level-offset) * ${level})` } }),
144
+ children: /* @__PURE__ */ jsx("div", {
145
+ ...getStyles("label"),
146
+ children: /* @__PURE__ */ jsx(Loader, { size: 16 })
147
+ })
148
+ })
149
+ }),
150
+ keepMounted && nested.length > 0 ? /* @__PURE__ */ jsx(Activity, {
151
+ mode: isExpanded ? "visible" : "hidden",
152
+ children: /* @__PURE__ */ jsx(Box, {
153
+ component: "ul",
154
+ role: "group",
155
+ ...getStyles("subtree"),
156
+ "data-level": level,
157
+ children: nested
158
+ })
159
+ }) : isExpanded && nested.length > 0 && /* @__PURE__ */ jsx(Box, {
116
160
  component: "ul",
117
161
  role: "group",
118
162
  ...getStyles("subtree"),
119
163
  "data-level": level,
120
164
  children: nested
121
165
  })
122
- }) : controller.expandedState[node.value] && nested.length > 0 && /* @__PURE__ */ jsx(Box, {
123
- component: "ul",
124
- role: "group",
125
- ...getStyles("subtree"),
126
- "data-level": level,
127
- children: nested
128
- })]
166
+ ]
129
167
  });
130
168
  }
131
169
  TreeNode.displayName = "@mantine/core/TreeNode";
@@ -1 +1 @@
1
- {"version":3,"file":"TreeNode.mjs","names":[],"sources":["../../../src/components/Tree/TreeNode.tsx"],"sourcesContent":["import { Activity, useRef } from 'react';\nimport { Box, findElementAncestor, GetStylesApi } from '../../core';\nimport type { RenderNode, TreeFactory, TreeNodeData } from './Tree';\nimport type { TreeController } from './use-tree';\n\nfunction getValuesRange(anchor: string | null, value: string | undefined, flatValues: string[]) {\n if (!anchor || !value) {\n return [];\n }\n\n const anchorIndex = flatValues.indexOf(anchor);\n const valueIndex = flatValues.indexOf(value);\n const start = Math.min(anchorIndex, valueIndex);\n const end = Math.max(anchorIndex, valueIndex);\n\n return flatValues.slice(start, end + 1);\n}\n\ninterface TreeNodeProps {\n node: TreeNodeData;\n getStyles: GetStylesApi<TreeFactory>;\n rootIndex: number | undefined;\n controller: TreeController;\n expandOnClick: boolean | undefined;\n flatValues: string[];\n isSubtree?: boolean;\n level?: number;\n renderNode: RenderNode | undefined;\n selectOnClick: boolean | undefined;\n allowRangeSelection: boolean | undefined;\n expandOnSpace: boolean | undefined;\n checkOnSpace: boolean | undefined;\n keepMounted: boolean | undefined;\n}\n\nexport function TreeNode({\n node,\n getStyles,\n rootIndex,\n controller,\n expandOnClick,\n selectOnClick,\n isSubtree,\n level = 1,\n renderNode,\n flatValues,\n allowRangeSelection,\n expandOnSpace,\n checkOnSpace,\n keepMounted,\n}: TreeNodeProps) {\n const ref = useRef<HTMLLIElement>(null);\n const nested = (node.children || []).map((child) => (\n <TreeNode\n key={child.value}\n node={child}\n flatValues={flatValues}\n getStyles={getStyles}\n rootIndex={undefined}\n level={level + 1}\n controller={controller}\n expandOnClick={expandOnClick}\n isSubtree\n renderNode={renderNode}\n selectOnClick={selectOnClick}\n allowRangeSelection={allowRangeSelection}\n expandOnSpace={expandOnSpace}\n checkOnSpace={checkOnSpace}\n keepMounted={keepMounted}\n />\n ));\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.nativeEvent.code === 'ArrowRight') {\n event.stopPropagation();\n event.preventDefault();\n\n if (controller.expandedState[node.value]) {\n event.currentTarget.querySelector<HTMLLIElement>('[role=treeitem]')?.focus();\n } else {\n controller.expand(node.value);\n }\n }\n\n if (event.nativeEvent.code === 'ArrowLeft') {\n event.stopPropagation();\n event.preventDefault();\n if (controller.expandedState[node.value] && (node.children || []).length > 0) {\n controller.collapse(node.value);\n } else if (isSubtree) {\n findElementAncestor(event.currentTarget as HTMLElement, '[role=treeitem]')?.focus();\n }\n }\n\n if (event.nativeEvent.code === 'ArrowDown' || event.nativeEvent.code === 'ArrowUp') {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n\n if (!root) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n const nodes = Array.from(root.querySelectorAll<HTMLLIElement>('[role=treeitem]')).filter(\n (treeNode) => treeNode.style.display !== 'none'\n );\n const index = nodes.indexOf(event.currentTarget as HTMLLIElement);\n\n if (index === -1) {\n return;\n }\n\n const nextIndex = event.nativeEvent.code === 'ArrowDown' ? index + 1 : index - 1;\n nodes[nextIndex]?.focus();\n\n if (event.shiftKey) {\n const selectNode = nodes[nextIndex];\n\n if (selectNode) {\n controller.setSelectedState(\n getValuesRange(controller.anchorNode, selectNode.dataset.value, flatValues)\n );\n }\n }\n }\n\n if (event.nativeEvent.code === 'Space') {\n if (expandOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.toggleExpanded(node.value);\n }\n\n if (checkOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.isNodeChecked(node.value)\n ? controller.uncheckNode(node.value)\n : controller.checkNode(node.value);\n }\n }\n };\n\n const handleNodeClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n\n if (allowRangeSelection && event.shiftKey && controller.anchorNode) {\n controller.setSelectedState(getValuesRange(controller.anchorNode, node.value, flatValues));\n ref.current?.focus();\n } else {\n expandOnClick && controller.toggleExpanded(node.value);\n selectOnClick && controller.select(node.value);\n ref.current?.focus();\n }\n };\n\n const selected = controller.selectedState.includes(node.value);\n const elementProps = {\n ...getStyles('label'),\n onClick: handleNodeClick,\n 'data-selected': selected || undefined,\n 'data-value': node.value,\n };\n\n return (\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level - 1})` },\n })}\n role=\"treeitem\"\n aria-selected={selected}\n data-value={node.value}\n data-selected={selected || undefined}\n data-level={level}\n tabIndex={rootIndex === 0 ? 0 : -1}\n onKeyDown={handleKeyDown}\n ref={ref}\n >\n {typeof renderNode === 'function' ? (\n renderNode({\n node,\n level,\n selected,\n tree: controller,\n expanded: controller.expandedState[node.value] || false,\n hasChildren: Array.isArray(node.children) && node.children.length > 0,\n elementProps,\n })\n ) : (\n <div {...elementProps}>{node.label}</div>\n )}\n\n {keepMounted && nested.length > 0 ? (\n <Activity mode={controller.expandedState[node.value] ? 'visible' : 'hidden'}>\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n </Activity>\n ) : (\n controller.expandedState[node.value] &&\n nested.length > 0 && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n )\n )}\n </li>\n );\n}\n\nTreeNode.displayName = '@mantine/core/TreeNode';\n"],"mappings":"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"}
1
+ {"version":3,"file":"TreeNode.mjs","names":[],"sources":["../../../src/components/Tree/TreeNode.tsx"],"sourcesContent":["import { Activity, useRef } from 'react';\nimport { Box, findElementAncestor, GetStylesApi } from '../../core';\nimport { Loader } from '../Loader';\nimport type { TreeDragDropPayload } from './move-tree-node/move-tree-node';\nimport type { RenderNode, TreeDragState, TreeFactory, TreeNodeData } from './Tree';\nimport type { TreeController } from './use-tree';\nimport { useTreeNodeDragDrop } from './use-tree-node-drag-drop';\n\nfunction getValuesRange(anchor: string | null, value: string | undefined, flatValues: string[]) {\n if (!anchor || !value) {\n return [];\n }\n\n const anchorIndex = flatValues.indexOf(anchor);\n const valueIndex = flatValues.indexOf(value);\n const start = Math.min(anchorIndex, valueIndex);\n const end = Math.max(anchorIndex, valueIndex);\n\n return flatValues.slice(start, end + 1);\n}\n\ninterface TreeNodeProps {\n node: TreeNodeData;\n getStyles: GetStylesApi<TreeFactory>;\n rootIndex: number | undefined;\n controller: TreeController;\n expandOnClick: boolean | undefined;\n flatValues: string[];\n isSubtree?: boolean;\n level?: number;\n renderNode: RenderNode | undefined;\n selectOnClick: boolean | undefined;\n allowRangeSelection: boolean | undefined;\n expandOnSpace: boolean | undefined;\n checkOnSpace: boolean | undefined;\n keepMounted: boolean | undefined;\n onDragDrop: ((payload: TreeDragDropPayload) => void) | undefined;\n dragStateRef: React.RefObject<TreeDragState>;\n data: TreeNodeData[];\n}\n\nexport function TreeNode({\n node,\n getStyles,\n rootIndex,\n controller,\n expandOnClick,\n selectOnClick,\n isSubtree,\n level = 1,\n renderNode,\n flatValues,\n allowRangeSelection,\n expandOnSpace,\n checkOnSpace,\n keepMounted,\n onDragDrop,\n dragStateRef,\n data,\n}: TreeNodeProps) {\n const ref = useRef<HTMLLIElement>(null);\n const hasLoadedChildren = Array.isArray(node.children);\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const isLoading = controller.isNodeLoading(node.value);\n const loadError = controller.getNodeLoadError(node.value);\n const isExpanded = controller.expandedState[node.value] || false;\n\n const nested = (node.children || []).map((child) => (\n <TreeNode\n key={child.value}\n node={child}\n flatValues={flatValues}\n getStyles={getStyles}\n rootIndex={undefined}\n level={level + 1}\n controller={controller}\n expandOnClick={expandOnClick}\n isSubtree\n renderNode={renderNode}\n selectOnClick={selectOnClick}\n allowRangeSelection={allowRangeSelection}\n expandOnSpace={expandOnSpace}\n checkOnSpace={checkOnSpace}\n keepMounted={keepMounted}\n onDragDrop={onDragDrop}\n dragStateRef={dragStateRef}\n data={data}\n />\n ));\n\n const dragProps = useTreeNodeDragDrop({\n nodeValue: node.value,\n hasChildren,\n data,\n onDragDrop,\n dragStateRef,\n });\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.nativeEvent.code === 'ArrowRight') {\n event.stopPropagation();\n event.preventDefault();\n\n if (isExpanded) {\n event.currentTarget.querySelector<HTMLLIElement>('[role=treeitem]')?.focus();\n } else {\n controller.expand(node.value);\n }\n }\n\n if (event.nativeEvent.code === 'ArrowLeft') {\n event.stopPropagation();\n event.preventDefault();\n if (isExpanded && hasChildren) {\n controller.collapse(node.value);\n } else if (isSubtree) {\n findElementAncestor(event.currentTarget as HTMLElement, '[role=treeitem]')?.focus();\n }\n }\n\n if (event.nativeEvent.code === 'ArrowDown' || event.nativeEvent.code === 'ArrowUp') {\n const root = findElementAncestor(event.currentTarget as HTMLElement, '[data-tree-root]');\n\n if (!root) {\n return;\n }\n\n event.stopPropagation();\n event.preventDefault();\n const nodes = Array.from(root.querySelectorAll<HTMLLIElement>('[role=treeitem]')).filter(\n (treeNode) => treeNode.style.display !== 'none'\n );\n const index = nodes.indexOf(event.currentTarget as HTMLLIElement);\n\n if (index === -1) {\n return;\n }\n\n const nextIndex = event.nativeEvent.code === 'ArrowDown' ? index + 1 : index - 1;\n nodes[nextIndex]?.focus();\n\n if (event.shiftKey) {\n const selectNode = nodes[nextIndex];\n\n if (selectNode) {\n controller.setSelectedState(\n getValuesRange(controller.anchorNode, selectNode.dataset.value, flatValues)\n );\n }\n }\n }\n\n if (event.nativeEvent.code === 'Space') {\n if (expandOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.toggleExpanded(node.value);\n }\n\n if (checkOnSpace) {\n event.stopPropagation();\n event.preventDefault();\n controller.isNodeChecked(node.value)\n ? controller.uncheckNode(node.value)\n : controller.checkNode(node.value);\n }\n }\n };\n\n const handleNodeClick = (event: React.MouseEvent) => {\n event.stopPropagation();\n\n if (allowRangeSelection && event.shiftKey && controller.anchorNode) {\n controller.setSelectedState(getValuesRange(controller.anchorNode, node.value, flatValues));\n ref.current?.focus();\n } else {\n if (expandOnClick) {\n controller.toggleExpanded(node.value);\n }\n\n selectOnClick && controller.select(node.value);\n ref.current?.focus();\n }\n };\n\n const selected = controller.selectedState.includes(node.value);\n const elementProps = {\n ...getStyles('label'),\n onClick: handleNodeClick,\n 'data-selected': selected || undefined,\n 'data-value': node.value,\n ...dragProps,\n };\n\n const withLoadingIndicator = isExpanded && isLoading && nested.length === 0;\n\n return (\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level - 1})` },\n })}\n role=\"treeitem\"\n aria-selected={selected}\n data-value={node.value}\n data-selected={selected || undefined}\n data-level={level}\n tabIndex={rootIndex === 0 ? 0 : -1}\n onKeyDown={handleKeyDown}\n ref={ref}\n >\n {typeof renderNode === 'function' ? (\n renderNode({\n node,\n level,\n selected,\n tree: controller,\n expanded: isExpanded,\n hasChildren,\n isLoading,\n loadError,\n elementProps,\n })\n ) : (\n <div {...elementProps}>{node.label}</div>\n )}\n\n {withLoadingIndicator && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n <li\n {...getStyles('node', {\n style: { '--label-offset': `calc(var(--level-offset) * ${level})` },\n })}\n >\n <div {...getStyles('label')}>\n <Loader size={16} />\n </div>\n </li>\n </Box>\n )}\n\n {keepMounted && nested.length > 0 ? (\n <Activity mode={isExpanded ? 'visible' : 'hidden'}>\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n </Activity>\n ) : (\n isExpanded &&\n nested.length > 0 && (\n <Box component=\"ul\" role=\"group\" {...getStyles('subtree')} data-level={level}>\n {nested}\n </Box>\n )\n )}\n </li>\n );\n}\n\nTreeNode.displayName = '@mantine/core/TreeNode';\n"],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ "use client";
2
+ //#region packages/@mantine/core/src/components/Tree/filter-tree-data/filter-tree-data.ts
3
+ function defaultTreeNodeFilter(query, node) {
4
+ return (typeof node.label === "string" ? node.label : node.value).toLowerCase().includes(query.toLowerCase().trim());
5
+ }
6
+ function filterTreeData(data, query, filter = defaultTreeNodeFilter) {
7
+ if (!query.trim()) return data;
8
+ const result = [];
9
+ for (const node of data) {
10
+ const nodeMatches = filter(query, node);
11
+ const filteredChildren = Array.isArray(node.children) && node.children.length > 0 ? filterTreeData(node.children, query, filter) : [];
12
+ if (nodeMatches || filteredChildren.length > 0) result.push(filteredChildren.length > 0 ? {
13
+ ...node,
14
+ children: filteredChildren
15
+ } : { ...node });
16
+ }
17
+ return result;
18
+ }
19
+ //#endregion
20
+ export { defaultTreeNodeFilter, filterTreeData };
21
+
22
+ //# sourceMappingURL=filter-tree-data.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-tree-data.mjs","names":[],"sources":["../../../../src/components/Tree/filter-tree-data/filter-tree-data.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\n\nexport type TreeNodeFilter = (query: string, node: TreeNodeData) => boolean;\n\nexport function defaultTreeNodeFilter(query: string, node: TreeNodeData): boolean {\n const label = typeof node.label === 'string' ? node.label : node.value;\n return label.toLowerCase().includes(query.toLowerCase().trim());\n}\n\nexport function filterTreeData(\n data: TreeNodeData[],\n query: string,\n filter: TreeNodeFilter = defaultTreeNodeFilter\n): TreeNodeData[] {\n if (!query.trim()) {\n return data;\n }\n\n const result: TreeNodeData[] = [];\n\n for (const node of data) {\n const nodeMatches = filter(query, node);\n const filteredChildren =\n Array.isArray(node.children) && node.children.length > 0\n ? filterTreeData(node.children, query, filter)\n : [];\n\n if (nodeMatches || filteredChildren.length > 0) {\n result.push(\n filteredChildren.length > 0 ? { ...node, children: filteredChildren } : { ...node }\n );\n }\n }\n\n return result;\n}\n"],"mappings":";;AAIA,SAAgB,sBAAsB,OAAe,MAA6B;AAEhF,SADc,OAAO,KAAK,UAAU,WAAW,KAAK,QAAQ,KAAK,OACpD,aAAa,CAAC,SAAS,MAAM,aAAa,CAAC,MAAM,CAAC;;AAGjE,SAAgB,eACd,MACA,OACA,SAAyB,uBACT;AAChB,KAAI,CAAC,MAAM,MAAM,CACf,QAAO;CAGT,MAAM,SAAyB,EAAE;AAEjC,MAAK,MAAM,QAAQ,MAAM;EACvB,MAAM,cAAc,OAAO,OAAO,KAAK;EACvC,MAAM,mBACJ,MAAM,QAAQ,KAAK,SAAS,IAAI,KAAK,SAAS,SAAS,IACnD,eAAe,KAAK,UAAU,OAAO,OAAO,GAC5C,EAAE;AAER,MAAI,eAAe,iBAAiB,SAAS,EAC3C,QAAO,KACL,iBAAiB,SAAS,IAAI;GAAE,GAAG;GAAM,UAAU;GAAkB,GAAG,EAAE,GAAG,MAAM,CACpF;;AAIL,QAAO"}
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ //#region packages/@mantine/core/src/components/Tree/flatten-tree-data/flatten-tree-data.ts
3
+ function flattenTreeDataTo(acc, data, expandedState, parent, level) {
4
+ for (let i = 0; i < data.length; i++) {
5
+ const node = data[i];
6
+ const hasLoadedChildren = Array.isArray(node.children);
7
+ const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;
8
+ const hasChildren = hasLoadedChildren || hasAsyncChildren;
9
+ const expanded = expandedState[node.value] || false;
10
+ acc.push({
11
+ node,
12
+ level,
13
+ parent,
14
+ hasChildren,
15
+ expanded
16
+ });
17
+ if (expanded && hasLoadedChildren) flattenTreeDataTo(acc, node.children, expandedState, node.value, level + 1);
18
+ }
19
+ }
20
+ function flattenTreeData(data, expandedState) {
21
+ const result = [];
22
+ flattenTreeDataTo(result, data, expandedState, null, 1);
23
+ return result;
24
+ }
25
+ //#endregion
26
+ export { flattenTreeData };
27
+
28
+ //# sourceMappingURL=flatten-tree-data.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flatten-tree-data.mjs","names":[],"sources":["../../../../src/components/Tree/flatten-tree-data/flatten-tree-data.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\nimport type { TreeExpandedState } from '../use-tree';\n\nexport interface FlattenedTreeNodeData {\n /** Node data from tree data */\n node: TreeNodeData;\n\n /** Nesting level of the node, starts at 1 */\n level: number;\n\n /** Value of the parent node, `null` for root nodes */\n parent: string | null;\n\n /** Whether the node has children */\n hasChildren: boolean;\n\n /** Whether the node is expanded */\n expanded: boolean;\n}\n\nfunction flattenTreeDataTo(\n acc: FlattenedTreeNodeData[],\n data: TreeNodeData[],\n expandedState: TreeExpandedState,\n parent: string | null,\n level: number\n): void {\n for (let i = 0; i < data.length; i++) {\n const node = data[i];\n const hasLoadedChildren = Array.isArray(node.children);\n const hasAsyncChildren = !!node.hasChildren && !hasLoadedChildren;\n const hasChildren = hasLoadedChildren || hasAsyncChildren;\n const expanded = expandedState[node.value] || false;\n\n acc.push({ node, level, parent, hasChildren, expanded });\n\n if (expanded && hasLoadedChildren) {\n flattenTreeDataTo(acc, node.children!, expandedState, node.value, level + 1);\n }\n }\n}\n\nexport function flattenTreeData(\n data: TreeNodeData[],\n expandedState: TreeExpandedState\n): FlattenedTreeNodeData[] {\n const result: FlattenedTreeNodeData[] = [];\n flattenTreeDataTo(result, data, expandedState, null, 1);\n return result;\n}\n"],"mappings":";;AAoBA,SAAS,kBACP,KACA,MACA,eACA,QACA,OACM;AACN,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACpC,MAAM,OAAO,KAAK;EAClB,MAAM,oBAAoB,MAAM,QAAQ,KAAK,SAAS;EACtD,MAAM,mBAAmB,CAAC,CAAC,KAAK,eAAe,CAAC;EAChD,MAAM,cAAc,qBAAqB;EACzC,MAAM,WAAW,cAAc,KAAK,UAAU;AAE9C,MAAI,KAAK;GAAE;GAAM;GAAO;GAAQ;GAAa;GAAU,CAAC;AAExD,MAAI,YAAY,kBACd,mBAAkB,KAAK,KAAK,UAAW,eAAe,KAAK,OAAO,QAAQ,EAAE;;;AAKlF,SAAgB,gBACd,MACA,eACyB;CACzB,MAAM,SAAkC,EAAE;AAC1C,mBAAkB,QAAQ,MAAM,eAAe,MAAM,EAAE;AACvD,QAAO"}
@@ -28,6 +28,6 @@ function getAllChildrenNodes(data) {
28
28
  }, []);
29
29
  }
30
30
  //#endregion
31
- export { getAllChildrenNodes, getChildrenNodesValues };
31
+ export { findTreeNode, getAllChildrenNodes, getChildrenNodesValues };
32
32
 
33
33
  //# sourceMappingURL=get-children-nodes-values.mjs.map
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ //#region packages/@mantine/core/src/components/Tree/merge-async-children/merge-async-children.ts
3
+ function mergeAsyncChildren(data, parentValue, children) {
4
+ let changed = false;
5
+ const result = data.map((node) => {
6
+ if (node.value === parentValue) {
7
+ changed = true;
8
+ const merged = {
9
+ ...node,
10
+ children
11
+ };
12
+ delete merged.hasChildren;
13
+ return merged;
14
+ }
15
+ if (Array.isArray(node.children)) {
16
+ const updatedChildren = mergeAsyncChildren(node.children, parentValue, children);
17
+ if (updatedChildren !== node.children) {
18
+ changed = true;
19
+ return {
20
+ ...node,
21
+ children: updatedChildren
22
+ };
23
+ }
24
+ }
25
+ return node;
26
+ });
27
+ return changed ? result : data;
28
+ }
29
+ //#endregion
30
+ export { mergeAsyncChildren };
31
+
32
+ //# sourceMappingURL=merge-async-children.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-async-children.mjs","names":[],"sources":["../../../../src/components/Tree/merge-async-children/merge-async-children.ts"],"sourcesContent":["import type { TreeNodeData } from '../Tree';\n\nexport function mergeAsyncChildren(\n data: TreeNodeData[],\n parentValue: string,\n children: TreeNodeData[]\n): TreeNodeData[] {\n let changed = false;\n\n const result = data.map((node) => {\n if (node.value === parentValue) {\n changed = true;\n const merged: TreeNodeData = { ...node, children };\n delete merged.hasChildren;\n return merged;\n }\n\n if (Array.isArray(node.children)) {\n const updatedChildren = mergeAsyncChildren(node.children, parentValue, children);\n if (updatedChildren !== node.children) {\n changed = true;\n return { ...node, children: updatedChildren };\n }\n }\n\n return node;\n });\n\n return changed ? result : data;\n}\n"],"mappings":";;AAEA,SAAgB,mBACd,MACA,aACA,UACgB;CAChB,IAAI,UAAU;CAEd,MAAM,SAAS,KAAK,KAAK,SAAS;AAChC,MAAI,KAAK,UAAU,aAAa;AAC9B,aAAU;GACV,MAAM,SAAuB;IAAE,GAAG;IAAM;IAAU;AAClD,UAAO,OAAO;AACd,UAAO;;AAGT,MAAI,MAAM,QAAQ,KAAK,SAAS,EAAE;GAChC,MAAM,kBAAkB,mBAAmB,KAAK,UAAU,aAAa,SAAS;AAChF,OAAI,oBAAoB,KAAK,UAAU;AACrC,cAAU;AACV,WAAO;KAAE,GAAG;KAAM,UAAU;KAAiB;;;AAIjD,SAAO;GACP;AAEF,QAAO,UAAU,SAAS"}
@@ -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"}