@proyecto-viviana/solidaria-components 0.2.9 → 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 (222) hide show
  1. package/README.md +39 -272
  2. package/dist/ActionBar.d.ts +21 -13
  3. package/dist/ActionBar.d.ts.map +1 -1
  4. package/dist/ActionGroup.d.ts +8 -8
  5. package/dist/ActionGroup.d.ts.map +1 -1
  6. package/dist/Alert.d.ts +5 -5
  7. package/dist/Alert.d.ts.map +1 -1
  8. package/dist/Autocomplete.d.ts +5 -5
  9. package/dist/Autocomplete.d.ts.map +1 -1
  10. package/dist/Breadcrumbs.d.ts +18 -7
  11. package/dist/Breadcrumbs.d.ts.map +1 -1
  12. package/dist/Button.d.ts +24 -5
  13. package/dist/Button.d.ts.map +1 -1
  14. package/dist/Calendar.d.ts +38 -7
  15. package/dist/Calendar.d.ts.map +1 -1
  16. package/dist/Checkbox.d.ts +32 -7
  17. package/dist/Checkbox.d.ts.map +1 -1
  18. package/dist/Collection.d.ts +19 -14
  19. package/dist/Collection.d.ts.map +1 -1
  20. package/dist/Color.d.ts +103 -14
  21. package/dist/Color.d.ts.map +1 -1
  22. package/dist/ColorEditor.d.ts +6 -6
  23. package/dist/ColorEditor.d.ts.map +1 -1
  24. package/dist/ComboBox.d.ts +85 -19
  25. package/dist/ComboBox.d.ts.map +1 -1
  26. package/dist/ContextualHelpTrigger.d.ts +2 -2
  27. package/dist/ContextualHelpTrigger.d.ts.map +1 -1
  28. package/dist/DateField.d.ts +8 -6
  29. package/dist/DateField.d.ts.map +1 -1
  30. package/dist/DatePicker.d.ts +53 -22
  31. package/dist/DatePicker.d.ts.map +1 -1
  32. package/dist/DateRangePickerContext.d.ts +30 -0
  33. package/dist/DateRangePickerContext.d.ts.map +1 -0
  34. package/dist/Dialog.d.ts +5 -5
  35. package/dist/Dialog.d.ts.map +1 -1
  36. package/dist/Disclosure.d.ts +23 -5
  37. package/dist/Disclosure.d.ts.map +1 -1
  38. package/dist/DragAndDrop.d.ts +6 -6
  39. package/dist/DragAndDrop.d.ts.map +1 -1
  40. package/dist/DragPreview.d.ts +2 -2
  41. package/dist/DragPreview.d.ts.map +1 -1
  42. package/dist/DropZone.d.ts +4 -4
  43. package/dist/DropZone.d.ts.map +1 -1
  44. package/dist/FieldError.d.ts +9 -5
  45. package/dist/FieldError.d.ts.map +1 -1
  46. package/dist/FileTrigger.d.ts +3 -3
  47. package/dist/FileTrigger.d.ts.map +1 -1
  48. package/dist/Focusable.d.ts +2 -2
  49. package/dist/Focusable.d.ts.map +1 -1
  50. package/dist/Form.d.ts +18 -4
  51. package/dist/Form.d.ts.map +1 -1
  52. package/dist/GridList.d.ts +32 -12
  53. package/dist/GridList.d.ts.map +1 -1
  54. package/dist/HiddenDateInput.d.ts +26 -0
  55. package/dist/HiddenDateInput.d.ts.map +1 -0
  56. package/dist/HiddenTimeInput.d.ts +25 -0
  57. package/dist/HiddenTimeInput.d.ts.map +1 -0
  58. package/dist/Icon.d.ts +5 -5
  59. package/dist/Icon.d.ts.map +1 -1
  60. package/dist/Keyboard.d.ts +1 -1
  61. package/dist/Landmark.d.ts +3 -3
  62. package/dist/Landmark.d.ts.map +1 -1
  63. package/dist/Link.d.ts +10 -4
  64. package/dist/Link.d.ts.map +1 -1
  65. package/dist/ListBox.d.ts +32 -12
  66. package/dist/ListBox.d.ts.map +1 -1
  67. package/dist/ListDropTargetDelegate.d.ts +6 -6
  68. package/dist/ListDropTargetDelegate.d.ts.map +1 -1
  69. package/dist/Menu.d.ts +65 -14
  70. package/dist/Menu.d.ts.map +1 -1
  71. package/dist/Meter.d.ts +3 -3
  72. package/dist/Meter.d.ts.map +1 -1
  73. package/dist/Modal.d.ts +5 -5
  74. package/dist/Modal.d.ts.map +1 -1
  75. package/dist/NumberField.d.ts +8 -12
  76. package/dist/NumberField.d.ts.map +1 -1
  77. package/dist/Popover.d.ts +28 -5
  78. package/dist/Popover.d.ts.map +1 -1
  79. package/dist/Pressable.d.ts +2 -2
  80. package/dist/Pressable.d.ts.map +1 -1
  81. package/dist/ProgressBar.d.ts +5 -3
  82. package/dist/ProgressBar.d.ts.map +1 -1
  83. package/dist/RadioGroup.d.ts +43 -9
  84. package/dist/RadioGroup.d.ts.map +1 -1
  85. package/dist/RangeCalendar.d.ts +34 -7
  86. package/dist/RangeCalendar.d.ts.map +1 -1
  87. package/dist/RouterProvider.d.ts +2 -2
  88. package/dist/RouterProvider.d.ts.map +1 -1
  89. package/dist/SearchField.d.ts +23 -20
  90. package/dist/SearchField.d.ts.map +1 -1
  91. package/dist/Select.d.ts +41 -11
  92. package/dist/Select.d.ts.map +1 -1
  93. package/dist/SelectionIndicator.d.ts +3 -3
  94. package/dist/SelectionIndicator.d.ts.map +1 -1
  95. package/dist/Separator.d.ts +9 -3
  96. package/dist/Separator.d.ts.map +1 -1
  97. package/dist/SharedElementTransition.d.ts +6 -4
  98. package/dist/SharedElementTransition.d.ts.map +1 -1
  99. package/dist/Slider.d.ts +12 -8
  100. package/dist/Slider.d.ts.map +1 -1
  101. package/dist/StepList.d.ts +90 -0
  102. package/dist/StepList.d.ts.map +1 -0
  103. package/dist/Switch.d.ts +11 -5
  104. package/dist/Switch.d.ts.map +1 -1
  105. package/dist/Table.d.ts +187 -23
  106. package/dist/Table.d.ts.map +1 -1
  107. package/dist/Tabs.d.ts +45 -9
  108. package/dist/Tabs.d.ts.map +1 -1
  109. package/dist/TagGroup.d.ts +12 -10
  110. package/dist/TagGroup.d.ts.map +1 -1
  111. package/dist/Text.d.ts +2 -2
  112. package/dist/TextField.d.ts +15 -11
  113. package/dist/TextField.d.ts.map +1 -1
  114. package/dist/TimeField.d.ts +6 -6
  115. package/dist/TimeField.d.ts.map +1 -1
  116. package/dist/Toast.d.ts +29 -14
  117. package/dist/Toast.d.ts.map +1 -1
  118. package/dist/ToggleButton.d.ts +11 -5
  119. package/dist/ToggleButton.d.ts.map +1 -1
  120. package/dist/ToggleButtonGroup.d.ts +7 -7
  121. package/dist/ToggleButtonGroup.d.ts.map +1 -1
  122. package/dist/Toolbar.d.ts +7 -3
  123. package/dist/Toolbar.d.ts.map +1 -1
  124. package/dist/Tooltip.d.ts +50 -8
  125. package/dist/Tooltip.d.ts.map +1 -1
  126. package/dist/Tree.d.ts +66 -17
  127. package/dist/Tree.d.ts.map +1 -1
  128. package/dist/Virtualizer.d.ts +12 -12
  129. package/dist/Virtualizer.d.ts.map +1 -1
  130. package/dist/VirtualizerLayouts.d.ts +2 -2
  131. package/dist/VirtualizerLayouts.d.ts.map +1 -1
  132. package/dist/VisuallyHidden.d.ts +1 -1
  133. package/dist/VisuallyHidden.d.ts.map +1 -1
  134. package/dist/contexts.d.ts +5 -1
  135. package/dist/contexts.d.ts.map +1 -1
  136. package/dist/index.d.ts +73 -71
  137. package/dist/index.d.ts.map +1 -1
  138. package/dist/index.js +23247 -18564
  139. package/dist/index.js.map +1 -1
  140. package/dist/index.jsx +18110 -0
  141. package/dist/index.jsx.map +1 -0
  142. package/dist/useDragAndDrop.d.ts +13 -13
  143. package/dist/useDragAndDrop.d.ts.map +1 -1
  144. package/dist/utils.d.ts +2 -2
  145. package/dist/utils.d.ts.map +1 -1
  146. package/dist/virtualizer/Layout.d.ts +1 -1
  147. package/dist/virtualizer/Layout.d.ts.map +1 -1
  148. package/package.json +31 -32
  149. package/src/ActionBar.tsx +75 -72
  150. package/src/ActionGroup.tsx +53 -61
  151. package/src/Alert.tsx +17 -42
  152. package/src/Autocomplete.tsx +39 -44
  153. package/src/Breadcrumbs.tsx +149 -80
  154. package/src/Button.tsx +267 -70
  155. package/src/Calendar.tsx +218 -138
  156. package/src/Checkbox.tsx +413 -121
  157. package/src/Collection.tsx +67 -58
  158. package/src/Color.tsx +803 -380
  159. package/src/ColorEditor.tsx +131 -149
  160. package/src/ComboBox.tsx +414 -249
  161. package/src/ContextualHelpTrigger.tsx +86 -74
  162. package/src/DateField.tsx +185 -91
  163. package/src/DatePicker.tsx +524 -213
  164. package/src/DateRangePickerContext.tsx +44 -0
  165. package/src/Dialog.tsx +156 -118
  166. package/src/Disclosure.tsx +127 -80
  167. package/src/DragAndDrop.tsx +60 -54
  168. package/src/DragPreview.tsx +13 -11
  169. package/src/DropZone.tsx +42 -22
  170. package/src/FieldError.tsx +45 -23
  171. package/src/FileTrigger.tsx +19 -19
  172. package/src/Focusable.tsx +21 -24
  173. package/src/Form.tsx +71 -16
  174. package/src/GridList.tsx +273 -197
  175. package/src/HiddenDateInput.tsx +153 -0
  176. package/src/HiddenTimeInput.tsx +133 -0
  177. package/src/Icon.tsx +22 -43
  178. package/src/Keyboard.tsx +3 -3
  179. package/src/Landmark.tsx +37 -63
  180. package/src/Link.tsx +125 -75
  181. package/src/ListBox.tsx +332 -233
  182. package/src/ListDropTargetDelegate.ts +81 -80
  183. package/src/Menu.tsx +1023 -274
  184. package/src/Meter.tsx +38 -56
  185. package/src/Modal.tsx +243 -175
  186. package/src/NumberField.tsx +139 -143
  187. package/src/Popover.tsx +386 -233
  188. package/src/Pressable.tsx +21 -21
  189. package/src/ProgressBar.tsx +48 -57
  190. package/src/RadioGroup.tsx +524 -122
  191. package/src/RangeCalendar.tsx +157 -90
  192. package/src/RouterProvider.tsx +30 -47
  193. package/src/SearchField.tsx +362 -143
  194. package/src/Select.tsx +656 -233
  195. package/src/SelectionIndicator.tsx +18 -15
  196. package/src/Separator.tsx +47 -49
  197. package/src/SharedElementTransition.tsx +103 -97
  198. package/src/Slider.tsx +138 -98
  199. package/src/StepList.tsx +272 -0
  200. package/src/Switch.tsx +93 -46
  201. package/src/Table.tsx +1308 -342
  202. package/src/Tabs.tsx +324 -103
  203. package/src/TagGroup.tsx +139 -126
  204. package/src/Text.tsx +3 -3
  205. package/src/TextField.tsx +389 -79
  206. package/src/TimeField.tsx +136 -76
  207. package/src/Toast.tsx +209 -157
  208. package/src/ToggleButton.tsx +47 -37
  209. package/src/ToggleButtonGroup.tsx +39 -34
  210. package/src/Toolbar.tsx +54 -69
  211. package/src/Tooltip.tsx +387 -119
  212. package/src/Tree.tsx +651 -368
  213. package/src/Virtualizer.tsx +208 -180
  214. package/src/VirtualizerLayouts.ts +45 -30
  215. package/src/VisuallyHidden.tsx +19 -19
  216. package/src/contexts.ts +29 -37
  217. package/src/index.ts +110 -195
  218. package/src/useDragAndDrop.ts +87 -71
  219. package/src/utils.tsx +40 -55
  220. package/src/virtualizer/Layout.ts +14 -22
  221. package/dist/index.ssr.js +0 -16996
  222. package/dist/index.ssr.js.map +0 -1
package/src/Calendar.tsx CHANGED
@@ -7,6 +7,7 @@
7
7
 
8
8
  import {
9
9
  type JSX,
10
+ type Accessor,
10
11
  createContext,
11
12
  createMemo,
12
13
  createSignal,
@@ -15,15 +16,16 @@ import {
15
16
  For,
16
17
  Index,
17
18
  Show,
18
- } from 'solid-js';
19
+ } from "solid-js";
19
20
 
20
21
  import {
21
22
  createCalendar,
22
23
  createCalendarGrid,
23
24
  createCalendarCell,
25
+ createHover,
24
26
  type AriaCalendarProps,
25
27
  type AriaCalendarGridProps,
26
- } from '@proyecto-viviana/solidaria';
28
+ } from "@proyecto-viviana/solidaria";
27
29
  import {
28
30
  createCalendarState,
29
31
  type CalendarState,
@@ -32,7 +34,7 @@ import {
32
34
  type DateValue,
33
35
  endOfMonth,
34
36
  isSameMonth,
35
- } from '@proyecto-viviana/solid-stately';
37
+ } from "@proyecto-viviana/solid-stately";
36
38
  import {
37
39
  type RenderChildren,
38
40
  type ClassNameOrFunction,
@@ -41,22 +43,36 @@ import {
41
43
  useRenderProps,
42
44
  dataAttr,
43
45
  useIsHydrated,
44
- } from './utils';
46
+ } from "./utils";
47
+ import { VisuallyHidden } from "./VisuallyHidden";
45
48
 
46
- // ============================================
47
- // TYPES
48
- // ============================================
49
+ type RefLike<T> = ((el: T) => void) | { current?: T | null } | undefined;
50
+
51
+ function assignRef<T>(ref: RefLike<T>, el: T): void {
52
+ if (!ref) {
53
+ return;
54
+ }
55
+
56
+ if (typeof ref === "function") {
57
+ ref(el);
58
+ } else {
59
+ ref.current = el;
60
+ }
61
+ }
49
62
 
50
63
  export interface CalendarRenderProps {
51
64
  /** Whether the calendar is disabled. */
52
65
  isDisabled: boolean;
53
66
  /** Whether the calendar is read-only. */
54
67
  isReadOnly: boolean;
68
+ /** Whether the current selection is invalid. */
69
+ isInvalid: boolean;
55
70
  }
56
71
 
57
72
  export interface CalendarProps<T extends DateValue = DateValue>
58
- extends Omit<AriaCalendarProps, 'id' | 'isDisabled' | 'isReadOnly'>,
59
- Omit<CalendarStateProps<T>, 'locale'>,
73
+ extends
74
+ Omit<AriaCalendarProps, "id" | "isDisabled" | "isReadOnly">,
75
+ Omit<CalendarStateProps<T>, "locale">,
60
76
  SlotProps {
61
77
  /** The children of the component. */
62
78
  children?: JSX.Element;
@@ -66,6 +82,8 @@ export interface CalendarProps<T extends DateValue = DateValue>
66
82
  style?: StyleOrFunction<CalendarRenderProps>;
67
83
  /** The locale to use for formatting. */
68
84
  locale?: string;
85
+ /** Ref for the calendar root element. */
86
+ ref?: RefLike<HTMLDivElement>;
69
87
  }
70
88
 
71
89
  export interface CalendarGridRenderProps {
@@ -73,13 +91,16 @@ export interface CalendarGridRenderProps {
73
91
  isDisabled: boolean;
74
92
  }
75
93
 
76
- export interface CalendarGridProps extends Omit<AriaCalendarGridProps, 'startDate' | 'endDate'>, SlotProps {
94
+ export interface CalendarGridProps
95
+ extends Omit<AriaCalendarGridProps, "startDate" | "endDate">, SlotProps {
77
96
  /** The children of the component (render function receiving weeks). */
78
97
  children?: (date: CalendarDate) => JSX.Element;
79
98
  /** The CSS className for the element. */
80
99
  class?: ClassNameOrFunction<CalendarGridRenderProps>;
81
100
  /** The inline style for the element. */
82
101
  style?: StyleOrFunction<CalendarGridRenderProps>;
102
+ /** Class name for weekday header cells. */
103
+ headerCellClass?: string;
83
104
  /** Number of weeks to offset from the start. */
84
105
  offset?: { months?: number };
85
106
  }
@@ -89,16 +110,30 @@ export interface CalendarCellRenderProps {
89
110
  isSelected: boolean;
90
111
  /** Whether the cell is focused. */
91
112
  isFocused: boolean;
113
+ /** Whether the cell should display a keyboard focus ring. */
114
+ isFocusVisible: boolean;
92
115
  /** Whether the cell is disabled. */
93
116
  isDisabled: boolean;
94
117
  /** Whether the cell is unavailable. */
95
118
  isUnavailable: boolean;
119
+ /** Whether the cell is part of an invalid selection. */
120
+ isInvalid: boolean;
96
121
  /** Whether the cell is outside the visible month. */
97
122
  isOutsideMonth: boolean;
98
123
  /** Whether the cell represents today. */
99
124
  isToday: boolean;
100
125
  /** Whether the cell is pressed. */
101
126
  isPressed: boolean;
127
+ /** Whether the cell is hovered. */
128
+ isHovered: boolean;
129
+ /** Whether the cell is the first day slot in its row. */
130
+ isFirstChild: boolean;
131
+ /** Whether the cell is the last day slot in its row. */
132
+ isLastChild: boolean;
133
+ /** Whether the cell is in the first rendered week row. */
134
+ isFirstWeek: boolean;
135
+ /** Whether the cell is in the last rendered week row. */
136
+ isLastWeek: boolean;
102
137
  /** The formatted date string. */
103
138
  formattedDate: string;
104
139
  }
@@ -112,6 +147,10 @@ export interface CalendarCellProps extends SlotProps {
112
147
  class?: ClassNameOrFunction<CalendarCellRenderProps>;
113
148
  /** The inline style for the element. */
114
149
  style?: StyleOrFunction<CalendarCellRenderProps>;
150
+ /** Class name for the table cell wrapper. */
151
+ cellClass?: ClassNameOrFunction<CalendarCellRenderProps>;
152
+ /** Inline style for the table cell wrapper. */
153
+ cellStyle?: StyleOrFunction<CalendarCellRenderProps>;
115
154
  }
116
155
 
117
156
  export interface CalendarHeaderCellProps extends SlotProps {
@@ -135,25 +174,22 @@ export interface CalendarGridBodyProps extends SlotProps {
135
174
  style?: JSX.CSSProperties;
136
175
  }
137
176
 
138
- // ============================================
139
- // CONTEXT
140
- // ============================================
141
-
142
177
  export const CalendarContext = createContext<CalendarState<DateValue> | null>(null);
143
- const CalendarGridMonthContext = createContext<CalendarDate | null>(null);
178
+ const CalendarGridMonthContext = createContext<Accessor<CalendarDate> | null>(null);
179
+ const CalendarGridCellPositionContext = createContext<Accessor<{
180
+ weekIndex: number;
181
+ dayIndex: number;
182
+ lastWeekIndex: number;
183
+ }> | null>(null);
144
184
 
145
185
  export function useCalendarContext(): CalendarState<DateValue> {
146
186
  const context = useContext(CalendarContext);
147
187
  if (!context) {
148
- throw new Error('Calendar components must be used within a Calendar');
188
+ throw new Error("Calendar components must be used within a Calendar");
149
189
  }
150
190
  return context;
151
191
  }
152
192
 
153
- // ============================================
154
- // CALENDAR COMPONENT
155
- // ============================================
156
-
157
193
  /**
158
194
  * A calendar displays a grid of days in a month and allows users to select a single date.
159
195
  *
@@ -171,9 +207,7 @@ export function useCalendarContext(): CalendarState<DateValue> {
171
207
  * </Calendar>
172
208
  * ```
173
209
  */
174
- export function Calendar<T extends DateValue = CalendarDate>(
175
- props: CalendarProps<T>
176
- ): JSX.Element {
210
+ export function Calendar<T extends DateValue = CalendarDate>(props: CalendarProps<T>): JSX.Element {
177
211
  const inheritedState = useContext(CalendarContext);
178
212
 
179
213
  // Use hydration-safe pattern for client-only rendering
@@ -182,74 +216,85 @@ export function Calendar<T extends DateValue = CalendarDate>(
182
216
  return (
183
217
  <Show
184
218
  when={isHydrated()}
185
- fallback={<div class="solidaria-Calendar solidaria-Calendar--placeholder" aria-hidden="true" />}
219
+ fallback={
220
+ <div class="solidaria-Calendar solidaria-Calendar--placeholder" aria-hidden="true" />
221
+ }
186
222
  >
187
- <Show
188
- when={inheritedState}
189
- fallback={<CalendarInner {...props} />}
190
- >
191
- <CalendarWithState
192
- state={inheritedState as CalendarState<DateValue>}
193
- {...props}
194
- />
223
+ <Show when={inheritedState} fallback={<CalendarInner {...props} />}>
224
+ <CalendarWithState state={inheritedState as CalendarState<DateValue>} {...props} />
195
225
  </Show>
196
226
  </Show>
197
227
  );
198
228
  }
199
229
 
200
230
  function CalendarWithState<T extends DateValue = CalendarDate>(
201
- props: CalendarProps<T> & { state: CalendarState<DateValue> }
231
+ props: CalendarProps<T> & { state: CalendarState<DateValue> },
202
232
  ): JSX.Element {
203
- const [local, _stateProps, rest] = splitProps(
233
+ const [local, stateProps, rest] = splitProps(
204
234
  props,
205
- ['children', 'class', 'style', 'slot', 'state'],
235
+ ["children", "class", "style", "slot", "state", "ref"],
206
236
  [
207
- 'value',
208
- 'defaultValue',
209
- 'onChange',
210
- 'minValue',
211
- 'maxValue',
212
- 'isDisabled',
213
- 'isReadOnly',
214
- 'autoFocus',
215
- 'focusedValue',
216
- 'defaultFocusedValue',
217
- 'onFocusChange',
218
- 'locale',
219
- 'isDateUnavailable',
220
- 'visibleMonths',
221
- 'isDateDisabled',
222
- 'validationState',
223
- 'errorMessage',
224
- 'firstDayOfWeek',
225
- ]
237
+ "value",
238
+ "defaultValue",
239
+ "onChange",
240
+ "minValue",
241
+ "maxValue",
242
+ "isDisabled",
243
+ "isReadOnly",
244
+ "autoFocus",
245
+ "focusedValue",
246
+ "defaultFocusedValue",
247
+ "onFocusChange",
248
+ "locale",
249
+ "createCalendar",
250
+ "isDateUnavailable",
251
+ "visibleMonths",
252
+ "pageBehavior",
253
+ "selectionAlignment",
254
+ "isDateDisabled",
255
+ "validationState",
256
+ "errorMessage",
257
+ "firstDayOfWeek",
258
+ ],
226
259
  );
227
260
 
228
261
  const state = () => props.state;
229
- const calendarAria = createCalendar(rest, state());
262
+ const calendarAria = createCalendar(
263
+ () => ({
264
+ ...rest,
265
+ errorMessage: stateProps.errorMessage,
266
+ }),
267
+ state(),
268
+ );
230
269
 
231
270
  const renderValues = createMemo<CalendarRenderProps>(() => ({
232
271
  isDisabled: state().isDisabled(),
233
272
  isReadOnly: state().isReadOnly(),
273
+ isInvalid: state().isValueInvalid(),
234
274
  }));
235
275
 
236
276
  const renderProps = useRenderProps(
237
277
  {
238
278
  class: local.class,
239
279
  style: local.style,
240
- defaultClassName: 'solidaria-Calendar',
280
+ defaultClassName: "solidaria-Calendar",
241
281
  },
242
- renderValues
282
+ renderValues,
243
283
  );
244
284
 
245
285
  return (
246
286
  <div
247
287
  {...calendarAria.calendarProps}
288
+ ref={(el) => assignRef(local.ref, el)}
248
289
  class={renderProps.class()}
249
290
  style={renderProps.style()}
250
291
  data-disabled={dataAttr(state().isDisabled())}
251
292
  data-readonly={dataAttr(state().isReadOnly())}
293
+ data-invalid={dataAttr(state().isValueInvalid())}
252
294
  >
295
+ <VisuallyHidden>
296
+ <h2>{String(calendarAria.calendarProps["aria-label"] ?? "")}</h2>
297
+ </VisuallyHidden>
253
298
  {props.children}
254
299
  </div>
255
300
  );
@@ -258,76 +303,85 @@ function CalendarWithState<T extends DateValue = CalendarDate>(
258
303
  /**
259
304
  * Internal Calendar component that renders after client mount.
260
305
  */
261
- function CalendarInner<T extends DateValue = CalendarDate>(
262
- props: CalendarProps<T>
263
- ): JSX.Element {
306
+ function CalendarInner<T extends DateValue = CalendarDate>(props: CalendarProps<T>): JSX.Element {
264
307
  const [local, stateProps, rest] = splitProps(
265
308
  props,
266
- ['children', 'class', 'style', 'slot'],
309
+ ["children", "class", "style", "slot", "ref"],
267
310
  [
268
- 'value',
269
- 'defaultValue',
270
- 'onChange',
271
- 'minValue',
272
- 'maxValue',
273
- 'isDisabled',
274
- 'isReadOnly',
275
- 'autoFocus',
276
- 'focusedValue',
277
- 'defaultFocusedValue',
278
- 'onFocusChange',
279
- 'locale',
280
- 'isDateUnavailable',
281
- 'visibleMonths',
282
- 'isDateDisabled',
283
- 'validationState',
284
- 'errorMessage',
285
- 'firstDayOfWeek',
286
- ]
311
+ "value",
312
+ "defaultValue",
313
+ "onChange",
314
+ "minValue",
315
+ "maxValue",
316
+ "isDisabled",
317
+ "isReadOnly",
318
+ "autoFocus",
319
+ "focusedValue",
320
+ "defaultFocusedValue",
321
+ "onFocusChange",
322
+ "locale",
323
+ "createCalendar",
324
+ "isDateUnavailable",
325
+ "visibleMonths",
326
+ "pageBehavior",
327
+ "selectionAlignment",
328
+ "isDateDisabled",
329
+ "validationState",
330
+ "errorMessage",
331
+ "firstDayOfWeek",
332
+ ],
287
333
  );
288
334
 
289
335
  // Create calendar state
290
336
  const state = createCalendarState(stateProps);
291
337
 
292
338
  // Create calendar ARIA props
293
- const calendarAria = createCalendar(rest, state as unknown as CalendarState<DateValue>);
339
+ const calendarAria = createCalendar(
340
+ () => ({
341
+ ...rest,
342
+ errorMessage: stateProps.errorMessage,
343
+ }),
344
+ state as unknown as CalendarState<DateValue>,
345
+ );
294
346
 
295
- // Render props values
296
347
  const renderValues = createMemo<CalendarRenderProps>(() => ({
297
348
  isDisabled: state.isDisabled(),
298
349
  isReadOnly: state.isReadOnly(),
350
+ isInvalid: state.isValueInvalid(),
299
351
  }));
300
352
 
301
- // Resolve render props
302
353
  const renderProps = useRenderProps(
303
354
  {
304
355
  class: local.class,
305
356
  style: local.style,
306
- defaultClassName: 'solidaria-Calendar',
357
+ defaultClassName: "solidaria-Calendar",
307
358
  },
308
- renderValues
359
+ renderValues,
309
360
  );
310
361
 
311
362
  return (
312
363
  <CalendarContext.Provider value={state as unknown as CalendarState<DateValue>}>
313
364
  <div
314
365
  {...calendarAria.calendarProps}
366
+ ref={(el) => assignRef(local.ref, el)}
315
367
  class={renderProps.class()}
316
368
  style={renderProps.style()}
317
369
  data-disabled={dataAttr(state.isDisabled())}
318
370
  data-readonly={dataAttr(state.isReadOnly())}
371
+ data-invalid={dataAttr(state.isValueInvalid())}
319
372
  >
373
+ <VisuallyHidden>
374
+ <h2>{String(calendarAria.calendarProps["aria-label"] ?? "")}</h2>
375
+ </VisuallyHidden>
320
376
  {props.children}
321
377
  </div>
322
378
  </CalendarContext.Provider>
323
379
  );
324
380
  }
325
381
 
326
- // ============================================
327
- // CALENDAR HEADING COMPONENT
328
- // ============================================
329
-
330
382
  export interface CalendarHeadingProps extends SlotProps {
383
+ /** The children of the component. */
384
+ children?: RenderChildren<{ title: string }>;
331
385
  /** The CSS className for the element. */
332
386
  class?: string;
333
387
  /** The inline style for the element. */
@@ -339,25 +393,29 @@ export interface CalendarHeadingProps extends SlotProps {
339
393
  */
340
394
  export function CalendarHeading(props: CalendarHeadingProps): JSX.Element {
341
395
  const state = useCalendarContext();
396
+ const renderValues = createMemo(() => ({
397
+ title: state.title(),
398
+ }));
399
+ const renderProps = useRenderProps(
400
+ {
401
+ children: props.children,
402
+ class: props.class,
403
+ style: props.style,
404
+ defaultClassName: "solidaria-CalendarHeading",
405
+ },
406
+ renderValues,
407
+ );
342
408
 
343
409
  return (
344
- <h2
345
- class={props.class ?? 'solidaria-CalendarHeading'}
346
- style={props.style}
347
- aria-live="polite"
348
- >
349
- {state.title()}
410
+ <h2 class={renderProps.class()} style={renderProps.style()} aria-live="polite">
411
+ {typeof props.children === "function" ? renderProps.renderChildren() : state.title()}
350
412
  </h2>
351
413
  );
352
414
  }
353
415
 
354
- // ============================================
355
- // CALENDAR BUTTON COMPONENT
356
- // ============================================
357
-
358
416
  export interface CalendarButtonProps extends SlotProps {
359
417
  /** The slot for this button (previous or next). */
360
- slot?: 'previous' | 'next';
418
+ slot?: "previous" | "next";
361
419
  /** The children of the component. */
362
420
  children?: JSX.Element;
363
421
  /** The CSS className for the element. */
@@ -376,7 +434,7 @@ export function CalendarButton(props: CalendarButtonProps): JSX.Element {
376
434
  const calendarAria = createCalendar({}, state);
377
435
 
378
436
  const buttonProps = createMemo(() => {
379
- if (props.slot === 'previous') {
437
+ if (props.slot === "previous") {
380
438
  return calendarAria.prevButtonProps;
381
439
  }
382
440
  return calendarAria.nextButtonProps;
@@ -385,7 +443,7 @@ export function CalendarButton(props: CalendarButtonProps): JSX.Element {
385
443
  return (
386
444
  <button
387
445
  {...buttonProps()}
388
- class={props.class ?? 'solidaria-CalendarButton'}
446
+ class={props.class ?? "solidaria-CalendarButton"}
389
447
  style={props.style}
390
448
  disabled={props.isDisabled || state.isDisabled()}
391
449
  >
@@ -394,10 +452,6 @@ export function CalendarButton(props: CalendarButtonProps): JSX.Element {
394
452
  );
395
453
  }
396
454
 
397
- // ============================================
398
- // CALENDAR GRID COMPONENT
399
- // ============================================
400
-
401
455
  /**
402
456
  * Displays a grid of calendar cells.
403
457
  */
@@ -410,7 +464,6 @@ export function CalendarGrid(props: CalendarGridProps): JSX.Element {
410
464
  return offsetMonths ? baseStart.add({ months: offsetMonths }) : baseStart;
411
465
  });
412
466
 
413
- // Create grid ARIA props
414
467
  const gridAria = createCalendarGrid(
415
468
  {
416
469
  startDate: startDate(),
@@ -418,22 +471,20 @@ export function CalendarGrid(props: CalendarGridProps): JSX.Element {
418
471
  weekdayStyle: props.weekdayStyle,
419
472
  },
420
473
  state,
421
- gridRef
474
+ gridRef,
422
475
  );
423
476
 
424
- // Render props values
425
477
  const renderValues = createMemo<CalendarGridRenderProps>(() => ({
426
478
  isDisabled: state.isDisabled(),
427
479
  }));
428
480
 
429
- // Resolve render props
430
481
  const renderProps = useRenderProps(
431
482
  {
432
483
  class: props.class,
433
484
  style: props.style,
434
- defaultClassName: 'solidaria-CalendarGrid',
485
+ defaultClassName: "solidaria-CalendarGrid",
435
486
  },
436
- renderValues
487
+ renderValues,
437
488
  );
438
489
 
439
490
  // Memoize ALL dates for the grid at once to avoid reactive loops.
@@ -452,7 +503,7 @@ export function CalendarGrid(props: CalendarGridProps): JSX.Element {
452
503
  });
453
504
 
454
505
  return (
455
- <CalendarGridMonthContext.Provider value={startDate()}>
506
+ <CalendarGridMonthContext.Provider value={startDate}>
456
507
  <table
457
508
  ref={setGridRef}
458
509
  {...gridAria.gridProps}
@@ -463,7 +514,7 @@ export function CalendarGrid(props: CalendarGridProps): JSX.Element {
463
514
  <tr>
464
515
  <For each={gridAria.weekDays}>
465
516
  {(day) => (
466
- <th scope="col" class="solidaria-CalendarHeaderCell">
517
+ <th scope="col" class={props.headerCellClass ?? "solidaria-CalendarHeaderCell"}>
467
518
  {day}
468
519
  </th>
469
520
  )}
@@ -472,12 +523,20 @@ export function CalendarGrid(props: CalendarGridProps): JSX.Element {
472
523
  </thead>
473
524
  <tbody>
474
525
  <Index each={allDates()}>
475
- {(weekDates) => (
526
+ {(weekDates, weekIndex) => (
476
527
  <tr>
477
528
  <Index each={weekDates()}>
478
- {(date) => (
529
+ {(date, dayIndex) => (
479
530
  <Show when={date()} fallback={<td />}>
480
- {props.children?.(date()!)}
531
+ <CalendarGridCellPositionContext.Provider
532
+ value={() => ({
533
+ weekIndex,
534
+ dayIndex,
535
+ lastWeekIndex: allDates().length - 1,
536
+ })}
537
+ >
538
+ {props.children?.(date()!)}
539
+ </CalendarGridCellPositionContext.Provider>
481
540
  </Show>
482
541
  )}
483
542
  </Index>
@@ -492,7 +551,7 @@ export function CalendarGrid(props: CalendarGridProps): JSX.Element {
492
551
 
493
552
  export function CalendarGridHeader(props: CalendarGridHeaderProps): JSX.Element {
494
553
  return (
495
- <thead class={props.class ?? 'solidaria-CalendarGridHeader'} style={props.style}>
554
+ <thead class={props.class ?? "solidaria-CalendarGridHeader"} style={props.style}>
496
555
  {props.children}
497
556
  </thead>
498
557
  );
@@ -500,7 +559,7 @@ export function CalendarGridHeader(props: CalendarGridHeaderProps): JSX.Element
500
559
 
501
560
  export function CalendarGridBody(props: CalendarGridBodyProps): JSX.Element {
502
561
  return (
503
- <tbody class={props.class ?? 'solidaria-CalendarGridBody'} style={props.style}>
562
+ <tbody class={props.class ?? "solidaria-CalendarGridBody"} style={props.style}>
504
563
  {props.children}
505
564
  </tbody>
506
565
  );
@@ -508,84 +567,106 @@ export function CalendarGridBody(props: CalendarGridBodyProps): JSX.Element {
508
567
 
509
568
  export function CalendarHeaderCell(props: CalendarHeaderCellProps): JSX.Element {
510
569
  return (
511
- <th
512
- scope="col"
513
- class={props.class ?? 'solidaria-CalendarHeaderCell'}
514
- style={props.style}
515
- >
570
+ <th scope="col" class={props.class ?? "solidaria-CalendarHeaderCell"} style={props.style}>
516
571
  {props.children}
517
572
  </th>
518
573
  );
519
574
  }
520
575
 
521
- // ============================================
522
- // CALENDAR CELL COMPONENT
523
- // ============================================
524
-
525
576
  /**
526
577
  * A cell in the calendar grid representing a single day.
527
578
  */
528
579
  export function CalendarCell(props: CalendarCellProps): JSX.Element {
529
580
  const state = useCalendarContext();
530
581
  const currentMonthStart = useContext(CalendarGridMonthContext);
582
+ const cellPosition = useContext(CalendarGridCellPositionContext);
531
583
  const [cellRef, setCellRef] = createSignal<HTMLDivElement | null>(null);
532
- const isOutsideMonth = createMemo(() => currentMonthStart != null && !isSameMonth(currentMonthStart, props.date));
584
+ const isOutsideMonth = createMemo(
585
+ () => currentMonthStart != null && !isSameMonth(currentMonthStart(), props.date),
586
+ );
587
+ const position = createMemo(
588
+ () =>
589
+ cellPosition?.() ?? {
590
+ weekIndex: 0,
591
+ dayIndex: 0,
592
+ lastWeekIndex: 0,
593
+ },
594
+ );
533
595
 
534
- // Create cell ARIA props
535
596
  const cellAria = createCalendarCell(
536
597
  () => ({
537
598
  date: props.date,
538
599
  isOutsideMonth: isOutsideMonth(),
539
600
  }),
540
601
  state,
541
- cellRef
602
+ cellRef,
542
603
  );
604
+ const { hoverProps, isHovered } = createHover(() => ({
605
+ isDisabled: cellAria.isDisabled || cellAria.isUnavailable,
606
+ }));
543
607
 
544
- // Render props values
545
608
  const renderValues = createMemo<CalendarCellRenderProps>(() => ({
546
609
  isSelected: cellAria.isSelected,
547
610
  isFocused: cellAria.isFocused,
611
+ isFocusVisible: cellAria.isFocusVisible,
548
612
  isDisabled: cellAria.isDisabled,
549
613
  isUnavailable: cellAria.isUnavailable,
614
+ isInvalid: cellAria.isInvalid,
550
615
  isOutsideMonth: cellAria.isOutsideMonth,
551
616
  isToday: cellAria.isToday,
552
617
  isPressed: cellAria.isPressed,
618
+ isHovered: isHovered(),
619
+ isFirstChild: position().dayIndex === 0,
620
+ isLastChild: position().dayIndex === 6,
621
+ isFirstWeek: position().weekIndex === 0,
622
+ isLastWeek: position().weekIndex === position().lastWeekIndex,
553
623
  formattedDate: cellAria.formattedDate,
554
624
  }));
555
625
 
556
- // Resolve render props
557
626
  const renderProps = useRenderProps(
558
627
  {
559
628
  children: props.children,
560
629
  class: props.class,
561
630
  style: props.style,
562
- defaultClassName: 'solidaria-CalendarCell',
631
+ defaultClassName: "solidaria-CalendarCell",
632
+ },
633
+ renderValues,
634
+ );
635
+ const cellRenderProps = useRenderProps(
636
+ {
637
+ class: props.cellClass,
638
+ style: props.cellStyle,
639
+ defaultClassName: "solidaria-CalendarCellWrapper",
563
640
  },
564
- renderValues
641
+ renderValues,
565
642
  );
566
643
 
567
644
  // Determine children content - avoid Show for SSR hydration compatibility
568
645
  const getChildren = () => {
569
- if (typeof props.children === 'function') {
646
+ if (typeof props.children === "function") {
570
647
  return renderProps.renderChildren();
571
648
  }
572
649
  return cellAria.formattedDate;
573
650
  };
574
651
 
575
652
  return (
576
- <td {...cellAria.cellProps}>
653
+ <td {...cellAria.cellProps} class={cellRenderProps.class()} style={cellRenderProps.style()}>
577
654
  <div
578
655
  ref={setCellRef}
579
656
  {...cellAria.buttonProps}
657
+ {...hoverProps}
580
658
  class={renderProps.class()}
581
659
  style={renderProps.style()}
582
660
  data-selected={dataAttr(cellAria.isSelected)}
583
661
  data-focused={dataAttr(cellAria.isFocused)}
662
+ data-focus-visible={dataAttr(cellAria.isFocusVisible)}
584
663
  data-disabled={dataAttr(cellAria.isDisabled)}
585
664
  data-unavailable={dataAttr(cellAria.isUnavailable)}
665
+ data-invalid={dataAttr(cellAria.isInvalid)}
586
666
  data-outside-month={dataAttr(cellAria.isOutsideMonth)}
587
667
  data-today={dataAttr(cellAria.isToday)}
588
668
  data-pressed={dataAttr(cellAria.isPressed)}
669
+ data-hovered={dataAttr(isHovered())}
589
670
  >
590
671
  {getChildren()}
591
672
  </div>
@@ -593,5 +674,4 @@ export function CalendarCell(props: CalendarCellProps): JSX.Element {
593
674
  );
594
675
  }
595
676
 
596
- // Re-export types
597
677
  export type { CalendarState, CalendarDate, DateValue };