@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.
Files changed (254) hide show
  1. package/README.md +30 -283
  2. package/dist/autocomplete/createAutocompleteState.d.ts +2 -2
  3. package/dist/autocomplete/index.d.ts +1 -1
  4. package/dist/calendar/IncompleteDate.d.ts +61 -0
  5. package/dist/calendar/createCalendarState.d.ts +41 -16
  6. package/dist/calendar/createDateFieldState.d.ts +39 -9
  7. package/dist/calendar/createDatePickerState.d.ts +60 -0
  8. package/dist/calendar/createRangeCalendarState.d.ts +37 -10
  9. package/dist/calendar/createTimeFieldState.d.ts +34 -7
  10. package/dist/calendar/index.d.ts +7 -6
  11. package/dist/checkbox/createCheckboxGroupState.d.ts +6 -6
  12. package/dist/checkbox/index.d.ts +1 -1
  13. package/dist/collections/ListCollection.d.ts +1 -1
  14. package/dist/collections/createListState.d.ts +11 -8
  15. package/dist/collections/createMenuState.d.ts +7 -7
  16. package/dist/collections/createSelectionState.d.ts +22 -10
  17. package/dist/collections/getChildNodes.d.ts +11 -0
  18. package/dist/collections/index.d.ts +6 -5
  19. package/dist/collections/types.d.ts +12 -12
  20. package/dist/color/Color.d.ts +1 -1
  21. package/dist/color/createColorAreaState.d.ts +4 -2
  22. package/dist/color/createColorFieldState.d.ts +38 -12
  23. package/dist/color/createColorSliderState.d.ts +9 -2
  24. package/dist/color/createColorWheelState.d.ts +13 -2
  25. package/dist/color/getColorChannels.d.ts +1 -1
  26. package/dist/color/index.d.ts +6 -6
  27. package/dist/color/types.d.ts +4 -4
  28. package/dist/combobox/createComboBoxState.d.ts +34 -13
  29. package/dist/combobox/index.d.ts +1 -1
  30. package/dist/data/createAsyncList.d.ts +4 -4
  31. package/dist/data/createListData.d.ts +2 -2
  32. package/dist/data/createTreeData.d.ts +6 -2
  33. package/dist/data/index.d.ts +3 -3
  34. package/dist/datepicker/index.d.ts +2 -4
  35. package/dist/disclosure/createDisclosureState.d.ts +2 -2
  36. package/dist/disclosure/index.d.ts +1 -1
  37. package/dist/dnd/createDragState.d.ts +2 -2
  38. package/dist/dnd/createDraggableCollectionState.d.ts +2 -2
  39. package/dist/dnd/createDropState.d.ts +2 -2
  40. package/dist/dnd/createDroppableCollectionState.d.ts +3 -3
  41. package/dist/dnd/index.d.ts +5 -5
  42. package/dist/dnd/types.d.ts +19 -17
  43. package/dist/form/createFormValidationState.d.ts +3 -3
  44. package/dist/form/index.d.ts +1 -1
  45. package/dist/grid/createGridState.d.ts +2 -2
  46. package/dist/grid/index.d.ts +2 -2
  47. package/dist/grid/types.d.ts +27 -11
  48. package/dist/index.d.ts +31 -30
  49. package/dist/index.js +9077 -7246
  50. package/dist/index.js.map +1 -1
  51. package/dist/menu/index.d.ts +2 -2
  52. package/dist/numberfield/createNumberFieldState.d.ts +2 -2
  53. package/dist/numberfield/index.d.ts +1 -1
  54. package/dist/overlays/createOverlayTriggerState.d.ts +2 -2
  55. package/dist/overlays/index.d.ts +1 -1
  56. package/dist/radio/createRadioGroupState.d.ts +7 -7
  57. package/dist/radio/index.d.ts +1 -1
  58. package/dist/searchfield/createSearchFieldState.d.ts +2 -2
  59. package/dist/searchfield/index.d.ts +2 -2
  60. package/dist/select/createSelectState.d.ts +14 -8
  61. package/dist/select/index.d.ts +1 -1
  62. package/dist/selection/Selection.d.ts +16 -0
  63. package/dist/selection/SelectionManager.d.ts +110 -0
  64. package/dist/selection/createMultipleSelectionState.d.ts +59 -0
  65. package/dist/selection/index.d.ts +6 -5
  66. package/dist/slider/createSliderState.d.ts +3 -3
  67. package/dist/slider/index.d.ts +2 -2
  68. package/dist/steplist/createStepListState.d.ts +48 -0
  69. package/dist/steplist/index.d.ts +1 -0
  70. package/dist/table/TableCollection.d.ts +33 -3
  71. package/dist/table/createTableColumnResizeState.d.ts +54 -0
  72. package/dist/table/createTableState.d.ts +2 -2
  73. package/dist/table/createTreeGridState.d.ts +15 -0
  74. package/dist/table/index.d.ts +6 -3
  75. package/dist/table/types.d.ts +68 -10
  76. package/dist/tabs/createTabListState.d.ts +5 -5
  77. package/dist/tabs/index.d.ts +1 -1
  78. package/dist/textfield/createTextFieldState.d.ts +2 -2
  79. package/dist/textfield/index.d.ts +1 -1
  80. package/dist/toast/createToastState.d.ts +24 -2
  81. package/dist/toast/index.d.ts +1 -1
  82. package/dist/toggle/createToggleGroupState.d.ts +4 -4
  83. package/dist/toggle/createToggleState.d.ts +2 -2
  84. package/dist/toggle/index.d.ts +2 -2
  85. package/dist/tooltip/createTooltipTriggerState.d.ts +2 -2
  86. package/dist/tooltip/index.d.ts +1 -1
  87. package/dist/tree/TreeCollection.d.ts +2 -2
  88. package/dist/tree/createTreeState.d.ts +2 -2
  89. package/dist/tree/index.d.ts +3 -3
  90. package/dist/tree/types.d.ts +27 -13
  91. package/dist/utils/index.d.ts +1 -1
  92. package/dist/utils/reactivity.d.ts +1 -1
  93. package/package.json +29 -30
  94. package/src/autocomplete/createAutocompleteState.d.ts +19 -17
  95. package/src/autocomplete/createAutocompleteState.ts +24 -30
  96. package/src/autocomplete/index.d.ts +6 -2
  97. package/src/autocomplete/index.ts +1 -1
  98. package/src/calendar/IncompleteDate.ts +430 -0
  99. package/src/calendar/createCalendarState.d.ts +139 -117
  100. package/src/calendar/createCalendarState.ts +308 -94
  101. package/src/calendar/createDateFieldState.d.ts +130 -95
  102. package/src/calendar/createDateFieldState.ts +447 -334
  103. package/src/calendar/createDatePickerState.ts +347 -0
  104. package/src/calendar/createRangeCalendarState.d.ts +154 -129
  105. package/src/calendar/createRangeCalendarState.ts +411 -85
  106. package/src/calendar/createTimeFieldState.d.ts +81 -79
  107. package/src/calendar/createTimeFieldState.ts +187 -108
  108. package/src/calendar/index.d.ts +80 -7
  109. package/src/calendar/index.ts +23 -12
  110. package/src/checkbox/createCheckboxGroupState.d.ts +57 -55
  111. package/src/checkbox/createCheckboxGroupState.ts +20 -29
  112. package/src/checkbox/index.d.ts +6 -2
  113. package/src/checkbox/index.ts +1 -1
  114. package/src/collections/ListCollection.d.ts +25 -22
  115. package/src/collections/ListCollection.ts +6 -6
  116. package/src/collections/createListState.d.ts +73 -58
  117. package/src/collections/createListState.ts +67 -35
  118. package/src/collections/createMenuState.d.ts +36 -31
  119. package/src/collections/createMenuState.ts +21 -12
  120. package/src/collections/createSelectionState.d.ts +78 -65
  121. package/src/collections/createSelectionState.ts +66 -52
  122. package/src/collections/getChildNodes.ts +98 -0
  123. package/src/collections/index.d.ts +38 -6
  124. package/src/collections/index.ts +14 -10
  125. package/src/collections/types.d.ts +101 -101
  126. package/src/collections/types.ts +12 -12
  127. package/src/color/Color.d.ts +20 -5
  128. package/src/color/Color.ts +357 -254
  129. package/src/color/createColorAreaState.d.ts +67 -65
  130. package/src/color/createColorAreaState.ts +21 -13
  131. package/src/color/createColorFieldState.d.ts +46 -44
  132. package/src/color/createColorFieldState.ts +285 -149
  133. package/src/color/createColorSliderState.d.ts +58 -56
  134. package/src/color/createColorSliderState.ts +45 -14
  135. package/src/color/createColorWheelState.d.ts +42 -40
  136. package/src/color/createColorWheelState.ts +101 -64
  137. package/src/color/getColorChannels.ts +7 -5
  138. package/src/color/index.d.ts +36 -7
  139. package/src/color/index.ts +6 -9
  140. package/src/color/types.d.ts +68 -63
  141. package/src/color/types.ts +11 -19
  142. package/src/combobox/createComboBoxState.d.ts +107 -105
  143. package/src/combobox/createComboBoxState.ts +184 -89
  144. package/src/combobox/index.d.ts +10 -2
  145. package/src/combobox/index.ts +1 -1
  146. package/src/data/createAsyncList.ts +89 -63
  147. package/src/data/createListData.ts +67 -67
  148. package/src/data/createTreeData.ts +304 -91
  149. package/src/data/index.ts +3 -3
  150. package/src/datepicker/index.ts +6 -10
  151. package/src/disclosure/createDisclosureState.d.ts +47 -43
  152. package/src/disclosure/createDisclosureState.ts +7 -21
  153. package/src/disclosure/index.d.ts +10 -2
  154. package/src/disclosure/index.ts +1 -1
  155. package/src/dnd/createDragState.d.ts +51 -42
  156. package/src/dnd/createDragState.ts +12 -14
  157. package/src/dnd/createDraggableCollectionState.d.ts +52 -41
  158. package/src/dnd/createDraggableCollectionState.ts +14 -21
  159. package/src/dnd/createDropState.d.ts +64 -45
  160. package/src/dnd/createDropState.ts +22 -32
  161. package/src/dnd/createDroppableCollectionState.d.ts +88 -59
  162. package/src/dnd/createDroppableCollectionState.ts +40 -43
  163. package/src/dnd/index.d.ts +55 -6
  164. package/src/dnd/index.ts +6 -18
  165. package/src/dnd/types.d.ts +170 -157
  166. package/src/dnd/types.ts +24 -22
  167. package/src/form/createFormValidationState.d.ts +47 -45
  168. package/src/form/createFormValidationState.ts +30 -63
  169. package/src/form/index.d.ts +16 -2
  170. package/src/form/index.ts +1 -1
  171. package/src/grid/createGridState.d.ts +7 -4
  172. package/src/grid/createGridState.ts +78 -51
  173. package/src/grid/index.d.ts +3 -3
  174. package/src/grid/index.ts +2 -8
  175. package/src/grid/types.d.ts +136 -129
  176. package/src/grid/types.ts +34 -18
  177. package/src/index.d.ts +311 -26
  178. package/src/index.ts +59 -89
  179. package/src/menu/index.ts +2 -4
  180. package/src/numberfield/createNumberFieldState.d.ts +56 -54
  181. package/src/numberfield/createNumberFieldState.ts +26 -31
  182. package/src/numberfield/index.d.ts +6 -2
  183. package/src/numberfield/index.ts +1 -1
  184. package/src/overlays/createOverlayTriggerState.d.ts +22 -20
  185. package/src/overlays/createOverlayTriggerState.ts +3 -4
  186. package/src/overlays/index.d.ts +6 -2
  187. package/src/overlays/index.ts +1 -1
  188. package/src/radio/createRadioGroupState.d.ts +54 -52
  189. package/src/radio/createRadioGroupState.ts +27 -29
  190. package/src/radio/index.d.ts +7 -2
  191. package/src/radio/index.ts +1 -1
  192. package/src/searchfield/createSearchFieldState.d.ts +16 -14
  193. package/src/searchfield/createSearchFieldState.ts +5 -11
  194. package/src/searchfield/index.d.ts +3 -3
  195. package/src/searchfield/index.ts +2 -5
  196. package/src/select/createSelectState.d.ts +63 -61
  197. package/src/select/createSelectState.ts +42 -29
  198. package/src/select/index.d.ts +2 -2
  199. package/src/select/index.ts +1 -5
  200. package/src/selection/Selection.ts +28 -0
  201. package/src/selection/SelectionManager.ts +526 -0
  202. package/src/selection/createMultipleSelectionState.ts +247 -0
  203. package/src/selection/index.ts +12 -7
  204. package/src/slider/createSliderState.d.ts +60 -60
  205. package/src/slider/createSliderState.ts +55 -33
  206. package/src/slider/index.d.ts +3 -3
  207. package/src/slider/index.ts +2 -6
  208. package/src/ssr/index.d.ts +1 -1
  209. package/src/ssr/index.ts +2 -2
  210. package/src/steplist/createStepListState.ts +191 -0
  211. package/src/steplist/index.ts +5 -0
  212. package/src/table/TableCollection.d.ts +42 -40
  213. package/src/table/TableCollection.ts +266 -99
  214. package/src/table/createTableColumnResizeState.ts +242 -0
  215. package/src/table/createTableState.d.ts +7 -4
  216. package/src/table/createTableState.ts +30 -7
  217. package/src/table/createTreeGridState.ts +146 -0
  218. package/src/table/index.d.ts +14 -4
  219. package/src/table/index.ts +13 -3
  220. package/src/table/types.d.ts +98 -92
  221. package/src/table/types.ts +83 -13
  222. package/src/tabs/createTabListState.d.ts +59 -57
  223. package/src/tabs/createTabListState.ts +34 -39
  224. package/src/tabs/index.d.ts +8 -2
  225. package/src/tabs/index.ts +1 -1
  226. package/src/textfield/createTextFieldState.d.ts +16 -14
  227. package/src/textfield/createTextFieldState.ts +7 -18
  228. package/src/textfield/index.d.ts +6 -2
  229. package/src/textfield/index.ts +1 -1
  230. package/src/toast/createToastState.d.ts +92 -86
  231. package/src/toast/createToastState.ts +90 -52
  232. package/src/toast/index.d.ts +12 -2
  233. package/src/toast/index.ts +2 -1
  234. package/src/toggle/createToggleGroupState.ts +11 -21
  235. package/src/toggle/createToggleState.d.ts +19 -19
  236. package/src/toggle/createToggleState.ts +2 -16
  237. package/src/toggle/index.d.ts +2 -2
  238. package/src/toggle/index.ts +2 -6
  239. package/src/tooltip/createTooltipTriggerState.d.ts +17 -17
  240. package/src/tooltip/createTooltipTriggerState.ts +12 -11
  241. package/src/tooltip/index.d.ts +7 -2
  242. package/src/tooltip/index.ts +1 -1
  243. package/src/tree/TreeCollection.d.ts +26 -23
  244. package/src/tree/TreeCollection.ts +29 -22
  245. package/src/tree/createTreeState.d.ts +7 -4
  246. package/src/tree/createTreeState.ts +70 -41
  247. package/src/tree/index.d.ts +10 -4
  248. package/src/tree/index.ts +3 -3
  249. package/src/tree/types.d.ts +131 -126
  250. package/src/tree/types.ts +30 -13
  251. package/src/utils/index.d.ts +2 -2
  252. package/src/utils/index.ts +1 -1
  253. package/src/utils/reactivity.d.ts +2 -2
  254. package/src/utils/reactivity.ts +3 -3
@@ -4,10 +4,12 @@
4
4
  * Based on @react-stately/list.
5
5
  */
6
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';
7
+ import { createMemo, type Accessor } from "solid-js";
8
+ import { access, type MaybeAccessor } from "../utils";
9
+ import { ListCollection } from "./ListCollection";
10
+ import type { SelectionState, SelectionPressEvent } from "./createSelectionState";
11
+ import { createMultipleSelectionState } from "../selection/createMultipleSelectionState";
12
+ import { SelectionManager } from "../selection/SelectionManager";
11
13
  import type {
12
14
  Collection,
13
15
  CollectionItemLike,
@@ -17,7 +19,7 @@ import type {
17
19
  Key,
18
20
  SelectionBehavior,
19
21
  SelectionMode,
20
- } from './types';
22
+ } from "./types";
21
23
 
22
24
  export interface ListStateProps<T = unknown> {
23
25
  /** The items in the list (for dynamic rendering). */
@@ -39,11 +41,11 @@ export interface ListStateProps<T = unknown> {
39
41
  /** Whether empty selection is disallowed. */
40
42
  disallowEmptySelection?: boolean;
41
43
  /** Currently selected keys (controlled). */
42
- selectedKeys?: 'all' | Iterable<Key>;
44
+ selectedKeys?: "all" | Iterable<Key>;
43
45
  /** Default selected keys (uncontrolled). */
44
- defaultSelectedKeys?: 'all' | Iterable<Key>;
46
+ defaultSelectedKeys?: "all" | Iterable<Key>;
45
47
  /** Handler for selection changes. */
46
- onSelectionChange?: (keys: 'all' | Set<Key>) => void;
48
+ onSelectionChange?: (keys: "all" | Set<Key>) => void;
47
49
  /** Whether to allow duplicate selection events. */
48
50
  allowDuplicateSelectionEvents?: boolean;
49
51
  }
@@ -51,6 +53,8 @@ export interface ListStateProps<T = unknown> {
51
53
  export interface ListState<T = unknown> extends SelectionState {
52
54
  /** The collection of items. */
53
55
  readonly collection: Accessor<Collection<T>>;
56
+ /** The collection-aware selection manager (single source of truth for selection). */
57
+ readonly selectionManager: SelectionManager<T>;
54
58
  /** Whether the collection is focused. */
55
59
  readonly isFocused: Accessor<boolean>;
56
60
  /** Set the focused state. */
@@ -67,7 +71,7 @@ export interface ListState<T = unknown> extends SelectionState {
67
71
  * Creates state for a list component with selection.
68
72
  */
69
73
  export function createListState<T = unknown>(
70
- props: MaybeAccessor<ListStateProps<T>>
74
+ props: MaybeAccessor<ListStateProps<T>>,
71
75
  ): ListState<T> {
72
76
  const getProps = () => access(props);
73
77
 
@@ -79,12 +83,11 @@ export function createListState<T = unknown>(
79
83
  const nodes: CollectionNode<T>[] = items.map((item, index) => {
80
84
  const o = item as CollectionItemLike;
81
85
  const key = p.getKey?.(item) ?? o.key ?? o.id ?? index;
82
- const textValue =
83
- p.getTextValue?.(item) ?? o.textValue ?? o.label ?? String(item);
86
+ const textValue = p.getTextValue?.(item) ?? o.textValue ?? o.label ?? String(item);
84
87
  const isDisabled = p.getDisabled?.(item) ?? o.isDisabled ?? false;
85
88
 
86
89
  return {
87
- type: 'item' as const,
90
+ type: "item" as const,
88
91
  key,
89
92
  value: item,
90
93
  textValue,
@@ -117,8 +120,9 @@ export function createListState<T = unknown>(
117
120
  return [...new Set([...propsDisabled, ...itemDisabled])];
118
121
  });
119
122
 
120
- // Create selection state
121
- const selectionState = createSelectionState({
123
+ // Raw selection + focus state (the lower layer). This owns the selected keys,
124
+ // focus, selection behavior, and disabled keys, but is not collection-aware.
125
+ const state = createMultipleSelectionState({
122
126
  get selectionMode() {
123
127
  return getProps().selectionMode;
124
128
  },
@@ -148,32 +152,60 @@ export function createListState<T = unknown>(
148
152
  },
149
153
  });
150
154
 
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
- };
155
+ // The collection-aware selection manager (the upper layer): the single source
156
+ // of truth for every selection operation. It reads the collection live so it
157
+ // stays reactive as the collection memo recomputes.
158
+ const selectionManager = new SelectionManager<T>(() => collection(), state);
160
159
 
161
160
  return {
162
161
  collection,
163
- isFocused,
164
- setFocused: setIsFocused,
165
- focusedKey,
166
- setFocusedKey,
167
- childFocusStrategy,
168
- ...selectionState,
162
+ selectionManager,
163
+
164
+ // Focus — delegate to the raw state (the single source of truth). The
165
+ // setter routes through the manager so it inherits the existence guard and
166
+ // the upstream 'first' child-focus default.
167
+ isFocused: () => state.isFocused,
168
+ setFocused: (isFocused: boolean) => state.setFocused(isFocused),
169
+ focusedKey: () => state.focusedKey,
170
+ setFocusedKey: (key: Key | null, childStrategy?: FocusStrategy) =>
171
+ selectionManager.setFocusedKey(key, childStrategy),
172
+ childFocusStrategy: () => state.childFocusStrategy,
173
+
174
+ // Flattened selection surface — delegates to the manager so the list path
175
+ // shares one faithful engine. extendSelection keeps its legacy second
176
+ // argument for back-compat, but ignores it (the manager reads the
177
+ // collection itself).
178
+ selectionMode: () => selectionManager.selectionMode,
179
+ selectionBehavior: () => selectionManager.selectionBehavior,
180
+ disallowEmptySelection: () => selectionManager.disallowEmptySelection,
181
+ selectedKeys: () => state.selectedKeys,
182
+ disabledKeys: () => selectionManager.disabledKeys,
183
+ disabledBehavior: () => selectionManager.disabledBehavior,
184
+ isEmpty: () => selectionManager.isEmpty,
185
+ isSelectAll: () => selectionManager.isSelectAll,
186
+ isSelected: (key: Key) => selectionManager.isSelected(key),
187
+ isDisabled: (key: Key) => selectionManager.isDisabled(key),
188
+ setSelectionBehavior: (behavior: SelectionBehavior) =>
189
+ selectionManager.setSelectionBehavior(behavior),
190
+ toggleSelection: (key: Key) => selectionManager.toggleSelection(key),
191
+ replaceSelection: (key: Key) => selectionManager.replaceSelection(key),
192
+ setSelectedKeys: (keys: Iterable<Key>) => selectionManager.setSelectedKeys(keys),
193
+ selectAll: () => selectionManager.selectAll(),
194
+ clearSelection: () => selectionManager.clearSelection(),
195
+ toggleSelectAll: () => selectionManager.toggleSelectAll(),
196
+ extendSelection: (toKey: Key, _collection?: Collection) =>
197
+ selectionManager.extendSelection(toKey),
198
+ select: (key: Key, e?: SelectionPressEvent) => selectionManager.select(key, e),
169
199
  };
170
200
  }
171
201
 
172
202
  /**
173
203
  * Props for single selection list state.
174
204
  */
175
- export interface SingleSelectListStateProps<T = unknown>
176
- extends Omit<ListStateProps<T>, 'selectionMode' | 'selectedKeys' | 'defaultSelectedKeys' | 'onSelectionChange'> {
205
+ export interface SingleSelectListStateProps<T = unknown> extends Omit<
206
+ ListStateProps<T>,
207
+ "selectionMode" | "selectedKeys" | "defaultSelectedKeys" | "onSelectionChange"
208
+ > {
177
209
  /** The currently selected key (controlled). */
178
210
  selectedKey?: Key | null;
179
211
  /** The default selected key (uncontrolled). */
@@ -195,7 +227,7 @@ export interface SingleSelectListState<T = unknown> extends ListState<T> {
195
227
  * Creates state for a single-select list component.
196
228
  */
197
229
  export function createSingleSelectListState<T = unknown>(
198
- props: MaybeAccessor<SingleSelectListStateProps<T>>
230
+ props: MaybeAccessor<SingleSelectListStateProps<T>>,
199
231
  ): SingleSelectListState<T> {
200
232
  const getProps = () => access(props);
201
233
 
@@ -219,7 +251,7 @@ export function createSingleSelectListState<T = unknown>(
219
251
  get disabledBehavior() {
220
252
  return getProps().disabledBehavior;
221
253
  },
222
- selectionMode: 'single',
254
+ selectionMode: "single",
223
255
  disallowEmptySelection: true,
224
256
  allowDuplicateSelectionEvents: true,
225
257
  get selectedKeys() {
@@ -231,7 +263,7 @@ export function createSingleSelectListState<T = unknown>(
231
263
  return key != null ? [key] : undefined;
232
264
  },
233
265
  onSelectionChange(keys) {
234
- if (keys === 'all') return;
266
+ if (keys === "all") return;
235
267
  const key = keys.values().next().value ?? null;
236
268
  getProps().onSelectionChange?.(key);
237
269
  },
@@ -239,7 +271,7 @@ export function createSingleSelectListState<T = unknown>(
239
271
 
240
272
  const selectedKey: Accessor<Key | null> = () => {
241
273
  const keys = listState.selectedKeys();
242
- if (keys === 'all') return null;
274
+ if (keys === "all") return null;
243
275
  return keys.values().next().value ?? null;
244
276
  };
245
277
 
@@ -2,49 +2,54 @@
2
2
  * State management for menu components.
3
3
  * Based on @react-stately/menu.
4
4
  */
5
- import { type MaybeAccessor } from '../utils';
6
- import { type ListState, type ListStateProps } from './createListState';
7
- import type { Key } from './types';
8
- export interface MenuStateProps<T = unknown> extends Omit<ListStateProps<T>, 'selectionMode' | 'disallowEmptySelection'> {
9
- /** Handler called when an item is activated (pressed). */
10
- onAction?: (key: Key) => void;
11
- /** Handler called when the menu should close. */
12
- onClose?: () => void;
5
+ import { type MaybeAccessor } from "../utils";
6
+ import { type ListState, type ListStateProps } from "./createListState";
7
+ import type { Key } from "./types";
8
+ export interface MenuStateProps<T = unknown> extends Omit<
9
+ ListStateProps<T>,
10
+ "selectionMode" | "disallowEmptySelection"
11
+ > {
12
+ /** Handler called when an item is activated (pressed). */
13
+ onAction?: (key: Key) => void;
14
+ /** Handler called when the menu should close. */
15
+ onClose?: () => void;
13
16
  }
14
17
  export interface MenuState<T = unknown> extends ListState<T> {
15
- /** Close the menu. */
16
- close(): void;
18
+ /** Close the menu. */
19
+ close(): void;
17
20
  }
18
21
  /**
19
22
  * Creates state for a menu component.
20
23
  * Menus are single-select lists that support actions.
21
24
  */
22
- export declare function createMenuState<T = unknown>(props: MaybeAccessor<MenuStateProps<T>>): MenuState<T>;
25
+ export declare function createMenuState<T = unknown>(
26
+ props: MaybeAccessor<MenuStateProps<T>>,
27
+ ): MenuState<T>;
23
28
  export interface MenuTriggerStateProps {
24
- /** Whether the menu is open (controlled). */
25
- isOpen?: boolean;
26
- /** Default open state (uncontrolled). */
27
- defaultOpen?: boolean;
28
- /** Handler called when the open state changes. */
29
- onOpenChange?: (isOpen: boolean) => void;
29
+ /** Whether the menu is open (controlled). */
30
+ isOpen?: boolean;
31
+ /** Default open state (uncontrolled). */
32
+ defaultOpen?: boolean;
33
+ /** Handler called when the open state changes. */
34
+ onOpenChange?: (isOpen: boolean) => void;
30
35
  }
31
36
  export interface MenuTriggerState {
32
- /** Whether the menu is open. */
33
- readonly isOpen: () => boolean;
34
- /** Open the menu. */
35
- open(): void;
36
- /** Close the menu. */
37
- close(): void;
38
- /** Toggle the menu. */
39
- toggle(): void;
40
- /** Focus strategy for when the menu opens. */
41
- readonly focusStrategy: () => 'first' | 'last' | null;
42
- /** Set the focus strategy. */
43
- setFocusStrategy(strategy: 'first' | 'last' | null): void;
37
+ /** Whether the menu is open. */
38
+ readonly isOpen: () => boolean;
39
+ /** Open the menu. */
40
+ open(): void;
41
+ /** Close the menu. */
42
+ close(): void;
43
+ /** Toggle the menu. */
44
+ toggle(): void;
45
+ /** Focus strategy for when the menu opens. */
46
+ readonly focusStrategy: () => "first" | "last" | null;
47
+ /** Set the focus strategy. */
48
+ setFocusStrategy(strategy: "first" | "last" | null): void;
44
49
  }
45
50
  /**
46
51
  * Creates state for a menu trigger (button that opens a menu).
47
52
  * This is essentially the same as overlay trigger state but with focus strategy.
48
53
  */
49
- export { createOverlayTriggerState as createMenuTriggerState } from '../overlays';
50
- //# sourceMappingURL=createMenuState.d.ts.map
54
+ export { createOverlayTriggerState as createMenuTriggerState } from "../overlays";
55
+ //# sourceMappingURL=createMenuState.d.ts.map
@@ -3,12 +3,11 @@
3
3
  * Based on @react-stately/menu.
4
4
  */
5
5
 
6
- import { access, type MaybeAccessor } from '../utils';
7
- import { createListState, type ListState, type ListStateProps } from './createListState';
8
- import type { Key } from './types';
6
+ import { access, type MaybeAccessor } from "../utils";
7
+ import { createListState, type ListState, type ListStateProps } from "./createListState";
8
+ import type { Key } from "./types";
9
9
 
10
- export interface MenuStateProps<T = unknown>
11
- extends Omit<ListStateProps<T>, 'selectionMode' | 'disallowEmptySelection'> {
10
+ export interface MenuStateProps<T = unknown> extends ListStateProps<T> {
12
11
  /** Handler called when an item is activated (pressed). */
13
12
  onAction?: (key: Key) => void;
14
13
  /** Handler called when the menu should close. */
@@ -25,11 +24,11 @@ export interface MenuState<T = unknown> extends ListState<T> {
25
24
  * Menus are single-select lists that support actions.
26
25
  */
27
26
  export function createMenuState<T = unknown>(
28
- props: MaybeAccessor<MenuStateProps<T>>
27
+ props: MaybeAccessor<MenuStateProps<T>>,
29
28
  ): MenuState<T> {
30
29
  const getProps = () => access(props);
31
30
 
32
- // Create list state with single selection
31
+ // Menus default to action-only items, but can opt into single or multiple selection.
33
32
  const listState = createListState<T>({
34
33
  get items() {
35
34
  return getProps().items;
@@ -49,20 +48,30 @@ export function createMenuState<T = unknown>(
49
48
  get disabledBehavior() {
50
49
  return getProps().disabledBehavior;
51
50
  },
52
- selectionMode: 'none', // Menus typically use onAction, not selection
53
- disallowEmptySelection: true,
51
+ get selectionMode() {
52
+ return getProps().selectionMode ?? "none";
53
+ },
54
+ get disallowEmptySelection() {
55
+ return getProps().disallowEmptySelection;
56
+ },
54
57
  get selectedKeys() {
58
+ if ((getProps().selectionMode ?? "none") === "none") return undefined;
55
59
  return getProps().selectedKeys;
56
60
  },
57
61
  get defaultSelectedKeys() {
62
+ if ((getProps().selectionMode ?? "none") === "none") return undefined;
58
63
  return getProps().defaultSelectedKeys;
59
64
  },
60
65
  get onSelectionChange() {
66
+ if ((getProps().selectionMode ?? "none") === "none") return undefined;
61
67
  return getProps().onSelectionChange;
62
68
  },
63
69
  get selectionBehavior() {
64
70
  return getProps().selectionBehavior;
65
71
  },
72
+ get allowDuplicateSelectionEvents() {
73
+ return getProps().allowDuplicateSelectionEvents;
74
+ },
66
75
  });
67
76
 
68
77
  const close = () => {
@@ -94,13 +103,13 @@ export interface MenuTriggerState {
94
103
  /** Toggle the menu. */
95
104
  toggle(): void;
96
105
  /** Focus strategy for when the menu opens. */
97
- readonly focusStrategy: () => 'first' | 'last' | null;
106
+ readonly focusStrategy: () => "first" | "last" | null;
98
107
  /** Set the focus strategy. */
99
- setFocusStrategy(strategy: 'first' | 'last' | null): void;
108
+ setFocusStrategy(strategy: "first" | "last" | null): void;
100
109
  }
101
110
 
102
111
  /**
103
112
  * Creates state for a menu trigger (button that opens a menu).
104
113
  * This is essentially the same as overlay trigger state but with focus strategy.
105
114
  */
106
- export { createOverlayTriggerState as createMenuTriggerState } from '../overlays';
115
+ export { createOverlayTriggerState as createMenuTriggerState } from "../overlays";
@@ -2,75 +2,88 @@
2
2
  * Selection state management for collections.
3
3
  * Based on @react-stately/selection.
4
4
  */
5
- import { type Accessor } from 'solid-js';
6
- import { type MaybeAccessor } from '../utils';
7
- import type { Collection, DisabledBehavior, Key, Selection, SelectionBehavior, SelectionMode } from './types';
5
+ import { type Accessor } from "solid-js";
6
+ import { type MaybeAccessor } from "../utils";
7
+ import type {
8
+ Collection,
9
+ DisabledBehavior,
10
+ Key,
11
+ Selection,
12
+ SelectionBehavior,
13
+ SelectionMode,
14
+ } from "./types";
8
15
  export interface SelectionStateProps {
9
- /** The selection mode. */
10
- selectionMode?: SelectionMode;
11
- /** How selection behaves on interaction. */
12
- selectionBehavior?: SelectionBehavior;
13
- /** Whether empty selection is disallowed. */
14
- disallowEmptySelection?: boolean;
15
- /** Currently selected keys (controlled). */
16
- selectedKeys?: 'all' | Iterable<Key>;
17
- /** Default selected keys (uncontrolled). */
18
- defaultSelectedKeys?: 'all' | Iterable<Key>;
19
- /** Handler for selection changes. */
20
- onSelectionChange?: (keys: Selection) => void;
21
- /** Keys of disabled items. */
22
- disabledKeys?: Iterable<Key>;
23
- /** How disabled keys behave. */
24
- disabledBehavior?: DisabledBehavior;
25
- /** Whether to allow duplicate selection events. */
26
- allowDuplicateSelectionEvents?: boolean;
16
+ /** The selection mode. */
17
+ selectionMode?: SelectionMode;
18
+ /** How selection behaves on interaction. */
19
+ selectionBehavior?: SelectionBehavior;
20
+ /** Whether empty selection is disallowed. */
21
+ disallowEmptySelection?: boolean;
22
+ /** Currently selected keys (controlled). */
23
+ selectedKeys?: "all" | Iterable<Key>;
24
+ /** Default selected keys (uncontrolled). */
25
+ defaultSelectedKeys?: "all" | Iterable<Key>;
26
+ /** Handler for selection changes. */
27
+ onSelectionChange?: (keys: Selection) => void;
28
+ /** Keys of disabled items. */
29
+ disabledKeys?: Iterable<Key>;
30
+ /** How disabled keys behave. */
31
+ disabledBehavior?: DisabledBehavior;
32
+ /** Whether to allow duplicate selection events. */
33
+ allowDuplicateSelectionEvents?: boolean;
27
34
  }
28
35
  export interface SelectionState {
29
- /** The selection mode. */
30
- readonly selectionMode: Accessor<SelectionMode>;
31
- /** The selection behavior. */
32
- readonly selectionBehavior: Accessor<SelectionBehavior>;
33
- /** Whether empty selection is disallowed. */
34
- readonly disallowEmptySelection: Accessor<boolean>;
35
- /** The currently selected keys. */
36
- readonly selectedKeys: Accessor<Selection>;
37
- /** Set of disabled keys. */
38
- readonly disabledKeys: Accessor<Set<Key>>;
39
- /** How disabled keys behave. */
40
- readonly disabledBehavior: Accessor<DisabledBehavior>;
41
- /** Whether the selection is empty. */
42
- readonly isEmpty: Accessor<boolean>;
43
- /** Whether all items are selected. */
44
- readonly isSelectAll: Accessor<boolean>;
45
- /** Check if a key is selected. */
46
- isSelected(key: Key): boolean;
47
- /** Check if a key is disabled. */
48
- isDisabled(key: Key): boolean;
49
- /** Set the selection behavior. */
50
- setSelectionBehavior(behavior: SelectionBehavior): void;
51
- /** Toggle selection for a key. */
52
- toggleSelection(key: Key): void;
53
- /** Replace selection with a single key. */
54
- replaceSelection(key: Key): void;
55
- /** Set multiple selected keys. */
56
- setSelectedKeys(keys: Iterable<Key>): void;
57
- /** Select all items. */
58
- selectAll(): void;
59
- /** Clear all selection. */
60
- clearSelection(): void;
61
- /** Toggle between select all and clear. */
62
- toggleSelectAll(): void;
63
- /** Extend selection to a key (for shift-click). */
64
- extendSelection(toKey: Key, collection: Collection): void;
65
- /** Select a key based on interaction. */
66
- select(key: Key, e?: {
67
- shiftKey?: boolean;
68
- ctrlKey?: boolean;
69
- metaKey?: boolean;
70
- }, collection?: Collection): void;
36
+ /** The selection mode. */
37
+ readonly selectionMode: Accessor<SelectionMode>;
38
+ /** The selection behavior. */
39
+ readonly selectionBehavior: Accessor<SelectionBehavior>;
40
+ /** Whether empty selection is disallowed. */
41
+ readonly disallowEmptySelection: Accessor<boolean>;
42
+ /** The currently selected keys. */
43
+ readonly selectedKeys: Accessor<Selection>;
44
+ /** Set of disabled keys. */
45
+ readonly disabledKeys: Accessor<Set<Key>>;
46
+ /** How disabled keys behave. */
47
+ readonly disabledBehavior: Accessor<DisabledBehavior>;
48
+ /** Whether the selection is empty. */
49
+ readonly isEmpty: Accessor<boolean>;
50
+ /** Whether all items are selected. */
51
+ readonly isSelectAll: Accessor<boolean>;
52
+ /** Check if a key is selected. */
53
+ isSelected(key: Key): boolean;
54
+ /** Check if a key is disabled. */
55
+ isDisabled(key: Key): boolean;
56
+ /** Set the selection behavior. */
57
+ setSelectionBehavior(behavior: SelectionBehavior): void;
58
+ /** Toggle selection for a key. */
59
+ toggleSelection(key: Key): void;
60
+ /** Replace selection with a single key. */
61
+ replaceSelection(key: Key): void;
62
+ /** Set multiple selected keys. */
63
+ setSelectedKeys(keys: Iterable<Key>): void;
64
+ /** Select all items. */
65
+ selectAll(): void;
66
+ /** Clear all selection. */
67
+ clearSelection(): void;
68
+ /** Toggle between select all and clear. */
69
+ toggleSelectAll(): void;
70
+ /** Extend selection to a key (for shift-click). */
71
+ extendSelection(toKey: Key, collection: Collection): void;
72
+ /** Select a key based on interaction. */
73
+ select(
74
+ key: Key,
75
+ e?: {
76
+ shiftKey?: boolean;
77
+ ctrlKey?: boolean;
78
+ metaKey?: boolean;
79
+ },
80
+ collection?: Collection,
81
+ ): void;
71
82
  }
72
83
  /**
73
84
  * Creates selection state for a collection.
74
85
  */
75
- export declare function createSelectionState(props?: MaybeAccessor<SelectionStateProps>): SelectionState;
76
- //# sourceMappingURL=createSelectionState.d.ts.map
86
+ export declare function createSelectionState(
87
+ props?: MaybeAccessor<SelectionStateProps>,
88
+ ): SelectionState;
89
+ //# sourceMappingURL=createSelectionState.d.ts.map