@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
@@ -1,5 +1,13 @@
1
1
  /**
2
2
  * ComboBox state management for Solid Stately.
3
3
  */
4
- export { createComboBoxState, defaultContainsFilter, type ComboBoxState, type ComboBoxStateProps, type FilterFn, type MenuTriggerAction, type FocusStrategy, } from './createComboBoxState';
5
- //# sourceMappingURL=index.d.ts.map
4
+ export {
5
+ createComboBoxState,
6
+ defaultContainsFilter,
7
+ type ComboBoxState,
8
+ type ComboBoxStateProps,
9
+ type FilterFn,
10
+ type MenuTriggerAction,
11
+ type FocusStrategy,
12
+ } from "./createComboBoxState";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -1,13 +1,13 @@
1
- /**
2
- * ComboBox state management for Solid Stately.
3
- */
4
-
5
- export {
6
- createComboBoxState,
7
- defaultContainsFilter,
8
- type ComboBoxState,
9
- type ComboBoxStateProps,
10
- type FilterFn,
11
- type MenuTriggerAction,
12
- type FocusStrategy,
13
- } from './createComboBoxState';
1
+ /**
2
+ * ComboBox state management for Solid Stately.
3
+ */
4
+
5
+ export {
6
+ createComboBoxState,
7
+ defaultContainsFilter,
8
+ type ComboBoxState,
9
+ type ComboBoxStateProps,
10
+ type FilterFn,
11
+ type MenuTriggerAction,
12
+ type FocusStrategy,
13
+ } from "./createComboBoxState";
@@ -0,0 +1,403 @@
1
+ /**
2
+ * createAsyncList - SolidJS port of React Spectrum's useAsyncList
3
+ *
4
+ * Manages state for an immutable async loaded list data structure, and provides
5
+ * convenience methods to update the data over time. Manages loading and error
6
+ * states, pagination, and sorting.
7
+ */
8
+
9
+ import { createSignal, untrack } from "solid-js";
10
+
11
+ export type Key = string | number;
12
+ export type Selection = "all" | Set<Key>;
13
+ export type LoadingState = "idle" | "loading" | "loadingMore" | "sorting" | "filtering" | "error";
14
+
15
+ export interface SortDescriptor {
16
+ /** The key of the column to sort by. */
17
+ column?: Key;
18
+ /** The direction to sort by. */
19
+ direction?: "ascending" | "descending";
20
+ }
21
+
22
+ export interface AsyncListLoadOptions<T, C> {
23
+ /** The items currently in the list. */
24
+ items: T[];
25
+ /** The keys of the currently selected items in the list. */
26
+ selectedKeys: Selection;
27
+ /** The current sort descriptor for the list. */
28
+ sortDescriptor?: SortDescriptor;
29
+ /** An abort signal used to notify the load function that the request has been aborted. */
30
+ signal: AbortSignal;
31
+ /** The pagination cursor returned from the last page load. */
32
+ cursor?: C;
33
+ /** The current filter text used to perform server side filtering. */
34
+ filterText?: string;
35
+ /** The current loading state of the list. */
36
+ loadingState?: LoadingState;
37
+ }
38
+
39
+ export interface AsyncListStateUpdate<T, C> {
40
+ /** The new items to append to the list. */
41
+ items: Iterable<T>;
42
+ /** The keys to add to the selection. */
43
+ selectedKeys?: Iterable<Key>;
44
+ /** The sort descriptor to set. */
45
+ sortDescriptor?: SortDescriptor;
46
+ /** The pagination cursor to be used for the next page load. */
47
+ cursor?: C;
48
+ /** The updated filter text for the list. */
49
+ filterText?: string;
50
+ }
51
+
52
+ export type AsyncListLoadFunction<T, C> = (
53
+ state: AsyncListLoadOptions<T, C>,
54
+ ) => AsyncListStateUpdate<T, C> | Promise<AsyncListStateUpdate<T, C>>;
55
+
56
+ export interface AsyncListOptions<T, C> {
57
+ /** The keys for the initially selected items. */
58
+ initialSelectedKeys?: "all" | Iterable<Key>;
59
+ /** The initial sort descriptor. */
60
+ initialSortDescriptor?: SortDescriptor;
61
+ /** The initial filter text. */
62
+ initialFilterText?: string;
63
+ /** A function that returns a unique key for an item object. */
64
+ getKey?: (item: T) => Key;
65
+ /** A function that loads the data for the items in the list. */
66
+ load: AsyncListLoadFunction<T, C>;
67
+ /** An optional function that performs sorting. */
68
+ sort?: AsyncListLoadFunction<T, C>;
69
+ }
70
+
71
+ export interface AsyncListData<T> {
72
+ /** The items in the list. */
73
+ readonly items: T[];
74
+ /** The keys of the currently selected items in the list. */
75
+ readonly selectedKeys: Selection;
76
+ /** The current sort descriptor for the list. */
77
+ readonly sortDescriptor: SortDescriptor | undefined;
78
+ /** Whether data is currently being loaded. */
79
+ readonly isLoading: boolean;
80
+ /** If loading data failed, then this contains the error that occurred. */
81
+ readonly error: Error | undefined;
82
+ /** The current filter text. */
83
+ readonly filterText: string;
84
+ /** The current loading state for the list. */
85
+ readonly loadingState: LoadingState;
86
+
87
+ /** Reloads the data in the list. */
88
+ reload(): void;
89
+ /** Loads the next page of data in the list. */
90
+ loadMore(): void;
91
+ /** Triggers sorting for the list. */
92
+ sort(descriptor: SortDescriptor): void;
93
+
94
+ /** Sets the selected keys. */
95
+ setSelectedKeys(keys: Selection): void;
96
+ /** Sets the filter text. */
97
+ setFilterText(filterText: string): void;
98
+
99
+ /** Gets an item from the list by key. */
100
+ getItem(key: Key): T | undefined;
101
+ /** Inserts items into the list at the given index. */
102
+ insert(index: number, ...values: T[]): void;
103
+ /** Inserts items before a given key. */
104
+ insertBefore(key: Key, ...values: T[]): void;
105
+ /** Inserts items after a given key. */
106
+ insertAfter(key: Key, ...values: T[]): void;
107
+ /** Appends items to the list. */
108
+ append(...values: T[]): void;
109
+ /** Prepends items to the list. */
110
+ prepend(...values: T[]): void;
111
+ /** Removes items from the list by their keys. */
112
+ remove(...keys: Key[]): void;
113
+ /** Removes all items from the list that are currently in the set of selected items. */
114
+ removeSelectedItems(): void;
115
+ /** Moves an item within the list. */
116
+ move(key: Key, toIndex: number): void;
117
+ /** Updates an item in the list. */
118
+ update(key: Key, newValue: T): void;
119
+ }
120
+
121
+ interface InternalState<T, C> {
122
+ loadingState: LoadingState;
123
+ items: T[];
124
+ selectedKeys: Selection;
125
+ sortDescriptor?: SortDescriptor;
126
+ error?: Error;
127
+ cursor?: C;
128
+ filterText: string;
129
+ abortController?: AbortController;
130
+ }
131
+
132
+ /**
133
+ * Manages state for an immutable async loaded list data structure, and provides
134
+ * convenience methods to update the data over time. Manages loading and error
135
+ * states, pagination, and sorting.
136
+ */
137
+ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>): AsyncListData<T> {
138
+ const defaultGetKey = (item: T): Key => {
139
+ const candidate = item as { id?: Key; key?: Key };
140
+ return candidate.id ?? candidate.key ?? String(item);
141
+ };
142
+
143
+ const {
144
+ load,
145
+ sort: sortFn,
146
+ initialSelectedKeys,
147
+ initialSortDescriptor,
148
+ getKey = defaultGetKey,
149
+ initialFilterText = "",
150
+ } = options;
151
+
152
+ const [state, setState] = createSignal<InternalState<T, C>>({
153
+ loadingState: "idle",
154
+ items: [],
155
+ selectedKeys: initialSelectedKeys === "all" ? "all" : new Set(initialSelectedKeys || []),
156
+ sortDescriptor: initialSortDescriptor,
157
+ filterText: initialFilterText,
158
+ });
159
+
160
+ async function dispatchFetch(
161
+ type: "loading" | "loadingMore" | "sorting" | "filtering",
162
+ fn: AsyncListLoadFunction<T, C>,
163
+ opts?: { sortDescriptor?: SortDescriptor; filterText?: string },
164
+ ) {
165
+ const abortController = new AbortController();
166
+ const currentState = untrack(state);
167
+
168
+ // Update to loading state
169
+ setState((s) => {
170
+ // Abort previous request if one is in progress
171
+ if (s.abortController) {
172
+ s.abortController.abort();
173
+ }
174
+ return {
175
+ ...s,
176
+ loadingState: type,
177
+ items: type === "loading" ? [] : s.items,
178
+ sortDescriptor: opts?.sortDescriptor ?? s.sortDescriptor,
179
+ filterText: opts?.filterText ?? s.filterText,
180
+ abortController,
181
+ };
182
+ });
183
+
184
+ try {
185
+ const previousFilterText = opts?.filterText ?? currentState.filterText;
186
+ const response = await fn({
187
+ items: currentState.items.slice(),
188
+ selectedKeys: currentState.selectedKeys,
189
+ sortDescriptor: opts?.sortDescriptor ?? currentState.sortDescriptor,
190
+ signal: abortController.signal,
191
+ cursor: type === "loadingMore" ? currentState.cursor : undefined,
192
+ filterText: previousFilterText,
193
+ loadingState: currentState.loadingState,
194
+ });
195
+
196
+ setState((s) => {
197
+ // Ignore stale response
198
+ if (s.abortController !== abortController) return s;
199
+
200
+ const newItems = [...(response.items ?? [])];
201
+ const items = type === "loadingMore" ? [...s.items, ...newItems] : newItems;
202
+
203
+ let selectedKeys: Selection;
204
+ if (type === "loadingMore") {
205
+ selectedKeys =
206
+ s.selectedKeys === "all" || response.selectedKeys === "all"
207
+ ? "all"
208
+ : new Set([...(s.selectedKeys as Set<Key>), ...(response.selectedKeys ?? [])]);
209
+ } else {
210
+ selectedKeys = response.selectedKeys
211
+ ? response.selectedKeys === "all"
212
+ ? "all"
213
+ : new Set(response.selectedKeys)
214
+ : s.selectedKeys;
215
+ }
216
+
217
+ return {
218
+ ...s,
219
+ loadingState: "idle",
220
+ items,
221
+ selectedKeys,
222
+ sortDescriptor: response.sortDescriptor ?? s.sortDescriptor,
223
+ cursor: response.cursor as C | undefined,
224
+ filterText: response.filterText ?? s.filterText,
225
+ error: undefined,
226
+ abortController: undefined,
227
+ };
228
+ });
229
+
230
+ // Trigger another filter if filterText changed in the response
231
+ const responseFilterText = response.filterText ?? previousFilterText;
232
+ if (
233
+ responseFilterText &&
234
+ responseFilterText !== previousFilterText &&
235
+ !abortController.signal.aborted
236
+ ) {
237
+ dispatchFetch("filtering", load, { filterText: responseFilterText });
238
+ }
239
+ } catch (e) {
240
+ setState((s) => {
241
+ if (s.abortController !== abortController) return s;
242
+ return {
243
+ ...s,
244
+ loadingState: "error",
245
+ error: e as Error,
246
+ abortController: undefined,
247
+ };
248
+ });
249
+ }
250
+ }
251
+
252
+ // Trigger initial load immediately
253
+ dispatchFetch("loading", load);
254
+
255
+ return {
256
+ get items() {
257
+ return state().items;
258
+ },
259
+ get selectedKeys() {
260
+ return state().selectedKeys;
261
+ },
262
+ get sortDescriptor() {
263
+ return state().sortDescriptor;
264
+ },
265
+ get isLoading() {
266
+ const ls = state().loadingState;
267
+ return ls === "loading" || ls === "loadingMore" || ls === "sorting" || ls === "filtering";
268
+ },
269
+ get error() {
270
+ return state().error;
271
+ },
272
+ get filterText() {
273
+ return state().filterText;
274
+ },
275
+ get loadingState() {
276
+ return state().loadingState;
277
+ },
278
+
279
+ reload() {
280
+ dispatchFetch("loading", load);
281
+ },
282
+
283
+ loadMore() {
284
+ const s = state();
285
+ if (
286
+ s.loadingState === "loading" ||
287
+ s.loadingState === "loadingMore" ||
288
+ s.loadingState === "filtering" ||
289
+ s.cursor == null
290
+ ) {
291
+ return;
292
+ }
293
+ dispatchFetch("loadingMore", load);
294
+ },
295
+
296
+ sort(descriptor: SortDescriptor) {
297
+ dispatchFetch("sorting", (sortFn || load) as AsyncListLoadFunction<T, C>, {
298
+ sortDescriptor: descriptor,
299
+ });
300
+ },
301
+
302
+ setSelectedKeys(keys: Selection) {
303
+ setState((s) => ({ ...s, selectedKeys: keys }));
304
+ },
305
+
306
+ setFilterText(filterText: string) {
307
+ dispatchFetch("filtering", load, { filterText });
308
+ },
309
+
310
+ getItem(key: Key) {
311
+ return state().items.find((item) => getKey(item) === key);
312
+ },
313
+
314
+ insert(index: number, ...values: T[]) {
315
+ setState((s) => ({
316
+ ...s,
317
+ items: [...s.items.slice(0, index), ...values, ...s.items.slice(index)],
318
+ }));
319
+ },
320
+
321
+ insertBefore(key: Key, ...values: T[]) {
322
+ setState((s) => {
323
+ const index = s.items.findIndex((item) => getKey(item) === key);
324
+ if (index === -1) return s;
325
+ return {
326
+ ...s,
327
+ items: [...s.items.slice(0, index), ...values, ...s.items.slice(index)],
328
+ };
329
+ });
330
+ },
331
+
332
+ insertAfter(key: Key, ...values: T[]) {
333
+ setState((s) => {
334
+ const index = s.items.findIndex((item) => getKey(item) === key);
335
+ if (index === -1) return s;
336
+ return {
337
+ ...s,
338
+ items: [...s.items.slice(0, index + 1), ...values, ...s.items.slice(index + 1)],
339
+ };
340
+ });
341
+ },
342
+
343
+ append(...values: T[]) {
344
+ setState((s) => ({ ...s, items: [...s.items, ...values] }));
345
+ },
346
+
347
+ prepend(...values: T[]) {
348
+ setState((s) => ({ ...s, items: [...values, ...s.items] }));
349
+ },
350
+
351
+ remove(...keys: Key[]) {
352
+ setState((s) => {
353
+ const keySet = new Set(keys);
354
+ const items = s.items.filter((item) => !keySet.has(getKey(item)));
355
+ let selectedKeys = s.selectedKeys;
356
+ if (selectedKeys !== "all") {
357
+ const newSelection = new Set(selectedKeys);
358
+ for (const key of keys) {
359
+ newSelection.delete(key);
360
+ }
361
+ selectedKeys = newSelection;
362
+ }
363
+ return { ...s, items, selectedKeys };
364
+ });
365
+ },
366
+
367
+ removeSelectedItems() {
368
+ setState((s) => {
369
+ if (s.selectedKeys === "all") {
370
+ return { ...s, items: [], selectedKeys: new Set() };
371
+ }
372
+ const sel = s.selectedKeys;
373
+ return {
374
+ ...s,
375
+ items: s.items.filter((item) => !sel.has(getKey(item))),
376
+ selectedKeys: new Set(),
377
+ };
378
+ });
379
+ },
380
+
381
+ move(key: Key, toIndex: number) {
382
+ setState((s) => {
383
+ const index = s.items.findIndex((item) => getKey(item) === key);
384
+ if (index === -1) return s;
385
+ const copy = s.items.slice();
386
+ const [item] = copy.splice(index, 1);
387
+ copy.splice(toIndex, 0, item);
388
+ return { ...s, items: copy };
389
+ });
390
+ },
391
+
392
+ update(key: Key, newValue: T) {
393
+ setState((s) => {
394
+ const index = s.items.findIndex((item) => getKey(item) === key);
395
+ if (index === -1) return s;
396
+ return {
397
+ ...s,
398
+ items: [...s.items.slice(0, index), newValue, ...s.items.slice(index + 1)],
399
+ };
400
+ });
401
+ },
402
+ };
403
+ }