@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
@@ -14,7 +14,7 @@ import {
14
14
  createSignal,
15
15
  splitProps,
16
16
  useContext,
17
- } from 'solid-js';
17
+ } from "solid-js";
18
18
  import {
19
19
  createDisclosureState,
20
20
  createDisclosureGroupState,
@@ -22,11 +22,13 @@ import {
22
22
  type DisclosureGroupState,
23
23
  type DisclosureStateProps,
24
24
  type DisclosureGroupStateProps,
25
- } from '@proyecto-viviana/solid-stately';
25
+ } from "@proyecto-viviana/solid-stately";
26
26
  import {
27
27
  createDisclosure,
28
28
  createDisclosureGroup,
29
- } from '@proyecto-viviana/solidaria';
29
+ createFocusRing,
30
+ mergeProps,
31
+ } from "@proyecto-viviana/solidaria";
30
32
  import {
31
33
  type RenderChildren,
32
34
  type ClassNameOrFunction,
@@ -34,17 +36,31 @@ import {
34
36
  useRenderProps,
35
37
  filterDOMProps,
36
38
  dataAttr,
37
- } from './utils';
39
+ } from "./utils";
38
40
 
39
- // ============================================
40
- // TYPES
41
- // ============================================
41
+ type RefLike<T> = T | ((el: T) => void) | { current?: T | null } | undefined;
42
+
43
+ function assignRef<T>(ref: RefLike<T>, el: T): void {
44
+ if (!ref) {
45
+ return;
46
+ }
47
+
48
+ if (typeof ref === "function") {
49
+ (ref as (el: T) => void)(el);
50
+ } else if (typeof ref === "object" && "current" in ref) {
51
+ ref.current = el;
52
+ }
53
+ }
42
54
 
43
55
  export interface DisclosureRenderProps {
44
56
  /** Whether the disclosure is expanded. */
45
57
  isExpanded: boolean;
58
+ /** Whether the disclosure has keyboard focus within. */
59
+ isFocusVisibleWithin: boolean;
46
60
  /** Whether the disclosure is disabled. */
47
61
  isDisabled: boolean;
62
+ /** The disclosure state. */
63
+ state: DisclosureState;
48
64
  }
49
65
 
50
66
  export interface DisclosureGroupRenderProps {
@@ -63,6 +79,8 @@ export interface DisclosureProps extends DisclosureStateProps {
63
79
  isDisabled?: boolean;
64
80
  /** A unique identifier for the disclosure (used in groups). */
65
81
  id?: string;
82
+ /** A ref for the disclosure root element. */
83
+ ref?: RefLike<HTMLDivElement>;
66
84
  }
67
85
 
68
86
  export interface DisclosureGroupProps extends DisclosureGroupStateProps {
@@ -72,30 +90,40 @@ export interface DisclosureGroupProps extends DisclosureGroupStateProps {
72
90
  class?: ClassNameOrFunction<DisclosureGroupRenderProps>;
73
91
  /** The inline style for the element. */
74
92
  style?: StyleOrFunction<DisclosureGroupRenderProps>;
93
+ /** A ref for the disclosure group root element. */
94
+ ref?: RefLike<HTMLDivElement>;
75
95
  }
76
96
 
77
- export interface DisclosureTriggerProps {
97
+ export interface DisclosureTriggerProps extends Omit<
98
+ JSX.ButtonHTMLAttributes<HTMLButtonElement>,
99
+ "children" | "class" | "style" | "type" | "ref"
100
+ > {
78
101
  /** The children of the trigger. */
79
102
  children?: JSX.Element;
80
103
  /** The CSS className for the element. */
81
104
  class?: string;
82
105
  /** The inline style for the element. */
83
106
  style?: JSX.CSSProperties;
107
+ /** A ref for the trigger button element. */
108
+ ref?: RefLike<HTMLButtonElement>;
84
109
  }
85
110
 
86
- export interface DisclosurePanelProps {
111
+ export interface DisclosurePanelProps extends Omit<
112
+ JSX.HTMLAttributes<HTMLElement>,
113
+ "children" | "class" | "style" | "role" | "ref"
114
+ > {
87
115
  /** The children of the panel. */
88
116
  children?: RenderChildren<DisclosureRenderProps>;
89
117
  /** The CSS className for the element. */
90
118
  class?: ClassNameOrFunction<DisclosureRenderProps>;
91
119
  /** The inline style for the element. */
92
120
  style?: StyleOrFunction<DisclosureRenderProps>;
121
+ /** The accessibility role for the disclosure panel. */
122
+ role?: "group" | "region";
123
+ /** A ref for the panel element. */
124
+ ref?: RefLike<HTMLDivElement>;
93
125
  }
94
126
 
95
- // ============================================
96
- // CONTEXT
97
- // ============================================
98
-
99
127
  interface DisclosureContextValue {
100
128
  state: DisclosureState;
101
129
  isDisabled: () => boolean;
@@ -103,6 +131,7 @@ interface DisclosureContextValue {
103
131
  disclosureAria: {
104
132
  readonly buttonProps: JSX.ButtonHTMLAttributes<HTMLButtonElement>;
105
133
  readonly panelProps: JSX.HTMLAttributes<HTMLElement>;
134
+ readonly isPressed: () => boolean;
106
135
  };
107
136
  }
108
137
 
@@ -124,10 +153,6 @@ export function useDisclosureGroupContext(): DisclosureGroupContextValue | null
124
153
  return useContext(DisclosureGroupContext);
125
154
  }
126
155
 
127
- // ============================================
128
- // DISCLOSURE GROUP (Accordion)
129
- // ============================================
130
-
131
156
  /**
132
157
  * DisclosureGroup manages a group of Disclosure components.
133
158
  * Use this to create an accordion where only one item can be expanded at a time.
@@ -152,13 +177,14 @@ export function DisclosureGroup(props: DisclosureGroupProps): JSX.Element {
152
177
  // the context provider renders causes them to evaluate outside the context.
153
178
  // See: https://github.com/solidjs/solid/issues/182
154
179
  const [local, rest] = splitProps(props, [
155
- 'class',
156
- 'style',
157
- 'allowsMultipleExpanded',
158
- 'isDisabled',
159
- 'expandedKeys',
160
- 'defaultExpandedKeys',
161
- 'onExpandedChange',
180
+ "class",
181
+ "style",
182
+ "allowsMultipleExpanded",
183
+ "isDisabled",
184
+ "expandedKeys",
185
+ "defaultExpandedKeys",
186
+ "onExpandedChange",
187
+ "ref",
162
188
  ]);
163
189
 
164
190
  // Create group state
@@ -171,12 +197,8 @@ export function DisclosureGroup(props: DisclosureGroupProps): JSX.Element {
171
197
  }));
172
198
 
173
199
  // Create group accessibility props
174
- const { groupProps } = createDisclosureGroup(
175
- () => ({ isDisabled: local.isDisabled }),
176
- state
177
- );
200
+ const { groupProps } = createDisclosureGroup(() => ({ isDisabled: local.isDisabled }), state);
178
201
 
179
- // Render props values
180
202
  const renderValues = createMemo<DisclosureGroupRenderProps>(() => ({
181
203
  isDisabled: state.isDisabled,
182
204
  }));
@@ -186,15 +208,15 @@ export function DisclosureGroup(props: DisclosureGroupProps): JSX.Element {
186
208
  {
187
209
  class: local.class,
188
210
  style: local.style,
189
- defaultClassName: 'solidaria-DisclosureGroup',
211
+ defaultClassName: "solidaria-DisclosureGroup",
190
212
  },
191
- renderValues
213
+ renderValues,
192
214
  );
193
215
 
194
- // Filter DOM props
195
- const domProps = createMemo(() => filterDOMProps(rest as Record<string, unknown>, { global: true }));
216
+ const domProps = createMemo(() =>
217
+ filterDOMProps(rest as Record<string, unknown>, { global: true }),
218
+ );
196
219
 
197
- // Context value
198
220
  const contextValue: DisclosureGroupContextValue = { state };
199
221
 
200
222
  // Extract ref from groupProps to avoid type conflicts
@@ -204,6 +226,7 @@ export function DisclosureGroup(props: DisclosureGroupProps): JSX.Element {
204
226
  <DisclosureGroupStateContext.Provider value={state}>
205
227
  <DisclosureGroupContext.Provider value={contextValue}>
206
228
  <div
229
+ ref={(el) => assignRef(local.ref, el)}
207
230
  {...domProps()}
208
231
  {...cleanGroupProps}
209
232
  class={renderProps.class()}
@@ -217,10 +240,6 @@ export function DisclosureGroup(props: DisclosureGroupProps): JSX.Element {
217
240
  );
218
241
  }
219
242
 
220
- // ============================================
221
- // DISCLOSURE
222
- // ============================================
223
-
224
243
  /**
225
244
  * Disclosure is a widget that can be toggled to show or hide content.
226
245
  *
@@ -238,13 +257,14 @@ export function Disclosure(props: DisclosureProps): JSX.Element {
238
257
  // the context provider renders causes them to evaluate outside the context.
239
258
  // See: https://github.com/solidjs/solid/issues/182
240
259
  const [local, rest] = splitProps(props, [
241
- 'class',
242
- 'style',
243
- 'isDisabled',
244
- 'isExpanded',
245
- 'defaultExpanded',
246
- 'onExpandedChange',
247
- 'id',
260
+ "class",
261
+ "style",
262
+ "isDisabled",
263
+ "isExpanded",
264
+ "defaultExpanded",
265
+ "onExpandedChange",
266
+ "id",
267
+ "ref",
248
268
  ]);
249
269
 
250
270
  // Check if we're inside a DisclosureGroup
@@ -284,13 +304,17 @@ export function Disclosure(props: DisclosureProps): JSX.Element {
284
304
  const disclosureAria = createDisclosure(
285
305
  () => ({ isDisabled: isDisabled() }),
286
306
  state,
287
- panelRef // Pass the accessor directly
307
+ panelRef, // Pass the accessor directly
288
308
  );
309
+ const { isFocusVisible: isFocusVisibleWithin, focusProps: focusWithinProps } = createFocusRing({
310
+ within: true,
311
+ });
289
312
 
290
- // Render props values
291
313
  const renderValues = createMemo<DisclosureRenderProps>(() => ({
292
314
  isExpanded: state.isExpanded(),
315
+ isFocusVisibleWithin: isFocusVisibleWithin(),
293
316
  isDisabled: isDisabled(),
317
+ state,
294
318
  }));
295
319
 
296
320
  // Resolve render props - don't pass children, we'll render props.children directly
@@ -298,22 +322,22 @@ export function Disclosure(props: DisclosureProps): JSX.Element {
298
322
  {
299
323
  class: local.class,
300
324
  style: local.style,
301
- defaultClassName: 'solidaria-Disclosure',
325
+ defaultClassName: "solidaria-Disclosure",
302
326
  },
303
- renderValues
327
+ renderValues,
304
328
  );
305
329
 
306
- // Filter DOM props
307
- const domProps = createMemo(() => filterDOMProps(rest as Record<string, unknown>, { global: true }));
330
+ const domProps = createMemo(() =>
331
+ filterDOMProps(rest as Record<string, unknown>, { global: true }),
332
+ );
308
333
 
309
334
  // Context value - pass the disclosureAria object with getters intact
310
335
  const contextValue: DisclosureContextValue = {
311
336
  state,
312
- isDisabled, // Pass the accessor function, not the value
337
+ isDisabled, // Pass the accessor function, not the value
313
338
  disclosureAria,
314
339
  };
315
340
 
316
- // Setter for panel ref
317
341
  const setPanelRef = (el: HTMLElement | null) => {
318
342
  setPanelRefSignal(el);
319
343
  };
@@ -323,11 +347,16 @@ export function Disclosure(props: DisclosureProps): JSX.Element {
323
347
  <DisclosureContext.Provider value={contextValue}>
324
348
  <DisclosurePanelRefContext.Provider value={setPanelRef}>
325
349
  <div
326
- {...domProps()}
350
+ ref={(el) => assignRef(local.ref, el)}
351
+ {...mergeProps(
352
+ domProps() as Record<string, unknown>,
353
+ focusWithinProps as Record<string, unknown>,
354
+ )}
327
355
  class={renderProps.class()}
328
356
  style={renderProps.style()}
329
357
  data-expanded={dataAttr(state.isExpanded())}
330
358
  data-disabled={dataAttr(isDisabled())}
359
+ data-focus-visible-within={dataAttr(isFocusVisibleWithin())}
331
360
  >
332
361
  {props.children}
333
362
  </div>
@@ -340,10 +369,6 @@ export function Disclosure(props: DisclosureProps): JSX.Element {
340
369
  // Internal context to pass panel ref setter
341
370
  const DisclosurePanelRefContext = createContext<((el: HTMLElement | null) => void) | null>(null);
342
371
 
343
- // ============================================
344
- // DISCLOSURE TRIGGER
345
- // ============================================
346
-
347
372
  /**
348
373
  * DisclosureTrigger is the button that toggles the disclosure.
349
374
  * Pattern matches SelectTrigger for consistency.
@@ -352,7 +377,7 @@ export function DisclosureTrigger(props: DisclosureTriggerProps): JSX.Element {
352
377
  // Get context - now safe because parent uses lazy children evaluation
353
378
  const context = useContext(DisclosureContext);
354
379
  if (!context) {
355
- throw new Error('DisclosureTrigger must be used within a Disclosure');
380
+ throw new Error("DisclosureTrigger must be used within a Disclosure");
356
381
  }
357
382
 
358
383
  const { state, disclosureAria, isDisabled } = context;
@@ -366,80 +391,102 @@ export function DisclosureTrigger(props: DisclosureTriggerProps): JSX.Element {
366
391
  const { ref: _ref, ...rest } = disclosureAria.buttonProps as Record<string, unknown>;
367
392
  return rest;
368
393
  };
394
+ const { isFocused, isFocusVisible, focusProps } = createFocusRing();
395
+ const [local, rest] = splitProps(props, ["children", "class", "style", "ref"]);
396
+ const domProps = createMemo(() =>
397
+ filterDOMProps(rest as Record<string, unknown>, { global: true }),
398
+ );
399
+ const cleanFocusProps = () => {
400
+ const { ref: _ref, ...rest } = focusProps as Record<string, unknown>;
401
+ return rest;
402
+ };
369
403
 
370
404
  return (
371
405
  <button
372
- {...getButtonProps()}
406
+ {...mergeProps(domProps() as Record<string, unknown>, getButtonProps(), cleanFocusProps())}
407
+ ref={(el) => assignRef(local.ref, el)}
373
408
  type="button"
374
- class={props.class}
375
- style={props.style}
409
+ class={local.class}
410
+ style={local.style}
376
411
  data-expanded={dataAttr(isExpanded())}
377
412
  data-disabled={dataAttr(isDisabled())}
413
+ data-pressed={dataAttr(disclosureAria.isPressed())}
414
+ data-focused={dataAttr(isFocused())}
415
+ data-focus-visible={dataAttr(isFocusVisible())}
378
416
  >
379
- {props.children}
417
+ {local.children}
380
418
  </button>
381
419
  );
382
420
  }
383
421
 
384
- // ============================================
385
- // DISCLOSURE PANEL
386
- // ============================================
387
-
388
422
  /**
389
423
  * DisclosurePanel contains the content that is shown/hidden.
390
424
  */
391
425
  export function DisclosurePanel(props: DisclosurePanelProps): JSX.Element {
392
426
  // Get context - now safe because parent uses lazy children evaluation
393
427
  const context = useContext(DisclosureContext);
428
+ if (!context) {
429
+ throw new Error("DisclosurePanel must be used within a Disclosure");
430
+ }
394
431
  const panelRefSetter = useContext(DisclosurePanelRefContext);
395
432
 
396
- const [local, rest] = splitProps(props, ['class', 'style']);
433
+ const [local, rest] = splitProps(props, ["class", "style", "role", "ref"]);
434
+ const { isFocusVisible: isFocusVisibleWithin, focusProps: focusWithinProps } = createFocusRing({
435
+ within: true,
436
+ });
397
437
 
398
438
  // Reactive accessors
399
- const isExpanded = () => context?.state.isExpanded() ?? false;
400
- const isDisabled = () => context?.isDisabled() ?? false;
439
+ const isExpanded = () => context.state.isExpanded();
440
+ const isDisabled = () => context.isDisabled();
401
441
 
402
- // Render props values
403
442
  const renderValues = createMemo<DisclosureRenderProps>(() => ({
404
443
  isExpanded: isExpanded(),
444
+ isFocusVisibleWithin: isFocusVisibleWithin(),
405
445
  isDisabled: isDisabled(),
446
+ state: context.state,
406
447
  }));
407
448
 
408
- // Resolve render props
409
449
  const renderProps = useRenderProps(
410
450
  {
411
451
  children: props.children,
412
452
  class: local.class,
413
453
  style: local.style,
414
- defaultClassName: 'solidaria-DisclosurePanel',
454
+ defaultClassName: "solidaria-DisclosurePanel",
415
455
  },
416
- renderValues
456
+ renderValues,
417
457
  );
418
458
 
419
- // Filter DOM props
420
- const domProps = createMemo(() => filterDOMProps(rest as Record<string, unknown>, { global: true }));
459
+ const domProps = createMemo(() =>
460
+ filterDOMProps(rest as Record<string, unknown>, { global: true }),
461
+ );
421
462
 
422
463
  // Get panelProps from the getter each time - this ensures reactivity
423
464
  // IMPORTANT: Call the getter fresh each render to get updated hidden attribute, etc.
424
465
  const getPanelProps = () => {
425
- if (!context) return { id: undefined, role: 'region', 'aria-labelledby': undefined, hidden: true };
426
466
  const { ref: _ref, ...rest } = context.disclosureAria.panelProps as Record<string, unknown>;
427
467
  return rest;
428
468
  };
429
469
 
430
470
  return (
431
471
  <div
432
- {...domProps()}
472
+ {...mergeProps(
473
+ domProps() as Record<string, unknown>,
474
+ focusWithinProps as Record<string, unknown>,
475
+ )}
433
476
  {...getPanelProps()}
434
- ref={(el) => panelRefSetter?.(el)}
477
+ ref={(el) => {
478
+ panelRefSetter?.(el);
479
+ assignRef(local.ref, el);
480
+ }}
481
+ role={local.role ?? "group"}
435
482
  class={renderProps.class()}
436
483
  style={renderProps.style()}
437
484
  data-expanded={dataAttr(isExpanded())}
485
+ data-focus-visible-within={dataAttr(isFocusVisibleWithin())}
438
486
  >
439
487
  {renderProps.renderChildren()}
440
488
  </div>
441
489
  );
442
490
  }
443
491
 
444
- // Re-export state types for convenience
445
492
  export type { DisclosureState, DisclosureGroupState };