torch-glare 2.4.0 → 2.4.1

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 (264) hide show
  1. package/README.md +8 -0
  2. package/apps/lib/components/ActionButton.tsx +7 -12
  3. package/apps/lib/components/ActionsGroup.tsx +4 -15
  4. package/apps/lib/components/AlertDialog.tsx +173 -191
  5. package/apps/lib/components/Avatar.tsx +13 -16
  6. package/apps/lib/components/Badge.tsx +1 -3
  7. package/apps/lib/components/BadgeField.tsx +76 -71
  8. package/apps/lib/components/Breadcrumb.tsx +49 -85
  9. package/apps/lib/components/Button.tsx +20 -19
  10. package/apps/lib/components/ButtonGroup.tsx +31 -41
  11. package/apps/lib/components/Calendar.tsx +51 -29
  12. package/apps/lib/components/Card.tsx +2 -13
  13. package/apps/lib/components/ChartBlockTool.ts +17 -52
  14. package/apps/lib/components/Checkbox.tsx +9 -16
  15. package/apps/lib/components/ContextMenu.tsx +97 -96
  16. package/apps/lib/components/CountBadge.tsx +4 -6
  17. package/apps/lib/components/DataTable.tsx +196 -216
  18. package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
  19. package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
  20. package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
  21. package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
  22. package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
  23. package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
  24. package/apps/lib/components/DataViews/InboxView.tsx +22 -68
  25. package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
  26. package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
  27. package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
  28. package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
  29. package/apps/lib/components/DataViews/TableView.tsx +8 -28
  30. package/apps/lib/components/DataViews/TreeView.tsx +12 -40
  31. package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
  32. package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
  33. package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
  34. package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
  35. package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
  36. package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
  37. package/apps/lib/components/DataViews/index.ts +26 -26
  38. package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
  39. package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
  40. package/apps/lib/components/DataViews/types.ts +104 -115
  41. package/apps/lib/components/DatePicker.tsx +198 -196
  42. package/apps/lib/components/Dialog.tsx +92 -105
  43. package/apps/lib/components/Divider.tsx +21 -24
  44. package/apps/lib/components/Drawer.tsx +79 -139
  45. package/apps/lib/components/DropdownMenu.tsx +131 -171
  46. package/apps/lib/components/FieldHint.tsx +4 -11
  47. package/apps/lib/components/Form.tsx +146 -155
  48. package/apps/lib/components/FormStepper.tsx +9 -39
  49. package/apps/lib/components/HeaderBar.tsx +1 -9
  50. package/apps/lib/components/ImageAttachment.tsx +111 -73
  51. package/apps/lib/components/InnerLabelField.tsx +20 -16
  52. package/apps/lib/components/Input.tsx +171 -172
  53. package/apps/lib/components/InputField.tsx +44 -45
  54. package/apps/lib/components/InputOTP.tsx +68 -69
  55. package/apps/lib/components/Label.tsx +31 -35
  56. package/apps/lib/components/LabelField.tsx +4 -5
  57. package/apps/lib/components/LabeledCheckBox.tsx +8 -12
  58. package/apps/lib/components/LabeledRadio.tsx +7 -5
  59. package/apps/lib/components/LinkButton.tsx +2 -9
  60. package/apps/lib/components/LoginButton.tsx +4 -9
  61. package/apps/lib/components/PasswordLevel.tsx +5 -5
  62. package/apps/lib/components/Popover.tsx +15 -33
  63. package/apps/lib/components/ProfileMenu.tsx +67 -72
  64. package/apps/lib/components/Radio.tsx +1 -5
  65. package/apps/lib/components/RadioCard.tsx +9 -28
  66. package/apps/lib/components/ScrollArea.tsx +45 -43
  67. package/apps/lib/components/SearchField.tsx +49 -39
  68. package/apps/lib/components/SearchableSelect.tsx +8 -14
  69. package/apps/lib/components/SearchableTable.tsx +108 -118
  70. package/apps/lib/components/SearchableTree.tsx +469 -0
  71. package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
  72. package/apps/lib/components/SectionBlock.tsx +4 -16
  73. package/apps/lib/components/Select.tsx +53 -80
  74. package/apps/lib/components/SimpleSelect.tsx +196 -187
  75. package/apps/lib/components/Skeleton.tsx +9 -12
  76. package/apps/lib/components/SlideDatePicker.tsx +215 -166
  77. package/apps/lib/components/SpinLoading.tsx +33 -49
  78. package/apps/lib/components/Stepper.tsx +13 -56
  79. package/apps/lib/components/Switch.tsx +8 -10
  80. package/apps/lib/components/TabFormItem.tsx +3 -12
  81. package/apps/lib/components/TabSwitch.tsx +7 -34
  82. package/apps/lib/components/Table.tsx +60 -75
  83. package/apps/lib/components/TableDnDWrapper.ts +15 -48
  84. package/apps/lib/components/TextEditor.tsx +93 -104
  85. package/apps/lib/components/Textarea.tsx +8 -12
  86. package/apps/lib/components/Timeline.tsx +21 -41
  87. package/apps/lib/components/Toast.tsx +83 -83
  88. package/apps/lib/components/Toggle.tsx +112 -114
  89. package/apps/lib/components/ToggleButton.tsx +1 -1
  90. package/apps/lib/components/Tooltip.tsx +24 -19
  91. package/apps/lib/components/TransparentLabel.tsx +61 -62
  92. package/apps/lib/components/TreeDropDown.tsx +86 -52
  93. package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
  94. package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
  95. package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
  96. package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
  97. package/apps/lib/components/TreeFolder/icons.tsx +14 -17
  98. package/apps/lib/components/TreeFolder/index.ts +15 -8
  99. package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
  100. package/apps/lib/components/TreeFolder/types.ts +32 -32
  101. package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
  102. package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
  103. package/apps/lib/hooks/useClickOutside.ts +21 -20
  104. package/apps/lib/hooks/useDataViewsState.ts +86 -80
  105. package/apps/lib/hooks/useIsMobile.ts +12 -12
  106. package/apps/lib/hooks/useResize.ts +54 -65
  107. package/apps/lib/hooks/useTagSelection.ts +201 -201
  108. package/apps/lib/layouts/CNLayout.tsx +181 -140
  109. package/apps/lib/layouts/DataViewCard.tsx +4 -18
  110. package/apps/lib/layouts/FieldSection.tsx +2 -6
  111. package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
  112. package/apps/lib/providers/ThemeProvider.tsx +8 -23
  113. package/apps/lib/registry.json +1004 -0
  114. package/apps/lib/tsconfig.json +9 -0
  115. package/apps/lib/utils/cn.ts +1 -1
  116. package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
  117. package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
  118. package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
  119. package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
  120. package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
  121. package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
  122. package/apps/lib/utils/dateFormat.ts +64 -54
  123. package/apps/lib/utils/markdownParser.ts +2 -7
  124. package/apps/lib/utils/resize.ts +21 -25
  125. package/apps/lib/utils/types.ts +13 -13
  126. package/dist/bin/index.js +8 -2
  127. package/dist/bin/index.js.map +1 -1
  128. package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
  129. package/dist/src/shared/getAvailableFiles.js +6 -1
  130. package/dist/src/shared/getAvailableFiles.js.map +1 -1
  131. package/dist/src/shared/loadRegistry.d.ts +7 -0
  132. package/dist/src/shared/loadRegistry.d.ts.map +1 -0
  133. package/dist/src/shared/loadRegistry.js +31 -0
  134. package/dist/src/shared/loadRegistry.js.map +1 -0
  135. package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
  136. package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
  137. package/dist/src/shared/resolveInstallPlan.js +39 -0
  138. package/dist/src/shared/resolveInstallPlan.js.map +1 -0
  139. package/dist/src/types/main.d.ts +24 -0
  140. package/dist/src/types/main.d.ts.map +1 -1
  141. package/docs/README.md +10 -2
  142. package/docs/components/action-button.md +30 -24
  143. package/docs/components/actions-group.md +26 -20
  144. package/docs/components/alert-dialog.md +45 -45
  145. package/docs/components/avatar.md +6 -2
  146. package/docs/components/badge-field.md +6 -2
  147. package/docs/components/badge.md +7 -1
  148. package/docs/components/breadcrumb.md +15 -40
  149. package/docs/components/button-group.md +13 -10
  150. package/docs/components/button.md +58 -33
  151. package/docs/components/calendar.md +26 -19
  152. package/docs/components/card.md +19 -16
  153. package/docs/components/chart-block-tool.md +128 -0
  154. package/docs/components/checkbox.md +16 -8
  155. package/docs/components/cn-layout.md +7 -1
  156. package/docs/components/context-menu.md +18 -25
  157. package/docs/components/count-badge.md +7 -1
  158. package/docs/components/data-table.md +45 -33
  159. package/docs/components/data-views-config-panel.md +15 -11
  160. package/docs/components/data-views-layout.md +13 -16
  161. package/docs/components/date-picker.md +30 -23
  162. package/docs/components/dialog.md +43 -42
  163. package/docs/components/divider.md +10 -4
  164. package/docs/components/drawer.md +8 -33
  165. package/docs/components/dropdown-menu.md +25 -34
  166. package/docs/components/field-hint.md +37 -25
  167. package/docs/components/field-section.md +9 -3
  168. package/docs/components/form-stepper.md +6 -0
  169. package/docs/components/form.md +17 -20
  170. package/docs/components/header-bar.md +6 -0
  171. package/docs/components/image-attachment.md +33 -41
  172. package/docs/components/inbox-view.md +16 -5
  173. package/docs/components/inner-label-field.md +34 -24
  174. package/docs/components/input-field.md +18 -10
  175. package/docs/components/input-otp.md +14 -11
  176. package/docs/components/input.md +22 -16
  177. package/docs/components/kanban-view.md +15 -5
  178. package/docs/components/label-field.md +32 -22
  179. package/docs/components/label.md +43 -32
  180. package/docs/components/labeled-check-box.md +16 -8
  181. package/docs/components/labeled-radio.md +18 -11
  182. package/docs/components/link-button.md +7 -1
  183. package/docs/components/login-button.md +8 -2
  184. package/docs/components/password-level.md +37 -24
  185. package/docs/components/popover.md +26 -23
  186. package/docs/components/profile-menu.md +38 -27
  187. package/docs/components/radio-card.md +16 -9
  188. package/docs/components/radio.md +16 -8
  189. package/docs/components/scroll-area.md +6 -2
  190. package/docs/components/search-field.md +14 -6
  191. package/docs/components/searchable-select.md +19 -14
  192. package/docs/components/searchable-table.md +18 -13
  193. package/docs/components/searchable-tree-dialog.md +190 -0
  194. package/docs/components/searchable-tree.md +200 -0
  195. package/docs/components/section-block.md +12 -4
  196. package/docs/components/select.md +23 -18
  197. package/docs/components/simple-select.md +14 -10
  198. package/docs/components/skeleton.md +43 -33
  199. package/docs/components/slide-date-picker.md +37 -29
  200. package/docs/components/spin-loading.md +32 -23
  201. package/docs/components/stepper.md +6 -0
  202. package/docs/components/switch.md +14 -6
  203. package/docs/components/tab-form-item.md +7 -1
  204. package/docs/components/tab-switch.md +13 -6
  205. package/docs/components/table-dnd-wrapper.md +105 -0
  206. package/docs/components/table-view.md +15 -5
  207. package/docs/components/table.md +28 -28
  208. package/docs/components/text-editor.md +19 -13
  209. package/docs/components/textarea.md +15 -7
  210. package/docs/components/timeline.md +6 -0
  211. package/docs/components/toast.md +35 -26
  212. package/docs/components/toggle-button.md +24 -21
  213. package/docs/components/toggle.md +23 -15
  214. package/docs/components/tooltip.md +42 -30
  215. package/docs/components/transparent-label.md +29 -20
  216. package/docs/components/tree-drop-down.md +31 -23
  217. package/docs/components/tree-sub-layout.md +6 -2
  218. package/docs/components/tree-view.md +16 -5
  219. package/docs/explanation/architecture.md +54 -0
  220. package/docs/explanation/design-system.md +52 -0
  221. package/docs/how-to/data-views-from-backend-response.md +6 -4
  222. package/docs/how-to/guides.md +24 -18
  223. package/docs/migration/changelog.md +38 -0
  224. package/docs/reference/cli.md +87 -0
  225. package/docs/reference/components.md +11 -12
  226. package/docs/reference/hooks.md +8 -8
  227. package/docs/reference/providers.md +22 -22
  228. package/docs/reference/tailwind-plugins.md +2 -2
  229. package/docs/reference/theme.md +85 -0
  230. package/docs/reference/types.md +4 -4
  231. package/docs/reference/utilities.md +19 -26
  232. package/docs/tutorials/building-first-form.md +20 -13
  233. package/docs/tutorials/component-composition.md +34 -50
  234. package/docs/tutorials/getting-started.md +2 -2
  235. package/docs/tutorials/theming-basics.md +13 -10
  236. package/package.json +31 -3
  237. package/dist/src/commands/block.d.ts +0 -5
  238. package/dist/src/commands/block.d.ts.map +0 -1
  239. package/dist/src/commands/block.js +0 -255
  240. package/dist/src/commands/block.js.map +0 -1
  241. package/dist/src/shared/configureFonts.d.ts +0 -6
  242. package/dist/src/shared/configureFonts.d.ts.map +0 -1
  243. package/dist/src/shared/configureFonts.js +0 -106
  244. package/dist/src/shared/configureFonts.js.map +0 -1
  245. package/dist/src/shared/configureGlobalCss.d.ts +0 -6
  246. package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
  247. package/dist/src/shared/configureGlobalCss.js +0 -154
  248. package/dist/src/shared/configureGlobalCss.js.map +0 -1
  249. package/dist/src/shared/configureTailwind.d.ts +0 -7
  250. package/dist/src/shared/configureTailwind.d.ts.map +0 -1
  251. package/dist/src/shared/configureTailwind.js +0 -163
  252. package/dist/src/shared/configureTailwind.js.map +0 -1
  253. package/dist/src/shared/detectFramework.d.ts +0 -23
  254. package/dist/src/shared/detectFramework.d.ts.map +0 -1
  255. package/dist/src/shared/detectFramework.js +0 -119
  256. package/dist/src/shared/detectFramework.js.map +0 -1
  257. package/dist/src/shared/installBaseUtils.d.ts +0 -5
  258. package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
  259. package/dist/src/shared/installBaseUtils.js +0 -79
  260. package/dist/src/shared/installBaseUtils.js.map +0 -1
  261. package/dist/src/shared/resolveAliases.d.ts +0 -24
  262. package/dist/src/shared/resolveAliases.d.ts.map +0 -1
  263. package/dist/src/shared/resolveAliases.js +0 -98
  264. package/dist/src/shared/resolveAliases.js.map +0 -1
@@ -1,41 +1,38 @@
1
- import type { DynamicRecord, TreeConfig } from "../../components/DataViews/types"
2
- import { getByPath, setByPath } from "./pathUtils"
1
+ import type { DynamicRecord, TreeConfig } from "../../components/DataViews/types";
2
+ import { getByPath, setByPath } from "./pathUtils";
3
3
 
4
4
  export type TreeNode = {
5
- id: string
6
- record: DynamicRecord
7
- children: TreeNode[]
8
- depth: number
9
- parent: TreeNode | null
10
- }
5
+ id: string;
6
+ record: DynamicRecord;
7
+ children: TreeNode[];
8
+ depth: number;
9
+ parent: TreeNode | null;
10
+ };
11
11
 
12
12
  export type ResolvedTreeConfig = {
13
- childrenField?: string
14
- parentField?: string
15
- idField: string
16
- orderField?: string
17
- nodeLabel?: string
18
- defaultExpanded: "all" | "roots" | "none"
19
- }
13
+ childrenField?: string;
14
+ parentField?: string;
15
+ idField: string;
16
+ orderField?: string;
17
+ nodeLabel?: string;
18
+ defaultExpanded: "all" | "roots" | "none";
19
+ };
20
20
 
21
- const CHILDREN_PATTERNS = ["children", "items", "kids", "subItems", "nodes"]
22
- const PARENT_PATTERNS = ["parentId", "parent_id", "parent", "managerId", "manager"]
23
- const ID_PATTERNS = ["id", "_id", "uuid", "key"]
21
+ const CHILDREN_PATTERNS = ["children", "items", "kids", "subItems", "nodes"];
22
+ const PARENT_PATTERNS = ["parentId", "parent_id", "parent", "managerId", "manager"];
23
+ const ID_PATTERNS = ["id", "_id", "uuid", "key"];
24
24
 
25
- export function autoDetectTreeShape(
26
- data: DynamicRecord[],
27
- config: TreeConfig,
28
- ): ResolvedTreeConfig {
29
- const sample = data.find((r) => r != null && typeof r === "object") ?? {}
25
+ export function autoDetectTreeShape(data: DynamicRecord[], config: TreeConfig): ResolvedTreeConfig {
26
+ const sample = data.find((r) => r != null && typeof r === "object") ?? {};
30
27
 
31
- const idField = config.idField ?? pickKey(sample, ID_PATTERNS) ?? "id"
28
+ const idField = config.idField ?? pickKey(sample, ID_PATTERNS) ?? "id";
32
29
 
33
- let childrenField = config.childrenField
34
- let parentField = config.parentField
30
+ let childrenField = config.childrenField;
31
+ let parentField = config.parentField;
35
32
 
36
33
  if (!childrenField && !parentField) {
37
- childrenField = pickArrayKey(sample, CHILDREN_PATTERNS)
38
- if (!childrenField) parentField = pickKey(sample, PARENT_PATTERNS)
34
+ childrenField = pickArrayKey(sample, CHILDREN_PATTERNS);
35
+ if (!childrenField) parentField = pickKey(sample, PARENT_PATTERNS);
39
36
  }
40
37
 
41
38
  return {
@@ -45,98 +42,94 @@ export function autoDetectTreeShape(
45
42
  orderField: config.orderField,
46
43
  nodeLabel: config.nodeLabel,
47
44
  defaultExpanded: config.defaultExpanded ?? "roots",
48
- }
45
+ };
49
46
  }
50
47
 
51
48
  function pickKey(record: DynamicRecord, candidates: string[]): string | undefined {
52
49
  for (const key of candidates) {
53
- if (key in record) return key
50
+ if (key in record) return key;
54
51
  }
55
- return undefined
52
+ return undefined;
56
53
  }
57
54
 
58
55
  function pickArrayKey(record: DynamicRecord, candidates: string[]): string | undefined {
59
56
  for (const key of candidates) {
60
- if (key in record && Array.isArray(record[key])) return key
57
+ if (key in record && Array.isArray(record[key])) return key;
61
58
  }
62
- return undefined
59
+ return undefined;
63
60
  }
64
61
 
65
- export function buildTree(
66
- data: DynamicRecord[],
67
- config: ResolvedTreeConfig,
68
- ): TreeNode[] {
69
- if (!data || data.length === 0) return []
70
- if (config.childrenField) return buildFromNested(data, config)
71
- if (config.parentField) return buildFromFlat(data, config)
72
- return data.map((record, idx) => makeNode(record, config, idx, null, 0))
62
+ export function buildTree(data: DynamicRecord[], config: ResolvedTreeConfig): TreeNode[] {
63
+ if (!data || data.length === 0) return [];
64
+ if (config.childrenField) return buildFromNested(data, config);
65
+ if (config.parentField) return buildFromFlat(data, config);
66
+ return data.map((record, idx) => makeNode(record, config, idx, null, 0));
73
67
  }
74
68
 
75
- function buildFromNested(
76
- data: DynamicRecord[],
77
- config: ResolvedTreeConfig,
78
- ): TreeNode[] {
79
- const seen = new Set<string>()
69
+ function buildFromNested(data: DynamicRecord[], config: ResolvedTreeConfig): TreeNode[] {
70
+ const seen = new Set<string>();
80
71
 
81
- const visit = (record: DynamicRecord, depth: number, parent: TreeNode | null, idx: number): TreeNode => {
82
- const node = makeNode(record, config, idx, parent, depth)
72
+ const visit = (
73
+ record: DynamicRecord,
74
+ depth: number,
75
+ parent: TreeNode | null,
76
+ idx: number,
77
+ ): TreeNode => {
78
+ const node = makeNode(record, config, idx, parent, depth);
83
79
  if (seen.has(node.id)) {
84
- return { ...node, children: [] }
80
+ return { ...node, children: [] };
85
81
  }
86
- seen.add(node.id)
82
+ seen.add(node.id);
87
83
 
88
- const rawChildren = getByPath(record, config.childrenField)
84
+ const rawChildren = getByPath(record, config.childrenField);
89
85
  if (Array.isArray(rawChildren)) {
90
- node.children = rawChildren.map((child, ci) => visit(child, depth + 1, node, ci))
86
+ node.children = rawChildren.map((child, ci) => visit(child, depth + 1, node, ci));
91
87
  }
92
- return node
93
- }
88
+ return node;
89
+ };
94
90
 
95
- return data.map((record, idx) => visit(record, 0, null, idx))
91
+ return data.map((record, idx) => visit(record, 0, null, idx));
96
92
  }
97
93
 
98
- function buildFromFlat(
99
- data: DynamicRecord[],
100
- config: ResolvedTreeConfig,
101
- ): TreeNode[] {
102
- const byId = new Map<string, TreeNode>()
94
+ function buildFromFlat(data: DynamicRecord[], config: ResolvedTreeConfig): TreeNode[] {
95
+ const byId = new Map<string, TreeNode>();
103
96
  for (let i = 0; i < data.length; i++) {
104
- const record = data[i]
105
- const id = String(getByPath(record, config.idField) ?? `__row${i}`)
97
+ const record = data[i];
98
+ const id = String(getByPath(record, config.idField) ?? `__row${i}`);
106
99
  byId.set(id, {
107
100
  id,
108
101
  record,
109
102
  children: [],
110
103
  depth: 0,
111
104
  parent: null,
112
- })
105
+ });
113
106
  }
114
107
 
115
- const roots: TreeNode[] = []
108
+ const roots: TreeNode[] = [];
116
109
  for (const node of byId.values()) {
117
- const parentId = getByPath(node.record, config.parentField)
110
+ const parentId = getByPath(node.record, config.parentField);
118
111
  if (parentId == null) {
119
- roots.push(node)
120
- continue
112
+ roots.push(node);
113
+ continue;
121
114
  }
122
- const parent = byId.get(String(parentId))
115
+ const parent = byId.get(String(parentId));
123
116
  if (!parent || parent === node) {
124
- roots.push(node)
125
- continue
117
+ roots.push(node);
118
+ continue;
126
119
  }
127
- node.parent = parent
128
- parent.children.push(node)
120
+ node.parent = parent;
121
+ parent.children.push(node);
129
122
  }
130
123
 
131
124
  const setDepth = (n: TreeNode, d: number, guard = new Set<TreeNode>()) => {
132
- if (guard.has(n)) return
133
- guard.add(n)
134
- n.depth = d
135
- for (const c of n.children) setDepth(c, d + 1, guard)
136
- }
137
- for (const r of roots) setDepth(r, 0)
138
-
139
- return roots
125
+ if (guard.has(n)) return;
126
+ guard.add(n);
127
+ n.depth = d;
128
+ for (const c of n.children) setDepth(c, d + 1, guard);
129
+ };
130
+ for (const r of roots) setDepth(r, 0);
131
+
132
+ return roots;
140
133
  }
141
134
 
142
135
  function makeNode(
@@ -146,80 +139,80 @@ function makeNode(
146
139
  parent: TreeNode | null,
147
140
  depth: number,
148
141
  ): TreeNode {
149
- const idValue = getByPath(record, config.idField)
150
- const id = idValue != null ? String(idValue) : `__row${idx}`
151
- return { id, record, children: [], depth, parent }
142
+ const idValue = getByPath(record, config.idField);
143
+ const id = idValue != null ? String(idValue) : `__row${idx}`;
144
+ return { id, record, children: [], depth, parent };
152
145
  }
153
146
 
154
147
  export function findNodeById(roots: TreeNode[], id: string): TreeNode | null {
155
148
  for (const root of roots) {
156
- if (root.id === id) return root
157
- const inChild = findNodeById(root.children, id)
158
- if (inChild) return inChild
149
+ if (root.id === id) return root;
150
+ const inChild = findNodeById(root.children, id);
151
+ if (inChild) return inChild;
159
152
  }
160
- return null
153
+ return null;
161
154
  }
162
155
 
163
156
  export function* walk(node: TreeNode): Generator<TreeNode> {
164
- yield node
165
- for (const c of node.children) yield* walk(c)
157
+ yield node;
158
+ for (const c of node.children) yield* walk(c);
166
159
  }
167
160
 
168
161
  export function flatten(node: TreeNode): DynamicRecord[] {
169
- const out: DynamicRecord[] = []
170
- for (const n of walk(node)) out.push(n.record)
171
- return out
162
+ const out: DynamicRecord[] = [];
163
+ for (const n of walk(node)) out.push(n.record);
164
+ return out;
172
165
  }
173
166
 
174
167
  export function descendantIds(node: TreeNode): Set<string> {
175
- const out = new Set<string>()
176
- for (const n of walk(node)) out.add(n.id)
177
- return out
168
+ const out = new Set<string>();
169
+ for (const n of walk(node)) out.add(n.id);
170
+ return out;
178
171
  }
179
172
 
180
173
  export function allIds(roots: TreeNode[]): Set<string> {
181
- const out = new Set<string>()
182
- for (const r of roots) for (const n of walk(r)) out.add(n.id)
183
- return out
174
+ const out = new Set<string>();
175
+ for (const r of roots) for (const n of walk(r)) out.add(n.id);
176
+ return out;
184
177
  }
185
178
 
186
179
  export function initialExpansion(roots: TreeNode[], mode: "all" | "roots" | "none"): Set<string> {
187
- if (mode === "none") return new Set()
188
- if (mode === "roots") return new Set(roots.map((r) => r.id))
189
- return allIds(roots)
180
+ if (mode === "none") return new Set();
181
+ if (mode === "roots") return new Set(roots.map((r) => r.id));
182
+ return allIds(roots);
190
183
  }
191
184
 
192
185
  export function flattenAll(data: DynamicRecord[], childrenField: string): DynamicRecord[] {
193
- const out: DynamicRecord[] = []
186
+ const out: DynamicRecord[] = [];
194
187
  const dfs = (record: DynamicRecord) => {
195
- if (record == null || typeof record !== "object") return
196
- const { [childrenField]: kids, ...rest } = record
197
- out.push(rest as DynamicRecord)
198
- if (Array.isArray(kids)) for (const k of kids) dfs(k)
199
- }
200
- for (const r of data) dfs(r)
201
- return out
188
+ if (record == null || typeof record !== "object") return;
189
+ const { [childrenField]: kids, ...rest } = record;
190
+ out.push(rest as DynamicRecord);
191
+ if (Array.isArray(kids)) for (const k of kids) dfs(k);
192
+ };
193
+ for (const r of data) dfs(r);
194
+ return out;
202
195
  }
203
196
 
204
197
  export type MoveArgs = {
205
- dragIds: string[]
206
- parentId: string | null
207
- index: number
208
- }
198
+ dragIds: string[];
199
+ parentId: string | null;
200
+ index: number;
201
+ };
209
202
 
210
203
  export function applyMove(
211
204
  data: DynamicRecord[],
212
205
  config: ResolvedTreeConfig,
213
206
  args: MoveArgs,
214
207
  ): DynamicRecord[] {
215
- if (config.childrenField) return applyMoveNested(data, config, args)
216
- if (config.parentField) return applyMoveFlat(data, config, args)
217
- return applyMoveTopLevel(data, config, args)
208
+ if (config.childrenField) return applyMoveNested(data, config, args);
209
+ if (config.parentField) return applyMoveFlat(data, config, args);
210
+ return applyMoveTopLevel(data, config, args);
218
211
  }
219
212
 
220
213
  function recordId(record: DynamicRecord, idField: string, fallbackIdx: number): string {
221
- const v = getByPath(record, idField)
222
- return v != null ? String(v) : `__row${fallbackIdx}`
214
+ const v = getByPath(record, idField);
215
+ return v != null ? String(v) : `__row${fallbackIdx}`;
223
216
  }
224
217
 
225
218
  function applyMoveTopLevel(
@@ -227,16 +220,16 @@ function applyMoveTopLevel(
227
220
  config: ResolvedTreeConfig,
228
221
  args: MoveArgs,
229
222
  ): DynamicRecord[] {
230
- const ids = new Set(args.dragIds)
231
- const dragged: DynamicRecord[] = []
232
- const remaining: DynamicRecord[] = []
223
+ const ids = new Set(args.dragIds);
224
+ const dragged: DynamicRecord[] = [];
225
+ const remaining: DynamicRecord[] = [];
233
226
  data.forEach((rec, i) => {
234
- if (ids.has(recordId(rec, config.idField, i))) dragged.push(rec)
235
- else remaining.push(rec)
236
- })
237
- const target = args.parentId == null ? remaining : remaining
238
- const insertAt = Math.max(0, Math.min(args.index, target.length))
239
- return [...target.slice(0, insertAt), ...dragged, ...target.slice(insertAt)]
227
+ if (ids.has(recordId(rec, config.idField, i))) dragged.push(rec);
228
+ else remaining.push(rec);
229
+ });
230
+ const target = args.parentId == null ? remaining : remaining;
231
+ const insertAt = Math.max(0, Math.min(args.index, target.length));
232
+ return [...target.slice(0, insertAt), ...dragged, ...target.slice(insertAt)];
240
233
  }
241
234
 
242
235
  function applyMoveFlat(
@@ -244,63 +237,63 @@ function applyMoveFlat(
244
237
  config: ResolvedTreeConfig,
245
238
  args: MoveArgs,
246
239
  ): DynamicRecord[] {
247
- const idField = config.idField
248
- const parentField = config.parentField!
249
- const orderField = config.orderField
240
+ const idField = config.idField;
241
+ const parentField = config.parentField!;
242
+ const orderField = config.orderField;
250
243
 
251
- const dragSet = new Set(args.dragIds)
244
+ const dragSet = new Set(args.dragIds);
252
245
 
253
246
  if (args.parentId) {
254
247
  for (const d of data) {
255
- const id = String(getByPath(d, idField) ?? "")
256
- if (!dragSet.has(id)) continue
257
- let cur: string | null = args.parentId
248
+ const id = String(getByPath(d, idField) ?? "");
249
+ if (!dragSet.has(id)) continue;
250
+ let cur: string | null = args.parentId;
258
251
  while (cur) {
259
- if (cur === id) return data
260
- const search = cur
261
- const parentRec = data.find((r) => String(getByPath(r, idField) ?? "") === search)
262
- if (!parentRec) break
263
- const next = getByPath(parentRec, parentField)
264
- cur = next == null ? null : String(next)
252
+ if (cur === id) return data;
253
+ const search = cur;
254
+ const parentRec = data.find((r) => String(getByPath(r, idField) ?? "") === search);
255
+ if (!parentRec) break;
256
+ const next = getByPath(parentRec, parentField);
257
+ cur = next == null ? null : String(next);
265
258
  }
266
259
  }
267
260
  }
268
261
 
269
262
  const updatedParent: DynamicRecord[] = data.map((rec) => {
270
- const id = String(getByPath(rec, idField) ?? "")
271
- if (!dragSet.has(id)) return rec
272
- return setByPath(rec, parentField, args.parentId ?? null)
273
- })
263
+ const id = String(getByPath(rec, idField) ?? "");
264
+ if (!dragSet.has(id)) return rec;
265
+ return setByPath(rec, parentField, args.parentId ?? null);
266
+ });
274
267
 
275
- if (!orderField) return updatedParent
268
+ if (!orderField) return updatedParent;
276
269
 
277
270
  const siblingsAfter = updatedParent.filter((rec) => {
278
- const p = getByPath(rec, parentField)
279
- const norm = p == null ? null : String(p)
280
- return norm === (args.parentId ?? null)
281
- })
271
+ const p = getByPath(rec, parentField);
272
+ const norm = p == null ? null : String(p);
273
+ return norm === (args.parentId ?? null);
274
+ });
282
275
 
283
- const dragged: DynamicRecord[] = []
284
- const others: DynamicRecord[] = []
276
+ const dragged: DynamicRecord[] = [];
277
+ const others: DynamicRecord[] = [];
285
278
  siblingsAfter.forEach((rec) => {
286
- const id = String(getByPath(rec, idField) ?? "")
287
- if (dragSet.has(id)) dragged.push(rec)
288
- else others.push(rec)
289
- })
290
-
291
- const insertAt = Math.max(0, Math.min(args.index, others.length))
292
- const newOrder = [...others.slice(0, insertAt), ...dragged, ...others.slice(insertAt)]
293
- const orderById = new Map<string, number>()
279
+ const id = String(getByPath(rec, idField) ?? "");
280
+ if (dragSet.has(id)) dragged.push(rec);
281
+ else others.push(rec);
282
+ });
283
+
284
+ const insertAt = Math.max(0, Math.min(args.index, others.length));
285
+ const newOrder = [...others.slice(0, insertAt), ...dragged, ...others.slice(insertAt)];
286
+ const orderById = new Map<string, number>();
294
287
  newOrder.forEach((rec, i) => {
295
- const id = String(getByPath(rec, idField) ?? "")
296
- orderById.set(id, i)
297
- })
288
+ const id = String(getByPath(rec, idField) ?? "");
289
+ orderById.set(id, i);
290
+ });
298
291
 
299
292
  return updatedParent.map((rec) => {
300
- const id = String(getByPath(rec, idField) ?? "")
301
- if (!orderById.has(id)) return rec
302
- return setByPath(rec, orderField, orderById.get(id)!)
303
- })
293
+ const id = String(getByPath(rec, idField) ?? "");
294
+ if (!orderById.has(id)) return rec;
295
+ return setByPath(rec, orderField, orderById.get(id)!);
296
+ });
304
297
  }
305
298
 
306
299
  function applyMoveNested(
@@ -308,69 +301,69 @@ function applyMoveNested(
308
301
  config: ResolvedTreeConfig,
309
302
  args: MoveArgs,
310
303
  ): DynamicRecord[] {
311
- const childrenField = config.childrenField!
312
- const idField = config.idField
313
- const dragSet = new Set(args.dragIds)
304
+ const childrenField = config.childrenField!;
305
+ const idField = config.idField;
306
+ const dragSet = new Set(args.dragIds);
314
307
 
315
308
  const isAncestorOfDrag = (record: DynamicRecord, ancestors: DynamicRecord[]): boolean => {
316
- const id = String(getByPath(record, idField) ?? "")
309
+ const id = String(getByPath(record, idField) ?? "");
317
310
  if (dragSet.has(id)) {
318
311
  for (const a of ancestors) {
319
- const aid = String(getByPath(a, idField) ?? "")
320
- if (aid === args.parentId) return true
312
+ const aid = String(getByPath(a, idField) ?? "");
313
+ if (aid === args.parentId) return true;
321
314
  }
322
315
  }
323
- const kids = getByPath(record, childrenField)
316
+ const kids = getByPath(record, childrenField);
324
317
  if (Array.isArray(kids)) {
325
318
  for (const k of kids) {
326
- if (isAncestorOfDrag(k, [...ancestors, record])) return true
319
+ if (isAncestorOfDrag(k, [...ancestors, record])) return true;
327
320
  }
328
321
  }
329
- return false
330
- }
331
- for (const r of data) if (isAncestorOfDrag(r, [])) return data
322
+ return false;
323
+ };
324
+ for (const r of data) if (isAncestorOfDrag(r, [])) return data;
332
325
 
333
- const extracted: DynamicRecord[] = []
326
+ const extracted: DynamicRecord[] = [];
334
327
  const extract = (records: DynamicRecord[]): DynamicRecord[] =>
335
328
  records
336
329
  .map((rec) => {
337
- const id = String(getByPath(rec, idField) ?? "")
338
- const kids = getByPath(rec, childrenField)
339
- const newKids = Array.isArray(kids) ? extract(kids) : kids
340
- const next = Array.isArray(kids) ? setByPath(rec, childrenField, newKids) : rec
330
+ const id = String(getByPath(rec, idField) ?? "");
331
+ const kids = getByPath(rec, childrenField);
332
+ const newKids = Array.isArray(kids) ? extract(kids) : kids;
333
+ const next = Array.isArray(kids) ? setByPath(rec, childrenField, newKids) : rec;
341
334
  if (dragSet.has(id)) {
342
- extracted.push(next)
343
- return null
335
+ extracted.push(next);
336
+ return null;
344
337
  }
345
- return next
338
+ return next;
346
339
  })
347
- .filter((r): r is DynamicRecord => r !== null)
340
+ .filter((r): r is DynamicRecord => r !== null);
348
341
 
349
- let pruned = extract(data)
342
+ const pruned = extract(data);
350
343
 
351
344
  const insert = (records: DynamicRecord[]): DynamicRecord[] =>
352
345
  records.map((rec) => {
353
- const id = String(getByPath(rec, idField) ?? "")
346
+ const id = String(getByPath(rec, idField) ?? "");
354
347
  if (id === args.parentId) {
355
- const kids = getByPath(rec, childrenField)
356
- const arr = Array.isArray(kids) ? [...kids] : []
357
- const at = Math.max(0, Math.min(args.index, arr.length))
358
- arr.splice(at, 0, ...extracted)
359
- return setByPath(rec, childrenField, arr)
348
+ const kids = getByPath(rec, childrenField);
349
+ const arr = Array.isArray(kids) ? [...kids] : [];
350
+ const at = Math.max(0, Math.min(args.index, arr.length));
351
+ arr.splice(at, 0, ...extracted);
352
+ return setByPath(rec, childrenField, arr);
360
353
  }
361
- const kids = getByPath(rec, childrenField)
354
+ const kids = getByPath(rec, childrenField);
362
355
  if (Array.isArray(kids)) {
363
- return setByPath(rec, childrenField, insert(kids))
356
+ return setByPath(rec, childrenField, insert(kids));
364
357
  }
365
- return rec
366
- })
358
+ return rec;
359
+ });
367
360
 
368
361
  if (args.parentId == null) {
369
- const at = Math.max(0, Math.min(args.index, pruned.length))
370
- return [...pruned.slice(0, at), ...extracted, ...pruned.slice(at)]
362
+ const at = Math.max(0, Math.min(args.index, pruned.length));
363
+ return [...pruned.slice(0, at), ...extracted, ...pruned.slice(at)];
371
364
  }
372
365
 
373
- return insert(pruned)
366
+ return insert(pruned);
374
367
  }
375
368
 
376
369
  export function pruneTree(
@@ -378,26 +371,26 @@ export function pruneTree(
378
371
  predicate: (record: DynamicRecord) => boolean,
379
372
  ): TreeNode[] {
380
373
  const visit = (node: TreeNode, parent: TreeNode | null): TreeNode | null => {
381
- const newChildren: TreeNode[] = []
374
+ const newChildren: TreeNode[] = [];
382
375
  for (const c of node.children) {
383
- const next = visit(c, node)
384
- if (next) newChildren.push(next)
376
+ const next = visit(c, node);
377
+ if (next) newChildren.push(next);
385
378
  }
386
- const selfMatches = predicate(node.record)
387
- if (!selfMatches && newChildren.length === 0) return null
379
+ const selfMatches = predicate(node.record);
380
+ if (!selfMatches && newChildren.length === 0) return null;
388
381
  return {
389
382
  id: node.id,
390
383
  record: node.record,
391
384
  depth: node.depth,
392
385
  parent,
393
386
  children: newChildren,
394
- }
395
- }
387
+ };
388
+ };
396
389
 
397
- const out: TreeNode[] = []
390
+ const out: TreeNode[] = [];
398
391
  for (const r of roots) {
399
- const next = visit(r, null)
400
- if (next) out.push(next)
392
+ const next = visit(r, null);
393
+ if (next) out.push(next);
401
394
  }
402
- return out
395
+ return out;
403
396
  }