@proyecto-viviana/solid-stately 0.2.4 → 0.2.7

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 (82) hide show
  1. package/LICENSE +21 -0
  2. package/dist/autocomplete/createAutocompleteState.d.ts +2 -1
  3. package/dist/checkbox/createCheckboxGroupState.d.ts +10 -1
  4. package/dist/collections/types.d.ts +11 -0
  5. package/dist/color/getColorChannels.d.ts +20 -0
  6. package/dist/data/createAsyncList.d.ts +111 -0
  7. package/dist/data/createListData.d.ts +65 -0
  8. package/dist/data/createTreeData.d.ts +61 -0
  9. package/dist/data/index.d.ts +3 -0
  10. package/dist/datepicker/index.d.ts +10 -0
  11. package/dist/grid/types.d.ts +5 -1
  12. package/dist/index.d.ts +6 -1
  13. package/dist/index.js +3737 -2697
  14. package/dist/index.js.map +1 -7
  15. package/dist/menu/index.d.ts +8 -0
  16. package/dist/radio/createRadioGroupState.d.ts +10 -1
  17. package/dist/select/createSelectState.d.ts +17 -0
  18. package/dist/selection/index.d.ts +11 -0
  19. package/dist/toast/createToastState.d.ts +7 -1
  20. package/dist/toggle/createToggleGroupState.d.ts +45 -0
  21. package/dist/toggle/index.d.ts +1 -0
  22. package/dist/tree/TreeCollection.d.ts +3 -2
  23. package/package.json +6 -5
  24. package/src/autocomplete/createAutocompleteState.ts +10 -11
  25. package/src/calendar/createDateFieldState.ts +24 -1
  26. package/src/checkbox/createCheckboxGroupState.ts +42 -6
  27. package/src/collections/ListCollection.ts +152 -146
  28. package/src/collections/createListState.ts +266 -264
  29. package/src/collections/createMenuState.ts +106 -106
  30. package/src/collections/createSelectionState.ts +336 -336
  31. package/src/collections/index.ts +46 -46
  32. package/src/collections/types.ts +181 -169
  33. package/src/color/Color.ts +951 -951
  34. package/src/color/createColorAreaState.ts +293 -293
  35. package/src/color/createColorFieldState.ts +292 -292
  36. package/src/color/createColorSliderState.ts +241 -241
  37. package/src/color/createColorWheelState.ts +211 -211
  38. package/src/color/getColorChannels.ts +34 -0
  39. package/src/color/index.ts +47 -47
  40. package/src/color/types.ts +127 -127
  41. package/src/combobox/createComboBoxState.ts +703 -703
  42. package/src/combobox/index.ts +13 -13
  43. package/src/data/createAsyncList.ts +377 -0
  44. package/src/data/createListData.ts +298 -0
  45. package/src/data/createTreeData.ts +433 -0
  46. package/src/data/index.ts +25 -0
  47. package/src/datepicker/index.ts +36 -0
  48. package/src/disclosure/createDisclosureState.ts +4 -4
  49. package/src/dnd/createDragState.ts +153 -153
  50. package/src/dnd/createDraggableCollectionState.ts +165 -165
  51. package/src/dnd/createDropState.ts +212 -212
  52. package/src/dnd/createDroppableCollectionState.ts +357 -357
  53. package/src/dnd/index.ts +76 -76
  54. package/src/dnd/types.ts +317 -317
  55. package/src/form/createFormValidationState.ts +389 -389
  56. package/src/form/index.ts +15 -15
  57. package/src/grid/types.ts +5 -0
  58. package/src/index.ts +49 -0
  59. package/src/menu/index.ts +19 -0
  60. package/src/numberfield/createNumberFieldState.ts +427 -383
  61. package/src/numberfield/index.ts +5 -5
  62. package/src/overlays/createOverlayTriggerState.ts +67 -67
  63. package/src/overlays/index.ts +5 -5
  64. package/src/radio/createRadioGroupState.ts +44 -6
  65. package/src/searchfield/createSearchFieldState.ts +62 -62
  66. package/src/searchfield/index.ts +5 -5
  67. package/src/select/createSelectState.ts +290 -181
  68. package/src/select/index.ts +5 -5
  69. package/src/selection/index.ts +28 -0
  70. package/src/slider/createSliderState.ts +211 -211
  71. package/src/slider/index.ts +6 -6
  72. package/src/tabs/createTabListState.ts +37 -11
  73. package/src/toast/createToastState.d.ts +6 -1
  74. package/src/toast/createToastState.ts +8 -1
  75. package/src/toggle/createToggleGroupState.ts +127 -0
  76. package/src/toggle/index.ts +6 -0
  77. package/src/tooltip/createTooltipTriggerState.ts +183 -183
  78. package/src/tooltip/index.ts +6 -6
  79. package/src/tree/TreeCollection.ts +208 -175
  80. package/src/tree/createTreeState.ts +392 -392
  81. package/src/tree/index.ts +13 -13
  82. package/src/tree/types.ts +174 -174
@@ -1,264 +1,266 @@
1
- /**
2
- * State management for list-like components.
3
- * Combines collection and selection state.
4
- * Based on @react-stately/list.
5
- */
6
-
7
- import { createSignal, type Accessor } from 'solid-js';
8
- import { access, type MaybeAccessor } from '../utils';
9
- import { ListCollection } from './ListCollection';
10
- import { createSelectionState, type SelectionState } from './createSelectionState';
11
- import type {
12
- Collection,
13
- CollectionNode,
14
- DisabledBehavior,
15
- FocusStrategy,
16
- Key,
17
- SelectionBehavior,
18
- SelectionMode,
19
- } from './types';
20
-
21
- export interface ListStateProps<T = unknown> {
22
- /** The items in the list (for dynamic rendering). */
23
- items?: T[];
24
- /** Function to get a key from an item. */
25
- getKey?: (item: T) => Key;
26
- /** Function to get text value from an item. */
27
- getTextValue?: (item: T) => string;
28
- /** Function to check if an item is disabled. */
29
- getDisabled?: (item: T) => boolean;
30
- /** Keys of disabled items. */
31
- disabledKeys?: Iterable<Key>;
32
- /** How disabled keys behave. */
33
- disabledBehavior?: DisabledBehavior;
34
- /** The selection mode. */
35
- selectionMode?: SelectionMode;
36
- /** How selection behaves on interaction. */
37
- selectionBehavior?: SelectionBehavior;
38
- /** Whether empty selection is disallowed. */
39
- disallowEmptySelection?: boolean;
40
- /** Currently selected keys (controlled). */
41
- selectedKeys?: 'all' | Iterable<Key>;
42
- /** Default selected keys (uncontrolled). */
43
- defaultSelectedKeys?: 'all' | Iterable<Key>;
44
- /** Handler for selection changes. */
45
- onSelectionChange?: (keys: 'all' | Set<Key>) => void;
46
- /** Whether to allow duplicate selection events. */
47
- allowDuplicateSelectionEvents?: boolean;
48
- }
49
-
50
- export interface ListState<T = unknown> extends SelectionState {
51
- /** The collection of items. */
52
- readonly collection: Accessor<Collection<T>>;
53
- /** Whether the collection is focused. */
54
- readonly isFocused: Accessor<boolean>;
55
- /** Set the focused state. */
56
- setFocused(isFocused: boolean): void;
57
- /** The currently focused key. */
58
- readonly focusedKey: Accessor<Key | null>;
59
- /** Set the focused key. */
60
- setFocusedKey(key: Key | null, childStrategy?: FocusStrategy): void;
61
- /** The child focus strategy. */
62
- readonly childFocusStrategy: Accessor<FocusStrategy | null>;
63
- }
64
-
65
- /**
66
- * Creates state for a list component with selection.
67
- */
68
- export function createListState<T = unknown>(
69
- props: MaybeAccessor<ListStateProps<T>>
70
- ): ListState<T> {
71
- const getProps = () => access(props);
72
-
73
- // Build collection from items
74
- const collection: Accessor<Collection<T>> = () => {
75
- const p = getProps();
76
- const items = p.items ?? [];
77
-
78
- const nodes: CollectionNode<T>[] = items.map((item, index) => {
79
- const key = p.getKey?.(item) ?? (item as any).key ?? (item as any).id ?? index;
80
- const textValue =
81
- p.getTextValue?.(item) ?? (item as any).textValue ?? (item as any).label ?? String(item);
82
- const isDisabled = p.getDisabled?.(item) ?? (item as any).isDisabled ?? false;
83
-
84
- return {
85
- type: 'item' as const,
86
- key,
87
- value: item,
88
- textValue,
89
- rendered: null as any,
90
- level: 0,
91
- index,
92
- parentKey: null,
93
- hasChildNodes: false,
94
- childNodes: [],
95
- isDisabled,
96
- };
97
- });
98
-
99
- return new ListCollection(nodes);
100
- };
101
-
102
- // Combine disabled keys from props and items
103
- const combinedDisabledKeys = (): Iterable<Key> => {
104
- const p = getProps();
105
- const propsDisabled = p.disabledKeys ? [...p.disabledKeys] : [];
106
- const itemDisabled: Key[] = [];
107
-
108
- const coll = collection();
109
- for (const node of coll) {
110
- if (node.isDisabled) {
111
- itemDisabled.push(node.key);
112
- }
113
- }
114
-
115
- return [...new Set([...propsDisabled, ...itemDisabled])];
116
- };
117
-
118
- // Create selection state
119
- const selectionState = createSelectionState({
120
- get selectionMode() {
121
- return getProps().selectionMode;
122
- },
123
- get selectionBehavior() {
124
- return getProps().selectionBehavior;
125
- },
126
- get disallowEmptySelection() {
127
- return getProps().disallowEmptySelection;
128
- },
129
- get selectedKeys() {
130
- return getProps().selectedKeys;
131
- },
132
- get defaultSelectedKeys() {
133
- return getProps().defaultSelectedKeys;
134
- },
135
- get onSelectionChange() {
136
- return getProps().onSelectionChange;
137
- },
138
- get disabledKeys() {
139
- return combinedDisabledKeys();
140
- },
141
- get disabledBehavior() {
142
- return getProps().disabledBehavior;
143
- },
144
- get allowDuplicateSelectionEvents() {
145
- return getProps().allowDuplicateSelectionEvents;
146
- },
147
- });
148
-
149
- // Focus state
150
- const [isFocused, setIsFocused] = createSignal(false);
151
- const [focusedKey, setFocusedKeyInternal] = createSignal<Key | null>(null);
152
- const [childFocusStrategy, setChildFocusStrategy] = createSignal<FocusStrategy | null>(null);
153
-
154
- const setFocusedKey = (key: Key | null, childStrategy?: FocusStrategy) => {
155
- setFocusedKeyInternal(key);
156
- setChildFocusStrategy(childStrategy ?? null);
157
- };
158
-
159
- return {
160
- collection,
161
- isFocused,
162
- setFocused: setIsFocused,
163
- focusedKey,
164
- setFocusedKey,
165
- childFocusStrategy,
166
- ...selectionState,
167
- };
168
- }
169
-
170
- /**
171
- * Props for single selection list state.
172
- */
173
- export interface SingleSelectListStateProps<T = unknown>
174
- extends Omit<ListStateProps<T>, 'selectionMode' | 'selectedKeys' | 'defaultSelectedKeys' | 'onSelectionChange'> {
175
- /** The currently selected key (controlled). */
176
- selectedKey?: Key | null;
177
- /** The default selected key (uncontrolled). */
178
- defaultSelectedKey?: Key;
179
- /** Handler for selection changes. */
180
- onSelectionChange?: (key: Key | null) => void;
181
- }
182
-
183
- export interface SingleSelectListState<T = unknown> extends ListState<T> {
184
- /** The currently selected key. */
185
- readonly selectedKey: Accessor<Key | null>;
186
- /** Set the selected key. */
187
- setSelectedKey(key: Key | null): void;
188
- /** The currently selected item. */
189
- readonly selectedItem: Accessor<CollectionNode<T> | null>;
190
- }
191
-
192
- /**
193
- * Creates state for a single-select list component.
194
- */
195
- export function createSingleSelectListState<T = unknown>(
196
- props: MaybeAccessor<SingleSelectListStateProps<T>>
197
- ): SingleSelectListState<T> {
198
- const getProps = () => access(props);
199
-
200
- // Convert single selection props to multiple selection props
201
- const listState = createListState<T>({
202
- get items() {
203
- return getProps().items;
204
- },
205
- get getKey() {
206
- return getProps().getKey;
207
- },
208
- get getTextValue() {
209
- return getProps().getTextValue;
210
- },
211
- get getDisabled() {
212
- return getProps().getDisabled;
213
- },
214
- get disabledKeys() {
215
- return getProps().disabledKeys;
216
- },
217
- get disabledBehavior() {
218
- return getProps().disabledBehavior;
219
- },
220
- selectionMode: 'single',
221
- disallowEmptySelection: true,
222
- allowDuplicateSelectionEvents: true,
223
- get selectedKeys() {
224
- const key = getProps().selectedKey;
225
- return key != null ? [key] : [];
226
- },
227
- get defaultSelectedKeys() {
228
- const key = getProps().defaultSelectedKey;
229
- return key != null ? [key] : undefined;
230
- },
231
- onSelectionChange(keys) {
232
- if (keys === 'all') return;
233
- const key = keys.values().next().value ?? null;
234
- getProps().onSelectionChange?.(key);
235
- },
236
- });
237
-
238
- const selectedKey: Accessor<Key | null> = () => {
239
- const keys = listState.selectedKeys();
240
- if (keys === 'all') return null;
241
- return keys.values().next().value ?? null;
242
- };
243
-
244
- const setSelectedKey = (key: Key | null) => {
245
- if (key === null) {
246
- listState.clearSelection();
247
- } else {
248
- listState.replaceSelection(key);
249
- }
250
- };
251
-
252
- const selectedItem: Accessor<CollectionNode<T> | null> = () => {
253
- const key = selectedKey();
254
- if (key === null) return null;
255
- return listState.collection().getItem(key);
256
- };
257
-
258
- return {
259
- ...listState,
260
- selectedKey,
261
- setSelectedKey,
262
- selectedItem,
263
- };
264
- }
1
+ /**
2
+ * State management for list-like components.
3
+ * Combines collection and selection state.
4
+ * Based on @react-stately/list.
5
+ */
6
+
7
+ import { createSignal, createMemo, type Accessor } from 'solid-js';
8
+ import { access, type MaybeAccessor } from '../utils';
9
+ import { ListCollection } from './ListCollection';
10
+ import { createSelectionState, type SelectionState } from './createSelectionState';
11
+ import type {
12
+ Collection,
13
+ CollectionItemLike,
14
+ CollectionNode,
15
+ DisabledBehavior,
16
+ FocusStrategy,
17
+ Key,
18
+ SelectionBehavior,
19
+ SelectionMode,
20
+ } from './types';
21
+
22
+ export interface ListStateProps<T = unknown> {
23
+ /** The items in the list (for dynamic rendering). */
24
+ items?: T[];
25
+ /** Function to get a key from an item. */
26
+ getKey?: (item: T) => Key;
27
+ /** Function to get text value from an item. */
28
+ getTextValue?: (item: T) => string;
29
+ /** Function to check if an item is disabled. */
30
+ getDisabled?: (item: T) => boolean;
31
+ /** Keys of disabled items. */
32
+ disabledKeys?: Iterable<Key>;
33
+ /** How disabled keys behave. */
34
+ disabledBehavior?: DisabledBehavior;
35
+ /** The selection mode. */
36
+ selectionMode?: SelectionMode;
37
+ /** How selection behaves on interaction. */
38
+ selectionBehavior?: SelectionBehavior;
39
+ /** Whether empty selection is disallowed. */
40
+ disallowEmptySelection?: boolean;
41
+ /** Currently selected keys (controlled). */
42
+ selectedKeys?: 'all' | Iterable<Key>;
43
+ /** Default selected keys (uncontrolled). */
44
+ defaultSelectedKeys?: 'all' | Iterable<Key>;
45
+ /** Handler for selection changes. */
46
+ onSelectionChange?: (keys: 'all' | Set<Key>) => void;
47
+ /** Whether to allow duplicate selection events. */
48
+ allowDuplicateSelectionEvents?: boolean;
49
+ }
50
+
51
+ export interface ListState<T = unknown> extends SelectionState {
52
+ /** The collection of items. */
53
+ readonly collection: Accessor<Collection<T>>;
54
+ /** Whether the collection is focused. */
55
+ readonly isFocused: Accessor<boolean>;
56
+ /** Set the focused state. */
57
+ setFocused(isFocused: boolean): void;
58
+ /** The currently focused key. */
59
+ readonly focusedKey: Accessor<Key | null>;
60
+ /** Set the focused key. */
61
+ setFocusedKey(key: Key | null, childStrategy?: FocusStrategy): void;
62
+ /** The child focus strategy. */
63
+ readonly childFocusStrategy: Accessor<FocusStrategy | null>;
64
+ }
65
+
66
+ /**
67
+ * Creates state for a list component with selection.
68
+ */
69
+ export function createListState<T = unknown>(
70
+ props: MaybeAccessor<ListStateProps<T>>
71
+ ): ListState<T> {
72
+ const getProps = () => access(props);
73
+
74
+ // Build collection from items (memoized to avoid rebuilding on every access)
75
+ const collection: Accessor<Collection<T>> = createMemo(() => {
76
+ const p = getProps();
77
+ const items = p.items ?? [];
78
+
79
+ const nodes: CollectionNode<T>[] = items.map((item, index) => {
80
+ const o = item as CollectionItemLike;
81
+ const key = p.getKey?.(item) ?? o.key ?? o.id ?? index;
82
+ const textValue =
83
+ p.getTextValue?.(item) ?? o.textValue ?? o.label ?? String(item);
84
+ const isDisabled = p.getDisabled?.(item) ?? o.isDisabled ?? false;
85
+
86
+ return {
87
+ type: 'item' as const,
88
+ key,
89
+ value: item,
90
+ textValue,
91
+ rendered: null!,
92
+ level: 0,
93
+ index,
94
+ parentKey: null,
95
+ hasChildNodes: false,
96
+ childNodes: [],
97
+ isDisabled,
98
+ };
99
+ });
100
+
101
+ return new ListCollection(nodes);
102
+ });
103
+
104
+ // Combine disabled keys from props and items (memoized)
105
+ const combinedDisabledKeys = createMemo((): Iterable<Key> => {
106
+ const p = getProps();
107
+ const propsDisabled = p.disabledKeys ? [...p.disabledKeys] : [];
108
+ const itemDisabled: Key[] = [];
109
+
110
+ const coll = collection();
111
+ for (const node of coll) {
112
+ if (node.isDisabled) {
113
+ itemDisabled.push(node.key);
114
+ }
115
+ }
116
+
117
+ return [...new Set([...propsDisabled, ...itemDisabled])];
118
+ });
119
+
120
+ // Create selection state
121
+ const selectionState = createSelectionState({
122
+ get selectionMode() {
123
+ return getProps().selectionMode;
124
+ },
125
+ get selectionBehavior() {
126
+ return getProps().selectionBehavior;
127
+ },
128
+ get disallowEmptySelection() {
129
+ return getProps().disallowEmptySelection;
130
+ },
131
+ get selectedKeys() {
132
+ return getProps().selectedKeys;
133
+ },
134
+ get defaultSelectedKeys() {
135
+ return getProps().defaultSelectedKeys;
136
+ },
137
+ get onSelectionChange() {
138
+ return getProps().onSelectionChange;
139
+ },
140
+ get disabledKeys() {
141
+ return combinedDisabledKeys();
142
+ },
143
+ get disabledBehavior() {
144
+ return getProps().disabledBehavior;
145
+ },
146
+ get allowDuplicateSelectionEvents() {
147
+ return getProps().allowDuplicateSelectionEvents;
148
+ },
149
+ });
150
+
151
+ // Focus state
152
+ const [isFocused, setIsFocused] = createSignal(false);
153
+ const [focusedKey, setFocusedKeyInternal] = createSignal<Key | null>(null);
154
+ const [childFocusStrategy, setChildFocusStrategy] = createSignal<FocusStrategy | null>(null);
155
+
156
+ const setFocusedKey = (key: Key | null, childStrategy?: FocusStrategy) => {
157
+ setFocusedKeyInternal(key);
158
+ setChildFocusStrategy(childStrategy ?? null);
159
+ };
160
+
161
+ return {
162
+ collection,
163
+ isFocused,
164
+ setFocused: setIsFocused,
165
+ focusedKey,
166
+ setFocusedKey,
167
+ childFocusStrategy,
168
+ ...selectionState,
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Props for single selection list state.
174
+ */
175
+ export interface SingleSelectListStateProps<T = unknown>
176
+ extends Omit<ListStateProps<T>, 'selectionMode' | 'selectedKeys' | 'defaultSelectedKeys' | 'onSelectionChange'> {
177
+ /** The currently selected key (controlled). */
178
+ selectedKey?: Key | null;
179
+ /** The default selected key (uncontrolled). */
180
+ defaultSelectedKey?: Key;
181
+ /** Handler for selection changes. */
182
+ onSelectionChange?: (key: Key | null) => void;
183
+ }
184
+
185
+ export interface SingleSelectListState<T = unknown> extends ListState<T> {
186
+ /** The currently selected key. */
187
+ readonly selectedKey: Accessor<Key | null>;
188
+ /** Set the selected key. */
189
+ setSelectedKey(key: Key | null): void;
190
+ /** The currently selected item. */
191
+ readonly selectedItem: Accessor<CollectionNode<T> | null>;
192
+ }
193
+
194
+ /**
195
+ * Creates state for a single-select list component.
196
+ */
197
+ export function createSingleSelectListState<T = unknown>(
198
+ props: MaybeAccessor<SingleSelectListStateProps<T>>
199
+ ): SingleSelectListState<T> {
200
+ const getProps = () => access(props);
201
+
202
+ // Convert single selection props to multiple selection props
203
+ const listState = createListState<T>({
204
+ get items() {
205
+ return getProps().items;
206
+ },
207
+ get getKey() {
208
+ return getProps().getKey;
209
+ },
210
+ get getTextValue() {
211
+ return getProps().getTextValue;
212
+ },
213
+ get getDisabled() {
214
+ return getProps().getDisabled;
215
+ },
216
+ get disabledKeys() {
217
+ return getProps().disabledKeys;
218
+ },
219
+ get disabledBehavior() {
220
+ return getProps().disabledBehavior;
221
+ },
222
+ selectionMode: 'single',
223
+ disallowEmptySelection: true,
224
+ allowDuplicateSelectionEvents: true,
225
+ get selectedKeys() {
226
+ const key = getProps().selectedKey;
227
+ return key != null ? [key] : [];
228
+ },
229
+ get defaultSelectedKeys() {
230
+ const key = getProps().defaultSelectedKey;
231
+ return key != null ? [key] : undefined;
232
+ },
233
+ onSelectionChange(keys) {
234
+ if (keys === 'all') return;
235
+ const key = keys.values().next().value ?? null;
236
+ getProps().onSelectionChange?.(key);
237
+ },
238
+ });
239
+
240
+ const selectedKey: Accessor<Key | null> = () => {
241
+ const keys = listState.selectedKeys();
242
+ if (keys === 'all') return null;
243
+ return keys.values().next().value ?? null;
244
+ };
245
+
246
+ const setSelectedKey = (key: Key | null) => {
247
+ if (key === null) {
248
+ listState.clearSelection();
249
+ } else {
250
+ listState.replaceSelection(key);
251
+ }
252
+ };
253
+
254
+ const selectedItem: Accessor<CollectionNode<T> | null> = () => {
255
+ const key = selectedKey();
256
+ if (key === null) return null;
257
+ return listState.collection().getItem(key);
258
+ };
259
+
260
+ return {
261
+ ...listState,
262
+ selectedKey,
263
+ setSelectedKey,
264
+ selectedItem,
265
+ };
266
+ }