@proyecto-viviana/solid-stately 0.2.1 → 0.2.3

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 (216) hide show
  1. package/dist/index.js +43 -43
  2. package/dist/index.js.map +1 -1
  3. package/package.json +7 -5
  4. package/src/autocomplete/createAutocompleteState.d.ts +46 -0
  5. package/src/autocomplete/createAutocompleteState.d.ts.map +1 -0
  6. package/src/autocomplete/createAutocompleteState.ts +90 -0
  7. package/src/autocomplete/index.d.ts +2 -0
  8. package/src/autocomplete/index.d.ts.map +1 -0
  9. package/src/autocomplete/index.ts +5 -0
  10. package/src/calendar/createCalendarState.d.ts +130 -0
  11. package/src/calendar/createCalendarState.d.ts.map +1 -0
  12. package/src/calendar/createCalendarState.ts +461 -0
  13. package/src/calendar/createDateFieldState.d.ts +110 -0
  14. package/src/calendar/createDateFieldState.d.ts.map +1 -0
  15. package/src/calendar/createDateFieldState.ts +562 -0
  16. package/src/calendar/createRangeCalendarState.d.ts +146 -0
  17. package/src/calendar/createRangeCalendarState.d.ts.map +1 -0
  18. package/src/calendar/createRangeCalendarState.ts +535 -0
  19. package/src/calendar/createTimeFieldState.d.ts +95 -0
  20. package/src/calendar/createTimeFieldState.d.ts.map +1 -0
  21. package/src/calendar/createTimeFieldState.ts +483 -0
  22. package/src/calendar/index.d.ts +7 -0
  23. package/src/calendar/index.d.ts.map +1 -0
  24. package/src/calendar/index.ts +81 -0
  25. package/src/checkbox/createCheckboxGroupState.d.ts +71 -0
  26. package/src/checkbox/createCheckboxGroupState.d.ts.map +1 -0
  27. package/src/checkbox/createCheckboxGroupState.ts +193 -0
  28. package/src/checkbox/index.d.ts +2 -0
  29. package/src/checkbox/index.d.ts.map +1 -0
  30. package/src/checkbox/index.ts +5 -0
  31. package/src/collections/ListCollection.d.ts +37 -0
  32. package/src/collections/ListCollection.d.ts.map +1 -0
  33. package/src/collections/ListCollection.ts +146 -0
  34. package/src/collections/createListState.d.ts +79 -0
  35. package/src/collections/createListState.d.ts.map +1 -0
  36. package/src/collections/createListState.ts +264 -0
  37. package/src/collections/createMenuState.d.ts +50 -0
  38. package/src/collections/createMenuState.d.ts.map +1 -0
  39. package/src/collections/createMenuState.ts +106 -0
  40. package/src/collections/createSelectionState.d.ts +76 -0
  41. package/src/collections/createSelectionState.d.ts.map +1 -0
  42. package/src/collections/createSelectionState.ts +336 -0
  43. package/src/collections/index.d.ts +6 -0
  44. package/src/collections/index.d.ts.map +1 -0
  45. package/src/collections/index.ts +46 -0
  46. package/src/collections/types.d.ts +147 -0
  47. package/src/collections/types.d.ts.map +1 -0
  48. package/src/collections/types.ts +169 -0
  49. package/src/color/Color.d.ts +28 -0
  50. package/src/color/Color.d.ts.map +1 -0
  51. package/src/color/Color.ts +951 -0
  52. package/src/color/createColorAreaState.d.ts +76 -0
  53. package/src/color/createColorAreaState.d.ts.map +1 -0
  54. package/src/color/createColorAreaState.ts +293 -0
  55. package/src/color/createColorFieldState.d.ts +55 -0
  56. package/src/color/createColorFieldState.d.ts.map +1 -0
  57. package/src/color/createColorFieldState.ts +292 -0
  58. package/src/color/createColorSliderState.d.ts +67 -0
  59. package/src/color/createColorSliderState.d.ts.map +1 -0
  60. package/src/color/createColorSliderState.ts +241 -0
  61. package/src/color/createColorWheelState.d.ts +51 -0
  62. package/src/color/createColorWheelState.d.ts.map +1 -0
  63. package/src/color/createColorWheelState.ts +211 -0
  64. package/src/color/index.d.ts +10 -0
  65. package/src/color/index.d.ts.map +1 -0
  66. package/src/color/index.ts +47 -0
  67. package/src/color/types.d.ts +106 -0
  68. package/src/color/types.d.ts.map +1 -0
  69. package/src/color/types.ts +127 -0
  70. package/src/combobox/createComboBoxState.d.ts +125 -0
  71. package/src/combobox/createComboBoxState.d.ts.map +1 -0
  72. package/src/combobox/createComboBoxState.ts +703 -0
  73. package/src/combobox/index.d.ts +5 -0
  74. package/src/combobox/index.d.ts.map +1 -0
  75. package/src/combobox/index.ts +13 -0
  76. package/src/disclosure/createDisclosureState.d.ts +64 -0
  77. package/src/disclosure/createDisclosureState.d.ts.map +1 -0
  78. package/src/disclosure/createDisclosureState.ts +193 -0
  79. package/src/disclosure/index.d.ts +2 -0
  80. package/src/disclosure/index.d.ts.map +1 -0
  81. package/src/disclosure/index.ts +9 -0
  82. package/src/dnd/createDragState.d.ts +59 -0
  83. package/src/dnd/createDragState.d.ts.map +1 -0
  84. package/src/dnd/createDragState.ts +153 -0
  85. package/src/dnd/createDraggableCollectionState.d.ts +57 -0
  86. package/src/dnd/createDraggableCollectionState.d.ts.map +1 -0
  87. package/src/dnd/createDraggableCollectionState.ts +165 -0
  88. package/src/dnd/createDropState.d.ts +61 -0
  89. package/src/dnd/createDropState.d.ts.map +1 -0
  90. package/src/dnd/createDropState.ts +212 -0
  91. package/src/dnd/createDroppableCollectionState.d.ts +78 -0
  92. package/src/dnd/createDroppableCollectionState.d.ts.map +1 -0
  93. package/src/dnd/createDroppableCollectionState.ts +357 -0
  94. package/src/dnd/index.d.ts +11 -0
  95. package/src/dnd/index.d.ts.map +1 -0
  96. package/src/dnd/index.ts +76 -0
  97. package/src/dnd/types.d.ts +264 -0
  98. package/src/dnd/types.d.ts.map +1 -0
  99. package/src/dnd/types.ts +317 -0
  100. package/src/form/createFormValidationState.d.ts +100 -0
  101. package/src/form/createFormValidationState.d.ts.map +1 -0
  102. package/src/form/createFormValidationState.ts +389 -0
  103. package/src/form/index.d.ts +2 -0
  104. package/src/form/index.d.ts.map +1 -0
  105. package/src/form/index.ts +15 -0
  106. package/src/grid/createGridState.d.ts +12 -0
  107. package/src/grid/createGridState.d.ts.map +1 -0
  108. package/src/grid/createGridState.ts +327 -0
  109. package/src/grid/index.d.ts +7 -0
  110. package/src/grid/index.d.ts.map +1 -0
  111. package/src/grid/index.ts +13 -0
  112. package/src/grid/types.d.ts +156 -0
  113. package/src/grid/types.d.ts.map +1 -0
  114. package/src/grid/types.ts +179 -0
  115. package/src/index.d.ts +26 -0
  116. package/src/index.d.ts.map +1 -0
  117. package/src/index.ts +383 -0
  118. package/src/numberfield/createNumberFieldState.d.ts +65 -0
  119. package/src/numberfield/createNumberFieldState.d.ts.map +1 -0
  120. package/src/numberfield/createNumberFieldState.ts +383 -0
  121. package/src/numberfield/index.d.ts +2 -0
  122. package/src/numberfield/index.d.ts.map +1 -0
  123. package/src/numberfield/index.ts +5 -0
  124. package/src/overlays/createOverlayTriggerState.d.ts +32 -0
  125. package/src/overlays/createOverlayTriggerState.d.ts.map +1 -0
  126. package/src/overlays/createOverlayTriggerState.ts +67 -0
  127. package/src/overlays/index.d.ts +2 -0
  128. package/src/overlays/index.d.ts.map +1 -0
  129. package/src/overlays/index.ts +5 -0
  130. package/src/radio/createRadioGroupState.d.ts +77 -0
  131. package/src/radio/createRadioGroupState.d.ts.map +1 -0
  132. package/src/radio/createRadioGroupState.ts +201 -0
  133. package/src/radio/index.d.ts +2 -0
  134. package/src/radio/index.d.ts.map +1 -0
  135. package/src/radio/index.ts +6 -0
  136. package/src/searchfield/createSearchFieldState.d.ts +25 -0
  137. package/src/searchfield/createSearchFieldState.d.ts.map +1 -0
  138. package/src/searchfield/createSearchFieldState.ts +62 -0
  139. package/src/searchfield/index.d.ts +3 -0
  140. package/src/searchfield/index.d.ts.map +1 -0
  141. package/src/searchfield/index.ts +5 -0
  142. package/src/select/createSelectState.d.ts +73 -0
  143. package/src/select/createSelectState.d.ts.map +1 -0
  144. package/src/select/createSelectState.ts +181 -0
  145. package/src/select/index.d.ts +2 -0
  146. package/src/select/index.d.ts.map +1 -0
  147. package/src/select/index.ts +5 -0
  148. package/src/slider/createSliderState.d.ts +72 -0
  149. package/src/slider/createSliderState.d.ts.map +1 -0
  150. package/src/slider/createSliderState.ts +211 -0
  151. package/src/slider/index.d.ts +3 -0
  152. package/src/slider/index.d.ts.map +1 -0
  153. package/src/slider/index.ts +6 -0
  154. package/src/ssr/index.d.ts +28 -0
  155. package/src/ssr/index.d.ts.map +1 -0
  156. package/src/ssr/index.ts +41 -0
  157. package/src/table/TableCollection.d.ts +52 -0
  158. package/src/table/TableCollection.d.ts.map +1 -0
  159. package/src/table/TableCollection.ts +388 -0
  160. package/src/table/createTableState.d.ts +12 -0
  161. package/src/table/createTableState.d.ts.map +1 -0
  162. package/src/table/createTableState.ts +127 -0
  163. package/src/table/index.d.ts +8 -0
  164. package/src/table/index.d.ts.map +1 -0
  165. package/src/table/index.ts +18 -0
  166. package/src/table/types.d.ts +139 -0
  167. package/src/table/types.d.ts.map +1 -0
  168. package/src/table/types.ts +150 -0
  169. package/src/tabs/createTabListState.d.ts +68 -0
  170. package/src/tabs/createTabListState.d.ts.map +1 -0
  171. package/src/tabs/createTabListState.ts +240 -0
  172. package/src/tabs/index.d.ts +2 -0
  173. package/src/tabs/index.d.ts.map +1 -0
  174. package/src/tabs/index.ts +7 -0
  175. package/src/textfield/createTextFieldState.d.ts +30 -0
  176. package/src/textfield/createTextFieldState.d.ts.map +1 -0
  177. package/src/textfield/createTextFieldState.ts +75 -0
  178. package/src/textfield/index.d.ts +2 -0
  179. package/src/textfield/index.d.ts.map +1 -0
  180. package/src/textfield/index.ts +5 -0
  181. package/src/toast/createToastState.d.ts +118 -0
  182. package/src/toast/createToastState.d.ts.map +1 -0
  183. package/src/toast/createToastState.ts +316 -0
  184. package/src/toast/index.d.ts +2 -0
  185. package/src/toast/index.d.ts.map +1 -0
  186. package/src/toast/index.ts +11 -0
  187. package/src/toggle/createToggleState.d.ts +34 -0
  188. package/src/toggle/createToggleState.d.ts.map +1 -0
  189. package/src/toggle/createToggleState.ts +94 -0
  190. package/src/toggle/index.d.ts +2 -0
  191. package/src/toggle/index.d.ts.map +1 -0
  192. package/src/toggle/index.ts +5 -0
  193. package/src/tooltip/createTooltipTriggerState.d.ts +39 -0
  194. package/src/tooltip/createTooltipTriggerState.d.ts.map +1 -0
  195. package/src/tooltip/createTooltipTriggerState.ts +183 -0
  196. package/src/tooltip/index.d.ts +2 -0
  197. package/src/tooltip/index.d.ts.map +1 -0
  198. package/src/tooltip/index.ts +6 -0
  199. package/src/tree/TreeCollection.d.ts +40 -0
  200. package/src/tree/TreeCollection.d.ts.map +1 -0
  201. package/src/tree/TreeCollection.ts +175 -0
  202. package/src/tree/createTreeState.d.ts +14 -0
  203. package/src/tree/createTreeState.d.ts.map +1 -0
  204. package/src/tree/createTreeState.ts +392 -0
  205. package/src/tree/index.d.ts +7 -0
  206. package/src/tree/index.d.ts.map +1 -0
  207. package/src/tree/index.ts +13 -0
  208. package/src/tree/types.d.ts +157 -0
  209. package/src/tree/types.d.ts.map +1 -0
  210. package/src/tree/types.ts +174 -0
  211. package/src/utils/index.d.ts +2 -0
  212. package/src/utils/index.d.ts.map +1 -0
  213. package/src/utils/index.ts +1 -0
  214. package/src/utils/reactivity.d.ts +28 -0
  215. package/src/utils/reactivity.d.ts.map +1 -0
  216. package/src/utils/reactivity.ts +36 -0
@@ -0,0 +1,483 @@
1
+ /**
2
+ * TimeFieldState for Solid-Stately
3
+ *
4
+ * Provides state management for time field components with segment-based editing.
5
+ * Based on @react-stately/datepicker useTimeFieldState
6
+ */
7
+
8
+ import { createSignal, createMemo, type Accessor } from 'solid-js';
9
+ import {
10
+ type Time,
11
+ type CalendarDateTime,
12
+ type ZonedDateTime,
13
+ getLocalTimeZone,
14
+ DateFormatter,
15
+ } from '@internationalized/date';
16
+ import { access, type MaybeAccessor } from '../utils';
17
+ import type { ValidationState } from './createCalendarState';
18
+
19
+ // ============================================
20
+ // TYPES
21
+ // ============================================
22
+
23
+ export type TimeValue = Time | CalendarDateTime | ZonedDateTime;
24
+
25
+ export type TimeSegmentType =
26
+ | 'hour'
27
+ | 'minute'
28
+ | 'second'
29
+ | 'dayPeriod'
30
+ | 'literal';
31
+
32
+ export interface TimeSegment {
33
+ /** The type of segment. */
34
+ type: TimeSegmentType;
35
+ /** The text content of the segment. */
36
+ text: string;
37
+ /** The numeric value of the segment (if applicable). */
38
+ value?: number;
39
+ /** The minimum value for the segment. */
40
+ minValue?: number;
41
+ /** The maximum value for the segment. */
42
+ maxValue?: number;
43
+ /** Whether this segment is editable. */
44
+ isEditable: boolean;
45
+ /** Whether this segment is a placeholder. */
46
+ isPlaceholder: boolean;
47
+ /** A placeholder string for the segment. */
48
+ placeholder: string;
49
+ }
50
+
51
+ export interface TimeFieldStateProps<T extends TimeValue = Time> {
52
+ /** The current value (controlled). */
53
+ value?: MaybeAccessor<T | null>;
54
+ /** The default value (uncontrolled). */
55
+ defaultValue?: T | null;
56
+ /** Handler called when the value changes. */
57
+ onChange?: (value: T | null) => void;
58
+ /** The minimum allowed time. */
59
+ minValue?: MaybeAccessor<TimeValue | undefined>;
60
+ /** The maximum allowed time. */
61
+ maxValue?: MaybeAccessor<TimeValue | undefined>;
62
+ /** Whether the field is disabled. */
63
+ isDisabled?: MaybeAccessor<boolean>;
64
+ /** Whether the field is read-only. */
65
+ isReadOnly?: MaybeAccessor<boolean>;
66
+ /** Whether the field is required. */
67
+ isRequired?: MaybeAccessor<boolean>;
68
+ /** The locale to use for formatting. */
69
+ locale?: string;
70
+ /** The granularity (hour, minute, second). */
71
+ granularity?: 'hour' | 'minute' | 'second';
72
+ /** Whether to show 12 or 24 hour format. */
73
+ hourCycle?: 12 | 24;
74
+ /** Validation state. */
75
+ validationState?: MaybeAccessor<ValidationState | undefined>;
76
+ /** The placeholder value. */
77
+ placeholderValue?: T;
78
+ }
79
+
80
+ export interface TimeFieldState<T extends TimeValue = Time> {
81
+ /** The current value. */
82
+ value: Accessor<T | null>;
83
+ /** Sets the value. */
84
+ setValue: (value: T | null) => void;
85
+ /** The segments that make up the time. */
86
+ segments: Accessor<TimeSegment[]>;
87
+ /** Sets a segment value. */
88
+ setSegment: (type: TimeSegmentType, value: number) => void;
89
+ /** Increments a segment. */
90
+ incrementSegment: (type: TimeSegmentType) => void;
91
+ /** Decrements a segment. */
92
+ decrementSegment: (type: TimeSegmentType) => void;
93
+ /** Clears a segment. */
94
+ clearSegment: (type: TimeSegmentType) => void;
95
+ /** Whether the field is disabled. */
96
+ isDisabled: Accessor<boolean>;
97
+ /** Whether the field is read-only. */
98
+ isReadOnly: Accessor<boolean>;
99
+ /** Whether the field is required. */
100
+ isRequired: Accessor<boolean>;
101
+ /** The validation state. */
102
+ validationState: Accessor<ValidationState | undefined>;
103
+ /** The granularity. */
104
+ granularity: 'hour' | 'minute' | 'second';
105
+ /** Whether the value is invalid. */
106
+ isInvalid: Accessor<boolean>;
107
+ /** The locale. */
108
+ locale: string;
109
+ /** The hour cycle. */
110
+ hourCycle: 12 | 24;
111
+ }
112
+
113
+ // ============================================
114
+ // IMPLEMENTATION
115
+ // ============================================
116
+
117
+ /**
118
+ * Provides state management for a time field component.
119
+ */
120
+ export function createTimeFieldState<T extends TimeValue = Time>(
121
+ props: TimeFieldStateProps<T> = {}
122
+ ): TimeFieldState<T> {
123
+ const timeZone = getLocalTimeZone();
124
+ const locale = props.locale ?? 'en-US';
125
+ const granularity = props.granularity ?? 'minute';
126
+ const hourCycle = props.hourCycle ?? 12;
127
+
128
+ // State signals
129
+ const [internalValue, setInternalValue] = createSignal<T | null>(
130
+ props.defaultValue ?? null
131
+ );
132
+
133
+ // Track partial values during editing
134
+ const [placeholderParts, setPlaceholderParts] = createSignal<Partial<TimeParts>>({});
135
+
136
+ // Controlled vs uncontrolled value
137
+ const value = createMemo<T | null>(() => {
138
+ const controlled = access(props.value);
139
+ return controlled !== undefined ? controlled : internalValue();
140
+ });
141
+
142
+ // Derived states
143
+ const isDisabled = createMemo(() => access(props.isDisabled) ?? false);
144
+ const isReadOnly = createMemo(() => access(props.isReadOnly) ?? false);
145
+ const isRequired = createMemo(() => access(props.isRequired) ?? false);
146
+ const validationState = createMemo(() => access(props.validationState));
147
+
148
+ // Check if value is invalid
149
+ const isInvalid = createMemo(() => {
150
+ const v = value();
151
+ if (!v) return false;
152
+
153
+ const minValue = access(props.minValue);
154
+ const maxValue = access(props.maxValue);
155
+
156
+ if (minValue && compareTime(v, minValue) < 0) return true;
157
+ if (maxValue && compareTime(v, maxValue) > 0) return true;
158
+
159
+ return validationState() === 'invalid';
160
+ });
161
+
162
+ // Generate segments based on granularity
163
+ const segments = createMemo<TimeSegment[]>(() => {
164
+ const v = value();
165
+ const parts = placeholderParts();
166
+ const segs: TimeSegment[] = [];
167
+
168
+ // Determine format options
169
+ const formatOptions: Intl.DateTimeFormatOptions = {
170
+ hour: '2-digit',
171
+ minute: '2-digit',
172
+ hourCycle: hourCycle === 12 ? 'h12' : 'h23',
173
+ };
174
+
175
+ if (granularity === 'second') {
176
+ formatOptions.second = '2-digit';
177
+ }
178
+
179
+ // Use a base date for formatting
180
+ const baseDate = new Date();
181
+ if (v) {
182
+ baseDate.setHours(getHour(v), getMinute(v), getSecond(v));
183
+ }
184
+
185
+ const formatter = new DateFormatter(locale, formatOptions);
186
+ const formattedParts = formatter.formatToParts(baseDate);
187
+
188
+ for (const part of formattedParts) {
189
+ const type = mapTimePartType(part.type);
190
+
191
+ if (type === 'literal') {
192
+ segs.push({
193
+ type: 'literal',
194
+ text: part.value,
195
+ isEditable: false,
196
+ isPlaceholder: false,
197
+ placeholder: part.value,
198
+ });
199
+ } else if (type) {
200
+ const segValue = getTimeSegmentValue(v, type);
201
+ const partValue = parts[type as keyof TimeParts];
202
+ const hasValue = v !== null || partValue !== undefined;
203
+
204
+ segs.push({
205
+ type,
206
+ text: hasValue ? part.value : getTimePlaceholderText(type),
207
+ value: segValue ?? partValue,
208
+ minValue: getTimeMinValue(type, hourCycle),
209
+ maxValue: getTimeMaxValue(type, hourCycle),
210
+ isEditable: !isDisabled() && !isReadOnly(),
211
+ isPlaceholder: !hasValue,
212
+ placeholder: getTimePlaceholderText(type),
213
+ });
214
+ }
215
+ }
216
+
217
+ return segs;
218
+ });
219
+
220
+ // Set value with onChange callback
221
+ const setValue = (newValue: T | null) => {
222
+ if (isDisabled() || isReadOnly()) return;
223
+
224
+ const controlled = access(props.value);
225
+ if (controlled === undefined) {
226
+ setInternalValue(() => newValue);
227
+ }
228
+
229
+ if (props.onChange) {
230
+ props.onChange(newValue);
231
+ }
232
+
233
+ setPlaceholderParts({});
234
+ };
235
+
236
+ // Set a specific segment value
237
+ const setSegment = (type: TimeSegmentType, newValue: number) => {
238
+ if (isDisabled() || isReadOnly()) return;
239
+ if (type === 'literal') return;
240
+
241
+ const v = value();
242
+
243
+ if (v) {
244
+ const updated = updateTimePart(v, type, newValue, hourCycle);
245
+ setValue(updated as T);
246
+ } else {
247
+ setPlaceholderParts((prev) => ({
248
+ ...prev,
249
+ [type]: newValue,
250
+ }));
251
+ }
252
+ };
253
+
254
+ // Increment a segment
255
+ const incrementSegment = (type: TimeSegmentType) => {
256
+ if (isDisabled() || isReadOnly()) return;
257
+ if (type === 'literal') return;
258
+
259
+ const v = value();
260
+ const current = v
261
+ ? getTimeSegmentValue(v, type)
262
+ : placeholderParts()[type as keyof TimeParts];
263
+ const max = getTimeMaxValue(type, hourCycle);
264
+ const min = getTimeMinValue(type, hourCycle);
265
+
266
+ if (type === 'dayPeriod') {
267
+ // Toggle AM/PM
268
+ const currentHour = v ? getHour(v) : (placeholderParts().hour ?? 0);
269
+ const newHour = currentHour >= 12 ? currentHour - 12 : currentHour + 12;
270
+ setSegment('hour', newHour);
271
+ return;
272
+ }
273
+
274
+ const newValue = current !== undefined ? current + 1 : min;
275
+ setSegment(type, newValue > max ? min : newValue);
276
+ };
277
+
278
+ // Decrement a segment
279
+ const decrementSegment = (type: TimeSegmentType) => {
280
+ if (isDisabled() || isReadOnly()) return;
281
+ if (type === 'literal') return;
282
+
283
+ const v = value();
284
+ const current = v
285
+ ? getTimeSegmentValue(v, type)
286
+ : placeholderParts()[type as keyof TimeParts];
287
+ const max = getTimeMaxValue(type, hourCycle);
288
+ const min = getTimeMinValue(type, hourCycle);
289
+
290
+ if (type === 'dayPeriod') {
291
+ // Toggle AM/PM
292
+ const currentHour = v ? getHour(v) : (placeholderParts().hour ?? 0);
293
+ const newHour = currentHour >= 12 ? currentHour - 12 : currentHour + 12;
294
+ setSegment('hour', newHour);
295
+ return;
296
+ }
297
+
298
+ const newValue = current !== undefined ? current - 1 : max;
299
+ setSegment(type, newValue < min ? max : newValue);
300
+ };
301
+
302
+ // Clear a segment
303
+ const clearSegment = (type: TimeSegmentType) => {
304
+ if (isDisabled() || isReadOnly()) return;
305
+
306
+ const v = value();
307
+ if (v) {
308
+ setValue(null);
309
+ } else {
310
+ setPlaceholderParts((prev) => {
311
+ const next = { ...prev };
312
+ delete next[type as keyof TimeParts];
313
+ return next;
314
+ });
315
+ }
316
+ };
317
+
318
+ return {
319
+ value,
320
+ setValue,
321
+ segments,
322
+ setSegment,
323
+ incrementSegment,
324
+ decrementSegment,
325
+ clearSegment,
326
+ isDisabled,
327
+ isReadOnly,
328
+ isRequired,
329
+ validationState,
330
+ granularity,
331
+ isInvalid,
332
+ locale,
333
+ hourCycle,
334
+ };
335
+ }
336
+
337
+ // ============================================
338
+ // HELPER TYPES & FUNCTIONS
339
+ // ============================================
340
+
341
+ interface TimeParts {
342
+ hour?: number;
343
+ minute?: number;
344
+ second?: number;
345
+ }
346
+
347
+ function mapTimePartType(type: Intl.DateTimeFormatPartTypes): TimeSegmentType | null {
348
+ switch (type) {
349
+ case 'hour':
350
+ return 'hour';
351
+ case 'minute':
352
+ return 'minute';
353
+ case 'second':
354
+ return 'second';
355
+ case 'dayPeriod':
356
+ return 'dayPeriod';
357
+ case 'literal':
358
+ return 'literal';
359
+ default:
360
+ return null;
361
+ }
362
+ }
363
+
364
+ function getHour(time: TimeValue): number {
365
+ if ('hour' in time) {
366
+ return time.hour;
367
+ }
368
+ return 0;
369
+ }
370
+
371
+ function getMinute(time: TimeValue): number {
372
+ if ('minute' in time) {
373
+ return time.minute;
374
+ }
375
+ return 0;
376
+ }
377
+
378
+ function getSecond(time: TimeValue): number {
379
+ if ('second' in time) {
380
+ return time.second;
381
+ }
382
+ return 0;
383
+ }
384
+
385
+ function getTimeSegmentValue(
386
+ time: TimeValue | null,
387
+ type: TimeSegmentType
388
+ ): number | undefined {
389
+ if (!time) return undefined;
390
+
391
+ switch (type) {
392
+ case 'hour':
393
+ return getHour(time);
394
+ case 'minute':
395
+ return getMinute(time);
396
+ case 'second':
397
+ return getSecond(time);
398
+ case 'dayPeriod':
399
+ return getHour(time) >= 12 ? 1 : 0;
400
+ default:
401
+ return undefined;
402
+ }
403
+ }
404
+
405
+ function getTimeMinValue(type: TimeSegmentType, hourCycle: number): number {
406
+ switch (type) {
407
+ case 'hour':
408
+ return hourCycle === 12 ? 1 : 0;
409
+ case 'minute':
410
+ return 0;
411
+ case 'second':
412
+ return 0;
413
+ case 'dayPeriod':
414
+ return 0;
415
+ default:
416
+ return 0;
417
+ }
418
+ }
419
+
420
+ function getTimeMaxValue(type: TimeSegmentType, hourCycle: number): number {
421
+ switch (type) {
422
+ case 'hour':
423
+ return hourCycle === 12 ? 12 : 23;
424
+ case 'minute':
425
+ return 59;
426
+ case 'second':
427
+ return 59;
428
+ case 'dayPeriod':
429
+ return 1;
430
+ default:
431
+ return 0;
432
+ }
433
+ }
434
+
435
+ function getTimePlaceholderText(type: TimeSegmentType): string {
436
+ switch (type) {
437
+ case 'hour':
438
+ return '––';
439
+ case 'minute':
440
+ return '––';
441
+ case 'second':
442
+ return '––';
443
+ case 'dayPeriod':
444
+ return 'AM';
445
+ default:
446
+ return '';
447
+ }
448
+ }
449
+
450
+ function updateTimePart(
451
+ time: TimeValue,
452
+ type: TimeSegmentType,
453
+ value: number,
454
+ hourCycle: number
455
+ ): TimeValue {
456
+ if ('set' in time) {
457
+ switch (type) {
458
+ case 'hour':
459
+ return time.set({ hour: value });
460
+ case 'minute':
461
+ return time.set({ minute: value });
462
+ case 'second':
463
+ return time.set({ second: value });
464
+ default:
465
+ return time;
466
+ }
467
+ }
468
+ return time;
469
+ }
470
+
471
+ function compareTime(a: TimeValue, b: TimeValue): number {
472
+ const aHour = getHour(a);
473
+ const bHour = getHour(b);
474
+ if (aHour !== bHour) return aHour - bHour;
475
+
476
+ const aMinute = getMinute(a);
477
+ const bMinute = getMinute(b);
478
+ if (aMinute !== bMinute) return aMinute - bMinute;
479
+
480
+ const aSecond = getSecond(a);
481
+ const bSecond = getSecond(b);
482
+ return aSecond - bSecond;
483
+ }
@@ -0,0 +1,7 @@
1
+ export { createCalendarState, type CalendarStateProps, type CalendarState, type ValidationState, } from './createCalendarState';
2
+ export { createRangeCalendarState, type RangeCalendarStateProps, type RangeCalendarState, type DateRange, type RangeValue, } from './createRangeCalendarState';
3
+ export { createDateFieldState, type DateFieldStateProps, type DateFieldState, type DateSegment, type DateSegmentType, } from './createDateFieldState';
4
+ export { createTimeFieldState, type TimeFieldStateProps, type TimeFieldState, type TimeSegment, type TimeSegmentType, type TimeValue, } from './createTimeFieldState';
5
+ export type { CalendarDate, CalendarDateTime, ZonedDateTime, DateValue, Time, } from '@internationalized/date';
6
+ export { today, now, getLocalTimeZone, parseDate, parseDateTime, parseTime, parseAbsolute, parseAbsoluteToLocal, parseZonedDateTime, toCalendarDate, toCalendarDateTime, toZoned, toTime, CalendarDate as CalendarDateClass, CalendarDateTime as CalendarDateTimeClass, ZonedDateTime as ZonedDateTimeClass, Time as TimeClass, DateFormatter, isSameDay, isSameMonth, isSameYear, isToday, isWeekend, startOfMonth, endOfMonth, startOfWeek, endOfWeek, startOfYear, endOfYear, getWeeksInMonth, getDayOfWeek, minDate, maxDate, } from '@internationalized/date';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,SAAS,EACd,KAAK,UAAU,GAChB,MAAM,4BAA4B,CAAC;AAGpC,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,GACrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,SAAS,GACf,MAAM,wBAAwB,CAAC;AAGhC,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,IAAI,GACL,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EACL,KAAK,EACL,GAAG,EACH,gBAAgB,EAChB,SAAS,EACT,aAAa,EACb,SAAS,EACT,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,OAAO,EACP,MAAM,EACN,YAAY,IAAI,iBAAiB,EACjC,gBAAgB,IAAI,qBAAqB,EACzC,aAAa,IAAI,kBAAkB,EACnC,IAAI,IAAI,SAAS,EACjB,aAAa,EACb,SAAS,EACT,WAAW,EACX,UAAU,EACV,OAAO,EACP,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,eAAe,EACf,YAAY,EACZ,OAAO,EACP,OAAO,GACR,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,81 @@
1
+ // Calendar State
2
+ export {
3
+ createCalendarState,
4
+ type CalendarStateProps,
5
+ type CalendarState,
6
+ type ValidationState,
7
+ } from './createCalendarState';
8
+
9
+ // Range Calendar State
10
+ export {
11
+ createRangeCalendarState,
12
+ type RangeCalendarStateProps,
13
+ type RangeCalendarState,
14
+ type DateRange,
15
+ type RangeValue,
16
+ } from './createRangeCalendarState';
17
+
18
+ // Date Field State
19
+ export {
20
+ createDateFieldState,
21
+ type DateFieldStateProps,
22
+ type DateFieldState,
23
+ type DateSegment,
24
+ type DateSegmentType,
25
+ } from './createDateFieldState';
26
+
27
+ // Time Field State
28
+ export {
29
+ createTimeFieldState,
30
+ type TimeFieldStateProps,
31
+ type TimeFieldState,
32
+ type TimeSegment,
33
+ type TimeSegmentType,
34
+ type TimeValue,
35
+ } from './createTimeFieldState';
36
+
37
+ // Re-export date types from @internationalized/date
38
+ export type {
39
+ CalendarDate,
40
+ CalendarDateTime,
41
+ ZonedDateTime,
42
+ DateValue,
43
+ Time,
44
+ } from '@internationalized/date';
45
+
46
+ // Re-export commonly used date utilities
47
+ export {
48
+ today,
49
+ now,
50
+ getLocalTimeZone,
51
+ parseDate,
52
+ parseDateTime,
53
+ parseTime,
54
+ parseAbsolute,
55
+ parseAbsoluteToLocal,
56
+ parseZonedDateTime,
57
+ toCalendarDate,
58
+ toCalendarDateTime,
59
+ toZoned,
60
+ toTime,
61
+ CalendarDate as CalendarDateClass,
62
+ CalendarDateTime as CalendarDateTimeClass,
63
+ ZonedDateTime as ZonedDateTimeClass,
64
+ Time as TimeClass,
65
+ DateFormatter,
66
+ isSameDay,
67
+ isSameMonth,
68
+ isSameYear,
69
+ isToday,
70
+ isWeekend,
71
+ startOfMonth,
72
+ endOfMonth,
73
+ startOfWeek,
74
+ endOfWeek,
75
+ startOfYear,
76
+ endOfYear,
77
+ getWeeksInMonth,
78
+ getDayOfWeek,
79
+ minDate,
80
+ maxDate,
81
+ } from '@internationalized/date';
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Checkbox group state for Solid Stately
3
+ *
4
+ * Provides state management for a checkbox group component.
5
+ * Provides a name for the group, and manages selection and focus state.
6
+ *
7
+ * This is a 1:1 port of @react-stately/checkbox's useCheckboxGroupState.
8
+ */
9
+ import { Accessor } from 'solid-js';
10
+ import { type MaybeAccessor } from '../utils';
11
+ export interface CheckboxGroupProps {
12
+ /** The current selected values (controlled). */
13
+ value?: string[];
14
+ /** The default selected values (uncontrolled). */
15
+ defaultValue?: string[];
16
+ /** Handler that is called when the value changes. */
17
+ onChange?: (value: string[]) => void;
18
+ /** Whether the checkbox group is disabled. */
19
+ isDisabled?: boolean;
20
+ /** Whether the checkbox group is read only. */
21
+ isReadOnly?: boolean;
22
+ /** Whether the checkbox group is required. */
23
+ isRequired?: boolean;
24
+ /** Whether the checkbox group is invalid. */
25
+ isInvalid?: boolean;
26
+ /** The name of the checkbox group, used when submitting an HTML form. */
27
+ name?: string;
28
+ /** The form to associate the checkbox group with. */
29
+ form?: string;
30
+ /** The label for the checkbox group. */
31
+ label?: string;
32
+ /** Handler that is called when the checkbox group receives focus. */
33
+ onFocus?: (e: FocusEvent) => void;
34
+ /** Handler that is called when the checkbox group loses focus. */
35
+ onBlur?: (e: FocusEvent) => void;
36
+ /** Handler that is called when the checkbox group's focus status changes. */
37
+ onFocusChange?: (isFocused: boolean) => void;
38
+ }
39
+ export interface CheckboxGroupState {
40
+ /** Current selected values. */
41
+ readonly value: Accessor<readonly string[]>;
42
+ /** Default selected values. */
43
+ readonly defaultValue: readonly string[];
44
+ /** Whether the checkbox group is disabled. */
45
+ readonly isDisabled: boolean;
46
+ /** Whether the checkbox group is read only. */
47
+ readonly isReadOnly: boolean;
48
+ /** Whether the checkbox group is invalid. */
49
+ readonly isInvalid: boolean;
50
+ /**
51
+ * Whether the checkboxes in the group are required.
52
+ * This changes to false once at least one item is selected.
53
+ */
54
+ readonly isRequired: Accessor<boolean>;
55
+ /** Returns whether the given value is selected. */
56
+ isSelected(value: string): boolean;
57
+ /** Sets the selected values. */
58
+ setValue(value: string[]): void;
59
+ /** Adds a value to the set of selected values. */
60
+ addValue(value: string): void;
61
+ /** Removes a value from the set of selected values. */
62
+ removeValue(value: string): void;
63
+ /** Toggles a value in the set of selected values. */
64
+ toggleValue(value: string): void;
65
+ }
66
+ /**
67
+ * Provides state management for a checkbox group component.
68
+ * Provides a name for the group, and manages selection and focus state.
69
+ */
70
+ export declare function createCheckboxGroupState(props?: MaybeAccessor<CheckboxGroupProps>): CheckboxGroupState;
71
+ //# sourceMappingURL=createCheckboxGroupState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createCheckboxGroupState.d.ts","sourceRoot":"","sources":["createCheckboxGroupState.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAgB,QAAQ,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,KAAK,aAAa,EAAU,MAAM,UAAU,CAAC;AAMtD,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACrC,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,6CAA6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAClC,kEAAkE;IAClE,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IACjC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,kBAAkB;IACjC,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IAC5C,+BAA+B;IAC/B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,8CAA8C;IAC9C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,+CAA+C;IAC/C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;IACvC,mDAAmD;IACnD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChC,kDAAkD;IAClD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uDAAuD;IACvD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,qDAAqD;IACrD,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAClC;AAMD;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,KAAK,GAAE,aAAa,CAAC,kBAAkB,CAAM,GAC5C,kBAAkB,CA6GpB"}