@proyecto-viviana/solid-stately 0.2.3 → 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,181 +1,290 @@
1
- /**
2
- * State management for select components.
3
- * Based on @react-stately/select useSelectState.
4
- */
5
-
6
- import { createSignal, type Accessor } from 'solid-js';
7
- import { access, type MaybeAccessor } from '../utils';
8
- import { createListState } from '../collections/createListState';
9
- import { createOverlayTriggerState } from '../overlays';
10
- import type { Key, CollectionNode, Collection } from '../collections/types';
11
-
12
- export interface SelectStateProps<T = unknown> {
13
- /** The items to display in the select. */
14
- items: T[];
15
- /** Function to get the key for an item. */
16
- getKey?: (item: T) => Key;
17
- /** Function to get the text value for an item. */
18
- getTextValue?: (item: T) => string;
19
- /** Function to check if an item is disabled. */
20
- getDisabled?: (item: T) => boolean;
21
- /** Keys of disabled items. */
22
- disabledKeys?: Iterable<Key>;
23
- /** The currently selected key (controlled). */
24
- selectedKey?: Key | null;
25
- /** The default selected key (uncontrolled). */
26
- defaultSelectedKey?: Key | null;
27
- /** Handler called when the selection changes. */
28
- onSelectionChange?: (key: Key | null) => void;
29
- /** Whether the select is open (controlled). */
30
- isOpen?: boolean;
31
- /** Whether the select is open by default (uncontrolled). */
32
- defaultOpen?: boolean;
33
- /** Handler called when the open state changes. */
34
- onOpenChange?: (isOpen: boolean) => void;
35
- /** Whether the select is disabled. */
36
- isDisabled?: boolean;
37
- /** Whether the select is required. */
38
- isRequired?: boolean;
39
- }
40
-
41
- export interface SelectState<T = unknown> {
42
- /** The collection of items. */
43
- readonly collection: Accessor<Collection<T>>;
44
- /** Whether the select dropdown is open. */
45
- readonly isOpen: Accessor<boolean>;
46
- /** Open the select dropdown. */
47
- open(): void;
48
- /** Close the select dropdown. */
49
- close(): void;
50
- /** Toggle the select dropdown. */
51
- toggle(): void;
52
- /** The currently selected key. */
53
- readonly selectedKey: Accessor<Key | null>;
54
- /** The currently selected item. */
55
- readonly selectedItem: Accessor<CollectionNode<T> | null>;
56
- /** Set the selected key. */
57
- setSelectedKey(key: Key | null): void;
58
- /** The currently focused key. */
59
- readonly focusedKey: Accessor<Key | null>;
60
- /** Set the focused key. */
61
- setFocusedKey(key: Key | null): void;
62
- /** Whether the select has focus. */
63
- readonly isFocused: Accessor<boolean>;
64
- /** Set whether the select has focus. */
65
- setFocused(isFocused: boolean): void;
66
- /** Whether a specific key is disabled. */
67
- isKeyDisabled(key: Key): boolean;
68
- /** Whether the select is disabled. */
69
- readonly isDisabled: boolean;
70
- /** Whether the select is required. */
71
- readonly isRequired: boolean;
72
- }
73
-
74
- /**
75
- * Creates state for a select component.
76
- * Combines list state with overlay trigger state for dropdown behavior.
77
- */
78
- export function createSelectState<T = unknown>(
79
- props: MaybeAccessor<SelectStateProps<T>>
80
- ): SelectState<T> {
81
- const getProps = () => access(props);
82
-
83
- // Overlay trigger state for open/close
84
- const overlayState = createOverlayTriggerState({
85
- get isOpen() {
86
- return getProps().isOpen;
87
- },
88
- get defaultOpen() {
89
- return getProps().defaultOpen;
90
- },
91
- get onOpenChange() {
92
- return getProps().onOpenChange;
93
- },
94
- });
95
-
96
- // Track selected key
97
- const isControlled = () => getProps().selectedKey !== undefined;
98
- const [internalSelectedKey, setInternalSelectedKey] = createSignal<Key | null>(
99
- getProps().defaultSelectedKey ?? null
100
- );
101
-
102
- const selectedKey: Accessor<Key | null> = () => {
103
- return isControlled() ? (getProps().selectedKey ?? null) : internalSelectedKey();
104
- };
105
-
106
- const setSelectedKey = (key: Key | null) => {
107
- if (!isControlled()) {
108
- setInternalSelectedKey(key);
109
- }
110
- getProps().onSelectionChange?.(key);
111
- };
112
-
113
- // Create list state with single selection
114
- const listState = createListState<T>({
115
- get items() {
116
- return getProps().items;
117
- },
118
- get getKey() {
119
- return getProps().getKey;
120
- },
121
- get getTextValue() {
122
- return getProps().getTextValue;
123
- },
124
- get getDisabled() {
125
- return getProps().getDisabled;
126
- },
127
- get disabledKeys() {
128
- return getProps().disabledKeys;
129
- },
130
- selectionMode: 'single',
131
- disallowEmptySelection: true,
132
- get selectedKeys() {
133
- const key = selectedKey();
134
- return key != null ? [key] : [];
135
- },
136
- onSelectionChange(keys) {
137
- // Get the first (and only) selected key
138
- if (keys === 'all') return; // Not applicable for single select
139
- const key = keys.size > 0 ? Array.from(keys)[0] : null;
140
- setSelectedKey(key);
141
- // Close the dropdown after selection
142
- overlayState.close();
143
- },
144
- });
145
-
146
- // Get the selected item from the collection
147
- const selectedItem: Accessor<CollectionNode<T> | null> = () => {
148
- const key = selectedKey();
149
- if (key == null) return null;
150
- return listState.collection().getItem(key);
151
- };
152
-
153
- return {
154
- // Collection
155
- collection: listState.collection,
156
-
157
- // Focus management
158
- focusedKey: listState.focusedKey,
159
- setFocusedKey: listState.setFocusedKey,
160
- isFocused: listState.isFocused,
161
- setFocused: listState.setFocused,
162
-
163
- // Overlay state
164
- isOpen: overlayState.isOpen,
165
- open: overlayState.open,
166
- close: overlayState.close,
167
- toggle: overlayState.toggle,
168
-
169
- // Select-specific
170
- selectedKey,
171
- selectedItem,
172
- setSelectedKey,
173
- isKeyDisabled: (key: Key) => listState.isDisabled(key),
174
- get isDisabled() {
175
- return getProps().isDisabled ?? false;
176
- },
177
- get isRequired() {
178
- return getProps().isRequired ?? false;
179
- },
180
- };
181
- }
1
+ /**
2
+ * State management for select components.
3
+ * Based on @react-stately/select useSelectState.
4
+ */
5
+
6
+ import { createSignal, createMemo, type Accessor } from 'solid-js';
7
+ import { access, type MaybeAccessor } from '../utils';
8
+ import { createListState } from '../collections/createListState';
9
+ import { createOverlayTriggerState } from '../overlays';
10
+ import type { Key, CollectionNode, Collection } from '../collections/types';
11
+ import type { SelectionMode, Selection } from '../collections/types';
12
+
13
+ export interface SelectStateProps<T = unknown> {
14
+ /** The items to display in the select. */
15
+ items: T[];
16
+ /** Function to get the key for an item. */
17
+ getKey?: (item: T) => Key;
18
+ /** Function to get the text value for an item. */
19
+ getTextValue?: (item: T) => string;
20
+ /** Function to check if an item is disabled. */
21
+ getDisabled?: (item: T) => boolean;
22
+ /** Keys of disabled items. */
23
+ disabledKeys?: Iterable<Key>;
24
+ /** The currently selected key (controlled). */
25
+ selectedKey?: Key | null;
26
+ /** The default selected key (uncontrolled). */
27
+ defaultSelectedKey?: Key | null;
28
+ /** The selected keys (controlled, for multiple selection mode). */
29
+ selectedKeys?: 'all' | Iterable<Key>;
30
+ /** Default selected keys (uncontrolled, for multiple selection mode). */
31
+ defaultSelectedKeys?: 'all' | Iterable<Key>;
32
+ /** Handler called when the selection changes. */
33
+ onSelectionChange?: (key: Key | null) => void;
34
+ /** Handler called when selected keys change. */
35
+ onSelectionChangeKeys?: (keys: Selection) => void;
36
+ /** Selection mode for the select. */
37
+ selectionMode?: Extract<SelectionMode, 'single' | 'multiple'>;
38
+ /** Whether the select is open (controlled). */
39
+ isOpen?: boolean;
40
+ /** Whether the select is open by default (uncontrolled). */
41
+ defaultOpen?: boolean;
42
+ /** Handler called when the open state changes. */
43
+ onOpenChange?: (isOpen: boolean) => void;
44
+ /** Whether the select is disabled. */
45
+ isDisabled?: boolean;
46
+ /** Whether the select is required. */
47
+ isRequired?: boolean;
48
+ }
49
+
50
+ export interface SelectState<T = unknown> {
51
+ /** The collection of items. */
52
+ readonly collection: Accessor<Collection<T>>;
53
+ /** Whether the select dropdown is open. */
54
+ readonly isOpen: Accessor<boolean>;
55
+ /** Open the select dropdown. */
56
+ open(): void;
57
+ /** Close the select dropdown. */
58
+ close(): void;
59
+ /** Toggle the select dropdown. */
60
+ toggle(): void;
61
+ /** The currently selected key. */
62
+ readonly selectedKey: Accessor<Key | null>;
63
+ /** The selected keys. */
64
+ readonly selectedKeys: Accessor<Selection>;
65
+ /** The currently selected item. */
66
+ readonly selectedItem: Accessor<CollectionNode<T> | null>;
67
+ /** The currently selected items. */
68
+ readonly selectedItems: Accessor<CollectionNode<T>[]>;
69
+ /** Set the selected key. */
70
+ setSelectedKey(key: Key | null): void;
71
+ /** Set selected keys. */
72
+ setSelectedKeys(keys: Iterable<Key>): void;
73
+ /** The currently focused key. */
74
+ readonly focusedKey: Accessor<Key | null>;
75
+ /** Set the focused key. */
76
+ setFocusedKey(key: Key | null): void;
77
+ /** Whether the select has focus. */
78
+ readonly isFocused: Accessor<boolean>;
79
+ /** Set whether the select has focus. */
80
+ setFocused(isFocused: boolean): void;
81
+ /** Whether a specific key is disabled. */
82
+ isKeyDisabled(key: Key): boolean;
83
+ /** Whether the select is disabled. */
84
+ readonly isDisabled: boolean;
85
+ /** Whether the select is required. */
86
+ readonly isRequired: boolean;
87
+ /** The selection mode. */
88
+ readonly selectionMode: Accessor<'single' | 'multiple'>;
89
+ }
90
+
91
+ /**
92
+ * Creates state for a select component.
93
+ * Combines list state with overlay trigger state for dropdown behavior.
94
+ */
95
+ export function createSelectState<T = unknown>(
96
+ props: MaybeAccessor<SelectStateProps<T>>
97
+ ): SelectState<T> {
98
+ const getProps = () => access(props);
99
+ const selectionMode: Accessor<'single' | 'multiple'> = () => getProps().selectionMode ?? 'single';
100
+
101
+ // Overlay trigger state for open/close
102
+ const overlayState = createOverlayTriggerState({
103
+ get isOpen() {
104
+ return getProps().isOpen;
105
+ },
106
+ get defaultOpen() {
107
+ return getProps().defaultOpen;
108
+ },
109
+ get onOpenChange() {
110
+ return getProps().onOpenChange;
111
+ },
112
+ });
113
+
114
+ // Track selected key
115
+ const isControlledSingle = () => getProps().selectedKey !== undefined;
116
+ const isControlledMultiple = () => getProps().selectedKeys !== undefined;
117
+ const [internalSelectedKey, setInternalSelectedKey] = createSignal<Key | null>(
118
+ getProps().defaultSelectedKey ?? null
119
+ );
120
+ const [internalSelectedKeys, setInternalSelectedKeys] = createSignal<Selection>(
121
+ getProps().defaultSelectedKeys === 'all'
122
+ ? 'all'
123
+ : new Set(getProps().defaultSelectedKeys ?? [])
124
+ );
125
+
126
+ const selectedKey: Accessor<Key | null> = () => {
127
+ if (selectionMode() === 'multiple') {
128
+ const keys = selectedKeys();
129
+ if (keys === 'all') return null;
130
+ return keys.size > 0 ? Array.from(keys)[0] : null;
131
+ }
132
+
133
+ return isControlledSingle() ? (getProps().selectedKey ?? null) : internalSelectedKey();
134
+ };
135
+
136
+ const setSelectedKey = (key: Key | null) => {
137
+ if (selectionMode() === 'multiple') {
138
+ if (key == null) {
139
+ if (!isControlledMultiple()) {
140
+ setInternalSelectedKeys(new Set<Key>());
141
+ }
142
+ getProps().onSelectionChangeKeys?.(new Set<Key>());
143
+ getProps().onSelectionChange?.(null);
144
+ } else {
145
+ const next = new Set([key]);
146
+ if (!isControlledMultiple()) {
147
+ setInternalSelectedKeys(next);
148
+ }
149
+ getProps().onSelectionChangeKeys?.(next);
150
+ getProps().onSelectionChange?.(key);
151
+ }
152
+ return;
153
+ }
154
+
155
+ if (!isControlledSingle()) {
156
+ setInternalSelectedKey(key);
157
+ }
158
+ getProps().onSelectionChange?.(key);
159
+ getProps().onSelectionChangeKeys?.(key != null ? new Set([key]) : new Set<Key>());
160
+ };
161
+
162
+ const selectedKeys: Accessor<Selection> = createMemo(() => {
163
+ if (selectionMode() === 'multiple') {
164
+ if (isControlledMultiple()) {
165
+ const keys = getProps().selectedKeys;
166
+ return keys === 'all' ? 'all' : new Set<Key>(keys ?? []);
167
+ }
168
+ return internalSelectedKeys();
169
+ }
170
+
171
+ const key = selectedKey();
172
+ return key != null ? new Set<Key>([key]) : new Set<Key>();
173
+ });
174
+
175
+ const setSelectedKeys = (keys: Iterable<Key>) => {
176
+ const next = new Set(keys);
177
+ if (selectionMode() === 'multiple') {
178
+ if (!isControlledMultiple()) {
179
+ setInternalSelectedKeys(next);
180
+ }
181
+ getProps().onSelectionChangeKeys?.(next);
182
+ getProps().onSelectionChange?.(next.size > 0 ? Array.from(next)[0] : null);
183
+ return;
184
+ }
185
+
186
+ const key = next.size > 0 ? Array.from(next)[0] : null;
187
+ setSelectedKey(key);
188
+ };
189
+
190
+ // Create list state with select selection mode
191
+ const listState = createListState<T>({
192
+ get items() {
193
+ return getProps().items;
194
+ },
195
+ get getKey() {
196
+ return getProps().getKey;
197
+ },
198
+ get getTextValue() {
199
+ return getProps().getTextValue;
200
+ },
201
+ get getDisabled() {
202
+ return getProps().getDisabled;
203
+ },
204
+ get disabledKeys() {
205
+ return getProps().disabledKeys;
206
+ },
207
+ get selectionMode() {
208
+ return selectionMode();
209
+ },
210
+ disallowEmptySelection: true,
211
+ get selectedKeys() {
212
+ const keys = selectedKeys();
213
+ if (keys === 'all') return 'all';
214
+ return keys;
215
+ },
216
+ onSelectionChange(keys) {
217
+ if (selectionMode() === 'multiple') {
218
+ if (!isControlledMultiple()) {
219
+ setInternalSelectedKeys(keys);
220
+ }
221
+ getProps().onSelectionChangeKeys?.(keys);
222
+ if (keys !== 'all') {
223
+ getProps().onSelectionChange?.(keys.size > 0 ? Array.from(keys)[0] : null);
224
+ }
225
+ return;
226
+ }
227
+
228
+ // Get the first (and only) selected key
229
+ if (keys === 'all') return;
230
+ const key = keys.size > 0 ? Array.from(keys)[0] : null;
231
+ setSelectedKey(key);
232
+ // Close the dropdown after selection in single mode
233
+ overlayState.close();
234
+ },
235
+ });
236
+
237
+ // Get the selected item from the collection (memoized)
238
+ const selectedItem: Accessor<CollectionNode<T> | null> = createMemo(() => {
239
+ const key = selectedKey();
240
+ if (key == null) return null;
241
+ return listState.collection().getItem(key);
242
+ });
243
+
244
+ const selectedItems: Accessor<CollectionNode<T>[]> = createMemo(() => {
245
+ const keys = selectedKeys();
246
+ if (keys === 'all') {
247
+ return Array.from(listState.collection());
248
+ }
249
+
250
+ const items: CollectionNode<T>[] = [];
251
+ for (const key of keys) {
252
+ const item = listState.collection().getItem(key);
253
+ if (item) items.push(item);
254
+ }
255
+ return items;
256
+ });
257
+
258
+ return {
259
+ // Collection
260
+ collection: listState.collection,
261
+
262
+ // Focus management
263
+ focusedKey: listState.focusedKey,
264
+ setFocusedKey: listState.setFocusedKey,
265
+ isFocused: listState.isFocused,
266
+ setFocused: listState.setFocused,
267
+
268
+ // Overlay state
269
+ isOpen: overlayState.isOpen,
270
+ open: overlayState.open,
271
+ close: overlayState.close,
272
+ toggle: overlayState.toggle,
273
+
274
+ // Select-specific
275
+ selectionMode,
276
+ selectedKey,
277
+ selectedKeys,
278
+ selectedItem,
279
+ selectedItems,
280
+ setSelectedKey,
281
+ setSelectedKeys,
282
+ isKeyDisabled: (key: Key) => listState.isDisabled(key),
283
+ get isDisabled() {
284
+ return getProps().isDisabled ?? false;
285
+ },
286
+ get isRequired() {
287
+ return getProps().isRequired ?? false;
288
+ },
289
+ };
290
+ }
@@ -1,5 +1,5 @@
1
- export {
2
- createSelectState,
3
- type SelectStateProps,
4
- type SelectState,
5
- } from './createSelectState';
1
+ export {
2
+ createSelectState,
3
+ type SelectStateProps,
4
+ type SelectState,
5
+ } from './createSelectState';
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Selection compatibility surface.
3
+ *
4
+ * Provides a React Stately-like module entrypoint for selection state while
5
+ * delegating to the existing Solid collection selection primitives.
6
+ */
7
+
8
+ export {
9
+ createSelectionState,
10
+ type SelectionStateProps,
11
+ type SelectionState,
12
+ } from '../collections/createSelectionState';
13
+
14
+ export type {
15
+ Key,
16
+ Selection,
17
+ SelectionMode,
18
+ SelectionBehavior,
19
+ DisabledBehavior,
20
+ FocusStrategy,
21
+ } from '../collections/types';
22
+
23
+ export type MultipleSelectionStateProps = import('../collections/createSelectionState').SelectionStateProps;
24
+ export type MultipleSelectionState = import('../collections/createSelectionState').SelectionState;
25
+
26
+ export {
27
+ createSelectionState as useMultipleSelectionState,
28
+ } from '../collections/createSelectionState';