@proyecto-viviana/solid-stately 0.2.4 → 0.3.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 (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -283
  3. package/dist/autocomplete/createAutocompleteState.d.ts +3 -2
  4. package/dist/autocomplete/index.d.ts +1 -1
  5. package/dist/calendar/createCalendarState.d.ts +22 -7
  6. package/dist/calendar/createDateFieldState.d.ts +30 -7
  7. package/dist/calendar/createDatePickerState.d.ts +60 -0
  8. package/dist/calendar/createRangeCalendarState.d.ts +27 -8
  9. package/dist/calendar/createTimeFieldState.d.ts +34 -7
  10. package/dist/calendar/index.d.ts +7 -6
  11. package/dist/checkbox/createCheckboxGroupState.d.ts +12 -3
  12. package/dist/checkbox/index.d.ts +1 -1
  13. package/dist/collections/ListCollection.d.ts +1 -1
  14. package/dist/collections/createListState.d.ts +8 -8
  15. package/dist/collections/createMenuState.d.ts +7 -7
  16. package/dist/collections/createSelectionState.d.ts +5 -5
  17. package/dist/collections/index.d.ts +5 -5
  18. package/dist/collections/types.d.ts +23 -12
  19. package/dist/color/Color.d.ts +1 -1
  20. package/dist/color/createColorAreaState.d.ts +4 -2
  21. package/dist/color/createColorFieldState.d.ts +38 -12
  22. package/dist/color/createColorSliderState.d.ts +9 -2
  23. package/dist/color/createColorWheelState.d.ts +13 -2
  24. package/dist/color/getColorChannels.d.ts +20 -0
  25. package/dist/color/index.d.ts +6 -6
  26. package/dist/color/types.d.ts +4 -4
  27. package/dist/combobox/createComboBoxState.d.ts +27 -13
  28. package/dist/combobox/index.d.ts +1 -1
  29. package/dist/data/createAsyncList.d.ts +111 -0
  30. package/dist/data/createListData.d.ts +65 -0
  31. package/dist/data/createTreeData.d.ts +65 -0
  32. package/dist/data/index.d.ts +3 -0
  33. package/dist/datepicker/index.d.ts +8 -0
  34. package/dist/disclosure/createDisclosureState.d.ts +2 -2
  35. package/dist/disclosure/index.d.ts +1 -1
  36. package/dist/dnd/createDragState.d.ts +2 -2
  37. package/dist/dnd/createDraggableCollectionState.d.ts +2 -2
  38. package/dist/dnd/createDropState.d.ts +2 -2
  39. package/dist/dnd/createDroppableCollectionState.d.ts +3 -3
  40. package/dist/dnd/index.d.ts +5 -5
  41. package/dist/dnd/types.d.ts +16 -16
  42. package/dist/form/createFormValidationState.d.ts +3 -3
  43. package/dist/form/index.d.ts +1 -1
  44. package/dist/grid/createGridState.d.ts +2 -2
  45. package/dist/grid/index.d.ts +2 -2
  46. package/dist/grid/types.d.ts +17 -11
  47. package/dist/index.d.ts +31 -25
  48. package/dist/index.js +7990 -6264
  49. package/dist/index.js.map +1 -7
  50. package/dist/menu/index.d.ts +8 -0
  51. package/dist/numberfield/createNumberFieldState.d.ts +2 -2
  52. package/dist/numberfield/index.d.ts +1 -1
  53. package/dist/overlays/createOverlayTriggerState.d.ts +2 -2
  54. package/dist/overlays/index.d.ts +1 -1
  55. package/dist/radio/createRadioGroupState.d.ts +13 -4
  56. package/dist/radio/index.d.ts +1 -1
  57. package/dist/searchfield/createSearchFieldState.d.ts +2 -2
  58. package/dist/searchfield/index.d.ts +2 -2
  59. package/dist/select/createSelectState.d.ts +20 -3
  60. package/dist/select/index.d.ts +1 -1
  61. package/dist/selection/index.d.ts +11 -0
  62. package/dist/slider/createSliderState.d.ts +3 -3
  63. package/dist/slider/index.d.ts +2 -2
  64. package/dist/steplist/createStepListState.d.ts +48 -0
  65. package/dist/steplist/index.d.ts +1 -0
  66. package/dist/table/TableCollection.d.ts +3 -3
  67. package/dist/table/createTableColumnResizeState.d.ts +54 -0
  68. package/dist/table/createTableState.d.ts +2 -2
  69. package/dist/table/index.d.ts +5 -3
  70. package/dist/table/types.d.ts +10 -10
  71. package/dist/tabs/createTabListState.d.ts +5 -5
  72. package/dist/tabs/index.d.ts +1 -1
  73. package/dist/textfield/createTextFieldState.d.ts +2 -2
  74. package/dist/textfield/index.d.ts +1 -1
  75. package/dist/toast/createToastState.d.ts +15 -3
  76. package/dist/toast/index.d.ts +1 -1
  77. package/dist/toggle/createToggleGroupState.d.ts +45 -0
  78. package/dist/toggle/createToggleState.d.ts +2 -2
  79. package/dist/toggle/index.d.ts +2 -1
  80. package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
  81. package/dist/tooltip/index.d.ts +1 -1
  82. package/dist/tree/TreeCollection.d.ts +5 -4
  83. package/dist/tree/createTreeState.d.ts +2 -2
  84. package/dist/tree/index.d.ts +3 -3
  85. package/dist/tree/types.d.ts +19 -13
  86. package/dist/utils/index.d.ts +1 -1
  87. package/dist/utils/reactivity.d.ts +1 -1
  88. package/package.json +30 -30
  89. package/src/autocomplete/createAutocompleteState.d.ts +19 -17
  90. package/src/autocomplete/createAutocompleteState.ts +25 -32
  91. package/src/autocomplete/index.d.ts +6 -2
  92. package/src/autocomplete/index.ts +1 -1
  93. package/src/calendar/createCalendarState.d.ts +139 -117
  94. package/src/calendar/createCalendarState.ts +221 -74
  95. package/src/calendar/createDateFieldState.d.ts +130 -95
  96. package/src/calendar/createDateFieldState.ts +286 -151
  97. package/src/calendar/createDatePickerState.ts +347 -0
  98. package/src/calendar/createRangeCalendarState.d.ts +154 -129
  99. package/src/calendar/createRangeCalendarState.ts +293 -79
  100. package/src/calendar/createTimeFieldState.d.ts +81 -79
  101. package/src/calendar/createTimeFieldState.ts +187 -108
  102. package/src/calendar/index.d.ts +80 -7
  103. package/src/calendar/index.ts +21 -12
  104. package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
  105. package/src/checkbox/createCheckboxGroupState.ts +57 -30
  106. package/src/checkbox/index.d.ts +6 -2
  107. package/src/checkbox/index.ts +1 -1
  108. package/src/collections/ListCollection.d.ts +25 -22
  109. package/src/collections/ListCollection.ts +152 -146
  110. package/src/collections/createListState.d.ts +73 -58
  111. package/src/collections/createListState.ts +267 -264
  112. package/src/collections/createMenuState.d.ts +36 -31
  113. package/src/collections/createMenuState.ts +112 -106
  114. package/src/collections/createSelectionState.d.ts +78 -65
  115. package/src/collections/createSelectionState.ts +340 -336
  116. package/src/collections/index.d.ts +38 -6
  117. package/src/collections/index.ts +41 -46
  118. package/src/collections/types.d.ts +101 -101
  119. package/src/collections/types.ts +181 -169
  120. package/src/color/Color.d.ts +20 -5
  121. package/src/color/Color.ts +1054 -951
  122. package/src/color/createColorAreaState.d.ts +67 -65
  123. package/src/color/createColorAreaState.ts +301 -293
  124. package/src/color/createColorFieldState.d.ts +46 -44
  125. package/src/color/createColorFieldState.ts +428 -292
  126. package/src/color/createColorSliderState.d.ts +58 -56
  127. package/src/color/createColorSliderState.ts +272 -241
  128. package/src/color/createColorWheelState.d.ts +42 -40
  129. package/src/color/createColorWheelState.ts +248 -211
  130. package/src/color/getColorChannels.ts +36 -0
  131. package/src/color/index.d.ts +36 -7
  132. package/src/color/index.ts +44 -47
  133. package/src/color/types.d.ts +68 -63
  134. package/src/color/types.ts +119 -127
  135. package/src/combobox/createComboBoxState.d.ts +107 -105
  136. package/src/combobox/createComboBoxState.ts +790 -703
  137. package/src/combobox/index.d.ts +10 -2
  138. package/src/combobox/index.ts +13 -13
  139. package/src/data/createAsyncList.ts +403 -0
  140. package/src/data/createListData.ts +298 -0
  141. package/src/data/createTreeData.ts +646 -0
  142. package/src/data/index.ts +25 -0
  143. package/src/datepicker/index.ts +32 -0
  144. package/src/disclosure/createDisclosureState.d.ts +47 -43
  145. package/src/disclosure/createDisclosureState.ts +9 -23
  146. package/src/disclosure/index.d.ts +10 -2
  147. package/src/disclosure/index.ts +1 -1
  148. package/src/dnd/createDragState.d.ts +51 -42
  149. package/src/dnd/createDragState.ts +151 -153
  150. package/src/dnd/createDraggableCollectionState.d.ts +52 -41
  151. package/src/dnd/createDraggableCollectionState.ts +158 -165
  152. package/src/dnd/createDropState.d.ts +64 -45
  153. package/src/dnd/createDropState.ts +202 -212
  154. package/src/dnd/createDroppableCollectionState.d.ts +88 -59
  155. package/src/dnd/createDroppableCollectionState.ts +354 -357
  156. package/src/dnd/index.d.ts +54 -6
  157. package/src/dnd/index.ts +63 -76
  158. package/src/dnd/types.d.ts +167 -156
  159. package/src/dnd/types.ts +316 -317
  160. package/src/form/createFormValidationState.d.ts +47 -45
  161. package/src/form/createFormValidationState.ts +356 -389
  162. package/src/form/index.d.ts +16 -2
  163. package/src/form/index.ts +15 -15
  164. package/src/grid/createGridState.d.ts +7 -4
  165. package/src/grid/createGridState.ts +44 -51
  166. package/src/grid/index.d.ts +3 -3
  167. package/src/grid/index.ts +2 -8
  168. package/src/grid/types.d.ts +136 -129
  169. package/src/grid/types.ts +24 -17
  170. package/src/index.d.ts +310 -26
  171. package/src/index.ts +87 -79
  172. package/src/menu/index.ts +17 -0
  173. package/src/numberfield/createNumberFieldState.d.ts +56 -54
  174. package/src/numberfield/createNumberFieldState.ts +422 -383
  175. package/src/numberfield/index.d.ts +6 -2
  176. package/src/numberfield/index.ts +5 -5
  177. package/src/overlays/createOverlayTriggerState.d.ts +22 -20
  178. package/src/overlays/createOverlayTriggerState.ts +66 -67
  179. package/src/overlays/index.d.ts +6 -2
  180. package/src/overlays/index.ts +5 -5
  181. package/src/radio/createRadioGroupState.d.ts +54 -52
  182. package/src/radio/createRadioGroupState.ts +66 -30
  183. package/src/radio/index.d.ts +7 -2
  184. package/src/radio/index.ts +1 -1
  185. package/src/searchfield/createSearchFieldState.d.ts +16 -14
  186. package/src/searchfield/createSearchFieldState.ts +56 -62
  187. package/src/searchfield/index.d.ts +3 -3
  188. package/src/searchfield/index.ts +2 -5
  189. package/src/select/createSelectState.d.ts +63 -61
  190. package/src/select/createSelectState.ts +290 -181
  191. package/src/select/index.d.ts +2 -2
  192. package/src/select/index.ts +1 -5
  193. package/src/selection/index.ts +27 -0
  194. package/src/slider/createSliderState.d.ts +60 -60
  195. package/src/slider/createSliderState.ts +233 -211
  196. package/src/slider/index.d.ts +3 -3
  197. package/src/slider/index.ts +2 -6
  198. package/src/ssr/index.d.ts +1 -1
  199. package/src/ssr/index.ts +2 -2
  200. package/src/steplist/createStepListState.ts +191 -0
  201. package/src/steplist/index.ts +5 -0
  202. package/src/table/TableCollection.d.ts +42 -40
  203. package/src/table/TableCollection.ts +61 -64
  204. package/src/table/createTableColumnResizeState.ts +242 -0
  205. package/src/table/createTableState.d.ts +7 -4
  206. package/src/table/createTableState.ts +10 -7
  207. package/src/table/index.d.ts +14 -4
  208. package/src/table/index.ts +10 -3
  209. package/src/table/types.d.ts +98 -92
  210. package/src/table/types.ts +17 -13
  211. package/src/tabs/createTabListState.d.ts +59 -57
  212. package/src/tabs/createTabListState.ts +58 -39
  213. package/src/tabs/index.d.ts +8 -2
  214. package/src/tabs/index.ts +1 -1
  215. package/src/textfield/createTextFieldState.d.ts +16 -14
  216. package/src/textfield/createTextFieldState.ts +7 -18
  217. package/src/textfield/index.d.ts +6 -2
  218. package/src/textfield/index.ts +1 -1
  219. package/src/toast/createToastState.d.ts +92 -81
  220. package/src/toast/createToastState.ts +56 -44
  221. package/src/toast/index.d.ts +12 -2
  222. package/src/toast/index.ts +1 -1
  223. package/src/toggle/createToggleGroupState.ts +117 -0
  224. package/src/toggle/createToggleState.d.ts +19 -19
  225. package/src/toggle/createToggleState.ts +2 -16
  226. package/src/toggle/index.d.ts +2 -2
  227. package/src/toggle/index.ts +6 -4
  228. package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
  229. package/src/tooltip/createTooltipTriggerState.ts +184 -183
  230. package/src/tooltip/index.d.ts +7 -2
  231. package/src/tooltip/index.ts +6 -6
  232. package/src/tree/TreeCollection.d.ts +26 -23
  233. package/src/tree/TreeCollection.ts +215 -175
  234. package/src/tree/createTreeState.d.ts +7 -4
  235. package/src/tree/createTreeState.ts +390 -392
  236. package/src/tree/index.d.ts +10 -4
  237. package/src/tree/index.ts +13 -13
  238. package/src/tree/types.d.ts +131 -126
  239. package/src/tree/types.ts +183 -174
  240. package/src/utils/index.d.ts +2 -2
  241. package/src/utils/index.ts +1 -1
  242. package/src/utils/reactivity.d.ts +2 -2
  243. package/src/utils/reactivity.ts +3 -3
@@ -0,0 +1,646 @@
1
+ /**
2
+ * createTreeData - SolidJS port of React Spectrum's useTreeData
3
+ *
4
+ * Manages state for an immutable tree data structure, and provides
5
+ * convenience methods to update the data over time.
6
+ */
7
+
8
+ import { createSignal } from "solid-js";
9
+
10
+ export type Key = string | number;
11
+ export type Selection = "all" | Set<Key>;
12
+
13
+ export interface TreeNode<T> {
14
+ /** A unique key for the tree node. */
15
+ key: Key;
16
+ /** The key of the parent node. */
17
+ parentKey: Key | null;
18
+ /** The value object for the tree node. */
19
+ value: T;
20
+ /** The children of this node. */
21
+ children: TreeNode<T>[] | null;
22
+ }
23
+
24
+ export interface TreeOptions<T> {
25
+ /** Initial items in the tree. */
26
+ initialItems?: T[];
27
+ /** The keys for the initially selected items. */
28
+ initialSelectedKeys?: "all" | Iterable<Key>;
29
+ /** A function that returns a unique key for an item object. */
30
+ getKey?: (item: T) => Key;
31
+ /** A function that returns the children of an item object. */
32
+ getChildren?: (item: T) => T[];
33
+ }
34
+
35
+ export interface TreeData<T> {
36
+ /** The root items in the tree. */
37
+ readonly items: TreeNode<T>[];
38
+ /** The keys of the currently selected items in the tree. */
39
+ readonly selectedKeys: Selection;
40
+ /** Sets the selected keys. */
41
+ setSelectedKeys(keys: Selection): void;
42
+ /** Gets an item from the tree by key. */
43
+ getItem(key: Key): TreeNode<T> | undefined;
44
+ /** Inserts items into the tree. */
45
+ insert(parentKey: Key | null, index: number, ...values: T[]): void;
46
+ /** Inserts items before a given key. */
47
+ insertBefore(key: Key, ...values: T[]): void;
48
+ /** Inserts items after a given key. */
49
+ insertAfter(key: Key, ...values: T[]): void;
50
+ /** Appends items to a parent node. */
51
+ append(parentKey: Key | null, ...values: T[]): void;
52
+ /** Prepends items to a parent node. */
53
+ prepend(parentKey: Key | null, ...values: T[]): void;
54
+ /** Removes items from the tree by their keys. */
55
+ remove(...keys: Key[]): void;
56
+ /** Removes all items from the tree that are currently in the set of selected items. */
57
+ removeSelectedItems(): void;
58
+ /** Moves an item to a new parent. */
59
+ move(key: Key, toParentKey: Key | null, index: number): void;
60
+ /** Moves items before a given key. */
61
+ moveBefore(key: Key, keys: Iterable<Key>): void;
62
+ /** Moves items after a given key. */
63
+ moveAfter(key: Key, keys: Iterable<Key>): void;
64
+ /** Updates an item in the tree. */
65
+ update(key: Key, newValue: T): void;
66
+ }
67
+
68
+ interface TreeDataState<T> {
69
+ items: TreeNode<T>[];
70
+ nodeMap: Map<Key, TreeNode<T>>;
71
+ }
72
+
73
+ /**
74
+ * Manages state for an immutable tree data structure, and provides
75
+ * convenience methods to update the data over time.
76
+ */
77
+ export function createTreeData<T>(options: TreeOptions<T>): TreeData<T> {
78
+ const defaultGetKey = (item: T): Key => {
79
+ const candidate = item as { id?: Key; key?: Key };
80
+ return candidate.id ?? candidate.key ?? String(item);
81
+ };
82
+ const defaultGetChildren = (item: T): T[] => {
83
+ const candidate = item as { children?: T[] };
84
+ return candidate.children ?? [];
85
+ };
86
+
87
+ const {
88
+ initialItems = [],
89
+ initialSelectedKeys,
90
+ getKey = defaultGetKey,
91
+ getChildren = defaultGetChildren,
92
+ } = options;
93
+
94
+ // Build initial tree
95
+ const initialTree = buildTree(initialItems, new Map(), null, getKey, getChildren);
96
+
97
+ const [treeState, setTreeState] = createSignal<TreeDataState<T>>(initialTree);
98
+ const [selectedKeys, setSelectedKeys] = createSignal<Selection>(
99
+ initialSelectedKeys === "all" ? "all" : new Set(initialSelectedKeys || []),
100
+ );
101
+
102
+ function updateTree(
103
+ items: TreeNode<T>[],
104
+ key: Key | null,
105
+ update: (node: TreeNode<T>) => TreeNode<T> | null,
106
+ originalMap: Map<Key, TreeNode<T>>,
107
+ ): TreeDataState<T> {
108
+ let node = key != null ? originalMap.get(key) : null;
109
+ if (key != null && !node) return { items, nodeMap: originalMap };
110
+
111
+ const newMap = new Map(originalMap);
112
+
113
+ if (node) {
114
+ const updated = update(node);
115
+ if (!updated) {
116
+ // Delete node
117
+ deleteNode(node, newMap);
118
+ if (node.parentKey != null) {
119
+ return updateTree(
120
+ items,
121
+ node.parentKey,
122
+ (parent) => ({
123
+ ...parent,
124
+ children: parent.children!.filter((c) => c.key !== key),
125
+ }),
126
+ newMap,
127
+ );
128
+ }
129
+ return { items: items.filter((i) => i.key !== key), nodeMap: newMap };
130
+ }
131
+
132
+ newMap.set(key!, updated);
133
+ if (updated.children) {
134
+ for (const child of updated.children) {
135
+ addNode(child, newMap);
136
+ }
137
+ }
138
+
139
+ if (node.parentKey != null) {
140
+ return updateTree(
141
+ items,
142
+ node.parentKey,
143
+ (parent) => ({
144
+ ...parent,
145
+ children: parent.children!.map((c) => (c.key === key ? updated : c)),
146
+ }),
147
+ newMap,
148
+ );
149
+ }
150
+
151
+ return { items: items.map((i) => (i.key === key ? updated : i)), nodeMap: newMap };
152
+ }
153
+
154
+ return { items, nodeMap: newMap };
155
+ }
156
+
157
+ return {
158
+ get items() {
159
+ return treeState().items;
160
+ },
161
+ get selectedKeys() {
162
+ return selectedKeys();
163
+ },
164
+
165
+ setSelectedKeys(keys: Selection) {
166
+ setSelectedKeys(keys);
167
+ },
168
+
169
+ getItem(key: Key) {
170
+ return treeState().nodeMap.get(key);
171
+ },
172
+
173
+ insert(parentKey: Key | null, index: number, ...values: T[]) {
174
+ setTreeState((state) => {
175
+ const { items, nodeMap } = state;
176
+ const newMap = new Map(nodeMap);
177
+ const newNodes = values.map((v) => {
178
+ const tree = buildTree([v], newMap, parentKey, getKey, getChildren);
179
+ return tree.items[0];
180
+ });
181
+
182
+ if (parentKey == null) {
183
+ return {
184
+ items: [...items.slice(0, index), ...newNodes, ...items.slice(index)],
185
+ nodeMap: newMap,
186
+ };
187
+ }
188
+
189
+ return updateTree(
190
+ items,
191
+ parentKey,
192
+ (parent) => ({
193
+ ...parent,
194
+ children: [
195
+ ...(parent.children || []).slice(0, index),
196
+ ...newNodes,
197
+ ...(parent.children || []).slice(index),
198
+ ],
199
+ }),
200
+ newMap,
201
+ );
202
+ });
203
+ },
204
+
205
+ insertBefore(key: Key, ...values: T[]) {
206
+ setTreeState((state) => {
207
+ const { items, nodeMap } = state;
208
+ const node = nodeMap.get(key);
209
+ if (!node) return state;
210
+
211
+ const parent = node.parentKey != null ? nodeMap.get(node.parentKey) : null;
212
+ const siblings = parent?.children ?? items;
213
+ const index = siblings.findIndex((n) => n.key === key);
214
+ if (index === -1) return state;
215
+
216
+ const newMap = new Map(nodeMap);
217
+ const newNodes = values.map((v) => {
218
+ const tree = buildTree([v], newMap, node.parentKey, getKey, getChildren);
219
+ return tree.items[0];
220
+ });
221
+
222
+ if (node.parentKey == null) {
223
+ return {
224
+ items: [...items.slice(0, index), ...newNodes, ...items.slice(index)],
225
+ nodeMap: newMap,
226
+ };
227
+ }
228
+
229
+ return updateTree(
230
+ items,
231
+ node.parentKey,
232
+ (p) => ({
233
+ ...p,
234
+ children: [...p.children!.slice(0, index), ...newNodes, ...p.children!.slice(index)],
235
+ }),
236
+ newMap,
237
+ );
238
+ });
239
+ },
240
+
241
+ insertAfter(key: Key, ...values: T[]) {
242
+ setTreeState((state) => {
243
+ const { items, nodeMap } = state;
244
+ const node = nodeMap.get(key);
245
+ if (!node) return state;
246
+
247
+ const parent = node.parentKey != null ? nodeMap.get(node.parentKey) : null;
248
+ const siblings = parent?.children ?? items;
249
+ const index = siblings.findIndex((n) => n.key === key);
250
+ if (index === -1) return state;
251
+
252
+ const newMap = new Map(nodeMap);
253
+ const newNodes = values.map((v) => {
254
+ const tree = buildTree([v], newMap, node.parentKey, getKey, getChildren);
255
+ return tree.items[0];
256
+ });
257
+
258
+ if (node.parentKey == null) {
259
+ return {
260
+ items: [...items.slice(0, index + 1), ...newNodes, ...items.slice(index + 1)],
261
+ nodeMap: newMap,
262
+ };
263
+ }
264
+
265
+ return updateTree(
266
+ items,
267
+ node.parentKey,
268
+ (p) => ({
269
+ ...p,
270
+ children: [
271
+ ...p.children!.slice(0, index + 1),
272
+ ...newNodes,
273
+ ...p.children!.slice(index + 1),
274
+ ],
275
+ }),
276
+ newMap,
277
+ );
278
+ });
279
+ },
280
+
281
+ append(parentKey: Key | null, ...values: T[]) {
282
+ setTreeState((state) => {
283
+ const { items, nodeMap } = state;
284
+ const newMap = new Map(nodeMap);
285
+ const newNodes = values.map((v) => {
286
+ const tree = buildTree([v], newMap, parentKey, getKey, getChildren);
287
+ return tree.items[0];
288
+ });
289
+
290
+ if (parentKey == null) {
291
+ return { items: [...items, ...newNodes], nodeMap: newMap };
292
+ }
293
+
294
+ return updateTree(
295
+ items,
296
+ parentKey,
297
+ (parent) => ({
298
+ ...parent,
299
+ children: [...(parent.children || []), ...newNodes],
300
+ }),
301
+ newMap,
302
+ );
303
+ });
304
+ },
305
+
306
+ prepend(parentKey: Key | null, ...values: T[]) {
307
+ setTreeState((state) => {
308
+ const { items, nodeMap } = state;
309
+ const newMap = new Map(nodeMap);
310
+ const newNodes = values.map((v) => {
311
+ const tree = buildTree([v], newMap, parentKey, getKey, getChildren);
312
+ return tree.items[0];
313
+ });
314
+
315
+ if (parentKey == null) {
316
+ return { items: [...newNodes, ...items], nodeMap: newMap };
317
+ }
318
+
319
+ return updateTree(
320
+ items,
321
+ parentKey,
322
+ (parent) => ({
323
+ ...parent,
324
+ children: [...newNodes, ...(parent.children || [])],
325
+ }),
326
+ newMap,
327
+ );
328
+ });
329
+ },
330
+
331
+ remove(...keys: Key[]) {
332
+ setTreeState((state) => {
333
+ let { items, nodeMap } = state;
334
+ let newMap = new Map(nodeMap);
335
+ let newItems = items;
336
+
337
+ for (const key of keys) {
338
+ const result = updateTree(newItems, key, () => null, newMap);
339
+ newItems = result.items;
340
+ newMap = result.nodeMap;
341
+ }
342
+
343
+ return { items: newItems, nodeMap: newMap };
344
+ });
345
+
346
+ setSelectedKeys((sel) => {
347
+ if (sel === "all") return sel;
348
+ const newSel = new Set(sel);
349
+ for (const key of keys) {
350
+ newSel.delete(key);
351
+ }
352
+ return newSel;
353
+ });
354
+ },
355
+
356
+ removeSelectedItems() {
357
+ const sel = selectedKeys();
358
+ if (sel === "all") {
359
+ setTreeState({ items: [], nodeMap: new Map() });
360
+ setSelectedKeys(new Set<Key>());
361
+ return;
362
+ }
363
+
364
+ const keysToRemove = [...sel];
365
+ setTreeState((state) => {
366
+ let { items, nodeMap } = state;
367
+ let newMap = new Map(nodeMap);
368
+ let newItems = items;
369
+ for (const key of keysToRemove) {
370
+ const result = updateTree(newItems, key, () => null, newMap);
371
+ newItems = result.items;
372
+ newMap = result.nodeMap;
373
+ }
374
+ return { items: newItems, nodeMap: newMap };
375
+ });
376
+ setSelectedKeys(new Set<Key>());
377
+ },
378
+
379
+ move(key: Key, toParentKey: Key | null, index: number) {
380
+ setTreeState((state) => {
381
+ const { items, nodeMap } = state;
382
+ const node = nodeMap.get(key);
383
+ if (!node) return state;
384
+
385
+ // Cyclical move validation: prevent moving a node into its own subtree
386
+ if (toParentKey != null) {
387
+ let parent: TreeNode<T> | undefined = nodeMap.get(toParentKey);
388
+ while (parent) {
389
+ if (parent.key === key) return state;
390
+ parent = parent.parentKey != null ? nodeMap.get(parent.parentKey) : undefined;
391
+ }
392
+ }
393
+
394
+ // Remove the node
395
+ let newMap = new Map(nodeMap);
396
+ const removeResult = updateTree(items, key, () => null, newMap);
397
+ let newItems = removeResult.items;
398
+ newMap = removeResult.nodeMap;
399
+
400
+ // Re-add it at the target
401
+ const movedNode: TreeNode<T> = { ...node, parentKey: toParentKey };
402
+ addNode(movedNode, newMap);
403
+
404
+ if (toParentKey == null) {
405
+ return {
406
+ items: [...newItems.slice(0, index), movedNode, ...newItems.slice(index)],
407
+ nodeMap: newMap,
408
+ };
409
+ }
410
+
411
+ return updateTree(
412
+ newItems,
413
+ toParentKey,
414
+ (parent) => ({
415
+ ...parent,
416
+ children: [
417
+ ...(parent.children || []).slice(0, index),
418
+ movedNode,
419
+ ...(parent.children || []).slice(index),
420
+ ],
421
+ }),
422
+ newMap,
423
+ );
424
+ });
425
+ },
426
+
427
+ moveBefore(key: Key, keys: Iterable<Key>) {
428
+ setTreeState((state) => {
429
+ const { items, nodeMap } = state;
430
+ const node = nodeMap.get(key);
431
+ if (!node) return state;
432
+
433
+ const toParentKey = node.parentKey ?? null;
434
+ let parent: TreeNode<T> | null = null;
435
+ if (toParentKey != null) {
436
+ parent = nodeMap.get(toParentKey) ?? null;
437
+ }
438
+ const toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);
439
+ return moveItems(state, keys, parent, toIndex, updateTree, addNode);
440
+ });
441
+ },
442
+
443
+ moveAfter(key: Key, keys: Iterable<Key>) {
444
+ setTreeState((state) => {
445
+ const { items, nodeMap } = state;
446
+ const node = nodeMap.get(key);
447
+ if (!node) return state;
448
+
449
+ const toParentKey = node.parentKey ?? null;
450
+ let parent: TreeNode<T> | null = null;
451
+ if (toParentKey != null) {
452
+ parent = nodeMap.get(toParentKey) ?? null;
453
+ }
454
+ let toIndex = parent?.children ? parent.children.indexOf(node) : items.indexOf(node);
455
+ toIndex++;
456
+ return moveItems(state, keys, parent, toIndex, updateTree, addNode);
457
+ });
458
+ },
459
+
460
+ update(key: Key, newValue: T) {
461
+ setTreeState((state) => {
462
+ const { items, nodeMap } = state;
463
+ const newMap = new Map(nodeMap);
464
+
465
+ return updateTree(
466
+ items,
467
+ key,
468
+ (oldNode) => {
469
+ const node: TreeNode<T> = {
470
+ key: oldNode.key,
471
+ parentKey: oldNode.parentKey,
472
+ value: newValue,
473
+ children: null,
474
+ };
475
+ const tree = buildTree(getChildren(newValue), newMap, node.key, getKey, getChildren);
476
+ node.children = tree.items;
477
+ return node;
478
+ },
479
+ newMap,
480
+ );
481
+ });
482
+ },
483
+ };
484
+ }
485
+
486
+ function buildTree<T>(
487
+ items: T[],
488
+ nodeMap: Map<Key, TreeNode<T>>,
489
+ parentKey: Key | null,
490
+ getKey: (item: T) => Key,
491
+ getChildren: (item: T) => T[],
492
+ ): TreeDataState<T> {
493
+ const nodes: TreeNode<T>[] = [];
494
+
495
+ for (const item of items) {
496
+ const key = getKey(item);
497
+ const children = getChildren(item);
498
+
499
+ const childTree =
500
+ children.length > 0
501
+ ? buildTree(children, nodeMap, key, getKey, getChildren)
502
+ : { items: [], nodeMap };
503
+
504
+ const node: TreeNode<T> = {
505
+ key,
506
+ parentKey,
507
+ value: item,
508
+ children: childTree.items.length > 0 ? childTree.items : null,
509
+ };
510
+
511
+ nodeMap.set(key, node);
512
+ nodes.push(node);
513
+ }
514
+
515
+ return { items: nodes, nodeMap };
516
+ }
517
+
518
+ function addNode<T>(node: TreeNode<T>, map: Map<Key, TreeNode<T>>): void {
519
+ map.set(node.key, node);
520
+ if (node.children) {
521
+ for (const child of node.children) {
522
+ addNode(child, map);
523
+ }
524
+ }
525
+ }
526
+
527
+ function deleteNode<T>(node: TreeNode<T>, map: Map<Key, TreeNode<T>>): void {
528
+ map.delete(node.key);
529
+ if (node.children) {
530
+ for (const child of node.children) {
531
+ deleteNode(child, map);
532
+ }
533
+ }
534
+ }
535
+
536
+ function moveItems<T>(
537
+ state: TreeDataState<T>,
538
+ keys: Iterable<Key>,
539
+ toParent: TreeNode<T> | null,
540
+ toIndex: number,
541
+ updateTreeFn: (
542
+ items: TreeNode<T>[],
543
+ key: Key | null,
544
+ update: (node: TreeNode<T>) => TreeNode<T> | null,
545
+ originalMap: Map<Key, TreeNode<T>>,
546
+ ) => TreeDataState<T>,
547
+ addNodeFn: (node: TreeNode<T>, map: Map<Key, TreeNode<T>>) => void,
548
+ ): TreeDataState<T> {
549
+ const { items, nodeMap } = state;
550
+
551
+ // Cyclical move validation: prevent moving a node into its own subtree
552
+ const removeKeys = new Set(keys);
553
+ let ancestor: TreeNode<T> | null = toParent;
554
+ while (ancestor != null) {
555
+ if (removeKeys.has(ancestor.key)) {
556
+ throw new Error("Cannot move an item to be a child of itself.");
557
+ }
558
+ ancestor = ancestor.parentKey != null ? (nodeMap.get(ancestor.parentKey) ?? null) : null;
559
+ }
560
+
561
+ const originalToIndex = toIndex;
562
+ const keyArray = [...removeKeys];
563
+
564
+ // Depth-first traversal to determine in-order positions and remove items
565
+ const inOrderKeys = new Map<Key, number>();
566
+ const removedItems: TreeNode<T>[] = [];
567
+ let newItems = items;
568
+ let newMap = nodeMap;
569
+ let i = 0;
570
+
571
+ function traversal(
572
+ node: { children?: TreeNode<T>[] | null },
573
+ callbacks: {
574
+ inorder?: (child: TreeNode<T>) => void;
575
+ postorder?: (child: TreeNode<T>) => void;
576
+ },
577
+ ) {
578
+ callbacks.inorder?.(node as TreeNode<T>);
579
+ if (node.children) {
580
+ for (const child of node.children) {
581
+ traversal(child, callbacks);
582
+ callbacks.postorder?.(child);
583
+ }
584
+ }
585
+ }
586
+
587
+ traversal(
588
+ { children: items },
589
+ {
590
+ inorder(child) {
591
+ if (keyArray.includes(child.key)) {
592
+ inOrderKeys.set(child.key, i++);
593
+ }
594
+ },
595
+ postorder(child) {
596
+ if (keyArray.includes(child.key)) {
597
+ removedItems.push({ ...newMap.get(child.key)!, parentKey: toParent?.key ?? null });
598
+ const result = updateTreeFn(newItems, child.key, () => null, newMap);
599
+ newItems = result.items;
600
+ newMap = result.nodeMap;
601
+ }
602
+ // Decrement index if the removed child is in the target parent and before the target index
603
+ if (
604
+ (child.parentKey === toParent || child.parentKey === toParent?.key) &&
605
+ keyArray.includes(child.key) &&
606
+ (toParent?.children ? toParent.children.indexOf(child) : items.indexOf(child)) <
607
+ originalToIndex
608
+ ) {
609
+ toIndex--;
610
+ }
611
+ },
612
+ },
613
+ );
614
+
615
+ const inOrderItems = removedItems.sort((a, b) =>
616
+ inOrderKeys.get(a.key)! > inOrderKeys.get(b.key)! ? 1 : -1,
617
+ );
618
+
619
+ // If parentKey is null, insert into the root.
620
+ if (!toParent || toParent.key == null) {
621
+ inOrderItems.forEach((movedNode) => {
622
+ addNodeFn(movedNode, newMap);
623
+ });
624
+ return {
625
+ items: [...newItems.slice(0, toIndex), ...inOrderItems, ...newItems.slice(toIndex)],
626
+ nodeMap: newMap,
627
+ };
628
+ }
629
+
630
+ // Otherwise, update the parent node and its ancestors.
631
+ return updateTreeFn(
632
+ newItems,
633
+ toParent.key,
634
+ (parentNode) => ({
635
+ key: parentNode.key,
636
+ parentKey: parentNode.parentKey,
637
+ value: parentNode.value,
638
+ children: [
639
+ ...parentNode.children!.slice(0, toIndex),
640
+ ...inOrderItems,
641
+ ...parentNode.children!.slice(toIndex),
642
+ ],
643
+ }),
644
+ newMap,
645
+ );
646
+ }
@@ -0,0 +1,25 @@
1
+ export {
2
+ createListData,
3
+ type ListOptions,
4
+ type ListData,
5
+ type Key as ListDataKey,
6
+ type Selection as ListDataSelection,
7
+ } from "./createListData";
8
+
9
+ export {
10
+ createTreeData,
11
+ type TreeOptions,
12
+ type TreeData,
13
+ type TreeNode as TreeDataNode,
14
+ } from "./createTreeData";
15
+
16
+ export {
17
+ createAsyncList,
18
+ type AsyncListOptions,
19
+ type AsyncListData,
20
+ type AsyncListLoadFunction,
21
+ type AsyncListLoadOptions,
22
+ type AsyncListStateUpdate,
23
+ type SortDescriptor,
24
+ type LoadingState,
25
+ } from "./createAsyncList";
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Datepicker compatibility surface.
3
+ *
4
+ * This is a module-compat shim that maps React Stately datepicker hook names
5
+ * to existing Solid stately primitives.
6
+ */
7
+
8
+ export {
9
+ createDateFieldState,
10
+ createTimeFieldState,
11
+ createRangeCalendarState,
12
+ createDatePickerState,
13
+ type DateFieldStateProps as DateFieldStateOptions,
14
+ type DateFieldState,
15
+ type DateSegment,
16
+ type DateSegmentType as SegmentType,
17
+ type TimeFieldStateProps as TimeFieldStateOptions,
18
+ type TimeFieldState,
19
+ type TimeSegment,
20
+ type TimeSegmentType,
21
+ type RangeCalendarStateProps as DateRangePickerStateOptions,
22
+ type RangeCalendarState as DateRangePickerState,
23
+ type DatePickerState,
24
+ type DatePickerStateOptions,
25
+ } from "../calendar";
26
+
27
+ export {
28
+ createDateFieldState as useDateFieldState,
29
+ createTimeFieldState as useTimeFieldState,
30
+ createRangeCalendarState as useDateRangePickerState,
31
+ createDatePickerState as useDatePickerState,
32
+ } from "../calendar";