@proyecto-viviana/solidaria-components 0.2.5 → 0.3.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 (225) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +39 -272
  3. package/dist/ActionBar.d.ts +79 -0
  4. package/dist/ActionBar.d.ts.map +1 -0
  5. package/dist/ActionGroup.d.ts +74 -0
  6. package/dist/ActionGroup.d.ts.map +1 -0
  7. package/dist/Alert.d.ts +70 -0
  8. package/dist/Alert.d.ts.map +1 -0
  9. package/dist/Autocomplete.d.ts +5 -5
  10. package/dist/Autocomplete.d.ts.map +1 -1
  11. package/dist/Breadcrumbs.d.ts +27 -8
  12. package/dist/Breadcrumbs.d.ts.map +1 -1
  13. package/dist/Button.d.ts +28 -5
  14. package/dist/Button.d.ts.map +1 -1
  15. package/dist/Calendar.d.ts +51 -7
  16. package/dist/Calendar.d.ts.map +1 -1
  17. package/dist/Checkbox.d.ts +33 -8
  18. package/dist/Checkbox.d.ts.map +1 -1
  19. package/dist/Collection.d.ts +130 -0
  20. package/dist/Collection.d.ts.map +1 -0
  21. package/dist/Color.d.ts +210 -9
  22. package/dist/Color.d.ts.map +1 -1
  23. package/dist/ColorEditor.d.ts +42 -0
  24. package/dist/ColorEditor.d.ts.map +1 -0
  25. package/dist/ComboBox.d.ts +146 -16
  26. package/dist/ComboBox.d.ts.map +1 -1
  27. package/dist/ContextualHelpTrigger.d.ts +40 -0
  28. package/dist/ContextualHelpTrigger.d.ts.map +1 -0
  29. package/dist/DateField.d.ts +35 -8
  30. package/dist/DateField.d.ts.map +1 -1
  31. package/dist/DatePicker.d.ts +101 -5
  32. package/dist/DatePicker.d.ts.map +1 -1
  33. package/dist/DateRangePickerContext.d.ts +30 -0
  34. package/dist/DateRangePickerContext.d.ts.map +1 -0
  35. package/dist/Dialog.d.ts +5 -5
  36. package/dist/Dialog.d.ts.map +1 -1
  37. package/dist/Disclosure.d.ts +25 -5
  38. package/dist/Disclosure.d.ts.map +1 -1
  39. package/dist/DragAndDrop.d.ts +80 -0
  40. package/dist/DragAndDrop.d.ts.map +1 -0
  41. package/dist/DragPreview.d.ts +14 -0
  42. package/dist/DragPreview.d.ts.map +1 -0
  43. package/dist/DropZone.d.ts +27 -0
  44. package/dist/DropZone.d.ts.map +1 -0
  45. package/dist/FieldError.d.ts +27 -0
  46. package/dist/FieldError.d.ts.map +1 -0
  47. package/dist/FileTrigger.d.ts +26 -0
  48. package/dist/FileTrigger.d.ts.map +1 -0
  49. package/dist/Focusable.d.ts +27 -0
  50. package/dist/Focusable.d.ts.map +1 -0
  51. package/dist/Form.d.ts +41 -0
  52. package/dist/Form.d.ts.map +1 -0
  53. package/dist/GridList.d.ts +69 -10
  54. package/dist/GridList.d.ts.map +1 -1
  55. package/dist/HiddenDateInput.d.ts +26 -0
  56. package/dist/HiddenDateInput.d.ts.map +1 -0
  57. package/dist/HiddenTimeInput.d.ts +25 -0
  58. package/dist/HiddenTimeInput.d.ts.map +1 -0
  59. package/dist/Icon.d.ts +57 -0
  60. package/dist/Icon.d.ts.map +1 -0
  61. package/dist/Keyboard.d.ts +13 -0
  62. package/dist/Keyboard.d.ts.map +1 -0
  63. package/dist/Landmark.d.ts +3 -3
  64. package/dist/Landmark.d.ts.map +1 -1
  65. package/dist/Link.d.ts +10 -4
  66. package/dist/Link.d.ts.map +1 -1
  67. package/dist/ListBox.d.ts +73 -11
  68. package/dist/ListBox.d.ts.map +1 -1
  69. package/dist/ListDropTargetDelegate.d.ts +38 -0
  70. package/dist/ListDropTargetDelegate.d.ts.map +1 -0
  71. package/dist/Menu.d.ts +79 -10
  72. package/dist/Menu.d.ts.map +1 -1
  73. package/dist/Meter.d.ts +4 -4
  74. package/dist/Meter.d.ts.map +1 -1
  75. package/dist/Modal.d.ts +6 -4
  76. package/dist/Modal.d.ts.map +1 -1
  77. package/dist/NumberField.d.ts +10 -12
  78. package/dist/NumberField.d.ts.map +1 -1
  79. package/dist/Popover.d.ts +32 -7
  80. package/dist/Popover.d.ts.map +1 -1
  81. package/dist/Pressable.d.ts +27 -0
  82. package/dist/Pressable.d.ts.map +1 -0
  83. package/dist/ProgressBar.d.ts +6 -4
  84. package/dist/ProgressBar.d.ts.map +1 -1
  85. package/dist/RadioGroup.d.ts +43 -9
  86. package/dist/RadioGroup.d.ts.map +1 -1
  87. package/dist/RangeCalendar.d.ts +39 -7
  88. package/dist/RangeCalendar.d.ts.map +1 -1
  89. package/dist/RouterProvider.d.ts +75 -0
  90. package/dist/RouterProvider.d.ts.map +1 -0
  91. package/dist/SearchField.d.ts +23 -21
  92. package/dist/SearchField.d.ts.map +1 -1
  93. package/dist/Select.d.ts +48 -7
  94. package/dist/Select.d.ts.map +1 -1
  95. package/dist/SelectionIndicator.d.ts +30 -0
  96. package/dist/SelectionIndicator.d.ts.map +1 -0
  97. package/dist/Separator.d.ts +9 -3
  98. package/dist/Separator.d.ts.map +1 -1
  99. package/dist/SharedElementTransition.d.ts +41 -0
  100. package/dist/SharedElementTransition.d.ts.map +1 -0
  101. package/dist/Slider.d.ts +15 -8
  102. package/dist/Slider.d.ts.map +1 -1
  103. package/dist/StepList.d.ts +90 -0
  104. package/dist/StepList.d.ts.map +1 -0
  105. package/dist/Switch.d.ts +11 -5
  106. package/dist/Switch.d.ts.map +1 -1
  107. package/dist/Table.d.ts +222 -19
  108. package/dist/Table.d.ts.map +1 -1
  109. package/dist/Tabs.d.ts +47 -10
  110. package/dist/Tabs.d.ts.map +1 -1
  111. package/dist/TagGroup.d.ts +22 -10
  112. package/dist/TagGroup.d.ts.map +1 -1
  113. package/dist/Text.d.ts +10 -0
  114. package/dist/Text.d.ts.map +1 -0
  115. package/dist/TextField.d.ts +19 -11
  116. package/dist/TextField.d.ts.map +1 -1
  117. package/dist/TimeField.d.ts +32 -7
  118. package/dist/TimeField.d.ts.map +1 -1
  119. package/dist/Toast.d.ts +29 -14
  120. package/dist/Toast.d.ts.map +1 -1
  121. package/dist/ToggleButton.d.ts +36 -0
  122. package/dist/ToggleButton.d.ts.map +1 -0
  123. package/dist/ToggleButtonGroup.d.ts +33 -0
  124. package/dist/ToggleButtonGroup.d.ts.map +1 -0
  125. package/dist/Toolbar.d.ts +7 -3
  126. package/dist/Toolbar.d.ts.map +1 -1
  127. package/dist/Tooltip.d.ts +58 -7
  128. package/dist/Tooltip.d.ts.map +1 -1
  129. package/dist/Tree.d.ts +102 -11
  130. package/dist/Tree.d.ts.map +1 -1
  131. package/dist/Virtualizer.d.ts +61 -0
  132. package/dist/Virtualizer.d.ts.map +1 -0
  133. package/dist/VirtualizerLayouts.d.ts +82 -0
  134. package/dist/VirtualizerLayouts.d.ts.map +1 -0
  135. package/dist/VisuallyHidden.d.ts +4 -2
  136. package/dist/VisuallyHidden.d.ts.map +1 -1
  137. package/dist/contexts.d.ts +6 -1
  138. package/dist/contexts.d.ts.map +1 -1
  139. package/dist/index.d.ts +73 -39
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +23342 -10644
  142. package/dist/index.js.map +1 -7
  143. package/dist/index.jsx +18110 -0
  144. package/dist/index.jsx.map +1 -0
  145. package/dist/useDragAndDrop.d.ts +93 -0
  146. package/dist/useDragAndDrop.d.ts.map +1 -0
  147. package/dist/utils.d.ts +8 -2
  148. package/dist/utils.d.ts.map +1 -1
  149. package/dist/virtualizer/Layout.d.ts +79 -0
  150. package/dist/virtualizer/Layout.d.ts.map +1 -0
  151. package/package.json +33 -32
  152. package/src/ActionBar.tsx +251 -0
  153. package/src/ActionGroup.tsx +277 -0
  154. package/src/Alert.tsx +152 -0
  155. package/src/Autocomplete.tsx +39 -44
  156. package/src/Breadcrumbs.tsx +227 -72
  157. package/src/Button.tsx +315 -74
  158. package/src/Calendar.tsx +347 -141
  159. package/src/Checkbox.tsx +414 -123
  160. package/src/Collection.tsx +350 -0
  161. package/src/Color.tsx +1325 -284
  162. package/src/ColorEditor.tsx +213 -0
  163. package/src/ComboBox.tsx +644 -245
  164. package/src/ContextualHelpTrigger.tsx +195 -0
  165. package/src/DateField.tsx +274 -106
  166. package/src/DatePicker.tsx +892 -111
  167. package/src/DateRangePickerContext.tsx +44 -0
  168. package/src/Dialog.tsx +173 -104
  169. package/src/Disclosure.tsx +158 -105
  170. package/src/DragAndDrop.tsx +340 -0
  171. package/src/DragPreview.tsx +47 -0
  172. package/src/DropZone.tsx +233 -0
  173. package/src/FieldError.tsx +89 -0
  174. package/src/FileTrigger.tsx +83 -0
  175. package/src/Focusable.tsx +103 -0
  176. package/src/Form.tsx +140 -0
  177. package/src/GridList.tsx +542 -128
  178. package/src/HiddenDateInput.tsx +153 -0
  179. package/src/HiddenTimeInput.tsx +133 -0
  180. package/src/Icon.tsx +133 -0
  181. package/src/Keyboard.tsx +26 -0
  182. package/src/Landmark.tsx +37 -63
  183. package/src/Link.tsx +132 -69
  184. package/src/ListBox.tsx +656 -106
  185. package/src/ListDropTargetDelegate.ts +283 -0
  186. package/src/Menu.tsx +1234 -132
  187. package/src/Meter.tsx +44 -58
  188. package/src/Modal.tsx +262 -166
  189. package/src/NumberField.tsx +267 -151
  190. package/src/Popover.tsx +452 -343
  191. package/src/Pressable.tsx +108 -0
  192. package/src/ProgressBar.tsx +54 -59
  193. package/src/RadioGroup.tsx +533 -121
  194. package/src/RangeCalendar.tsx +249 -150
  195. package/src/RouterProvider.tsx +223 -0
  196. package/src/SearchField.tsx +460 -133
  197. package/src/Select.tsx +804 -233
  198. package/src/SelectionIndicator.tsx +108 -0
  199. package/src/Separator.tsx +47 -49
  200. package/src/SharedElementTransition.tsx +264 -0
  201. package/src/Slider.tsx +148 -98
  202. package/src/StepList.tsx +272 -0
  203. package/src/Switch.tsx +93 -46
  204. package/src/Table.tsx +1551 -225
  205. package/src/Tabs.tsx +377 -123
  206. package/src/TagGroup.tsx +233 -135
  207. package/src/Text.tsx +18 -0
  208. package/src/TextField.tsx +413 -86
  209. package/src/TimeField.tsx +232 -222
  210. package/src/Toast.tsx +306 -160
  211. package/src/ToggleButton.tsx +169 -0
  212. package/src/ToggleButtonGroup.tsx +141 -0
  213. package/src/Toolbar.tsx +61 -70
  214. package/src/Tooltip.tsx +473 -116
  215. package/src/Tree.tsx +1514 -175
  216. package/src/Virtualizer.tsx +730 -0
  217. package/src/VirtualizerLayouts.ts +280 -0
  218. package/src/VisuallyHidden.tsx +32 -38
  219. package/src/contexts.ts +29 -36
  220. package/src/index.ts +972 -620
  221. package/src/useDragAndDrop.ts +367 -0
  222. package/src/utils.tsx +69 -50
  223. package/src/virtualizer/Layout.ts +192 -0
  224. package/dist/index.ssr.js +0 -9785
  225. package/dist/index.ssr.js.map +0 -7
package/src/DateField.tsx CHANGED
@@ -8,26 +8,29 @@
8
8
  import {
9
9
  type JSX,
10
10
  createContext,
11
+ createEffect,
11
12
  createMemo,
12
13
  createSignal,
14
+ onCleanup,
13
15
  splitProps,
14
16
  useContext,
15
17
  For,
16
18
  Show,
17
- } from 'solid-js';
19
+ } from "solid-js";
18
20
  import {
19
21
  createDateField,
20
22
  createDateSegment,
21
23
  type AriaDateFieldProps,
22
- } from '@proyecto-viviana/solidaria';
24
+ } from "@proyecto-viviana/solidaria";
23
25
  import {
24
26
  createDateFieldState,
27
+ access,
25
28
  type DateFieldState,
26
29
  type DateFieldStateProps,
27
30
  type DateSegment as DateSegmentType,
28
31
  type CalendarDate,
29
32
  type DateValue,
30
- } from '@proyecto-viviana/solid-stately';
33
+ } from "@proyecto-viviana/solid-stately";
31
34
  import {
32
35
  type RenderChildren,
33
36
  type ClassNameOrFunction,
@@ -36,11 +39,13 @@ import {
36
39
  useRenderProps,
37
40
  dataAttr,
38
41
  useIsHydrated,
39
- } from './utils';
40
-
41
- // ============================================
42
- // TYPES
43
- // ============================================
42
+ } from "./utils";
43
+ import { HiddenDateInput } from "./HiddenDateInput";
44
+ import { FormContext, type FormProps } from "./Form";
45
+ import {
46
+ DateRangePickerContext,
47
+ type DateRangePickerFieldContextValue,
48
+ } from "./DateRangePickerContext";
44
49
 
45
50
  export interface DateFieldRenderProps {
46
51
  /** Whether the field is disabled. */
@@ -54,8 +59,9 @@ export interface DateFieldRenderProps {
54
59
  }
55
60
 
56
61
  export interface DateFieldProps<T extends DateValue = DateValue>
57
- extends Omit<AriaDateFieldProps, 'id' | 'isDisabled' | 'isReadOnly' | 'isRequired'>,
58
- Omit<DateFieldStateProps<T>, 'locale'>,
62
+ extends
63
+ Omit<AriaDateFieldProps, "id" | "isDisabled" | "isReadOnly" | "isRequired">,
64
+ Omit<DateFieldStateProps<T>, "locale">,
59
65
  SlotProps {
60
66
  /** The children of the component. */
61
67
  children?: JSX.Element | ((segment: DateSegmentType) => JSX.Element);
@@ -81,6 +87,8 @@ export interface DateInputProps extends SlotProps {
81
87
  class?: ClassNameOrFunction<DateInputRenderProps>;
82
88
  /** The inline style for the element. */
83
89
  style?: StyleOrFunction<DateInputRenderProps>;
90
+ /** Handler called during the pointer down capture phase. */
91
+ onPointerDownCapture?: JSX.EventHandler<HTMLDivElement, PointerEvent>;
84
92
  }
85
93
 
86
94
  export interface DateSegmentRenderProps {
@@ -91,7 +99,7 @@ export interface DateSegmentRenderProps {
91
99
  /** Whether the segment is a placeholder. */
92
100
  isPlaceholder: boolean;
93
101
  /** The segment type. */
94
- type: DateSegmentType['type'];
102
+ type: DateSegmentType["type"];
95
103
  /** The text to display. */
96
104
  text: string;
97
105
  }
@@ -107,23 +115,92 @@ export interface DateSegmentProps extends SlotProps {
107
115
  style?: StyleOrFunction<DateSegmentRenderProps>;
108
116
  }
109
117
 
110
- // ============================================
111
- // CONTEXT
112
- // ============================================
118
+ export interface DateFieldContextValue {
119
+ state: DateFieldState<DateValue>;
120
+ aria: {
121
+ labelProps: Record<string, unknown>;
122
+ inputProps: Record<string, unknown>;
123
+ descriptionProps: Record<string, unknown>;
124
+ errorMessageProps: Record<string, unknown>;
125
+ };
126
+ }
127
+
128
+ export const DateFieldContext = createContext<DateFieldContextValue | null>(null);
129
+ export const DateFieldStateContext = createContext<DateFieldState<DateValue> | null>(null);
130
+
131
+ function withFormValidationBehavior<P extends object>(props: P, formContext: FormProps | null): P {
132
+ if (!formContext?.validationBehavior) {
133
+ return props;
134
+ }
135
+
136
+ return new Proxy(props, {
137
+ get(target, property, receiver) {
138
+ const localValue = Reflect.get(target, property, receiver);
139
+ if (property === "validationBehavior" && localValue === undefined) {
140
+ return formContext.validationBehavior;
141
+ }
113
142
 
114
- export const DateFieldContext = createContext<DateFieldState<DateValue> | null>(null);
143
+ return localValue;
144
+ },
145
+ has(target, property) {
146
+ return (
147
+ Reflect.has(target, property) ||
148
+ (property === "validationBehavior" && formContext.validationBehavior !== undefined)
149
+ );
150
+ },
151
+ ownKeys(target) {
152
+ const keys = new Set(Reflect.ownKeys(target));
153
+ if (formContext.validationBehavior !== undefined) {
154
+ keys.add("validationBehavior");
155
+ }
156
+
157
+ return Array.from(keys);
158
+ },
159
+ getOwnPropertyDescriptor(target, property) {
160
+ const descriptor = Reflect.getOwnPropertyDescriptor(target, property);
161
+ if (descriptor) {
162
+ return descriptor;
163
+ }
164
+
165
+ if (property === "validationBehavior" && formContext.validationBehavior !== undefined) {
166
+ return {
167
+ enumerable: true,
168
+ configurable: true,
169
+ get: () => formContext.validationBehavior,
170
+ };
171
+ }
172
+
173
+ return undefined;
174
+ },
175
+ });
176
+ }
115
177
 
116
- export function useDateFieldContext(): DateFieldState<DateValue> {
178
+ export function useDateFieldContext(): DateFieldContextValue {
117
179
  const context = useContext(DateFieldContext);
118
180
  if (!context) {
119
- throw new Error('DateField components must be used within a DateField');
181
+ throw new Error("DateField components must be used within a DateField");
120
182
  }
121
183
  return context;
122
184
  }
123
185
 
124
- // ============================================
125
- // DATE FIELD COMPONENT
126
- // ============================================
186
+ function useDateInputContext(
187
+ slot?: string,
188
+ ): DateFieldContextValue | DateRangePickerFieldContextValue {
189
+ const dateFieldContext = useContext(DateFieldContext);
190
+ if (dateFieldContext) {
191
+ return dateFieldContext;
192
+ }
193
+
194
+ const dateRangePickerContext = useContext(DateRangePickerContext);
195
+ if (dateRangePickerContext && slot === "start") {
196
+ return dateRangePickerContext.startFieldContext;
197
+ }
198
+ if (dateRangePickerContext && slot === "end") {
199
+ return dateRangePickerContext.endFieldContext;
200
+ }
201
+
202
+ throw new Error("DateInput components must be used within a DateField or DateRangePicker slot");
203
+ }
127
204
 
128
205
  /**
129
206
  * A date field allows users to enter and edit date values using a keyboard.
@@ -139,59 +216,78 @@ export function useDateFieldContext(): DateFieldState<DateValue> {
139
216
  * ```
140
217
  */
141
218
  export function DateField<T extends DateValue = CalendarDate>(
142
- props: DateFieldProps<T>
219
+ props: DateFieldProps<T>,
143
220
  ): JSX.Element {
144
221
  // Use hydration-safe pattern for client-only rendering
145
222
  const isHydrated = useIsHydrated();
223
+ const formContext = useContext(FormContext);
146
224
 
147
225
  return (
148
226
  <Show
149
227
  when={isHydrated()}
150
- fallback={<div class="solidaria-DateField solidaria-DateField--placeholder" aria-hidden="true" />}
228
+ fallback={
229
+ <div class="solidaria-DateField solidaria-DateField--placeholder" aria-hidden="true" />
230
+ }
151
231
  >
152
- <DateFieldInner {...props} />
232
+ <DateFieldInner {...props} __formContext={formContext} />
153
233
  </Show>
154
234
  );
155
235
  }
156
236
 
237
+ type DateFieldInnerProps<T extends DateValue = DateValue> = DateFieldProps<T> & {
238
+ __formContext?: FormProps | null;
239
+ };
240
+
157
241
  /**
158
242
  * Internal DateField component that renders after client mount.
159
243
  */
160
244
  function DateFieldInner<T extends DateValue = CalendarDate>(
161
- props: DateFieldProps<T>
245
+ props: DateFieldInnerProps<T>,
162
246
  ): JSX.Element {
247
+ const formContext = props.__formContext ?? useContext(FormContext);
248
+ const mergedProps = withFormValidationBehavior(props, formContext);
163
249
  const [local, stateProps, rest] = splitProps(
164
- props,
165
- ['children', 'class', 'style', 'slot'],
250
+ mergedProps,
251
+ ["children", "class", "style", "slot", "__formContext"],
166
252
  [
167
- 'value',
168
- 'defaultValue',
169
- 'onChange',
170
- 'minValue',
171
- 'maxValue',
172
- 'isDisabled',
173
- 'isReadOnly',
174
- 'isRequired',
175
- 'locale',
176
- 'granularity',
177
- 'hourCycle',
178
- 'hideTimeZone',
179
- 'placeholderValue',
180
- 'validationState',
181
- 'description',
182
- 'errorMessage',
183
- ]
253
+ "value",
254
+ "defaultValue",
255
+ "onChange",
256
+ "minValue",
257
+ "maxValue",
258
+ "isInvalid",
259
+ "isDisabled",
260
+ "isReadOnly",
261
+ "isRequired",
262
+ "locale",
263
+ "granularity",
264
+ "hourCycle",
265
+ "hideTimeZone",
266
+ "placeholderValue",
267
+ "shouldForceLeadingZeros",
268
+ "validationState",
269
+ "validationBehavior",
270
+ "validate",
271
+ "description",
272
+ "errorMessage",
273
+ "isDateUnavailable",
274
+ ],
184
275
  );
185
276
 
186
277
  const [fieldRef, setFieldRef] = createSignal<HTMLDivElement | null>(null);
187
278
 
188
- // Create date field state
189
279
  const state = createDateFieldState(stateProps);
190
280
 
191
- // Create date field ARIA props
192
- const fieldAria = createDateField(rest, state as unknown as DateFieldState<DateValue>, fieldRef);
281
+ const fieldAria = createDateField(
282
+ () => ({
283
+ ...(rest as Record<string, unknown>),
284
+ description: stateProps.description,
285
+ errorMessage: stateProps.errorMessage,
286
+ }),
287
+ state as unknown as DateFieldState<DateValue>,
288
+ fieldRef,
289
+ );
193
290
 
194
- // Render props values
195
291
  const renderValues = createMemo<DateFieldRenderProps>(() => ({
196
292
  isDisabled: state.isDisabled(),
197
293
  isReadOnly: state.isReadOnly(),
@@ -199,97 +295,129 @@ function DateFieldInner<T extends DateValue = CalendarDate>(
199
295
  isInvalid: state.isInvalid(),
200
296
  }));
201
297
 
202
- // Resolve render props
203
298
  const renderProps = useRenderProps(
204
299
  {
205
300
  class: local.class,
206
301
  style: local.style,
207
- defaultClassName: 'solidaria-DateField',
302
+ defaultClassName: "solidaria-DateField",
208
303
  },
209
- renderValues
304
+ renderValues,
210
305
  );
211
306
 
307
+ const validationBehavior = () =>
308
+ (stateProps as { validationBehavior?: "aria" | "native" }).validationBehavior ??
309
+ formContext?.validationBehavior ??
310
+ "native";
311
+
212
312
  return (
213
- <DateFieldContext.Provider value={state as unknown as DateFieldState<DateValue>}>
214
- <div
215
- ref={setFieldRef}
216
- {...fieldAria.fieldProps}
217
- class={renderProps.class()}
218
- style={renderProps.style()}
219
- data-disabled={dataAttr(state.isDisabled())}
220
- data-readonly={dataAttr(state.isReadOnly())}
221
- data-required={dataAttr(state.isRequired())}
222
- data-invalid={dataAttr(state.isInvalid())}
313
+ <DateFieldStateContext.Provider value={state as unknown as DateFieldState<DateValue>}>
314
+ <DateFieldContext.Provider
315
+ value={{
316
+ state: state as unknown as DateFieldState<DateValue>,
317
+ aria: {
318
+ labelProps: fieldAria.labelProps,
319
+ inputProps: fieldAria.inputProps,
320
+ descriptionProps: fieldAria.descriptionProps,
321
+ errorMessageProps: fieldAria.errorMessageProps,
322
+ },
323
+ }}
223
324
  >
224
- {props.children as JSX.Element}
225
- </div>
226
- </DateFieldContext.Provider>
325
+ <div
326
+ ref={setFieldRef}
327
+ {...fieldAria.fieldProps}
328
+ class={renderProps.class()}
329
+ style={renderProps.style()}
330
+ data-disabled={dataAttr(state.isDisabled())}
331
+ data-readonly={dataAttr(state.isReadOnly())}
332
+ data-required={dataAttr(state.isRequired())}
333
+ data-invalid={dataAttr(state.isInvalid())}
334
+ >
335
+ {local.children as JSX.Element}
336
+ </div>
337
+ <Show when={(rest as Record<string, unknown>).name}>
338
+ <HiddenDateInput
339
+ name={(rest as Record<string, unknown>).name as string | undefined}
340
+ form={(rest as Record<string, unknown>).form as string | undefined}
341
+ value={state.value()}
342
+ autoComplete={(rest as Record<string, unknown>).autoComplete as string | undefined}
343
+ isDisabled={state.isDisabled()}
344
+ isRequired={state.isRequired()}
345
+ validationBehavior={validationBehavior()}
346
+ validationState={state}
347
+ focus={() => {
348
+ fieldRef()?.querySelector<HTMLElement>('[role="spinbutton"]')?.focus();
349
+ }}
350
+ minValue={access(stateProps.minValue) as DateValue | undefined}
351
+ maxValue={access(stateProps.maxValue) as DateValue | undefined}
352
+ granularity={state.granularity}
353
+ />
354
+ </Show>
355
+ </DateFieldContext.Provider>
356
+ </DateFieldStateContext.Provider>
227
357
  );
228
358
  }
229
359
 
230
- // ============================================
231
- // DATE INPUT COMPONENT
232
- // ============================================
233
-
234
360
  /**
235
361
  * The input area containing date segments.
236
362
  */
237
363
  export function DateInput(props: DateInputProps): JSX.Element {
238
- const state = useDateFieldContext();
364
+ const context = useDateInputContext(props.slot);
365
+ const { state, aria } = context;
239
366
  const [isFocused, setIsFocused] = createSignal(false);
367
+ const [inputRef, setInputRef] = createSignal<HTMLDivElement | null>(null);
240
368
 
241
- // Render props values
242
369
  const renderValues = createMemo<DateInputRenderProps>(() => ({
243
370
  isDisabled: state.isDisabled(),
244
371
  isFocused: isFocused(),
245
372
  }));
246
373
 
247
- // Resolve render props
248
374
  const renderProps = useRenderProps(
249
375
  {
250
376
  class: props.class,
251
377
  style: props.style,
252
- defaultClassName: 'solidaria-DateInput',
378
+ defaultClassName: "solidaria-DateInput",
253
379
  },
254
- renderValues
380
+ renderValues,
255
381
  );
256
382
 
383
+ createEffect(() => {
384
+ const element = inputRef();
385
+ const handler = props.onPointerDownCapture;
386
+ if (!element || !handler) return;
387
+
388
+ const listener = (event: PointerEvent) =>
389
+ (handler as unknown as (event: PointerEvent) => void)(event);
390
+ element.addEventListener("pointerdown", listener, { capture: true });
391
+ onCleanup(() => element.removeEventListener("pointerdown", listener, { capture: true }));
392
+ });
393
+
257
394
  return (
258
- <div
259
- role="presentation"
260
- class={renderProps.class()}
261
- style={renderProps.style()}
262
- data-disabled={dataAttr(state.isDisabled())}
263
- data-focused={dataAttr(isFocused())}
264
- onFocusIn={() => setIsFocused(true)}
265
- onFocusOut={() => setIsFocused(false)}
266
- >
267
- <For each={state.segments()}>
268
- {(segment) => props.children?.(segment)}
269
- </For>
270
- </div>
395
+ <DateFieldContext.Provider value={context as DateFieldContextValue}>
396
+ <div
397
+ ref={setInputRef}
398
+ {...aria.inputProps}
399
+ class={renderProps.class()}
400
+ style={renderProps.style()}
401
+ data-disabled={dataAttr(state.isDisabled())}
402
+ data-focused={dataAttr(isFocused())}
403
+ onFocusIn={() => setIsFocused(true)}
404
+ onFocusOut={() => setIsFocused(false)}
405
+ >
406
+ <For each={state.segments()}>{(segment) => props.children?.(segment)}</For>
407
+ </div>
408
+ </DateFieldContext.Provider>
271
409
  );
272
410
  }
273
411
 
274
- // ============================================
275
- // DATE SEGMENT COMPONENT
276
- // ============================================
277
-
278
412
  /**
279
413
  * A segment of a date field (year, month, day, etc.).
280
414
  */
281
415
  export function DateSegment(props: DateSegmentProps): JSX.Element {
282
- const state = useDateFieldContext();
283
- const [segmentRef, setSegmentRef] = createSignal<HTMLDivElement | null>(null);
284
-
285
- // Create segment ARIA props
286
- const segmentAria = createDateSegment(
287
- { segment: props.segment },
288
- state,
289
- segmentRef
290
- );
416
+ const { state } = useDateFieldContext();
417
+ const [segmentRef, setSegmentRef] = createSignal<HTMLElement | null>(null);
418
+
419
+ const segmentAria = createDateSegment({ segment: props.segment }, state, segmentRef);
291
420
 
292
- // Render props values
293
421
  const renderValues = createMemo<DateSegmentRenderProps>(() => ({
294
422
  isFocused: segmentAria.isFocused,
295
423
  isEditable: segmentAria.isEditable,
@@ -298,27 +426,26 @@ export function DateSegment(props: DateSegmentProps): JSX.Element {
298
426
  text: segmentAria.text,
299
427
  }));
300
428
 
301
- // Resolve render props
302
429
  const renderProps = useRenderProps(
303
430
  {
304
431
  children: props.children,
305
432
  class: props.class,
306
433
  style: props.style,
307
- defaultClassName: 'solidaria-DateSegment',
434
+ defaultClassName: "solidaria-DateSegment",
308
435
  },
309
- renderValues
436
+ renderValues,
310
437
  );
311
438
 
312
439
  // Determine children content - avoid Show for SSR hydration compatibility
313
440
  const getChildren = () => {
314
- if (typeof props.children === 'function') {
441
+ if (typeof props.children === "function") {
315
442
  return renderProps.renderChildren();
316
443
  }
317
444
  return segmentAria.text;
318
445
  };
319
446
 
320
447
  return (
321
- <div
448
+ <span
322
449
  ref={setSegmentRef}
323
450
  {...segmentAria.segmentProps}
324
451
  class={renderProps.class()}
@@ -329,9 +456,50 @@ export function DateSegment(props: DateSegmentProps): JSX.Element {
329
456
  data-type={props.segment.type}
330
457
  >
331
458
  {getChildren()}
332
- </div>
459
+ </span>
460
+ );
461
+ }
462
+
463
+ export interface DateFieldLabelProps {
464
+ children?: JSX.Element;
465
+ class?: string;
466
+ }
467
+
468
+ export function DateFieldLabel(props: DateFieldLabelProps): JSX.Element {
469
+ const { aria } = useDateFieldContext();
470
+ return (
471
+ <span {...aria.labelProps} class={props.class}>
472
+ {props.children}
473
+ </span>
474
+ );
475
+ }
476
+
477
+ export interface DateFieldDescriptionProps {
478
+ children?: JSX.Element;
479
+ class?: string;
480
+ }
481
+
482
+ export function DateFieldDescription(props: DateFieldDescriptionProps): JSX.Element {
483
+ const { aria } = useDateFieldContext();
484
+ return (
485
+ <p {...aria.descriptionProps} class={props.class}>
486
+ {props.children}
487
+ </p>
488
+ );
489
+ }
490
+
491
+ export interface DateFieldErrorMessageProps {
492
+ children?: JSX.Element;
493
+ class?: string;
494
+ }
495
+
496
+ export function DateFieldErrorMessage(props: DateFieldErrorMessageProps): JSX.Element {
497
+ const { aria } = useDateFieldContext();
498
+ return (
499
+ <p {...aria.errorMessageProps} class={props.class}>
500
+ {props.children}
501
+ </p>
333
502
  );
334
503
  }
335
504
 
336
- // Re-export types
337
505
  export type { DateFieldState, DateSegmentType };