@proyecto-viviana/solidaria-components 0.2.9 → 0.3.1

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 +23253 -18564
  139. package/dist/index.js.map +1 -1
  140. package/dist/index.jsx +18116 -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 +251 -176
  186. package/src/NumberField.tsx +139 -143
  187. package/src/Popover.tsx +396 -234
  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 +216 -158
  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 +49 -60
  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
@@ -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,14 +16,15 @@ import {
15
16
  For,
16
17
  Index,
17
18
  Show,
18
- } from 'solid-js';
19
+ } from "solid-js";
19
20
  import {
20
21
  createRangeCalendar,
21
22
  createCalendarGrid,
22
23
  createRangeCalendarCell,
24
+ createHover,
23
25
  type AriaRangeCalendarProps,
24
26
  type AriaCalendarGridProps,
25
- } from '@proyecto-viviana/solidaria';
27
+ } from "@proyecto-viviana/solidaria";
26
28
  import {
27
29
  createRangeCalendarState,
28
30
  type RangeCalendarState,
@@ -32,7 +34,7 @@ import {
32
34
  type RangeValue,
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,24 +43,38 @@ 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 RangeCalendarRenderProps {
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
  /** Whether the user is currently selecting a range. */
56
71
  isDragging: boolean;
57
72
  }
58
73
 
59
74
  export interface RangeCalendarProps<T extends DateValue = DateValue>
60
- extends Omit<AriaRangeCalendarProps, 'id' | 'isDisabled' | 'isReadOnly'>,
61
- Omit<RangeCalendarStateProps<T>, 'locale'>,
75
+ extends
76
+ Omit<AriaRangeCalendarProps, "id" | "isDisabled" | "isReadOnly">,
77
+ Omit<RangeCalendarStateProps<T>, "locale">,
62
78
  SlotProps {
63
79
  /** The children of the component. */
64
80
  children?: JSX.Element;
@@ -68,6 +84,8 @@ export interface RangeCalendarProps<T extends DateValue = DateValue>
68
84
  style?: StyleOrFunction<RangeCalendarRenderProps>;
69
85
  /** The locale to use for formatting. */
70
86
  locale?: string;
87
+ /** Ref for the range calendar root element. */
88
+ ref?: RefLike<HTMLDivElement>;
71
89
  }
72
90
 
73
91
  export interface RangeCalendarGridRenderProps {
@@ -75,13 +93,18 @@ export interface RangeCalendarGridRenderProps {
75
93
  isDisabled: boolean;
76
94
  }
77
95
 
78
- export interface RangeCalendarGridProps extends Omit<AriaCalendarGridProps, 'startDate' | 'endDate'>, SlotProps {
96
+ export interface RangeCalendarGridProps
97
+ extends Omit<AriaCalendarGridProps, "startDate" | "endDate">, SlotProps {
79
98
  /** The children of the component (render function receiving dates). */
80
99
  children?: (date: CalendarDate) => JSX.Element;
81
100
  /** The CSS className for the element. */
82
101
  class?: ClassNameOrFunction<RangeCalendarGridRenderProps>;
83
102
  /** The inline style for the element. */
84
103
  style?: StyleOrFunction<RangeCalendarGridRenderProps>;
104
+ /** Class name for weekday header cells. */
105
+ headerCellClass?: string;
106
+ /** Inline style for weekday header cells. */
107
+ headerCellStyle?: JSX.CSSProperties;
85
108
  /** Number of months to offset from the start. */
86
109
  offset?: { months?: number };
87
110
  }
@@ -99,12 +122,24 @@ export interface RangeCalendarCellRenderProps {
99
122
  isDisabled: boolean;
100
123
  /** Whether the cell is unavailable. */
101
124
  isUnavailable: boolean;
125
+ /** Whether the cell is part of an invalid selection. */
126
+ isInvalid: boolean;
102
127
  /** Whether the cell is outside the visible month. */
103
128
  isOutsideMonth: boolean;
104
129
  /** Whether the cell represents today. */
105
130
  isToday: boolean;
106
131
  /** Whether the cell is pressed. */
107
132
  isPressed: boolean;
133
+ /** Whether the cell is hovered. */
134
+ isHovered: boolean;
135
+ /** Whether the cell is the first day slot in its row. */
136
+ isFirstChild: boolean;
137
+ /** Whether the cell is the last day slot in its row. */
138
+ isLastChild: boolean;
139
+ /** Whether the cell is in the first rendered week row. */
140
+ isFirstWeek: boolean;
141
+ /** Whether the cell is in the last rendered week row. */
142
+ isLastWeek: boolean;
108
143
  /** The formatted date string. */
109
144
  formattedDate: string;
110
145
  }
@@ -118,28 +153,29 @@ export interface RangeCalendarCellProps extends SlotProps {
118
153
  class?: ClassNameOrFunction<RangeCalendarCellRenderProps>;
119
154
  /** The inline style for the element. */
120
155
  style?: StyleOrFunction<RangeCalendarCellRenderProps>;
156
+ /** Class name for the table cell wrapper. */
157
+ cellClass?: ClassNameOrFunction<RangeCalendarCellRenderProps>;
158
+ /** Inline style for the table cell wrapper. */
159
+ cellStyle?: StyleOrFunction<RangeCalendarCellRenderProps>;
121
160
  }
122
161
 
123
- // ============================================
124
- // CONTEXT
125
- // ============================================
126
-
127
162
  export const RangeCalendarContext = createContext<RangeCalendarState<DateValue> | null>(null);
128
163
  export const RangeCalendarStateContext = createContext<RangeCalendarState<DateValue> | null>(null);
129
- const RangeCalendarGridMonthContext = createContext<CalendarDate | null>(null);
164
+ const RangeCalendarGridMonthContext = createContext<Accessor<CalendarDate> | null>(null);
165
+ const RangeCalendarGridCellPositionContext = createContext<Accessor<{
166
+ weekIndex: number;
167
+ dayIndex: number;
168
+ lastWeekIndex: number;
169
+ }> | null>(null);
130
170
 
131
171
  export function useRangeCalendarContext(): RangeCalendarState<DateValue> {
132
172
  const context = useContext(RangeCalendarContext);
133
173
  if (!context) {
134
- throw new Error('RangeCalendar components must be used within a RangeCalendar');
174
+ throw new Error("RangeCalendar components must be used within a RangeCalendar");
135
175
  }
136
176
  return context;
137
177
  }
138
178
 
139
- // ============================================
140
- // RANGE CALENDAR COMPONENT
141
- // ============================================
142
-
143
179
  /**
144
180
  * A range calendar displays a grid of days and allows users to select a contiguous range of dates.
145
181
  *
@@ -158,7 +194,7 @@ export function useRangeCalendarContext(): RangeCalendarState<DateValue> {
158
194
  * ```
159
195
  */
160
196
  export function RangeCalendar<T extends DateValue = CalendarDate>(
161
- props: RangeCalendarProps<T>
197
+ props: RangeCalendarProps<T>,
162
198
  ): JSX.Element {
163
199
  // Use hydration-safe pattern for client-only rendering
164
200
  const isHydrated = useIsHydrated();
@@ -166,7 +202,12 @@ export function RangeCalendar<T extends DateValue = CalendarDate>(
166
202
  return (
167
203
  <Show
168
204
  when={isHydrated()}
169
- fallback={<div class="solidaria-RangeCalendar solidaria-RangeCalendar--placeholder" aria-hidden="true" />}
205
+ fallback={
206
+ <div
207
+ class="solidaria-RangeCalendar solidaria-RangeCalendar--placeholder"
208
+ aria-hidden="true"
209
+ />
210
+ }
170
211
  >
171
212
  <RangeCalendarInner {...props} />
172
213
  </Show>
@@ -177,53 +218,53 @@ export function RangeCalendar<T extends DateValue = CalendarDate>(
177
218
  * Internal RangeCalendar component that renders after client mount.
178
219
  */
179
220
  function RangeCalendarInner<T extends DateValue = CalendarDate>(
180
- props: RangeCalendarProps<T>
221
+ props: RangeCalendarProps<T>,
181
222
  ): JSX.Element {
182
223
  const [local, stateProps, rest] = splitProps(
183
224
  props,
184
- ['children', 'class', 'style', 'slot'],
225
+ ["children", "class", "style", "slot", "ref"],
185
226
  [
186
- 'value',
187
- 'defaultValue',
188
- 'onChange',
189
- 'minValue',
190
- 'maxValue',
191
- 'isDisabled',
192
- 'isReadOnly',
193
- 'focusedValue',
194
- 'defaultFocusedValue',
195
- 'onFocusChange',
196
- 'locale',
197
- 'isDateUnavailable',
198
- 'visibleMonths',
199
- 'isDateDisabled',
200
- 'validationState',
201
- 'allowsNonContiguousRanges',
202
- 'firstDayOfWeek',
203
- ]
227
+ "value",
228
+ "defaultValue",
229
+ "onChange",
230
+ "minValue",
231
+ "maxValue",
232
+ "isDisabled",
233
+ "isReadOnly",
234
+ "focusedValue",
235
+ "defaultFocusedValue",
236
+ "onFocusChange",
237
+ "locale",
238
+ "createCalendar",
239
+ "isDateUnavailable",
240
+ "visibleMonths",
241
+ "pageBehavior",
242
+ "selectionAlignment",
243
+ "isDateDisabled",
244
+ "validationState",
245
+ "allowsNonContiguousRanges",
246
+ "firstDayOfWeek",
247
+ ],
204
248
  );
205
249
 
206
- // Create range calendar state
207
250
  const state = createRangeCalendarState(stateProps);
208
251
 
209
- // Create range calendar ARIA props
210
252
  const calendarAria = createRangeCalendar(rest, state as unknown as RangeCalendarState<DateValue>);
211
253
 
212
- // Render props values
213
254
  const renderValues = createMemo<RangeCalendarRenderProps>(() => ({
214
255
  isDisabled: state.isDisabled(),
215
256
  isReadOnly: state.isReadOnly(),
257
+ isInvalid: state.isValueInvalid(),
216
258
  isDragging: state.isDragging(),
217
259
  }));
218
260
 
219
- // Resolve render props
220
261
  const renderProps = useRenderProps(
221
262
  {
222
263
  class: local.class,
223
264
  style: local.style,
224
- defaultClassName: 'solidaria-RangeCalendar',
265
+ defaultClassName: "solidaria-RangeCalendar",
225
266
  },
226
- renderValues
267
+ renderValues,
227
268
  );
228
269
 
229
270
  return (
@@ -231,12 +272,17 @@ function RangeCalendarInner<T extends DateValue = CalendarDate>(
231
272
  <RangeCalendarContext.Provider value={state as unknown as RangeCalendarState<DateValue>}>
232
273
  <div
233
274
  {...calendarAria.calendarProps}
275
+ ref={(el) => assignRef(local.ref, el)}
234
276
  class={renderProps.class()}
235
277
  style={renderProps.style()}
236
278
  data-disabled={dataAttr(state.isDisabled())}
237
279
  data-readonly={dataAttr(state.isReadOnly())}
280
+ data-invalid={dataAttr(state.isValueInvalid())}
238
281
  data-dragging={dataAttr(state.isDragging())}
239
282
  >
283
+ <VisuallyHidden>
284
+ <h2>{String(calendarAria.calendarProps["aria-label"] ?? "")}</h2>
285
+ </VisuallyHidden>
240
286
  {props.children}
241
287
  </div>
242
288
  </RangeCalendarContext.Provider>
@@ -244,10 +290,6 @@ function RangeCalendarInner<T extends DateValue = CalendarDate>(
244
290
  );
245
291
  }
246
292
 
247
- // ============================================
248
- // RANGE CALENDAR HEADING COMPONENT
249
- // ============================================
250
-
251
293
  export interface RangeCalendarHeadingProps extends SlotProps {
252
294
  /** The CSS className for the element. */
253
295
  class?: string;
@@ -263,7 +305,7 @@ export function RangeCalendarHeading(props: RangeCalendarHeadingProps): JSX.Elem
263
305
 
264
306
  return (
265
307
  <h2
266
- class={props.class ?? 'solidaria-RangeCalendarHeading'}
308
+ class={props.class ?? "solidaria-RangeCalendarHeading"}
267
309
  style={props.style}
268
310
  aria-live="polite"
269
311
  >
@@ -272,13 +314,9 @@ export function RangeCalendarHeading(props: RangeCalendarHeadingProps): JSX.Elem
272
314
  );
273
315
  }
274
316
 
275
- // ============================================
276
- // RANGE CALENDAR BUTTON COMPONENT
277
- // ============================================
278
-
279
317
  export interface RangeCalendarButtonProps extends SlotProps {
280
318
  /** The slot for this button (previous or next). */
281
- slot?: 'previous' | 'next';
319
+ slot?: "previous" | "next";
282
320
  /** The children of the component. */
283
321
  children?: JSX.Element;
284
322
  /** The CSS className for the element. */
@@ -297,28 +335,27 @@ export function RangeCalendarButton(props: RangeCalendarButtonProps): JSX.Elemen
297
335
  const calendarAria = createRangeCalendar({}, state);
298
336
 
299
337
  const buttonProps = createMemo(() => {
300
- if (props.slot === 'previous') {
338
+ if (props.slot === "previous") {
301
339
  return calendarAria.prevButtonProps;
302
340
  }
303
341
  return calendarAria.nextButtonProps;
304
342
  });
343
+ const isDisabled = createMemo(
344
+ () => props.isDisabled || Boolean(buttonProps().disabled) || state.isDisabled(),
345
+ );
305
346
 
306
347
  return (
307
348
  <button
308
349
  {...buttonProps()}
309
- class={props.class ?? 'solidaria-RangeCalendarButton'}
350
+ class={props.class ?? "solidaria-RangeCalendarButton"}
310
351
  style={props.style}
311
- disabled={props.isDisabled || state.isDisabled()}
352
+ disabled={isDisabled()}
312
353
  >
313
354
  {props.children}
314
355
  </button>
315
356
  );
316
357
  }
317
358
 
318
- // ============================================
319
- // RANGE CALENDAR GRID COMPONENT
320
- // ============================================
321
-
322
359
  /**
323
360
  * Displays a grid of range calendar cells.
324
361
  */
@@ -331,7 +368,6 @@ export function RangeCalendarGrid(props: RangeCalendarGridProps): JSX.Element {
331
368
  return offsetMonths ? baseStart.add({ months: offsetMonths }) : baseStart;
332
369
  });
333
370
 
334
- // Create grid ARIA props
335
371
  const gridAria = createCalendarGrid(
336
372
  {
337
373
  startDate: startDate(),
@@ -339,22 +375,20 @@ export function RangeCalendarGrid(props: RangeCalendarGridProps): JSX.Element {
339
375
  weekdayStyle: props.weekdayStyle,
340
376
  },
341
377
  state as unknown as Parameters<typeof createCalendarGrid>[1],
342
- gridRef
378
+ gridRef,
343
379
  );
344
380
 
345
- // Render props values
346
381
  const renderValues = createMemo<RangeCalendarGridRenderProps>(() => ({
347
382
  isDisabled: state.isDisabled(),
348
383
  }));
349
384
 
350
- // Resolve render props
351
385
  const renderProps = useRenderProps(
352
386
  {
353
387
  class: props.class,
354
388
  style: props.style,
355
- defaultClassName: 'solidaria-RangeCalendarGrid',
389
+ defaultClassName: "solidaria-RangeCalendarGrid",
356
390
  },
357
- renderValues
391
+ renderValues,
358
392
  );
359
393
 
360
394
  // Memoize all dates for the grid to avoid reactive loops in render paths.
@@ -371,7 +405,7 @@ export function RangeCalendarGrid(props: RangeCalendarGridProps): JSX.Element {
371
405
  });
372
406
 
373
407
  return (
374
- <RangeCalendarGridMonthContext.Provider value={startDate()}>
408
+ <RangeCalendarGridMonthContext.Provider value={startDate}>
375
409
  <table
376
410
  ref={setGridRef}
377
411
  {...gridAria.gridProps}
@@ -382,7 +416,11 @@ export function RangeCalendarGrid(props: RangeCalendarGridProps): JSX.Element {
382
416
  <tr>
383
417
  <For each={gridAria.weekDays}>
384
418
  {(day) => (
385
- <th scope="col" class="solidaria-RangeCalendarHeaderCell">
419
+ <th
420
+ scope="col"
421
+ class={props.headerCellClass ?? "solidaria-RangeCalendarHeaderCell"}
422
+ style={props.headerCellStyle}
423
+ >
386
424
  {day}
387
425
  </th>
388
426
  )}
@@ -391,12 +429,20 @@ export function RangeCalendarGrid(props: RangeCalendarGridProps): JSX.Element {
391
429
  </thead>
392
430
  <tbody>
393
431
  <Index each={allDates()}>
394
- {(weekDates) => (
432
+ {(weekDates, weekIndex) => (
395
433
  <tr>
396
434
  <Index each={weekDates()}>
397
- {(date) => (
435
+ {(date, dayIndex) => (
398
436
  <Show when={date()} fallback={<td />}>
399
- {props.children?.(date()!)}
437
+ <RangeCalendarGridCellPositionContext.Provider
438
+ value={() => ({
439
+ weekIndex,
440
+ dayIndex,
441
+ lastWeekIndex: allDates().length - 1,
442
+ })}
443
+ >
444
+ {props.children?.(date()!)}
445
+ </RangeCalendarGridCellPositionContext.Provider>
400
446
  </Show>
401
447
  )}
402
448
  </Index>
@@ -409,32 +455,38 @@ export function RangeCalendarGrid(props: RangeCalendarGridProps): JSX.Element {
409
455
  );
410
456
  }
411
457
 
412
- // ============================================
413
- // RANGE CALENDAR CELL COMPONENT
414
- // ============================================
415
-
416
458
  /**
417
459
  * A cell in the range calendar grid representing a single day.
418
460
  */
419
461
  export function RangeCalendarCell(props: RangeCalendarCellProps): JSX.Element {
420
462
  const state = useRangeCalendarContext();
421
463
  const currentMonthStart = useContext(RangeCalendarGridMonthContext);
464
+ const cellPosition = useContext(RangeCalendarGridCellPositionContext);
422
465
  const [cellRef, setCellRef] = createSignal<HTMLDivElement | null>(null);
423
466
  const isOutsideMonth = createMemo(
424
- () => currentMonthStart != null && !isSameMonth(currentMonthStart, props.date)
467
+ () => currentMonthStart != null && !isSameMonth(currentMonthStart(), props.date),
468
+ );
469
+ const position = createMemo(
470
+ () =>
471
+ cellPosition?.() ?? {
472
+ weekIndex: 0,
473
+ dayIndex: 0,
474
+ lastWeekIndex: 0,
475
+ },
425
476
  );
426
477
 
427
- // Create cell ARIA props
428
478
  const cellAria = createRangeCalendarCell(
429
479
  () => ({
430
480
  date: props.date,
431
481
  isOutsideMonth: isOutsideMonth(),
432
482
  }),
433
483
  state,
434
- cellRef
484
+ cellRef,
435
485
  );
486
+ const { hoverProps, isHovered } = createHover(() => ({
487
+ isDisabled: cellAria.isDisabled || cellAria.isUnavailable,
488
+ }));
436
489
 
437
- // Render props values
438
490
  const renderValues = createMemo<RangeCalendarCellRenderProps>(() => ({
439
491
  isSelected: cellAria.isSelected,
440
492
  isSelectionStart: cellAria.isSelectionStart,
@@ -442,36 +494,50 @@ export function RangeCalendarCell(props: RangeCalendarCellProps): JSX.Element {
442
494
  isFocused: cellAria.isFocused,
443
495
  isDisabled: cellAria.isDisabled,
444
496
  isUnavailable: cellAria.isUnavailable,
497
+ isInvalid: cellAria.isInvalid,
445
498
  isOutsideMonth: cellAria.isOutsideMonth,
446
499
  isToday: cellAria.isToday,
447
500
  isPressed: cellAria.isPressed,
501
+ isHovered: isHovered(),
502
+ isFirstChild: position().dayIndex === 0,
503
+ isLastChild: position().dayIndex === 6,
504
+ isFirstWeek: position().weekIndex === 0,
505
+ isLastWeek: position().weekIndex === position().lastWeekIndex,
448
506
  formattedDate: cellAria.formattedDate,
449
507
  }));
450
508
 
451
- // Resolve render props
452
509
  const renderProps = useRenderProps(
453
510
  {
454
511
  children: props.children,
455
512
  class: props.class,
456
513
  style: props.style,
457
- defaultClassName: 'solidaria-RangeCalendarCell',
514
+ defaultClassName: "solidaria-RangeCalendarCell",
515
+ },
516
+ renderValues,
517
+ );
518
+ const cellRenderProps = useRenderProps(
519
+ {
520
+ class: props.cellClass,
521
+ style: props.cellStyle,
522
+ defaultClassName: "solidaria-RangeCalendarCellWrapper",
458
523
  },
459
- renderValues
524
+ renderValues,
460
525
  );
461
526
 
462
527
  // Determine children content - avoid Show for SSR hydration compatibility
463
528
  const getChildren = () => {
464
- if (typeof props.children === 'function') {
529
+ if (typeof props.children === "function") {
465
530
  return renderProps.renderChildren();
466
531
  }
467
532
  return cellAria.formattedDate;
468
533
  };
469
534
 
470
535
  return (
471
- <td {...cellAria.cellProps}>
536
+ <td {...cellAria.cellProps} class={cellRenderProps.class()} style={cellRenderProps.style()}>
472
537
  <div
473
538
  ref={setCellRef}
474
539
  {...cellAria.buttonProps}
540
+ {...hoverProps}
475
541
  class={renderProps.class()}
476
542
  style={renderProps.style()}
477
543
  data-selected={dataAttr(cellAria.isSelected)}
@@ -480,9 +546,11 @@ export function RangeCalendarCell(props: RangeCalendarCellProps): JSX.Element {
480
546
  data-focused={dataAttr(cellAria.isFocused)}
481
547
  data-disabled={dataAttr(cellAria.isDisabled)}
482
548
  data-unavailable={dataAttr(cellAria.isUnavailable)}
549
+ data-invalid={dataAttr(cellAria.isInvalid)}
483
550
  data-outside-month={dataAttr(cellAria.isOutsideMonth)}
484
551
  data-today={dataAttr(cellAria.isToday)}
485
552
  data-pressed={dataAttr(cellAria.isPressed)}
553
+ data-hovered={dataAttr(isHovered())}
486
554
  >
487
555
  {getChildren()}
488
556
  </div>
@@ -490,5 +558,4 @@ export function RangeCalendarCell(props: RangeCalendarCellProps): JSX.Element {
490
558
  );
491
559
  }
492
560
 
493
- // Re-export types
494
561
  export type { RangeCalendarState, RangeValue };