@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
package/README.md CHANGED
@@ -1,113 +1,23 @@
1
1
  # @proyecto-viviana/solid-stately
2
2
 
3
- A SolidJS port of [React Stately](https://react-spectrum.adobe.com/react-stately/) - headless state management for UI components.
3
+ SolidJS port of React Stately state primitives.
4
4
 
5
- ## Installation
5
+ This package is the state layer below `solidaria` and
6
+ `solidaria-components`. It owns controlled/uncontrolled state, collection
7
+ models, selection, date/time state, validation state, and related utilities.
8
+
9
+ ## Install
6
10
 
7
11
  ```bash
8
- bun add @proyecto-viviana/solid-stately solid-js
12
+ npm install @proyecto-viviana/solid-stately solid-js
9
13
  ```
10
14
 
11
- ## Overview
12
-
13
- solid-stately provides state management hooks that handle the complex logic for UI components like toggles, selections, overlays, and collections. These hooks return reactive state and update functions that you can use with any UI.
14
-
15
- This package is the foundation layer of the Proyecto Viviana component library, providing the state logic that powers the accessibility hooks in `@proyecto-viviana/solidaria`.
16
-
17
- ## Available Hooks
18
-
19
- ### Toggle & Selection
20
-
21
- | Hook | Description |
22
- |------|-------------|
23
- | `createToggleState` | Boolean toggle state for checkboxes, switches |
24
- | `createCheckboxGroupState` | Multi-selection checkbox group |
25
- | `createRadioGroupState` | Single-selection radio group |
26
-
27
- ### Overlays
28
-
29
- | Hook | Description |
30
- |------|-------------|
31
- | `createOverlayTriggerState` | Open/close state for modals, popovers, menus |
32
-
33
- ### Collections & Lists
34
-
35
- | Hook | Description |
36
- |------|-------------|
37
- | `createListState` | List with selection and keyboard focus |
38
- | `createSingleSelectListState` | Single-selection list (e.g., for select dropdowns) |
39
- | `createSelectionState` | Low-level selection management |
40
- | `createMenuState` | Menu state with action support |
41
- | `createMenuTriggerState` | Menu trigger open/close state |
42
- | `createSelectState` | Select dropdown state |
43
- | `ListCollection` | Collection data structure for lists |
44
- | `createListCollection` | Create a list collection from items |
45
-
46
- ### Navigation
47
-
48
- | Hook | Description |
49
- |------|-------------|
50
- | `createTabListState` | Tab navigation state with keyboard support |
51
-
52
- ### Form Controls
53
-
54
- | Hook | Description |
55
- |------|-------------|
56
- | `createTextFieldState` | Text input state |
57
- | `createNumberFieldState` | Numeric input with validation |
58
- | `createSearchFieldState` | Search input with clear functionality |
59
- | `createSliderState` | Range slider state |
60
- | `createFormValidationState` | Form validation state with realtime/native modes |
61
-
62
- ### Grid & Table
63
-
64
- | Hook | Description |
65
- |------|-------------|
66
- | `createGridState` | Grid state with keyboard navigation |
67
- | `createTableState` | Table state with sorting and selection |
68
- | `TableCollection` | Collection data structure for tables |
69
-
70
- ### Tree
71
-
72
- | Hook | Description |
73
- |------|-------------|
74
- | `createTreeState` | Tree state with expand/collapse |
75
- | `TreeCollection` | Collection data structure for trees |
76
-
77
- ### Color
78
-
79
- | Hook | Description |
80
- |------|-------------|
81
- | `createColorSliderState` | Color channel slider state |
82
- | `createColorAreaState` | 2D color area picker state |
83
- | `createColorWheelState` | Circular hue wheel state |
84
- | `createColorFieldState` | Color text input state |
85
-
86
- ### Drag & Drop
87
-
88
- | Hook | Description |
89
- |------|-------------|
90
- | `createDragState` | Drag operation state |
91
- | `createDropState` | Drop target state |
92
- | `createDraggableCollectionState` | Collection-level drag state |
93
- | `createDroppableCollectionState` | Collection-level drop state |
94
-
95
- ### Utilities
96
-
97
- | Hook | Description |
98
- |------|-------------|
99
- | `createId` | Generate unique IDs (SSR-safe) |
100
- | `createIsSSR` | Detect server-side rendering |
101
- | `canUseDOM` | Check if DOM is available |
102
-
103
- ## Usage Examples
104
-
105
- ### Toggle State
15
+ ## Usage
106
16
 
107
17
  ```tsx
108
- import { createToggleState } from '@proyecto-viviana/solid-stately';
18
+ import { createToggleState } from "@proyecto-viviana/solid-stately";
109
19
 
110
- function Checkbox(props) {
20
+ export function Toggle(props) {
111
21
  const state = createToggleState({
112
22
  isSelected: props.isSelected,
113
23
  defaultSelected: props.defaultSelected,
@@ -115,198 +25,35 @@ function Checkbox(props) {
115
25
  });
116
26
 
117
27
  return (
118
- <label>
119
- <input
120
- type="checkbox"
121
- checked={state.isSelected()}
122
- onChange={() => state.toggle()}
123
- />
28
+ <button aria-pressed={state.isSelected()} onClick={() => state.toggle()}>
124
29
  {props.children}
125
- </label>
30
+ </button>
126
31
  );
127
32
  }
128
33
  ```
129
34
 
130
- ### List State with Selection
131
-
132
- ```tsx
133
- import { createListState } from '@proyecto-viviana/solid-stately';
134
-
135
- function ListBox(props) {
136
- const state = createListState({
137
- items: props.items,
138
- getKey: (item) => item.id,
139
- getTextValue: (item) => item.name,
140
- selectionMode: 'single',
141
- onSelectionChange: props.onSelectionChange,
142
- });
143
-
144
- return (
145
- <ul>
146
- <For each={props.items}>
147
- {(item) => {
148
- const key = item.id;
149
- const isSelected = () => state.selectionManager.isSelected(key);
150
-
151
- return (
152
- <li
153
- onClick={() => state.selectionManager.toggleSelection(key)}
154
- style={{ background: isSelected() ? 'blue' : 'white' }}
155
- >
156
- {item.name}
157
- </li>
158
- );
159
- }}
160
- </For>
161
- </ul>
162
- );
163
- }
164
- ```
35
+ ## Public Surface
165
36
 
166
- ### Overlay State
37
+ The source of truth is [`src/index.ts`](src/index.ts). Keep this README focused
38
+ on package purpose and verification rather than duplicating the full export
39
+ list.
167
40
 
168
- ```tsx
169
- import { createOverlayTriggerState } from '@proyecto-viviana/solid-stately';
41
+ Major areas currently covered:
170
42
 
171
- function Modal(props) {
172
- const state = createOverlayTriggerState({
173
- isOpen: props.isOpen,
174
- defaultOpen: props.defaultOpen,
175
- onOpenChange: props.onOpenChange,
176
- });
43
+ - toggles, checkbox groups, radio groups, and disclosure;
44
+ - overlays, tooltips, toasts, forms, and validation;
45
+ - collections, selection, menus, selects, combo boxes, tabs;
46
+ - grid, table, tree, list data, and async list helpers;
47
+ - date/time/calendar state and internationalized date helpers;
48
+ - number fields, search fields, sliders, and color state;
49
+ - drag-and-drop state and SSR utilities.
177
50
 
178
- return (
179
- <>
180
- <button onClick={() => state.open()}>Open Modal</button>
181
- <Show when={state.isOpen()}>
182
- <div class="modal">
183
- {props.children}
184
- <button onClick={() => state.close()}>Close</button>
185
- </div>
186
- </Show>
187
- </>
188
- );
189
- }
190
- ```
51
+ ## Verification
191
52
 
192
- ### Tab State
193
-
194
- ```tsx
195
- import { createTabListState } from '@proyecto-viviana/solid-stately';
196
-
197
- function Tabs(props) {
198
- const state = createTabListState({
199
- items: props.tabs,
200
- getKey: (tab) => tab.id,
201
- selectedKey: props.selectedKey,
202
- onSelectionChange: props.onSelectionChange,
203
- });
204
-
205
- return (
206
- <div>
207
- <div role="tablist">
208
- <For each={props.tabs}>
209
- {(tab) => (
210
- <button
211
- role="tab"
212
- aria-selected={state.selectedKey() === tab.id}
213
- onClick={() => state.setSelectedKey(tab.id)}
214
- >
215
- {tab.label}
216
- </button>
217
- )}
218
- </For>
219
- </div>
220
- <div role="tabpanel">
221
- {props.tabs.find(t => t.id === state.selectedKey())?.content}
222
- </div>
223
- </div>
224
- );
225
- }
226
- ```
227
-
228
- ### Slider State
229
-
230
- ```tsx
231
- import { createSliderState } from '@proyecto-viviana/solid-stately';
232
-
233
- function Slider(props) {
234
- const state = createSliderState({
235
- value: props.value,
236
- defaultValue: props.defaultValue ?? 50,
237
- minValue: props.minValue ?? 0,
238
- maxValue: props.maxValue ?? 100,
239
- step: props.step ?? 1,
240
- onChange: props.onChange,
241
- });
242
-
243
- const percent = () => state.getValuePercent() * 100;
244
-
245
- return (
246
- <div>
247
- <input
248
- type="range"
249
- min={state.minValue}
250
- max={state.maxValue}
251
- step={state.step}
252
- value={state.value()}
253
- onInput={(e) => state.setValue(parseFloat(e.target.value))}
254
- />
255
- <span>{state.getFormattedValue()}</span>
256
- </div>
257
- );
258
- }
259
- ```
260
-
261
- ## Key Concepts
262
-
263
- ### Controlled vs Uncontrolled
264
-
265
- All state hooks support both controlled and uncontrolled patterns:
266
-
267
- ```tsx
268
- // Uncontrolled - uses internal state
269
- const state = createToggleState({
270
- defaultSelected: false,
271
- onChange: (isSelected) => console.log('Changed:', isSelected),
272
- });
273
-
274
- // Controlled - uses external state
275
- const [isSelected, setIsSelected] = createSignal(false);
276
- const state = createToggleState({
277
- isSelected: isSelected(),
278
- onChange: setIsSelected,
279
- });
280
- ```
281
-
282
- ### MaybeAccessor Pattern
283
-
284
- Props can be passed as values or accessors for reactive updates:
285
-
286
- ```tsx
287
- // Static value
288
- createToggleState({ defaultSelected: true });
289
-
290
- // Reactive accessor
291
- createToggleState({
292
- get isDisabled() { return props.isDisabled; }
293
- });
294
- ```
295
-
296
- ## TypeScript
297
-
298
- All hooks are fully typed. Import types as needed:
299
-
300
- ```tsx
301
- import {
302
- createListState,
303
- type ListState,
304
- type ListStateProps,
305
- type Key,
306
- type Selection,
307
- } from '@proyecto-viviana/solid-stately';
53
+ ```bash
54
+ vp run --filter @proyecto-viviana/solid-stately build
55
+ vp test run packages
308
56
  ```
309
57
 
310
- ## License
311
-
312
- MIT
58
+ State changes should include tests for controlled and uncontrolled use, default
59
+ values, callbacks, validation, and disabled/read-only behavior where applicable.
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Based on @react-stately/autocomplete useAutocompleteState.
5
5
  */
6
- import { type Accessor } from 'solid-js';
7
- import { type MaybeAccessor } from '../utils';
6
+ import { type Accessor } from "solid-js";
7
+ import { type MaybeAccessor } from "../utils";
8
8
  export interface AutocompleteState {
9
9
  /** The current value of the autocomplete input. */
10
10
  inputValue: Accessor<string>;
@@ -1 +1 @@
1
- export { createAutocompleteState, type AutocompleteState, type AutocompleteStateOptions, } from './createAutocompleteState';
1
+ export { createAutocompleteState, type AutocompleteState, type AutocompleteStateOptions, } from "./createAutocompleteState";
@@ -0,0 +1,61 @@
1
+ /**
2
+ * IncompleteDate for Solid-Stately
3
+ *
4
+ * Represents a date that is incomplete or otherwise invalid as a result of user
5
+ * editing (for example February 31st, if the day is edited before the month).
6
+ * This lets a date field hold an invalid intermediate value while typing and
7
+ * only constrain it on blur, matching upstream behavior.
8
+ *
9
+ * Based on @react-stately/datepicker IncompleteDate
10
+ */
11
+ import { type AnyDateTime, type Calendar, type DateValue } from "@internationalized/date";
12
+ import type { DateSegmentType } from "./createDateFieldState";
13
+ type HourCycle = "h12" | "h11" | "h23" | "h24";
14
+ /**
15
+ * This class represents a date that is incomplete or otherwise invalid as a result of user editing.
16
+ * For example, it can represent temporary dates such as February 31st if the user edits the day
17
+ * before the month. Times are represented according to an hour cycle rather than always in 24 hour
18
+ * time. This enables the user to adjust the day period (e.g. am/pm) independently from the hour.
19
+ */
20
+ export declare class IncompleteDate {
21
+ calendar: Calendar;
22
+ era: string | null;
23
+ year: number | null;
24
+ month: number | null;
25
+ day: number | null;
26
+ hour: number | null;
27
+ hourCycle: HourCycle;
28
+ dayPeriod: number | null;
29
+ minute: number | null;
30
+ second: number | null;
31
+ millisecond: number | null;
32
+ offset: number | null;
33
+ constructor(calendar: Calendar, hourCycle: HourCycle, dateValue?: Partial<Omit<AnyDateTime, "copy">> | null);
34
+ copy(): IncompleteDate;
35
+ /** Checks whether all the specified segments have a value. */
36
+ isComplete(segments: DateSegmentType[]): boolean;
37
+ /** Checks whether the given date value matches this value for the specified segments. */
38
+ validate(dt: DateValue, segments: DateSegmentType[]): boolean;
39
+ /** Checks if the date is empty (i.e. all specified segments are null). */
40
+ isCleared(segments: DateSegmentType[]): boolean;
41
+ /** Sets the given field. */
42
+ set(field: DateSegmentType, value: number | string, placeholder: DateValue): IncompleteDate;
43
+ /** Sets the given field to null. */
44
+ clear(field: DateSegmentType): IncompleteDate;
45
+ /**
46
+ * Increments or decrements the given field. If it is null, then it is set to the placeholder
47
+ * value.
48
+ */
49
+ cycle(field: DateSegmentType, amount: number, placeholder: DateValue, displaySegments: DateSegmentType[]): IncompleteDate;
50
+ /**
51
+ * Converts the incomplete date to a full date value, using the provided value for any unset
52
+ * fields.
53
+ */
54
+ toValue(value: DateValue): DateValue;
55
+ getSegmentLimits(type: string): {
56
+ value: number | null;
57
+ minValue: number;
58
+ maxValue: number;
59
+ } | undefined;
60
+ }
61
+ export {};
@@ -4,17 +4,24 @@
4
4
  * Provides state management for calendar components.
5
5
  * Based on @react-stately/calendar useCalendarState
6
6
  */
7
- import { type Accessor } from 'solid-js';
8
- import { type CalendarDate, type DateValue } from '@internationalized/date';
9
- import { type MaybeAccessor } from '../utils';
10
- export type ValidationState = 'valid' | 'invalid';
11
- export interface CalendarStateProps<T extends DateValue = DateValue> {
7
+ import { type Accessor } from "solid-js";
8
+ import { type Calendar as InternationalizedCalendar, type CalendarDate, type CalendarIdentifier, type DateValue } from "@internationalized/date";
9
+ import { type MaybeAccessor } from "../utils";
10
+ export type ValidationState = "valid" | "invalid";
11
+ export type CalendarPageBehavior = "single" | "visible";
12
+ export type CalendarSelectionAlignment = "start" | "center" | "end";
13
+ export type CalendarDayOfWeek = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
14
+ export type CalendarSelectionMode = "single" | "multiple";
15
+ export type CalendarValueType<T, M extends CalendarSelectionMode> = M extends "single" ? T : readonly T[];
16
+ export interface CalendarStateProps<T extends DateValue = DateValue, M extends CalendarSelectionMode = "single"> {
12
17
  /** The current value (controlled). */
13
- value?: MaybeAccessor<T | null>;
18
+ value?: MaybeAccessor<CalendarValueType<T | null, M> | undefined>;
14
19
  /** The default value (uncontrolled). */
15
- defaultValue?: T | null;
20
+ defaultValue?: CalendarValueType<T | null, M> | null;
16
21
  /** Handler called when the value changes. */
17
- onChange?: (value: T) => void;
22
+ onChange?: (value: CalendarValueType<T | null, M>) => void;
23
+ /** Whether single or multiple date selection is enabled. */
24
+ selectionMode?: MaybeAccessor<M>;
18
25
  /** The minimum allowed date. */
19
26
  minValue?: MaybeAccessor<DateValue | undefined>;
20
27
  /** The maximum allowed date. */
@@ -26,17 +33,23 @@ export interface CalendarStateProps<T extends DateValue = DateValue> {
26
33
  /** Whether dates outside the visible range are automatically focused. */
27
34
  autoFocus?: boolean;
28
35
  /** The date that is focused when the calendar first mounts. */
29
- focusedValue?: MaybeAccessor<DateValue | undefined>;
36
+ focusedValue?: MaybeAccessor<DateValue | null | undefined>;
30
37
  /** The default focused date (uncontrolled). */
31
38
  defaultFocusedValue?: DateValue;
32
39
  /** Handler called when the focused date changes. */
33
40
  onFocusChange?: (date: CalendarDate) => void;
34
41
  /** The locale to use for formatting. */
35
- locale?: string;
42
+ locale?: MaybeAccessor<string | undefined>;
43
+ /** Creates a calendar object for a locale calendar identifier. */
44
+ createCalendar?: (identifier: CalendarIdentifier) => InternationalizedCalendar;
36
45
  /** Callback that is called for each date in the calendar to determine if it is unavailable. */
37
46
  isDateUnavailable?: (date: DateValue) => boolean;
38
47
  /** The number of months to display at once. */
39
48
  visibleMonths?: number;
49
+ /** Controls whether paging advances by one month or by the visible month range. */
50
+ pageBehavior?: CalendarPageBehavior;
51
+ /** Determines how the visible months align around the initial focused date. */
52
+ selectionAlignment?: CalendarSelectionAlignment;
40
53
  /** Whether to automatically focus the calendar when it is mounted. */
41
54
  autoFocusOnMount?: boolean;
42
55
  /** Controls which days are disabled. */
@@ -48,15 +61,21 @@ export interface CalendarStateProps<T extends DateValue = DateValue> {
48
61
  /** The first day of the week (0 = Sunday, 1 = Monday, etc.). */
49
62
  firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
50
63
  }
51
- export interface CalendarState<T extends DateValue = DateValue> {
52
- /** The currently selected date. */
53
- value: Accessor<T | null>;
54
- /** Sets the selected date. */
55
- setValue: (value: T | null) => void;
64
+ export interface CalendarState<T extends DateValue = DateValue, M extends CalendarSelectionMode = "single"> {
65
+ /** Whether single or multiple selection is enabled. */
66
+ selectionMode: Accessor<CalendarSelectionMode>;
67
+ /** The currently selected date(s). */
68
+ value: Accessor<CalendarValueType<T | null, M>>;
69
+ /** Sets the selected date(s). */
70
+ setValue: (value: CalendarValueType<T | null, M>) => void;
56
71
  /** The currently focused date. */
57
72
  focusedDate: Accessor<CalendarDate>;
58
73
  /** Sets the focused date. */
59
74
  setFocusedDate: (date: CalendarDate) => void;
75
+ /** The minimum allowed date that a user may select. */
76
+ minValue: Accessor<DateValue | null>;
77
+ /** The maximum allowed date that a user may select. */
78
+ maxValue: Accessor<DateValue | null>;
60
79
  /** Whether the calendar is disabled. */
61
80
  isDisabled: Accessor<boolean>;
62
81
  /** Whether the calendar is read-only. */
@@ -68,8 +87,14 @@ export interface CalendarState<T extends DateValue = DateValue> {
68
87
  }>;
69
88
  /** The timezone used for date calculations. */
70
89
  timeZone: string;
90
+ /** The locale used for formatting and locale-specific week starts. */
91
+ locale: Accessor<string>;
92
+ /** The explicitly requested first weekday, or undefined for the locale default. */
93
+ firstDayOfWeek: Accessor<CalendarDayOfWeek | undefined>;
71
94
  /** The validation state. */
72
95
  validationState: Accessor<ValidationState | undefined>;
96
+ /** Whether the current value is invalid according to validation state. */
97
+ isValueInvalid: Accessor<boolean>;
73
98
  /** Whether a date is selected. */
74
99
  isSelected: (date: DateValue) => boolean;
75
100
  /** Whether a date is focused. */
@@ -126,4 +151,4 @@ export interface CalendarState<T extends DateValue = DateValue> {
126
151
  /**
127
152
  * Provides state management for a calendar component.
128
153
  */
129
- export declare function createCalendarState<T extends DateValue = CalendarDate>(props?: CalendarStateProps<T>): CalendarState<T>;
154
+ export declare function createCalendarState<T extends DateValue = CalendarDate, M extends CalendarSelectionMode = "single">(props?: CalendarStateProps<T, M>): CalendarState<T, M>;
@@ -3,19 +3,26 @@
3
3
  *
4
4
  * Provides state management for date field components with segment-based editing.
5
5
  * Based on @react-stately/datepicker useDateFieldState
6
+ *
7
+ * Editing is modeled with an {@link IncompleteDate} display value so that invalid
8
+ * intermediate dates (e.g. February 31st, produced by editing the day before the
9
+ * month) are held as-typed while the field is focused and only constrained on blur
10
+ * via `confirmPlaceholder`, matching upstream behavior. Out-of-range values are
11
+ * never snapped to `minValue`/`maxValue`; they are kept and reported as invalid.
6
12
  */
7
- import { type Accessor } from 'solid-js';
8
- import { type CalendarDate, type DateValue } from '@internationalized/date';
9
- import { type MaybeAccessor } from '../utils';
10
- import type { ValidationState } from './createCalendarState';
11
- export type DateSegmentType = 'year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'dayPeriod' | 'era' | 'timeZoneName' | 'literal';
13
+ import { type Accessor } from "solid-js";
14
+ import { type CalendarDateTime, type DateValue } from "@internationalized/date";
15
+ import { type MaybeAccessor } from "../utils";
16
+ import type { ValidationState } from "./createCalendarState";
17
+ import { type ValidationBehavior, type ValidationFunction, type ValidationResult } from "../form";
18
+ export type DateSegmentType = "year" | "month" | "day" | "hour" | "minute" | "second" | "dayPeriod" | "era" | "timeZoneName" | "literal";
12
19
  export interface DateSegment {
13
20
  /** The type of segment. */
14
21
  type: DateSegmentType;
15
22
  /** The text content of the segment. */
16
23
  text: string;
17
24
  /** The numeric value of the segment (if applicable). */
18
- value?: number;
25
+ value?: number | null;
19
26
  /** The minimum value for the segment. */
20
27
  minValue?: number;
21
28
  /** The maximum value for the segment. */
@@ -44,18 +51,26 @@ export interface DateFieldStateProps<T extends DateValue = DateValue> {
44
51
  isReadOnly?: MaybeAccessor<boolean>;
45
52
  /** Whether the field is required. */
46
53
  isRequired?: MaybeAccessor<boolean>;
54
+ /** Whether the value is invalid (controlled). */
55
+ isInvalid?: boolean;
47
56
  /** The locale to use for formatting. */
48
57
  locale?: string;
49
58
  /** The granularity of the date/time (day, hour, minute, second). */
50
- granularity?: 'day' | 'hour' | 'minute' | 'second';
59
+ granularity?: "day" | "hour" | "minute" | "second";
51
60
  /** Whether to show the hour in 12 or 24 hour format. */
52
61
  hourCycle?: 12 | 24;
53
62
  /** Whether to hide the time zone. */
54
63
  hideTimeZone?: boolean;
55
64
  /** The placeholder date (determines segment structure). */
56
65
  placeholderValue?: DateValue;
66
+ /** Whether to force leading zeroes in month/day segments. */
67
+ shouldForceLeadingZeros?: boolean;
57
68
  /** Validation state. */
58
69
  validationState?: MaybeAccessor<ValidationState | undefined>;
70
+ /** Validation behavior mode. */
71
+ validationBehavior?: ValidationBehavior;
72
+ /** Custom validation function. */
73
+ validate?: ValidationFunction<T>;
59
74
  /** Description text. */
60
75
  description?: string;
61
76
  /** Error message. */
@@ -64,6 +79,8 @@ export interface DateFieldStateProps<T extends DateValue = DateValue> {
64
79
  allowsNonContiguousRanges?: boolean;
65
80
  /** Whether to create a date or datetime. */
66
81
  createCalendar?: (name: string) => unknown;
82
+ /** Whether a date is unavailable. */
83
+ isDateUnavailable?: (date: DateValue) => boolean;
67
84
  }
68
85
  export interface DateFieldState<T extends DateValue = DateValue> {
69
86
  /** The current value. */
@@ -95,15 +112,28 @@ export interface DateFieldState<T extends DateValue = DateValue> {
95
112
  /** The validation state. */
96
113
  validationState: Accessor<ValidationState | undefined>;
97
114
  /** The granularity. */
98
- granularity: 'day' | 'hour' | 'minute' | 'second';
115
+ granularity: "day" | "hour" | "minute" | "second";
99
116
  /** Whether the value is invalid. */
100
117
  isInvalid: Accessor<boolean>;
118
+ /** Realtime validation results, including native and custom constraints. */
119
+ realtimeValidation: Accessor<ValidationResult>;
120
+ /** Currently displayed validation results. */
121
+ displayValidation: Accessor<ValidationResult>;
122
+ /** Updates the current validation result. */
123
+ updateValidation: (result: ValidationResult) => void;
124
+ /** Resets displayed validation to valid. */
125
+ resetValidation: () => void;
126
+ /** Commits realtime validation to displayed validation. */
127
+ commitValidation: () => void;
101
128
  /** The locale. */
102
129
  locale: string;
103
130
  /** The time zone. */
104
131
  timeZone: string;
132
+ /** The default value. */
133
+ defaultValue: T | null;
105
134
  }
106
135
  /**
107
136
  * Provides state management for a date field component.
108
137
  */
109
- export declare function createDateFieldState<T extends DateValue = CalendarDate>(props?: DateFieldStateProps<T>): DateFieldState<T>;
138
+ export declare function createDateFieldState<T extends DateValue = DateValue>(props?: DateFieldStateProps<T>): DateFieldState<T>;
139
+ export type { CalendarDateTime };