@proyecto-viviana/solid-stately 0.2.7 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -283
- package/dist/autocomplete/createAutocompleteState.d.ts +2 -2
- package/dist/autocomplete/index.d.ts +1 -1
- package/dist/calendar/IncompleteDate.d.ts +61 -0
- package/dist/calendar/createCalendarState.d.ts +41 -16
- package/dist/calendar/createDateFieldState.d.ts +39 -9
- package/dist/calendar/createDatePickerState.d.ts +60 -0
- package/dist/calendar/createRangeCalendarState.d.ts +37 -10
- package/dist/calendar/createTimeFieldState.d.ts +34 -7
- package/dist/calendar/index.d.ts +7 -6
- package/dist/checkbox/createCheckboxGroupState.d.ts +6 -6
- package/dist/checkbox/index.d.ts +1 -1
- package/dist/collections/ListCollection.d.ts +1 -1
- package/dist/collections/createListState.d.ts +11 -8
- package/dist/collections/createMenuState.d.ts +7 -7
- package/dist/collections/createSelectionState.d.ts +22 -10
- package/dist/collections/getChildNodes.d.ts +11 -0
- package/dist/collections/index.d.ts +6 -5
- package/dist/collections/types.d.ts +12 -12
- package/dist/color/Color.d.ts +1 -1
- package/dist/color/createColorAreaState.d.ts +4 -2
- package/dist/color/createColorFieldState.d.ts +38 -12
- package/dist/color/createColorSliderState.d.ts +9 -2
- package/dist/color/createColorWheelState.d.ts +13 -2
- package/dist/color/getColorChannels.d.ts +1 -1
- package/dist/color/index.d.ts +6 -6
- package/dist/color/types.d.ts +4 -4
- package/dist/combobox/createComboBoxState.d.ts +34 -13
- package/dist/combobox/index.d.ts +1 -1
- package/dist/data/createAsyncList.d.ts +4 -4
- package/dist/data/createListData.d.ts +2 -2
- package/dist/data/createTreeData.d.ts +6 -2
- package/dist/data/index.d.ts +3 -3
- package/dist/datepicker/index.d.ts +2 -4
- package/dist/disclosure/createDisclosureState.d.ts +2 -2
- package/dist/disclosure/index.d.ts +1 -1
- package/dist/dnd/createDragState.d.ts +2 -2
- package/dist/dnd/createDraggableCollectionState.d.ts +2 -2
- package/dist/dnd/createDropState.d.ts +2 -2
- package/dist/dnd/createDroppableCollectionState.d.ts +3 -3
- package/dist/dnd/index.d.ts +5 -5
- package/dist/dnd/types.d.ts +19 -17
- package/dist/form/createFormValidationState.d.ts +3 -3
- package/dist/form/index.d.ts +1 -1
- package/dist/grid/createGridState.d.ts +2 -2
- package/dist/grid/index.d.ts +2 -2
- package/dist/grid/types.d.ts +27 -11
- package/dist/index.d.ts +31 -30
- package/dist/index.js +9077 -7246
- package/dist/index.js.map +1 -1
- package/dist/menu/index.d.ts +2 -2
- package/dist/numberfield/createNumberFieldState.d.ts +2 -2
- package/dist/numberfield/index.d.ts +1 -1
- package/dist/overlays/createOverlayTriggerState.d.ts +2 -2
- package/dist/overlays/index.d.ts +1 -1
- package/dist/radio/createRadioGroupState.d.ts +7 -7
- package/dist/radio/index.d.ts +1 -1
- package/dist/searchfield/createSearchFieldState.d.ts +2 -2
- package/dist/searchfield/index.d.ts +2 -2
- package/dist/select/createSelectState.d.ts +14 -8
- package/dist/select/index.d.ts +1 -1
- package/dist/selection/Selection.d.ts +16 -0
- package/dist/selection/SelectionManager.d.ts +110 -0
- package/dist/selection/createMultipleSelectionState.d.ts +59 -0
- package/dist/selection/index.d.ts +6 -5
- package/dist/slider/createSliderState.d.ts +3 -3
- package/dist/slider/index.d.ts +2 -2
- package/dist/steplist/createStepListState.d.ts +48 -0
- package/dist/steplist/index.d.ts +1 -0
- package/dist/table/TableCollection.d.ts +33 -3
- package/dist/table/createTableColumnResizeState.d.ts +54 -0
- package/dist/table/createTableState.d.ts +2 -2
- package/dist/table/createTreeGridState.d.ts +15 -0
- package/dist/table/index.d.ts +6 -3
- package/dist/table/types.d.ts +68 -10
- package/dist/tabs/createTabListState.d.ts +5 -5
- package/dist/tabs/index.d.ts +1 -1
- package/dist/textfield/createTextFieldState.d.ts +2 -2
- package/dist/textfield/index.d.ts +1 -1
- package/dist/toast/createToastState.d.ts +24 -2
- package/dist/toast/index.d.ts +1 -1
- package/dist/toggle/createToggleGroupState.d.ts +4 -4
- package/dist/toggle/createToggleState.d.ts +2 -2
- package/dist/toggle/index.d.ts +2 -2
- package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tree/TreeCollection.d.ts +2 -2
- package/dist/tree/createTreeState.d.ts +2 -2
- package/dist/tree/index.d.ts +3 -3
- package/dist/tree/types.d.ts +27 -13
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/reactivity.d.ts +1 -1
- package/package.json +29 -30
- package/src/autocomplete/createAutocompleteState.d.ts +19 -17
- package/src/autocomplete/createAutocompleteState.ts +24 -30
- package/src/autocomplete/index.d.ts +6 -2
- package/src/autocomplete/index.ts +1 -1
- package/src/calendar/IncompleteDate.ts +430 -0
- package/src/calendar/createCalendarState.d.ts +139 -117
- package/src/calendar/createCalendarState.ts +308 -94
- package/src/calendar/createDateFieldState.d.ts +130 -95
- package/src/calendar/createDateFieldState.ts +447 -334
- package/src/calendar/createDatePickerState.ts +347 -0
- package/src/calendar/createRangeCalendarState.d.ts +154 -129
- package/src/calendar/createRangeCalendarState.ts +411 -85
- package/src/calendar/createTimeFieldState.d.ts +81 -79
- package/src/calendar/createTimeFieldState.ts +187 -108
- package/src/calendar/index.d.ts +80 -7
- package/src/calendar/index.ts +23 -12
- package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
- package/src/checkbox/createCheckboxGroupState.ts +20 -29
- package/src/checkbox/index.d.ts +6 -2
- package/src/checkbox/index.ts +1 -1
- package/src/collections/ListCollection.d.ts +25 -22
- package/src/collections/ListCollection.ts +6 -6
- package/src/collections/createListState.d.ts +73 -58
- package/src/collections/createListState.ts +67 -35
- package/src/collections/createMenuState.d.ts +36 -31
- package/src/collections/createMenuState.ts +21 -12
- package/src/collections/createSelectionState.d.ts +78 -65
- package/src/collections/createSelectionState.ts +66 -52
- package/src/collections/getChildNodes.ts +98 -0
- package/src/collections/index.d.ts +38 -6
- package/src/collections/index.ts +14 -10
- package/src/collections/types.d.ts +101 -101
- package/src/collections/types.ts +12 -12
- package/src/color/Color.d.ts +20 -5
- package/src/color/Color.ts +357 -254
- package/src/color/createColorAreaState.d.ts +67 -65
- package/src/color/createColorAreaState.ts +21 -13
- package/src/color/createColorFieldState.d.ts +46 -44
- package/src/color/createColorFieldState.ts +285 -149
- package/src/color/createColorSliderState.d.ts +58 -56
- package/src/color/createColorSliderState.ts +45 -14
- package/src/color/createColorWheelState.d.ts +42 -40
- package/src/color/createColorWheelState.ts +101 -64
- package/src/color/getColorChannels.ts +7 -5
- package/src/color/index.d.ts +36 -7
- package/src/color/index.ts +6 -9
- package/src/color/types.d.ts +68 -63
- package/src/color/types.ts +11 -19
- package/src/combobox/createComboBoxState.d.ts +107 -105
- package/src/combobox/createComboBoxState.ts +184 -89
- package/src/combobox/index.d.ts +10 -2
- package/src/combobox/index.ts +1 -1
- package/src/data/createAsyncList.ts +89 -63
- package/src/data/createListData.ts +67 -67
- package/src/data/createTreeData.ts +304 -91
- package/src/data/index.ts +3 -3
- package/src/datepicker/index.ts +6 -10
- package/src/disclosure/createDisclosureState.d.ts +47 -43
- package/src/disclosure/createDisclosureState.ts +7 -21
- package/src/disclosure/index.d.ts +10 -2
- package/src/disclosure/index.ts +1 -1
- package/src/dnd/createDragState.d.ts +51 -42
- package/src/dnd/createDragState.ts +12 -14
- package/src/dnd/createDraggableCollectionState.d.ts +52 -41
- package/src/dnd/createDraggableCollectionState.ts +14 -21
- package/src/dnd/createDropState.d.ts +64 -45
- package/src/dnd/createDropState.ts +22 -32
- package/src/dnd/createDroppableCollectionState.d.ts +88 -59
- package/src/dnd/createDroppableCollectionState.ts +40 -43
- package/src/dnd/index.d.ts +55 -6
- package/src/dnd/index.ts +6 -18
- package/src/dnd/types.d.ts +170 -157
- package/src/dnd/types.ts +24 -22
- package/src/form/createFormValidationState.d.ts +47 -45
- package/src/form/createFormValidationState.ts +30 -63
- package/src/form/index.d.ts +16 -2
- package/src/form/index.ts +1 -1
- package/src/grid/createGridState.d.ts +7 -4
- package/src/grid/createGridState.ts +78 -51
- package/src/grid/index.d.ts +3 -3
- package/src/grid/index.ts +2 -8
- package/src/grid/types.d.ts +136 -129
- package/src/grid/types.ts +34 -18
- package/src/index.d.ts +311 -26
- package/src/index.ts +59 -89
- package/src/menu/index.ts +2 -4
- package/src/numberfield/createNumberFieldState.d.ts +56 -54
- package/src/numberfield/createNumberFieldState.ts +26 -31
- package/src/numberfield/index.d.ts +6 -2
- package/src/numberfield/index.ts +1 -1
- package/src/overlays/createOverlayTriggerState.d.ts +22 -20
- package/src/overlays/createOverlayTriggerState.ts +3 -4
- package/src/overlays/index.d.ts +6 -2
- package/src/overlays/index.ts +1 -1
- package/src/radio/createRadioGroupState.d.ts +54 -52
- package/src/radio/createRadioGroupState.ts +27 -29
- package/src/radio/index.d.ts +7 -2
- package/src/radio/index.ts +1 -1
- package/src/searchfield/createSearchFieldState.d.ts +16 -14
- package/src/searchfield/createSearchFieldState.ts +5 -11
- package/src/searchfield/index.d.ts +3 -3
- package/src/searchfield/index.ts +2 -5
- package/src/select/createSelectState.d.ts +63 -61
- package/src/select/createSelectState.ts +42 -29
- package/src/select/index.d.ts +2 -2
- package/src/select/index.ts +1 -5
- package/src/selection/Selection.ts +28 -0
- package/src/selection/SelectionManager.ts +526 -0
- package/src/selection/createMultipleSelectionState.ts +247 -0
- package/src/selection/index.ts +12 -7
- package/src/slider/createSliderState.d.ts +60 -60
- package/src/slider/createSliderState.ts +55 -33
- package/src/slider/index.d.ts +3 -3
- package/src/slider/index.ts +2 -6
- package/src/ssr/index.d.ts +1 -1
- package/src/ssr/index.ts +2 -2
- package/src/steplist/createStepListState.ts +191 -0
- package/src/steplist/index.ts +5 -0
- package/src/table/TableCollection.d.ts +42 -40
- package/src/table/TableCollection.ts +266 -99
- package/src/table/createTableColumnResizeState.ts +242 -0
- package/src/table/createTableState.d.ts +7 -4
- package/src/table/createTableState.ts +30 -7
- package/src/table/createTreeGridState.ts +146 -0
- package/src/table/index.d.ts +14 -4
- package/src/table/index.ts +13 -3
- package/src/table/types.d.ts +98 -92
- package/src/table/types.ts +83 -13
- package/src/tabs/createTabListState.d.ts +59 -57
- package/src/tabs/createTabListState.ts +34 -39
- package/src/tabs/index.d.ts +8 -2
- package/src/tabs/index.ts +1 -1
- package/src/textfield/createTextFieldState.d.ts +16 -14
- package/src/textfield/createTextFieldState.ts +7 -18
- package/src/textfield/index.d.ts +6 -2
- package/src/textfield/index.ts +1 -1
- package/src/toast/createToastState.d.ts +92 -86
- package/src/toast/createToastState.ts +90 -52
- package/src/toast/index.d.ts +12 -2
- package/src/toast/index.ts +2 -1
- package/src/toggle/createToggleGroupState.ts +11 -21
- package/src/toggle/createToggleState.d.ts +19 -19
- package/src/toggle/createToggleState.ts +2 -16
- package/src/toggle/index.d.ts +2 -2
- package/src/toggle/index.ts +2 -6
- package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
- package/src/tooltip/createTooltipTriggerState.ts +12 -11
- package/src/tooltip/index.d.ts +7 -2
- package/src/tooltip/index.ts +1 -1
- package/src/tree/TreeCollection.d.ts +26 -23
- package/src/tree/TreeCollection.ts +29 -22
- package/src/tree/createTreeState.d.ts +7 -4
- package/src/tree/createTreeState.ts +70 -41
- package/src/tree/index.d.ts +10 -4
- package/src/tree/index.ts +3 -3
- package/src/tree/types.d.ts +131 -126
- package/src/tree/types.ts +30 -13
- package/src/utils/index.d.ts +2 -2
- package/src/utils/index.ts +1 -1
- package/src/utils/reactivity.d.ts +2 -2
- package/src/utils/reactivity.ts +3 -3
|
@@ -6,17 +6,17 @@
|
|
|
6
6
|
* states, pagination, and sorting.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { createSignal, untrack } from
|
|
9
|
+
import { createSignal, untrack } from "solid-js";
|
|
10
10
|
|
|
11
11
|
export type Key = string | number;
|
|
12
|
-
export type Selection =
|
|
13
|
-
export type LoadingState =
|
|
12
|
+
export type Selection = "all" | Set<Key>;
|
|
13
|
+
export type LoadingState = "idle" | "loading" | "loadingMore" | "sorting" | "filtering" | "error";
|
|
14
14
|
|
|
15
15
|
export interface SortDescriptor {
|
|
16
16
|
/** The key of the column to sort by. */
|
|
17
17
|
column?: Key;
|
|
18
18
|
/** The direction to sort by. */
|
|
19
|
-
direction?:
|
|
19
|
+
direction?: "ascending" | "descending";
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export interface AsyncListLoadOptions<T, C> {
|
|
@@ -50,12 +50,12 @@ export interface AsyncListStateUpdate<T, C> {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export type AsyncListLoadFunction<T, C> = (
|
|
53
|
-
state: AsyncListLoadOptions<T, C
|
|
53
|
+
state: AsyncListLoadOptions<T, C>,
|
|
54
54
|
) => AsyncListStateUpdate<T, C> | Promise<AsyncListStateUpdate<T, C>>;
|
|
55
55
|
|
|
56
56
|
export interface AsyncListOptions<T, C> {
|
|
57
57
|
/** The keys for the initially selected items. */
|
|
58
|
-
initialSelectedKeys?:
|
|
58
|
+
initialSelectedKeys?: "all" | Iterable<Key>;
|
|
59
59
|
/** The initial sort descriptor. */
|
|
60
60
|
initialSortDescriptor?: SortDescriptor;
|
|
61
61
|
/** The initial filter text. */
|
|
@@ -135,25 +135,30 @@ interface InternalState<T, C> {
|
|
|
135
135
|
* states, pagination, and sorting.
|
|
136
136
|
*/
|
|
137
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
|
+
|
|
138
143
|
const {
|
|
139
144
|
load,
|
|
140
145
|
sort: sortFn,
|
|
141
146
|
initialSelectedKeys,
|
|
142
147
|
initialSortDescriptor,
|
|
143
|
-
getKey =
|
|
144
|
-
initialFilterText =
|
|
148
|
+
getKey = defaultGetKey,
|
|
149
|
+
initialFilterText = "",
|
|
145
150
|
} = options;
|
|
146
151
|
|
|
147
152
|
const [state, setState] = createSignal<InternalState<T, C>>({
|
|
148
|
-
loadingState:
|
|
153
|
+
loadingState: "idle",
|
|
149
154
|
items: [],
|
|
150
|
-
selectedKeys: initialSelectedKeys ===
|
|
155
|
+
selectedKeys: initialSelectedKeys === "all" ? "all" : new Set(initialSelectedKeys || []),
|
|
151
156
|
sortDescriptor: initialSortDescriptor,
|
|
152
157
|
filterText: initialFilterText,
|
|
153
158
|
});
|
|
154
159
|
|
|
155
160
|
async function dispatchFetch(
|
|
156
|
-
type:
|
|
161
|
+
type: "loading" | "loadingMore" | "sorting" | "filtering",
|
|
157
162
|
fn: AsyncListLoadFunction<T, C>,
|
|
158
163
|
opts?: { sortDescriptor?: SortDescriptor; filterText?: string },
|
|
159
164
|
) {
|
|
@@ -161,7 +166,7 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
161
166
|
const currentState = untrack(state);
|
|
162
167
|
|
|
163
168
|
// Update to loading state
|
|
164
|
-
setState(s => {
|
|
169
|
+
setState((s) => {
|
|
165
170
|
// Abort previous request if one is in progress
|
|
166
171
|
if (s.abortController) {
|
|
167
172
|
s.abortController.abort();
|
|
@@ -169,7 +174,7 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
169
174
|
return {
|
|
170
175
|
...s,
|
|
171
176
|
loadingState: type,
|
|
172
|
-
items: type ===
|
|
177
|
+
items: type === "loading" ? [] : s.items,
|
|
173
178
|
sortDescriptor: opts?.sortDescriptor ?? s.sortDescriptor,
|
|
174
179
|
filterText: opts?.filterText ?? s.filterText,
|
|
175
180
|
abortController,
|
|
@@ -183,37 +188,35 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
183
188
|
selectedKeys: currentState.selectedKeys,
|
|
184
189
|
sortDescriptor: opts?.sortDescriptor ?? currentState.sortDescriptor,
|
|
185
190
|
signal: abortController.signal,
|
|
186
|
-
cursor: type ===
|
|
191
|
+
cursor: type === "loadingMore" ? currentState.cursor : undefined,
|
|
187
192
|
filterText: previousFilterText,
|
|
188
193
|
loadingState: currentState.loadingState,
|
|
189
194
|
});
|
|
190
195
|
|
|
191
|
-
setState(s => {
|
|
196
|
+
setState((s) => {
|
|
192
197
|
// Ignore stale response
|
|
193
198
|
if (s.abortController !== abortController) return s;
|
|
194
199
|
|
|
195
200
|
const newItems = [...(response.items ?? [])];
|
|
196
|
-
const items = type ===
|
|
197
|
-
? [...s.items, ...newItems]
|
|
198
|
-
: newItems;
|
|
201
|
+
const items = type === "loadingMore" ? [...s.items, ...newItems] : newItems;
|
|
199
202
|
|
|
200
203
|
let selectedKeys: Selection;
|
|
201
|
-
if (type ===
|
|
202
|
-
selectedKeys =
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
...(response.selectedKeys ?? []),
|
|
207
|
-
]);
|
|
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 ?? [])]);
|
|
208
209
|
} else {
|
|
209
210
|
selectedKeys = response.selectedKeys
|
|
210
|
-
?
|
|
211
|
+
? response.selectedKeys === "all"
|
|
212
|
+
? "all"
|
|
213
|
+
: new Set(response.selectedKeys)
|
|
211
214
|
: s.selectedKeys;
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
return {
|
|
215
218
|
...s,
|
|
216
|
-
loadingState:
|
|
219
|
+
loadingState: "idle",
|
|
217
220
|
items,
|
|
218
221
|
selectedKeys,
|
|
219
222
|
sortDescriptor: response.sortDescriptor ?? s.sortDescriptor,
|
|
@@ -226,15 +229,19 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
226
229
|
|
|
227
230
|
// Trigger another filter if filterText changed in the response
|
|
228
231
|
const responseFilterText = response.filterText ?? previousFilterText;
|
|
229
|
-
if (
|
|
230
|
-
|
|
232
|
+
if (
|
|
233
|
+
responseFilterText &&
|
|
234
|
+
responseFilterText !== previousFilterText &&
|
|
235
|
+
!abortController.signal.aborted
|
|
236
|
+
) {
|
|
237
|
+
dispatchFetch("filtering", load, { filterText: responseFilterText });
|
|
231
238
|
}
|
|
232
239
|
} catch (e) {
|
|
233
|
-
setState(s => {
|
|
240
|
+
setState((s) => {
|
|
234
241
|
if (s.abortController !== abortController) return s;
|
|
235
242
|
return {
|
|
236
243
|
...s,
|
|
237
|
-
loadingState:
|
|
244
|
+
loadingState: "error",
|
|
238
245
|
error: e as Error,
|
|
239
246
|
abortController: undefined,
|
|
240
247
|
};
|
|
@@ -243,58 +250,77 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
243
250
|
}
|
|
244
251
|
|
|
245
252
|
// Trigger initial load immediately
|
|
246
|
-
dispatchFetch(
|
|
253
|
+
dispatchFetch("loading", load);
|
|
247
254
|
|
|
248
255
|
return {
|
|
249
|
-
get items() {
|
|
250
|
-
|
|
251
|
-
|
|
256
|
+
get items() {
|
|
257
|
+
return state().items;
|
|
258
|
+
},
|
|
259
|
+
get selectedKeys() {
|
|
260
|
+
return state().selectedKeys;
|
|
261
|
+
},
|
|
262
|
+
get sortDescriptor() {
|
|
263
|
+
return state().sortDescriptor;
|
|
264
|
+
},
|
|
252
265
|
get isLoading() {
|
|
253
266
|
const ls = state().loadingState;
|
|
254
|
-
return ls ===
|
|
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;
|
|
255
277
|
},
|
|
256
|
-
get error() { return state().error; },
|
|
257
|
-
get filterText() { return state().filterText; },
|
|
258
|
-
get loadingState() { return state().loadingState; },
|
|
259
278
|
|
|
260
279
|
reload() {
|
|
261
|
-
dispatchFetch(
|
|
280
|
+
dispatchFetch("loading", load);
|
|
262
281
|
},
|
|
263
282
|
|
|
264
283
|
loadMore() {
|
|
265
284
|
const s = state();
|
|
266
|
-
if (
|
|
285
|
+
if (
|
|
286
|
+
s.loadingState === "loading" ||
|
|
287
|
+
s.loadingState === "loadingMore" ||
|
|
288
|
+
s.loadingState === "filtering" ||
|
|
289
|
+
s.cursor == null
|
|
290
|
+
) {
|
|
267
291
|
return;
|
|
268
292
|
}
|
|
269
|
-
dispatchFetch(
|
|
293
|
+
dispatchFetch("loadingMore", load);
|
|
270
294
|
},
|
|
271
295
|
|
|
272
296
|
sort(descriptor: SortDescriptor) {
|
|
273
|
-
dispatchFetch(
|
|
297
|
+
dispatchFetch("sorting", (sortFn || load) as AsyncListLoadFunction<T, C>, {
|
|
298
|
+
sortDescriptor: descriptor,
|
|
299
|
+
});
|
|
274
300
|
},
|
|
275
301
|
|
|
276
302
|
setSelectedKeys(keys: Selection) {
|
|
277
|
-
setState(s => ({ ...s, selectedKeys: keys }));
|
|
303
|
+
setState((s) => ({ ...s, selectedKeys: keys }));
|
|
278
304
|
},
|
|
279
305
|
|
|
280
306
|
setFilterText(filterText: string) {
|
|
281
|
-
dispatchFetch(
|
|
307
|
+
dispatchFetch("filtering", load, { filterText });
|
|
282
308
|
},
|
|
283
309
|
|
|
284
310
|
getItem(key: Key) {
|
|
285
|
-
return state().items.find(item => getKey(item) === key);
|
|
311
|
+
return state().items.find((item) => getKey(item) === key);
|
|
286
312
|
},
|
|
287
313
|
|
|
288
314
|
insert(index: number, ...values: T[]) {
|
|
289
|
-
setState(s => ({
|
|
315
|
+
setState((s) => ({
|
|
290
316
|
...s,
|
|
291
317
|
items: [...s.items.slice(0, index), ...values, ...s.items.slice(index)],
|
|
292
318
|
}));
|
|
293
319
|
},
|
|
294
320
|
|
|
295
321
|
insertBefore(key: Key, ...values: T[]) {
|
|
296
|
-
setState(s => {
|
|
297
|
-
const index = s.items.findIndex(item => getKey(item) === key);
|
|
322
|
+
setState((s) => {
|
|
323
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
298
324
|
if (index === -1) return s;
|
|
299
325
|
return {
|
|
300
326
|
...s,
|
|
@@ -304,8 +330,8 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
304
330
|
},
|
|
305
331
|
|
|
306
332
|
insertAfter(key: Key, ...values: T[]) {
|
|
307
|
-
setState(s => {
|
|
308
|
-
const index = s.items.findIndex(item => getKey(item) === key);
|
|
333
|
+
setState((s) => {
|
|
334
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
309
335
|
if (index === -1) return s;
|
|
310
336
|
return {
|
|
311
337
|
...s,
|
|
@@ -315,19 +341,19 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
315
341
|
},
|
|
316
342
|
|
|
317
343
|
append(...values: T[]) {
|
|
318
|
-
setState(s => ({ ...s, items: [...s.items, ...values] }));
|
|
344
|
+
setState((s) => ({ ...s, items: [...s.items, ...values] }));
|
|
319
345
|
},
|
|
320
346
|
|
|
321
347
|
prepend(...values: T[]) {
|
|
322
|
-
setState(s => ({ ...s, items: [...values, ...s.items] }));
|
|
348
|
+
setState((s) => ({ ...s, items: [...values, ...s.items] }));
|
|
323
349
|
},
|
|
324
350
|
|
|
325
351
|
remove(...keys: Key[]) {
|
|
326
|
-
setState(s => {
|
|
352
|
+
setState((s) => {
|
|
327
353
|
const keySet = new Set(keys);
|
|
328
|
-
const items = s.items.filter(item => !keySet.has(getKey(item)));
|
|
354
|
+
const items = s.items.filter((item) => !keySet.has(getKey(item)));
|
|
329
355
|
let selectedKeys = s.selectedKeys;
|
|
330
|
-
if (selectedKeys !==
|
|
356
|
+
if (selectedKeys !== "all") {
|
|
331
357
|
const newSelection = new Set(selectedKeys);
|
|
332
358
|
for (const key of keys) {
|
|
333
359
|
newSelection.delete(key);
|
|
@@ -339,22 +365,22 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
339
365
|
},
|
|
340
366
|
|
|
341
367
|
removeSelectedItems() {
|
|
342
|
-
setState(s => {
|
|
343
|
-
if (s.selectedKeys ===
|
|
368
|
+
setState((s) => {
|
|
369
|
+
if (s.selectedKeys === "all") {
|
|
344
370
|
return { ...s, items: [], selectedKeys: new Set() };
|
|
345
371
|
}
|
|
346
372
|
const sel = s.selectedKeys;
|
|
347
373
|
return {
|
|
348
374
|
...s,
|
|
349
|
-
items: s.items.filter(item => !sel.has(getKey(item))),
|
|
375
|
+
items: s.items.filter((item) => !sel.has(getKey(item))),
|
|
350
376
|
selectedKeys: new Set(),
|
|
351
377
|
};
|
|
352
378
|
});
|
|
353
379
|
},
|
|
354
380
|
|
|
355
381
|
move(key: Key, toIndex: number) {
|
|
356
|
-
setState(s => {
|
|
357
|
-
const index = s.items.findIndex(item => getKey(item) === key);
|
|
382
|
+
setState((s) => {
|
|
383
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
358
384
|
if (index === -1) return s;
|
|
359
385
|
const copy = s.items.slice();
|
|
360
386
|
const [item] = copy.splice(index, 1);
|
|
@@ -364,8 +390,8 @@ export function createAsyncList<T, C = string>(options: AsyncListOptions<T, C>):
|
|
|
364
390
|
},
|
|
365
391
|
|
|
366
392
|
update(key: Key, newValue: T) {
|
|
367
|
-
setState(s => {
|
|
368
|
-
const index = s.items.findIndex(item => getKey(item) === key);
|
|
393
|
+
setState((s) => {
|
|
394
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
369
395
|
if (index === -1) return s;
|
|
370
396
|
return {
|
|
371
397
|
...s,
|
|
@@ -5,16 +5,16 @@
|
|
|
5
5
|
* convenience methods to update the data over time.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { createSignal, createMemo } from
|
|
8
|
+
import { createSignal, createMemo } from "solid-js";
|
|
9
9
|
|
|
10
10
|
export type Key = string | number;
|
|
11
|
-
export type Selection =
|
|
11
|
+
export type Selection = "all" | Set<Key>;
|
|
12
12
|
|
|
13
13
|
export interface ListOptions<T> {
|
|
14
14
|
/** Initial items in the list. */
|
|
15
15
|
initialItems?: T[];
|
|
16
16
|
/** The keys for the initially selected items. */
|
|
17
|
-
initialSelectedKeys?:
|
|
17
|
+
initialSelectedKeys?: "all" | Iterable<Key>;
|
|
18
18
|
/** The initial text to filter the list by. */
|
|
19
19
|
initialFilterText?: string;
|
|
20
20
|
/** A function that returns a unique key for an item object. */
|
|
@@ -75,48 +75,58 @@ interface ListState<T> {
|
|
|
75
75
|
* convenience methods to update the data over time.
|
|
76
76
|
*/
|
|
77
77
|
export function createListData<T>(options: ListOptions<T>): ListData<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
|
+
|
|
78
83
|
const {
|
|
79
84
|
initialItems = [],
|
|
80
85
|
initialSelectedKeys,
|
|
81
|
-
getKey =
|
|
86
|
+
getKey = defaultGetKey,
|
|
82
87
|
filter,
|
|
83
|
-
initialFilterText =
|
|
88
|
+
initialFilterText = "",
|
|
84
89
|
} = options;
|
|
85
90
|
|
|
86
91
|
const [state, setState] = createSignal<ListState<T>>({
|
|
87
92
|
items: initialItems,
|
|
88
|
-
selectedKeys: initialSelectedKeys ===
|
|
93
|
+
selectedKeys: initialSelectedKeys === "all" ? "all" : new Set(initialSelectedKeys || []),
|
|
89
94
|
filterText: initialFilterText,
|
|
90
95
|
});
|
|
91
96
|
|
|
92
97
|
const filteredItems = createMemo(() => {
|
|
93
98
|
const s = state();
|
|
94
|
-
return filter ? s.items.filter(item => filter(item, s.filterText)) : s.items;
|
|
99
|
+
return filter ? s.items.filter((item) => filter(item, s.filterText)) : s.items;
|
|
95
100
|
});
|
|
96
101
|
|
|
97
102
|
return {
|
|
98
|
-
get items() {
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
get items() {
|
|
104
|
+
return filteredItems();
|
|
105
|
+
},
|
|
106
|
+
get selectedKeys() {
|
|
107
|
+
return state().selectedKeys;
|
|
108
|
+
},
|
|
109
|
+
get filterText() {
|
|
110
|
+
return state().filterText;
|
|
111
|
+
},
|
|
101
112
|
|
|
102
113
|
setSelectedKeys(selectedKeys: Selection) {
|
|
103
|
-
setState(s => ({ ...s, selectedKeys }));
|
|
114
|
+
setState((s) => ({ ...s, selectedKeys }));
|
|
104
115
|
},
|
|
105
116
|
|
|
106
117
|
addKeysToSelection(selectedKeys: Selection) {
|
|
107
|
-
setState(s => {
|
|
108
|
-
if (s.selectedKeys ===
|
|
109
|
-
if (selectedKeys ===
|
|
118
|
+
setState((s) => {
|
|
119
|
+
if (s.selectedKeys === "all") return s;
|
|
120
|
+
if (selectedKeys === "all") return { ...s, selectedKeys: "all" };
|
|
110
121
|
return { ...s, selectedKeys: new Set([...s.selectedKeys, ...selectedKeys]) };
|
|
111
122
|
});
|
|
112
123
|
},
|
|
113
124
|
|
|
114
125
|
removeKeysFromSelection(selectedKeys: Selection) {
|
|
115
|
-
setState(s => {
|
|
116
|
-
if (selectedKeys ===
|
|
117
|
-
const selection: Set<Key> =
|
|
118
|
-
? new Set(s.items.map(getKey))
|
|
119
|
-
: new Set(s.selectedKeys);
|
|
126
|
+
setState((s) => {
|
|
127
|
+
if (selectedKeys === "all") return { ...s, selectedKeys: new Set() };
|
|
128
|
+
const selection: Set<Key> =
|
|
129
|
+
s.selectedKeys === "all" ? new Set(s.items.map(getKey)) : new Set(s.selectedKeys);
|
|
120
130
|
for (const key of selectedKeys) {
|
|
121
131
|
selection.delete(key);
|
|
122
132
|
}
|
|
@@ -125,54 +135,53 @@ export function createListData<T>(options: ListOptions<T>): ListData<T> {
|
|
|
125
135
|
},
|
|
126
136
|
|
|
127
137
|
setFilterText(filterText: string) {
|
|
128
|
-
setState(s => ({ ...s, filterText }));
|
|
138
|
+
setState((s) => ({ ...s, filterText }));
|
|
129
139
|
},
|
|
130
140
|
|
|
131
141
|
getItem(key: Key) {
|
|
132
|
-
return state().items.find(item => getKey(item) === key);
|
|
142
|
+
return state().items.find((item) => getKey(item) === key);
|
|
133
143
|
},
|
|
134
144
|
|
|
135
145
|
insert(index: number, ...values: T[]) {
|
|
136
|
-
setState(s => insertItems(s, index, ...values));
|
|
146
|
+
setState((s) => insertItems(s, index, ...values));
|
|
137
147
|
},
|
|
138
148
|
|
|
139
149
|
insertBefore(key: Key, ...values: T[]) {
|
|
140
|
-
setState(s => {
|
|
141
|
-
|
|
142
|
-
if (index === -1)
|
|
143
|
-
index = s.items.length === 0 ? 0 : -1;
|
|
144
|
-
if (index === -1) return s;
|
|
145
|
-
}
|
|
150
|
+
setState((s) => {
|
|
151
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
152
|
+
if (index === -1) return s;
|
|
146
153
|
return insertItems(s, index, ...values);
|
|
147
154
|
});
|
|
148
155
|
},
|
|
149
156
|
|
|
150
157
|
insertAfter(key: Key, ...values: T[]) {
|
|
151
|
-
setState(s => {
|
|
152
|
-
let index = s.items.findIndex(item => getKey(item) === key);
|
|
158
|
+
setState((s) => {
|
|
159
|
+
let index = s.items.findIndex((item) => getKey(item) === key);
|
|
153
160
|
if (index === -1) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
161
|
+
if (s.items.length === 0) {
|
|
162
|
+
index = 0;
|
|
163
|
+
} else {
|
|
164
|
+
return s;
|
|
165
|
+
}
|
|
157
166
|
}
|
|
158
167
|
return insertItems(s, index + 1, ...values);
|
|
159
168
|
});
|
|
160
169
|
},
|
|
161
170
|
|
|
162
171
|
prepend(...values: T[]) {
|
|
163
|
-
setState(s => insertItems(s, 0, ...values));
|
|
172
|
+
setState((s) => insertItems(s, 0, ...values));
|
|
164
173
|
},
|
|
165
174
|
|
|
166
175
|
append(...values: T[]) {
|
|
167
|
-
setState(s => insertItems(s, s.items.length, ...values));
|
|
176
|
+
setState((s) => insertItems(s, s.items.length, ...values));
|
|
168
177
|
},
|
|
169
178
|
|
|
170
179
|
remove(...keys: Key[]) {
|
|
171
|
-
setState(s => {
|
|
180
|
+
setState((s) => {
|
|
172
181
|
const keySet = new Set(keys);
|
|
173
|
-
const items = s.items.filter(item => !keySet.has(getKey(item)));
|
|
174
|
-
let selection: Selection =
|
|
175
|
-
if (s.selectedKeys !==
|
|
182
|
+
const items = s.items.filter((item) => !keySet.has(getKey(item)));
|
|
183
|
+
let selection: Selection = "all";
|
|
184
|
+
if (s.selectedKeys !== "all") {
|
|
176
185
|
selection = new Set(s.selectedKeys);
|
|
177
186
|
for (const key of keys) {
|
|
178
187
|
(selection as Set<Key>).delete(key);
|
|
@@ -184,19 +193,19 @@ export function createListData<T>(options: ListOptions<T>): ListData<T> {
|
|
|
184
193
|
},
|
|
185
194
|
|
|
186
195
|
removeSelectedItems() {
|
|
187
|
-
setState(s => {
|
|
188
|
-
if (s.selectedKeys ===
|
|
196
|
+
setState((s) => {
|
|
197
|
+
if (s.selectedKeys === "all") {
|
|
189
198
|
return { ...s, items: [], selectedKeys: new Set() };
|
|
190
199
|
}
|
|
191
200
|
const selectedKeys = s.selectedKeys;
|
|
192
|
-
const items = s.items.filter(item => !selectedKeys.has(getKey(item)));
|
|
201
|
+
const items = s.items.filter((item) => !selectedKeys.has(getKey(item)));
|
|
193
202
|
return { ...s, items, selectedKeys: new Set() };
|
|
194
203
|
});
|
|
195
204
|
},
|
|
196
205
|
|
|
197
206
|
move(key: Key, toIndex: number) {
|
|
198
|
-
setState(s => {
|
|
199
|
-
const index = s.items.findIndex(item => getKey(item) === key);
|
|
207
|
+
setState((s) => {
|
|
208
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
200
209
|
if (index === -1) return s;
|
|
201
210
|
const copy = s.items.slice();
|
|
202
211
|
const [item] = copy.splice(index, 1);
|
|
@@ -206,43 +215,38 @@ export function createListData<T>(options: ListOptions<T>): ListData<T> {
|
|
|
206
215
|
},
|
|
207
216
|
|
|
208
217
|
moveBefore(key: Key, keys: Iterable<Key>) {
|
|
209
|
-
setState(s => {
|
|
210
|
-
const toIndex = s.items.findIndex(item => getKey(item) === key);
|
|
218
|
+
setState((s) => {
|
|
219
|
+
const toIndex = s.items.findIndex((item) => getKey(item) === key);
|
|
211
220
|
if (toIndex === -1) return s;
|
|
212
221
|
const keyArray = Array.isArray(keys) ? keys : [...keys];
|
|
213
222
|
const indices = keyArray
|
|
214
|
-
.map(k => s.items.findIndex(item => getKey(item) === k))
|
|
223
|
+
.map((k) => s.items.findIndex((item) => getKey(item) === k))
|
|
215
224
|
.sort((a, b) => a - b);
|
|
216
225
|
return moveItems(s, indices, toIndex);
|
|
217
226
|
});
|
|
218
227
|
},
|
|
219
228
|
|
|
220
229
|
moveAfter(key: Key, keys: Iterable<Key>) {
|
|
221
|
-
setState(s => {
|
|
222
|
-
const toIndex = s.items.findIndex(item => getKey(item) === key);
|
|
230
|
+
setState((s) => {
|
|
231
|
+
const toIndex = s.items.findIndex((item) => getKey(item) === key);
|
|
223
232
|
if (toIndex === -1) return s;
|
|
224
233
|
const keyArray = Array.isArray(keys) ? keys : [...keys];
|
|
225
234
|
const indices = keyArray
|
|
226
|
-
.map(k => s.items.findIndex(item => getKey(item) === k))
|
|
235
|
+
.map((k) => s.items.findIndex((item) => getKey(item) === k))
|
|
227
236
|
.sort((a, b) => a - b);
|
|
228
237
|
return moveItems(s, indices, toIndex + 1);
|
|
229
238
|
});
|
|
230
239
|
},
|
|
231
240
|
|
|
232
241
|
update(key: Key, newValue: T | ((prev: T) => T)) {
|
|
233
|
-
setState(s => {
|
|
234
|
-
const index = s.items.findIndex(item => getKey(item) === key);
|
|
242
|
+
setState((s) => {
|
|
243
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
235
244
|
if (index === -1) return s;
|
|
236
|
-
const updatedValue =
|
|
237
|
-
? (newValue as (prev: T) => T)(s.items[index])
|
|
238
|
-
: newValue;
|
|
245
|
+
const updatedValue =
|
|
246
|
+
typeof newValue === "function" ? (newValue as (prev: T) => T)(s.items[index]) : newValue;
|
|
239
247
|
return {
|
|
240
248
|
...s,
|
|
241
|
-
items: [
|
|
242
|
-
...s.items.slice(0, index),
|
|
243
|
-
updatedValue,
|
|
244
|
-
...s.items.slice(index + 1),
|
|
245
|
-
],
|
|
249
|
+
items: [...s.items.slice(0, index), updatedValue, ...s.items.slice(index + 1)],
|
|
246
250
|
};
|
|
247
251
|
});
|
|
248
252
|
},
|
|
@@ -252,18 +256,14 @@ export function createListData<T>(options: ListOptions<T>): ListData<T> {
|
|
|
252
256
|
function insertItems<T>(state: ListState<T>, index: number, ...values: T[]): ListState<T> {
|
|
253
257
|
return {
|
|
254
258
|
...state,
|
|
255
|
-
items: [
|
|
256
|
-
...state.items.slice(0, index),
|
|
257
|
-
...values,
|
|
258
|
-
...state.items.slice(index),
|
|
259
|
-
],
|
|
259
|
+
items: [...state.items.slice(0, index), ...values, ...state.items.slice(index)],
|
|
260
260
|
};
|
|
261
261
|
}
|
|
262
262
|
|
|
263
263
|
function moveItems<T>(state: ListState<T>, indices: number[], toIndex: number): ListState<T> {
|
|
264
|
-
toIndex -= indices.filter(index => index < toIndex).length;
|
|
264
|
+
toIndex -= indices.filter((index) => index < toIndex).length;
|
|
265
265
|
|
|
266
|
-
const moves = indices.map(from => ({
|
|
266
|
+
const moves = indices.map((from) => ({
|
|
267
267
|
from,
|
|
268
268
|
to: toIndex++,
|
|
269
269
|
}));
|