@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.
- package/LICENSE +21 -0
- package/README.md +30 -283
- package/dist/autocomplete/createAutocompleteState.d.ts +3 -2
- package/dist/autocomplete/index.d.ts +1 -1
- package/dist/calendar/createCalendarState.d.ts +22 -7
- package/dist/calendar/createDateFieldState.d.ts +30 -7
- package/dist/calendar/createDatePickerState.d.ts +60 -0
- package/dist/calendar/createRangeCalendarState.d.ts +27 -8
- package/dist/calendar/createTimeFieldState.d.ts +34 -7
- package/dist/calendar/index.d.ts +7 -6
- package/dist/checkbox/createCheckboxGroupState.d.ts +12 -3
- package/dist/checkbox/index.d.ts +1 -1
- package/dist/collections/ListCollection.d.ts +1 -1
- package/dist/collections/createListState.d.ts +8 -8
- package/dist/collections/createMenuState.d.ts +7 -7
- package/dist/collections/createSelectionState.d.ts +5 -5
- package/dist/collections/index.d.ts +5 -5
- package/dist/collections/types.d.ts +23 -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 +20 -0
- package/dist/color/index.d.ts +6 -6
- package/dist/color/types.d.ts +4 -4
- package/dist/combobox/createComboBoxState.d.ts +27 -13
- package/dist/combobox/index.d.ts +1 -1
- package/dist/data/createAsyncList.d.ts +111 -0
- package/dist/data/createListData.d.ts +65 -0
- package/dist/data/createTreeData.d.ts +65 -0
- package/dist/data/index.d.ts +3 -0
- package/dist/datepicker/index.d.ts +8 -0
- 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 +16 -16
- 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 +17 -11
- package/dist/index.d.ts +31 -25
- package/dist/index.js +7990 -6264
- package/dist/index.js.map +1 -7
- package/dist/menu/index.d.ts +8 -0
- 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 +13 -4
- 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 +20 -3
- package/dist/select/index.d.ts +1 -1
- package/dist/selection/index.d.ts +11 -0
- 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 +3 -3
- package/dist/table/createTableColumnResizeState.d.ts +54 -0
- package/dist/table/createTableState.d.ts +2 -2
- package/dist/table/index.d.ts +5 -3
- package/dist/table/types.d.ts +10 -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 +15 -3
- package/dist/toast/index.d.ts +1 -1
- package/dist/toggle/createToggleGroupState.d.ts +45 -0
- package/dist/toggle/createToggleState.d.ts +2 -2
- package/dist/toggle/index.d.ts +2 -1
- package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
- package/dist/tooltip/index.d.ts +1 -1
- package/dist/tree/TreeCollection.d.ts +5 -4
- package/dist/tree/createTreeState.d.ts +2 -2
- package/dist/tree/index.d.ts +3 -3
- package/dist/tree/types.d.ts +19 -13
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/reactivity.d.ts +1 -1
- package/package.json +30 -30
- package/src/autocomplete/createAutocompleteState.d.ts +19 -17
- package/src/autocomplete/createAutocompleteState.ts +25 -32
- package/src/autocomplete/index.d.ts +6 -2
- package/src/autocomplete/index.ts +1 -1
- package/src/calendar/createCalendarState.d.ts +139 -117
- package/src/calendar/createCalendarState.ts +221 -74
- package/src/calendar/createDateFieldState.d.ts +130 -95
- package/src/calendar/createDateFieldState.ts +286 -151
- package/src/calendar/createDatePickerState.ts +347 -0
- package/src/calendar/createRangeCalendarState.d.ts +154 -129
- package/src/calendar/createRangeCalendarState.ts +293 -79
- 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 +21 -12
- package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
- package/src/checkbox/createCheckboxGroupState.ts +57 -30
- 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 +152 -146
- package/src/collections/createListState.d.ts +73 -58
- package/src/collections/createListState.ts +267 -264
- package/src/collections/createMenuState.d.ts +36 -31
- package/src/collections/createMenuState.ts +112 -106
- package/src/collections/createSelectionState.d.ts +78 -65
- package/src/collections/createSelectionState.ts +340 -336
- package/src/collections/index.d.ts +38 -6
- package/src/collections/index.ts +41 -46
- package/src/collections/types.d.ts +101 -101
- package/src/collections/types.ts +181 -169
- package/src/color/Color.d.ts +20 -5
- package/src/color/Color.ts +1054 -951
- package/src/color/createColorAreaState.d.ts +67 -65
- package/src/color/createColorAreaState.ts +301 -293
- package/src/color/createColorFieldState.d.ts +46 -44
- package/src/color/createColorFieldState.ts +428 -292
- package/src/color/createColorSliderState.d.ts +58 -56
- package/src/color/createColorSliderState.ts +272 -241
- package/src/color/createColorWheelState.d.ts +42 -40
- package/src/color/createColorWheelState.ts +248 -211
- package/src/color/getColorChannels.ts +36 -0
- package/src/color/index.d.ts +36 -7
- package/src/color/index.ts +44 -47
- package/src/color/types.d.ts +68 -63
- package/src/color/types.ts +119 -127
- package/src/combobox/createComboBoxState.d.ts +107 -105
- package/src/combobox/createComboBoxState.ts +790 -703
- package/src/combobox/index.d.ts +10 -2
- package/src/combobox/index.ts +13 -13
- package/src/data/createAsyncList.ts +403 -0
- package/src/data/createListData.ts +298 -0
- package/src/data/createTreeData.ts +646 -0
- package/src/data/index.ts +25 -0
- package/src/datepicker/index.ts +32 -0
- package/src/disclosure/createDisclosureState.d.ts +47 -43
- package/src/disclosure/createDisclosureState.ts +9 -23
- 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 +151 -153
- package/src/dnd/createDraggableCollectionState.d.ts +52 -41
- package/src/dnd/createDraggableCollectionState.ts +158 -165
- package/src/dnd/createDropState.d.ts +64 -45
- package/src/dnd/createDropState.ts +202 -212
- package/src/dnd/createDroppableCollectionState.d.ts +88 -59
- package/src/dnd/createDroppableCollectionState.ts +354 -357
- package/src/dnd/index.d.ts +54 -6
- package/src/dnd/index.ts +63 -76
- package/src/dnd/types.d.ts +167 -156
- package/src/dnd/types.ts +316 -317
- package/src/form/createFormValidationState.d.ts +47 -45
- package/src/form/createFormValidationState.ts +356 -389
- package/src/form/index.d.ts +16 -2
- package/src/form/index.ts +15 -15
- package/src/grid/createGridState.d.ts +7 -4
- package/src/grid/createGridState.ts +44 -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 +24 -17
- package/src/index.d.ts +310 -26
- package/src/index.ts +87 -79
- package/src/menu/index.ts +17 -0
- package/src/numberfield/createNumberFieldState.d.ts +56 -54
- package/src/numberfield/createNumberFieldState.ts +422 -383
- package/src/numberfield/index.d.ts +6 -2
- package/src/numberfield/index.ts +5 -5
- package/src/overlays/createOverlayTriggerState.d.ts +22 -20
- package/src/overlays/createOverlayTriggerState.ts +66 -67
- package/src/overlays/index.d.ts +6 -2
- package/src/overlays/index.ts +5 -5
- package/src/radio/createRadioGroupState.d.ts +54 -52
- package/src/radio/createRadioGroupState.ts +66 -30
- 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 +56 -62
- 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 +290 -181
- package/src/select/index.d.ts +2 -2
- package/src/select/index.ts +1 -5
- package/src/selection/index.ts +27 -0
- package/src/slider/createSliderState.d.ts +60 -60
- package/src/slider/createSliderState.ts +233 -211
- 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 +61 -64
- package/src/table/createTableColumnResizeState.ts +242 -0
- package/src/table/createTableState.d.ts +7 -4
- package/src/table/createTableState.ts +10 -7
- package/src/table/index.d.ts +14 -4
- package/src/table/index.ts +10 -3
- package/src/table/types.d.ts +98 -92
- package/src/table/types.ts +17 -13
- package/src/tabs/createTabListState.d.ts +59 -57
- package/src/tabs/createTabListState.ts +58 -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 -81
- package/src/toast/createToastState.ts +56 -44
- package/src/toast/index.d.ts +12 -2
- package/src/toast/index.ts +1 -1
- package/src/toggle/createToggleGroupState.ts +117 -0
- 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 +6 -4
- package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
- package/src/tooltip/createTooltipTriggerState.ts +184 -183
- package/src/tooltip/index.d.ts +7 -2
- package/src/tooltip/index.ts +6 -6
- package/src/tree/TreeCollection.d.ts +26 -23
- package/src/tree/TreeCollection.ts +215 -175
- package/src/tree/createTreeState.d.ts +7 -4
- package/src/tree/createTreeState.ts +390 -392
- package/src/tree/index.d.ts +10 -4
- package/src/tree/index.ts +13 -13
- package/src/tree/types.d.ts +131 -126
- package/src/tree/types.ts +183 -174
- 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
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createListData - SolidJS port of React Spectrum's useListData
|
|
3
|
+
*
|
|
4
|
+
* Manages state for an immutable list data structure, and provides
|
|
5
|
+
* convenience methods to update the data over time.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createSignal, createMemo } from "solid-js";
|
|
9
|
+
|
|
10
|
+
export type Key = string | number;
|
|
11
|
+
export type Selection = "all" | Set<Key>;
|
|
12
|
+
|
|
13
|
+
export interface ListOptions<T> {
|
|
14
|
+
/** Initial items in the list. */
|
|
15
|
+
initialItems?: T[];
|
|
16
|
+
/** The keys for the initially selected items. */
|
|
17
|
+
initialSelectedKeys?: "all" | Iterable<Key>;
|
|
18
|
+
/** The initial text to filter the list by. */
|
|
19
|
+
initialFilterText?: string;
|
|
20
|
+
/** A function that returns a unique key for an item object. */
|
|
21
|
+
getKey?: (item: T) => Key;
|
|
22
|
+
/** A function that returns whether an item matches the current filter text. */
|
|
23
|
+
filter?: (item: T, filterText: string) => boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ListData<T> {
|
|
27
|
+
/** The items in the list. */
|
|
28
|
+
readonly items: T[];
|
|
29
|
+
/** The keys of the currently selected items in the list. */
|
|
30
|
+
readonly selectedKeys: Selection;
|
|
31
|
+
/** The current filter text. */
|
|
32
|
+
readonly filterText: string;
|
|
33
|
+
/** Sets the selected keys. */
|
|
34
|
+
setSelectedKeys(keys: Selection): void;
|
|
35
|
+
/** Adds the given keys to the current selected keys. */
|
|
36
|
+
addKeysToSelection(keys: Selection): void;
|
|
37
|
+
/** Removes the given keys from the current selected keys. */
|
|
38
|
+
removeKeysFromSelection(keys: Selection): void;
|
|
39
|
+
/** Sets the filter text. */
|
|
40
|
+
setFilterText(filterText: string): void;
|
|
41
|
+
/** Gets an item from the list by key. */
|
|
42
|
+
getItem(key: Key): T | undefined;
|
|
43
|
+
/** Inserts items into the list at the given index. */
|
|
44
|
+
insert(index: number, ...values: T[]): void;
|
|
45
|
+
/** Inserts items into the list before the item at the given key. */
|
|
46
|
+
insertBefore(key: Key, ...values: T[]): void;
|
|
47
|
+
/** Inserts items into the list after the item at the given key. */
|
|
48
|
+
insertAfter(key: Key, ...values: T[]): void;
|
|
49
|
+
/** Appends items to the list. */
|
|
50
|
+
append(...values: T[]): void;
|
|
51
|
+
/** Prepends items to the list. */
|
|
52
|
+
prepend(...values: T[]): void;
|
|
53
|
+
/** Removes items from the list by their keys. */
|
|
54
|
+
remove(...keys: Key[]): void;
|
|
55
|
+
/** Removes all items from the list that are currently in the set of selected items. */
|
|
56
|
+
removeSelectedItems(): void;
|
|
57
|
+
/** Moves an item within the list. */
|
|
58
|
+
move(key: Key, toIndex: number): void;
|
|
59
|
+
/** Moves one or more items before a given key. */
|
|
60
|
+
moveBefore(key: Key, keys: Iterable<Key>): void;
|
|
61
|
+
/** Moves one or more items after a given key. */
|
|
62
|
+
moveAfter(key: Key, keys: Iterable<Key>): void;
|
|
63
|
+
/** Updates an item in the list. */
|
|
64
|
+
update(key: Key, newValue: T | ((prev: T) => T)): void;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface ListState<T> {
|
|
68
|
+
items: T[];
|
|
69
|
+
selectedKeys: Selection;
|
|
70
|
+
filterText: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Manages state for an immutable list data structure, and provides
|
|
75
|
+
* convenience methods to update the data over time.
|
|
76
|
+
*/
|
|
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
|
+
|
|
83
|
+
const {
|
|
84
|
+
initialItems = [],
|
|
85
|
+
initialSelectedKeys,
|
|
86
|
+
getKey = defaultGetKey,
|
|
87
|
+
filter,
|
|
88
|
+
initialFilterText = "",
|
|
89
|
+
} = options;
|
|
90
|
+
|
|
91
|
+
const [state, setState] = createSignal<ListState<T>>({
|
|
92
|
+
items: initialItems,
|
|
93
|
+
selectedKeys: initialSelectedKeys === "all" ? "all" : new Set(initialSelectedKeys || []),
|
|
94
|
+
filterText: initialFilterText,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const filteredItems = createMemo(() => {
|
|
98
|
+
const s = state();
|
|
99
|
+
return filter ? s.items.filter((item) => filter(item, s.filterText)) : s.items;
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
get items() {
|
|
104
|
+
return filteredItems();
|
|
105
|
+
},
|
|
106
|
+
get selectedKeys() {
|
|
107
|
+
return state().selectedKeys;
|
|
108
|
+
},
|
|
109
|
+
get filterText() {
|
|
110
|
+
return state().filterText;
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
setSelectedKeys(selectedKeys: Selection) {
|
|
114
|
+
setState((s) => ({ ...s, selectedKeys }));
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
addKeysToSelection(selectedKeys: Selection) {
|
|
118
|
+
setState((s) => {
|
|
119
|
+
if (s.selectedKeys === "all") return s;
|
|
120
|
+
if (selectedKeys === "all") return { ...s, selectedKeys: "all" };
|
|
121
|
+
return { ...s, selectedKeys: new Set([...s.selectedKeys, ...selectedKeys]) };
|
|
122
|
+
});
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
removeKeysFromSelection(selectedKeys: Selection) {
|
|
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);
|
|
130
|
+
for (const key of selectedKeys) {
|
|
131
|
+
selection.delete(key);
|
|
132
|
+
}
|
|
133
|
+
return { ...s, selectedKeys: selection };
|
|
134
|
+
});
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
setFilterText(filterText: string) {
|
|
138
|
+
setState((s) => ({ ...s, filterText }));
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
getItem(key: Key) {
|
|
142
|
+
return state().items.find((item) => getKey(item) === key);
|
|
143
|
+
},
|
|
144
|
+
|
|
145
|
+
insert(index: number, ...values: T[]) {
|
|
146
|
+
setState((s) => insertItems(s, index, ...values));
|
|
147
|
+
},
|
|
148
|
+
|
|
149
|
+
insertBefore(key: Key, ...values: T[]) {
|
|
150
|
+
setState((s) => {
|
|
151
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
152
|
+
if (index === -1) return s;
|
|
153
|
+
return insertItems(s, index, ...values);
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
|
|
157
|
+
insertAfter(key: Key, ...values: T[]) {
|
|
158
|
+
setState((s) => {
|
|
159
|
+
let index = s.items.findIndex((item) => getKey(item) === key);
|
|
160
|
+
if (index === -1) {
|
|
161
|
+
if (s.items.length === 0) {
|
|
162
|
+
index = 0;
|
|
163
|
+
} else {
|
|
164
|
+
return s;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return insertItems(s, index + 1, ...values);
|
|
168
|
+
});
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
prepend(...values: T[]) {
|
|
172
|
+
setState((s) => insertItems(s, 0, ...values));
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
append(...values: T[]) {
|
|
176
|
+
setState((s) => insertItems(s, s.items.length, ...values));
|
|
177
|
+
},
|
|
178
|
+
|
|
179
|
+
remove(...keys: Key[]) {
|
|
180
|
+
setState((s) => {
|
|
181
|
+
const keySet = new Set(keys);
|
|
182
|
+
const items = s.items.filter((item) => !keySet.has(getKey(item)));
|
|
183
|
+
let selection: Selection = "all";
|
|
184
|
+
if (s.selectedKeys !== "all") {
|
|
185
|
+
selection = new Set(s.selectedKeys);
|
|
186
|
+
for (const key of keys) {
|
|
187
|
+
(selection as Set<Key>).delete(key);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (items.length === 0) selection = new Set();
|
|
191
|
+
return { ...s, items, selectedKeys: selection };
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
removeSelectedItems() {
|
|
196
|
+
setState((s) => {
|
|
197
|
+
if (s.selectedKeys === "all") {
|
|
198
|
+
return { ...s, items: [], selectedKeys: new Set() };
|
|
199
|
+
}
|
|
200
|
+
const selectedKeys = s.selectedKeys;
|
|
201
|
+
const items = s.items.filter((item) => !selectedKeys.has(getKey(item)));
|
|
202
|
+
return { ...s, items, selectedKeys: new Set() };
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
move(key: Key, toIndex: number) {
|
|
207
|
+
setState((s) => {
|
|
208
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
209
|
+
if (index === -1) return s;
|
|
210
|
+
const copy = s.items.slice();
|
|
211
|
+
const [item] = copy.splice(index, 1);
|
|
212
|
+
copy.splice(toIndex, 0, item);
|
|
213
|
+
return { ...s, items: copy };
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
moveBefore(key: Key, keys: Iterable<Key>) {
|
|
218
|
+
setState((s) => {
|
|
219
|
+
const toIndex = s.items.findIndex((item) => getKey(item) === key);
|
|
220
|
+
if (toIndex === -1) return s;
|
|
221
|
+
const keyArray = Array.isArray(keys) ? keys : [...keys];
|
|
222
|
+
const indices = keyArray
|
|
223
|
+
.map((k) => s.items.findIndex((item) => getKey(item) === k))
|
|
224
|
+
.sort((a, b) => a - b);
|
|
225
|
+
return moveItems(s, indices, toIndex);
|
|
226
|
+
});
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
moveAfter(key: Key, keys: Iterable<Key>) {
|
|
230
|
+
setState((s) => {
|
|
231
|
+
const toIndex = s.items.findIndex((item) => getKey(item) === key);
|
|
232
|
+
if (toIndex === -1) return s;
|
|
233
|
+
const keyArray = Array.isArray(keys) ? keys : [...keys];
|
|
234
|
+
const indices = keyArray
|
|
235
|
+
.map((k) => s.items.findIndex((item) => getKey(item) === k))
|
|
236
|
+
.sort((a, b) => a - b);
|
|
237
|
+
return moveItems(s, indices, toIndex + 1);
|
|
238
|
+
});
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
update(key: Key, newValue: T | ((prev: T) => T)) {
|
|
242
|
+
setState((s) => {
|
|
243
|
+
const index = s.items.findIndex((item) => getKey(item) === key);
|
|
244
|
+
if (index === -1) return s;
|
|
245
|
+
const updatedValue =
|
|
246
|
+
typeof newValue === "function" ? (newValue as (prev: T) => T)(s.items[index]) : newValue;
|
|
247
|
+
return {
|
|
248
|
+
...s,
|
|
249
|
+
items: [...s.items.slice(0, index), updatedValue, ...s.items.slice(index + 1)],
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function insertItems<T>(state: ListState<T>, index: number, ...values: T[]): ListState<T> {
|
|
257
|
+
return {
|
|
258
|
+
...state,
|
|
259
|
+
items: [...state.items.slice(0, index), ...values, ...state.items.slice(index)],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function moveItems<T>(state: ListState<T>, indices: number[], toIndex: number): ListState<T> {
|
|
264
|
+
toIndex -= indices.filter((index) => index < toIndex).length;
|
|
265
|
+
|
|
266
|
+
const moves = indices.map((from) => ({
|
|
267
|
+
from,
|
|
268
|
+
to: toIndex++,
|
|
269
|
+
}));
|
|
270
|
+
|
|
271
|
+
for (let i = 0; i < moves.length; i++) {
|
|
272
|
+
const a = moves[i].from;
|
|
273
|
+
for (let j = i; j < moves.length; j++) {
|
|
274
|
+
const b = moves[j].from;
|
|
275
|
+
if (b > a) moves[j].from--;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
for (let i = 0; i < moves.length; i++) {
|
|
280
|
+
const a = moves[i];
|
|
281
|
+
for (let j = moves.length - 1; j > i; j--) {
|
|
282
|
+
const b = moves[j];
|
|
283
|
+
if (b.from < a.to) {
|
|
284
|
+
a.to++;
|
|
285
|
+
} else {
|
|
286
|
+
b.from++;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
const copy = state.items.slice();
|
|
292
|
+
for (const m of moves) {
|
|
293
|
+
const [item] = copy.splice(m.from, 1);
|
|
294
|
+
copy.splice(m.to, 0, item);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return { ...state, items: copy };
|
|
298
|
+
}
|