@proyecto-viviana/solidaria-components 0.3.2 → 0.4.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.
- package/dist/ActionBar.js +184 -0
- package/dist/ActionBar.js.map +1 -0
- package/dist/ActionBar.jsx +128 -0
- package/dist/ActionBar.jsx.map +1 -0
- package/dist/ActionGroup.js +179 -0
- package/dist/ActionGroup.js.map +1 -0
- package/dist/ActionGroup.jsx +129 -0
- package/dist/ActionGroup.jsx.map +1 -0
- package/dist/Alert.js +111 -0
- package/dist/Alert.js.map +1 -0
- package/dist/Alert.jsx +82 -0
- package/dist/Alert.jsx.map +1 -0
- package/dist/Autocomplete.js +130 -0
- package/dist/Autocomplete.js.map +1 -0
- package/dist/Autocomplete.jsx +116 -0
- package/dist/Autocomplete.jsx.map +1 -0
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Breadcrumbs.js +334 -0
- package/dist/Breadcrumbs.js.map +1 -0
- package/dist/Breadcrumbs.jsx +266 -0
- package/dist/Breadcrumbs.jsx.map +1 -0
- package/dist/Button.d.ts.map +1 -1
- package/dist/Button.js +348 -0
- package/dist/Button.js.map +1 -0
- package/dist/Button.jsx +314 -0
- package/dist/Button.jsx.map +1 -0
- package/dist/Calendar.d.ts +4 -4
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Calendar.js +538 -0
- package/dist/Calendar.js.map +1 -0
- package/dist/Calendar.jsx +333 -0
- package/dist/Calendar.jsx.map +1 -0
- package/dist/CalendarPicker.d.ts +33 -0
- package/dist/CalendarPicker.d.ts.map +1 -0
- package/dist/CalendarPicker.js +44 -0
- package/dist/CalendarPicker.js.map +1 -0
- package/dist/CalendarPicker.jsx +44 -0
- package/dist/CalendarPicker.jsx.map +1 -0
- package/dist/Checkbox.d.ts +83 -4
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox.js +923 -0
- package/dist/Checkbox.js.map +1 -0
- package/dist/Checkbox.jsx +707 -0
- package/dist/Checkbox.jsx.map +1 -0
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +202 -0
- package/dist/Collection.js.map +1 -0
- package/dist/Collection.jsx +152 -0
- package/dist/Collection.jsx.map +1 -0
- package/dist/Color.d.ts.map +1 -1
- package/dist/Color.js +1720 -0
- package/dist/Color.js.map +1 -0
- package/dist/Color.jsx +1344 -0
- package/dist/Color.jsx.map +1 -0
- package/dist/ColorEditor.js +208 -0
- package/dist/ColorEditor.js.map +1 -0
- package/dist/ColorEditor.jsx +120 -0
- package/dist/ColorEditor.jsx.map +1 -0
- package/dist/ComboBox.d.ts +4 -4
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ComboBox.js +992 -0
- package/dist/ComboBox.js.map +1 -0
- package/dist/ComboBox.jsx +714 -0
- package/dist/ComboBox.jsx.map +1 -0
- package/dist/ContextualHelpTrigger.js +146 -0
- package/dist/ContextualHelpTrigger.js.map +1 -0
- package/dist/ContextualHelpTrigger.jsx +109 -0
- package/dist/ContextualHelpTrigger.jsx.map +1 -0
- package/dist/DateField.d.ts +3 -3
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DateField.js +4 -0
- package/dist/DateField.jsx +4 -0
- package/dist/DateField2.js +499 -0
- package/dist/DateField2.js.map +1 -0
- package/dist/DateField2.jsx +317 -0
- package/dist/DateField2.jsx.map +1 -0
- package/dist/DatePicker.d.ts +4 -4
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DatePicker.js +991 -0
- package/dist/DatePicker.js.map +1 -0
- package/dist/DatePicker.jsx +682 -0
- package/dist/DatePicker.jsx.map +1 -0
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +337 -0
- package/dist/Dialog.js.map +1 -0
- package/dist/Dialog.jsx +192 -0
- package/dist/Dialog.jsx.map +1 -0
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/Disclosure.js +328 -0
- package/dist/Disclosure.js.map +1 -0
- package/dist/Disclosure.jsx +230 -0
- package/dist/Disclosure.jsx.map +1 -0
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragAndDrop.js +176 -0
- package/dist/DragAndDrop.js.map +1 -0
- package/dist/DragAndDrop.jsx +160 -0
- package/dist/DragAndDrop.jsx.map +1 -0
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/DropZone.js +189 -0
- package/dist/DropZone.js.map +1 -0
- package/dist/DropZone.jsx +144 -0
- package/dist/DropZone.jsx.map +1 -0
- package/dist/FieldError.js +66 -0
- package/dist/FieldError.js.map +1 -0
- package/dist/FieldError.jsx +47 -0
- package/dist/FieldError.jsx.map +1 -0
- package/dist/FileTrigger.js +79 -0
- package/dist/FileTrigger.js.map +1 -0
- package/dist/FileTrigger.jsx +49 -0
- package/dist/FileTrigger.jsx.map +1 -0
- package/dist/Focusable.js +70 -0
- package/dist/Focusable.js.map +1 -0
- package/dist/Focusable.jsx +69 -0
- package/dist/Focusable.jsx.map +1 -0
- package/dist/Form.js +99 -0
- package/dist/Form.js.map +1 -0
- package/dist/Form.jsx +73 -0
- package/dist/Form.jsx.map +1 -0
- package/dist/GridList.d.ts +34 -2
- package/dist/GridList.d.ts.map +1 -1
- package/dist/GridList.js +723 -0
- package/dist/GridList.js.map +1 -0
- package/dist/GridList.jsx +552 -0
- package/dist/GridList.jsx.map +1 -0
- package/dist/HiddenTimeInput.js +104 -0
- package/dist/HiddenTimeInput.js.map +1 -0
- package/dist/HiddenTimeInput.jsx +69 -0
- package/dist/HiddenTimeInput.jsx.map +1 -0
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Icon.js +127 -0
- package/dist/Icon.js.map +1 -0
- package/dist/Icon.jsx +72 -0
- package/dist/Icon.jsx.map +1 -0
- package/dist/Keyboard.js +30 -0
- package/dist/Keyboard.js.map +1 -0
- package/dist/Keyboard.jsx +24 -0
- package/dist/Keyboard.jsx.map +1 -0
- package/dist/Landmark.js +134 -0
- package/dist/Landmark.js.map +1 -0
- package/dist/Landmark.jsx +118 -0
- package/dist/Landmark.jsx.map +1 -0
- package/dist/Link.d.ts.map +1 -1
- package/dist/Link.js +219 -0
- package/dist/Link.js.map +1 -0
- package/dist/Link.jsx +189 -0
- package/dist/Link.jsx.map +1 -0
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListBox.js +670 -0
- package/dist/ListBox.js.map +1 -0
- package/dist/ListBox.jsx +508 -0
- package/dist/ListBox.jsx.map +1 -0
- package/dist/Menu.d.ts +27 -9
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Menu.js +1254 -0
- package/dist/Menu.js.map +1 -0
- package/dist/Menu.jsx +1042 -0
- package/dist/Menu.jsx.map +1 -0
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Meter.js +123 -0
- package/dist/Meter.js.map +1 -0
- package/dist/Meter.jsx +107 -0
- package/dist/Meter.jsx.map +1 -0
- package/dist/Modal.d.ts.map +1 -1
- package/dist/Modal.js +380 -0
- package/dist/Modal.js.map +1 -0
- package/dist/Modal.jsx +314 -0
- package/dist/Modal.jsx.map +1 -0
- package/dist/NumberField.d.ts +3 -3
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/NumberField.js +573 -0
- package/dist/NumberField.js.map +1 -0
- package/dist/NumberField.jsx +443 -0
- package/dist/NumberField.jsx.map +1 -0
- package/dist/Popover.d.ts +10 -2
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Popover.js +464 -0
- package/dist/Popover.js.map +1 -0
- package/dist/Popover.jsx +333 -0
- package/dist/Popover.jsx.map +1 -0
- package/dist/Pressable.js +69 -0
- package/dist/Pressable.js.map +1 -0
- package/dist/Pressable.jsx +68 -0
- package/dist/Pressable.jsx.map +1 -0
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/ProgressBar.js +130 -0
- package/dist/ProgressBar.js.map +1 -0
- package/dist/ProgressBar.jsx +114 -0
- package/dist/ProgressBar.jsx.map +1 -0
- package/dist/RadioGroup.d.ts +82 -4
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RadioGroup.js +931 -0
- package/dist/RadioGroup.js.map +1 -0
- package/dist/RadioGroup.jsx +681 -0
- package/dist/RadioGroup.jsx.map +1 -0
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RangeCalendar.js +410 -0
- package/dist/RangeCalendar.js.map +1 -0
- package/dist/RangeCalendar.jsx +253 -0
- package/dist/RangeCalendar.jsx.map +1 -0
- package/dist/RouterProvider.js +118 -0
- package/dist/RouterProvider.js.map +1 -0
- package/dist/RouterProvider.jsx +112 -0
- package/dist/RouterProvider.jsx.map +1 -0
- package/dist/SearchField.d.ts +2 -2
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/SearchField.js +643 -0
- package/dist/SearchField.js.map +1 -0
- package/dist/SearchField.jsx +526 -0
- package/dist/SearchField.jsx.map +1 -0
- package/dist/Select.d.ts.map +1 -1
- package/dist/Select.js +1031 -0
- package/dist/Select.js.map +1 -0
- package/dist/Select.jsx +744 -0
- package/dist/Select.jsx.map +1 -0
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/SelectionIndicator.js +86 -0
- package/dist/SelectionIndicator.js.map +1 -0
- package/dist/SelectionIndicator.jsx +50 -0
- package/dist/SelectionIndicator.jsx.map +1 -0
- package/dist/Separator.js +97 -0
- package/dist/Separator.js.map +1 -0
- package/dist/Separator.jsx +85 -0
- package/dist/Separator.jsx.map +1 -0
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/SharedElementTransition.js +165 -0
- package/dist/SharedElementTransition.js.map +1 -0
- package/dist/SharedElementTransition.jsx +138 -0
- package/dist/SharedElementTransition.jsx.map +1 -0
- package/dist/Slider.d.ts +33 -1
- package/dist/Slider.d.ts.map +1 -1
- package/dist/Slider.js +515 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Slider.jsx +403 -0
- package/dist/Slider.jsx.map +1 -0
- package/dist/StepList.js +198 -0
- package/dist/StepList.js.map +1 -0
- package/dist/StepList.jsx +141 -0
- package/dist/StepList.jsx.map +1 -0
- package/dist/Switch.d.ts +65 -2
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Switch.js +534 -0
- package/dist/Switch.js.map +1 -0
- package/dist/Switch.jsx +393 -0
- package/dist/Switch.jsx.map +1 -0
- package/dist/Table.d.ts +48 -0
- package/dist/Table.d.ts.map +1 -1
- package/dist/Table.js +1759 -0
- package/dist/Table.js.map +1 -0
- package/dist/Table.jsx +1348 -0
- package/dist/Table.jsx.map +1 -0
- package/dist/Tabs.d.ts +0 -4
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/Tabs.js +595 -0
- package/dist/Tabs.js.map +1 -0
- package/dist/Tabs.jsx +367 -0
- package/dist/Tabs.jsx.map +1 -0
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/TagGroup.js +378 -0
- package/dist/TagGroup.js.map +1 -0
- package/dist/TagGroup.jsx +270 -0
- package/dist/TagGroup.jsx.map +1 -0
- package/dist/Text.d.ts +18 -6
- package/dist/Text.d.ts.map +1 -1
- package/dist/Text.js +42 -0
- package/dist/Text.js.map +1 -0
- package/dist/Text.jsx +35 -0
- package/dist/Text.jsx.map +1 -0
- package/dist/TextField.d.ts +6 -6
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TextField.js +436 -0
- package/dist/TextField.js.map +1 -0
- package/dist/TextField.jsx +403 -0
- package/dist/TextField.jsx.map +1 -0
- package/dist/TimeField.d.ts +3 -3
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/TimeField.js +372 -0
- package/dist/TimeField.js.map +1 -0
- package/dist/TimeField.jsx +224 -0
- package/dist/TimeField.jsx.map +1 -0
- package/dist/Toast.d.ts +14 -0
- package/dist/Toast.d.ts.map +1 -1
- package/dist/Toast.js +551 -0
- package/dist/Toast.js.map +1 -0
- package/dist/Toast.jsx +361 -0
- package/dist/Toast.jsx.map +1 -0
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButton.js +123 -0
- package/dist/ToggleButton.js.map +1 -0
- package/dist/ToggleButton.jsx +88 -0
- package/dist/ToggleButton.jsx.map +1 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.js +114 -0
- package/dist/ToggleButtonGroup.js.map +1 -0
- package/dist/ToggleButtonGroup.jsx +85 -0
- package/dist/ToggleButtonGroup.jsx.map +1 -0
- package/dist/Toolbar.js +112 -0
- package/dist/Toolbar.js.map +1 -0
- package/dist/Toolbar.jsx +92 -0
- package/dist/Toolbar.jsx.map +1 -0
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tooltip.js +539 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/Tooltip.jsx +465 -0
- package/dist/Tooltip.jsx.map +1 -0
- package/dist/Tree.d.ts +14 -2
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Tree.js +1424 -0
- package/dist/Tree.js.map +1 -0
- package/dist/Tree.jsx +1172 -0
- package/dist/Tree.jsx.map +1 -0
- package/dist/Virtualizer.d.ts +16 -2
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/Virtualizer.js +2 -0
- package/dist/Virtualizer.jsx +2 -0
- package/dist/Virtualizer2.js +751 -0
- package/dist/Virtualizer2.js.map +1 -0
- package/dist/Virtualizer2.jsx +730 -0
- package/dist/Virtualizer2.jsx.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +18 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.js +42 -0
- package/dist/VisuallyHidden.js.map +1 -0
- package/dist/VisuallyHidden.jsx +35 -0
- package/dist/VisuallyHidden.jsx.map +1 -0
- package/dist/contexts.js +33 -0
- package/dist/contexts.js.map +1 -0
- package/dist/contexts.jsx +33 -0
- package/dist/contexts.jsx.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +70 -23932
- package/dist/index.jsx +70 -18337
- package/dist/useDragAndDrop.js +2 -0
- package/dist/useDragAndDrop.jsx +2 -0
- package/dist/useDragAndDrop2.js +395 -0
- package/dist/useDragAndDrop2.js.map +1 -0
- package/dist/useDragAndDrop2.jsx +395 -0
- package/dist/useDragAndDrop2.jsx.map +1 -0
- package/dist/utils.d.ts +83 -11
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +285 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.jsx +277 -0
- package/dist/utils.jsx.map +1 -0
- package/dist/virtualizer/Layout.js +144 -0
- package/dist/virtualizer/Layout.js.map +1 -0
- package/dist/virtualizer/Layout.jsx +144 -0
- package/dist/virtualizer/Layout.jsx.map +1 -0
- package/package.json +401 -4
- package/src/Breadcrumbs.tsx +3 -1
- package/src/Button.tsx +22 -2
- package/src/Calendar.tsx +27 -10
- package/src/CalendarPicker.tsx +73 -0
- package/src/Checkbox.tsx +539 -3
- package/src/Collection.tsx +9 -3
- package/src/Color.tsx +42 -14
- package/src/ComboBox.tsx +50 -6
- package/src/DateField.tsx +20 -2
- package/src/DatePicker.tsx +57 -5
- package/src/Dialog.tsx +13 -5
- package/src/Disclosure.tsx +3 -1
- package/src/DragAndDrop.tsx +3 -1
- package/src/DropZone.tsx +3 -1
- package/src/GridList.tsx +125 -24
- package/src/Icon.tsx +3 -1
- package/src/Link.tsx +3 -1
- package/src/ListBox.tsx +31 -4
- package/src/Menu.tsx +252 -128
- package/src/Meter.tsx +3 -1
- package/src/Modal.tsx +100 -52
- package/src/NumberField.tsx +51 -8
- package/src/Popover.tsx +40 -10
- package/src/ProgressBar.tsx +3 -1
- package/src/RadioGroup.tsx +468 -4
- package/src/RangeCalendar.tsx +3 -1
- package/src/SearchField.tsx +27 -3
- package/src/Select.tsx +22 -7
- package/src/SelectionIndicator.tsx +3 -1
- package/src/SharedElementTransition.tsx +3 -1
- package/src/Slider.tsx +159 -13
- package/src/Switch.tsx +395 -2
- package/src/Table.tsx +409 -95
- package/src/Tabs.tsx +16 -45
- package/src/TagGroup.tsx +3 -1
- package/src/Text.tsx +31 -10
- package/src/TextField.tsx +43 -5
- package/src/TimeField.tsx +20 -2
- package/src/Toast.tsx +79 -14
- package/src/ToggleButton.tsx +3 -1
- package/src/ToggleButtonGroup.tsx +3 -1
- package/src/Tooltip.tsx +3 -1
- package/src/Tree.tsx +77 -9
- package/src/Virtualizer.tsx +180 -31
- package/src/VirtualizerLayouts.ts +45 -10
- package/src/index.ts +50 -0
- package/src/utils.tsx +243 -27
- package/dist/index.js.map +0 -1
- package/dist/index.jsx.map +0 -1
package/src/RadioGroup.tsx
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import {
|
|
9
9
|
type JSX,
|
|
10
10
|
type ParentProps,
|
|
11
|
+
type Context,
|
|
11
12
|
createContext,
|
|
12
13
|
createMemo,
|
|
13
14
|
createSignal,
|
|
@@ -43,9 +44,11 @@ import {
|
|
|
43
44
|
type ClassNameOrFunction,
|
|
44
45
|
type StyleOrFunction,
|
|
45
46
|
type SlotProps,
|
|
47
|
+
Provider,
|
|
46
48
|
useRenderProps,
|
|
47
49
|
filterDOMProps,
|
|
48
50
|
} from "./utils";
|
|
51
|
+
import { TextContext } from "./Text";
|
|
49
52
|
|
|
50
53
|
type RefLike<T> = ((el: T) => void) | { current?: T | null } | undefined;
|
|
51
54
|
|
|
@@ -147,6 +150,15 @@ export interface RadioGroupProps
|
|
|
147
150
|
description?: JSX.Element;
|
|
148
151
|
/** An error message for the radio group. */
|
|
149
152
|
errorMessage?: JSX.Element;
|
|
153
|
+
/**
|
|
154
|
+
* Whether this component renders the visible description/error help-text nodes.
|
|
155
|
+
* Defaults to `true`. A styled layer (e.g. solid-spectrum) passes `false` to keep
|
|
156
|
+
* the id-minting and `aria-describedby` wiring here (so child radios inherit the
|
|
157
|
+
* group's shared description via `radioGroupData`) while owning the visible node
|
|
158
|
+
* itself — mirroring RAC, where the group exposes a `TextContext`/`FieldError`
|
|
159
|
+
* slot rather than rendering its own help text.
|
|
160
|
+
*/
|
|
161
|
+
renderHelpText?: boolean;
|
|
150
162
|
}
|
|
151
163
|
|
|
152
164
|
export interface RadioProps extends Omit<AriaRadioProps, "children">, SlotProps {
|
|
@@ -213,7 +225,14 @@ export function RadioGroup(props: ParentProps<RadioGroupProps>): JSX.Element {
|
|
|
213
225
|
props,
|
|
214
226
|
) as ParentProps<RadioGroupProps>)
|
|
215
227
|
: props;
|
|
216
|
-
const [local, ariaProps] = splitProps(mergedProps, [
|
|
228
|
+
const [local, ariaProps] = splitProps(mergedProps, [
|
|
229
|
+
"class",
|
|
230
|
+
"style",
|
|
231
|
+
"render",
|
|
232
|
+
"ref",
|
|
233
|
+
"slot",
|
|
234
|
+
"renderHelpText",
|
|
235
|
+
]);
|
|
217
236
|
|
|
218
237
|
const state = createRadioGroupState(() => ({
|
|
219
238
|
value: mergedProps.value,
|
|
@@ -255,7 +274,9 @@ export function RadioGroup(props: ParentProps<RadioGroupProps>): JSX.Element {
|
|
|
255
274
|
|
|
256
275
|
const renderProps = useRenderProps(
|
|
257
276
|
{
|
|
258
|
-
children
|
|
277
|
+
get children() {
|
|
278
|
+
return props.children;
|
|
279
|
+
},
|
|
259
280
|
class: local.class,
|
|
260
281
|
style: local.style,
|
|
261
282
|
defaultClassName: "solidaria-RadioGroup",
|
|
@@ -366,12 +387,12 @@ export function RadioGroup(props: ParentProps<RadioGroupProps>): JSX.Element {
|
|
|
366
387
|
return (
|
|
367
388
|
<>
|
|
368
389
|
{renderedChildren()}
|
|
369
|
-
<Show when={mergedProps.description}>
|
|
390
|
+
<Show when={(local.renderHelpText ?? true) && mergedProps.description}>
|
|
370
391
|
<div {...(groupAria.descriptionProps as unknown as JSX.HTMLAttributes<HTMLDivElement>)}>
|
|
371
392
|
{mergedProps.description}
|
|
372
393
|
</div>
|
|
373
394
|
</Show>
|
|
374
|
-
<Show when={isInvalid() && mergedProps.errorMessage}>
|
|
395
|
+
<Show when={(local.renderHelpText ?? true) && isInvalid() && mergedProps.errorMessage}>
|
|
375
396
|
<div {...(groupAria.errorMessageProps as unknown as JSX.HTMLAttributes<HTMLDivElement>)}>
|
|
376
397
|
{mergedProps.errorMessage}
|
|
377
398
|
</div>
|
|
@@ -766,3 +787,446 @@ export function Radio(props: RadioProps): JSX.Element {
|
|
|
766
787
|
</Show>
|
|
767
788
|
);
|
|
768
789
|
}
|
|
790
|
+
|
|
791
|
+
// ============================================================================
|
|
792
|
+
// RadioField + RadioButton — the RAC form-field split (RAC 1.19)
|
|
793
|
+
// ----------------------------------------------------------------------------
|
|
794
|
+
// Upstream split the monolithic Radio into a RadioField wrapper (owns the radio
|
|
795
|
+
// aria + optional description) containing a RadioButton control (the clickable
|
|
796
|
+
// indicator + label). Mirrors react-aria-components/src/RadioGroup.tsx. The
|
|
797
|
+
// legacy `Radio` above stays as the deprecated monolith for back-compat.
|
|
798
|
+
//
|
|
799
|
+
// Spine note: upstream wires the two halves with InternalRadioContext +
|
|
800
|
+
// SelectionIndicatorContext + TextContext slots through `<Provider>`. Our
|
|
801
|
+
// `<Provider>` is inert and TextContext carries no slots yet
|
|
802
|
+
// (`port-context-slots`), so — exactly like RadioImpl already does — we use a
|
|
803
|
+
// native Solid context and bridge `description`/`errorMessage` with explicit
|
|
804
|
+
// ids. Like the legacy `Radio`, both halves require a surrounding RadioGroup.
|
|
805
|
+
// ============================================================================
|
|
806
|
+
|
|
807
|
+
export interface RadioFieldRenderProps {
|
|
808
|
+
/** Whether the radio is selected. */
|
|
809
|
+
isSelected: boolean;
|
|
810
|
+
/** Whether the radio is disabled. */
|
|
811
|
+
isDisabled: boolean;
|
|
812
|
+
/** Whether the radio is read only. */
|
|
813
|
+
isReadOnly: boolean;
|
|
814
|
+
/** Whether the radio is invalid. */
|
|
815
|
+
isInvalid: boolean;
|
|
816
|
+
/** Whether the radio is required. */
|
|
817
|
+
isRequired: boolean;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
export interface RadioButtonRenderProps extends RadioRenderProps {}
|
|
821
|
+
|
|
822
|
+
export interface RadioFieldProps extends Omit<AriaRadioProps, "children">, SlotProps {
|
|
823
|
+
/** The children of the component (typically a `RadioButton`). A function may receive render props. */
|
|
824
|
+
children?: RenderChildren<RadioFieldRenderProps>;
|
|
825
|
+
/** The CSS className for the element. */
|
|
826
|
+
class?: ClassNameOrFunction<RadioFieldRenderProps>;
|
|
827
|
+
/** The inline style for the element. */
|
|
828
|
+
style?: StyleOrFunction<RadioFieldRenderProps>;
|
|
829
|
+
/** Ref for the radio field root element. */
|
|
830
|
+
ref?: RefLike<HTMLDivElement>;
|
|
831
|
+
/** Ref for the underlying input element. */
|
|
832
|
+
inputRef?: RefLike<HTMLInputElement>;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
export interface RadioButtonProps extends SlotProps {
|
|
836
|
+
/** The children of the component. A function may receive render props. */
|
|
837
|
+
children?: RenderChildren<RadioButtonRenderProps>;
|
|
838
|
+
/** The CSS className for the element. */
|
|
839
|
+
class?: ClassNameOrFunction<RadioButtonRenderProps>;
|
|
840
|
+
/** The inline style for the element. */
|
|
841
|
+
style?: StyleOrFunction<RadioButtonRenderProps>;
|
|
842
|
+
/** Ref for the outer label element. */
|
|
843
|
+
ref?: RefLike<HTMLLabelElement>;
|
|
844
|
+
/** Handler called when hover starts. */
|
|
845
|
+
onHoverStart?: () => void;
|
|
846
|
+
/** Handler called when hover ends. */
|
|
847
|
+
onHoverEnd?: () => void;
|
|
848
|
+
/** Handler called when hover state changes. */
|
|
849
|
+
onHoverChange?: (isHovered: boolean) => void;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
export interface RadioFieldContextValue extends Partial<RadioFieldProps> {
|
|
853
|
+
slots?: Record<string, Partial<RadioFieldProps>>;
|
|
854
|
+
}
|
|
855
|
+
export const RadioFieldContext = createContext<RadioFieldContextValue | null>(null);
|
|
856
|
+
|
|
857
|
+
/** Carries the radio aria + state from a RadioField/Radio wrapper to its RadioButton. */
|
|
858
|
+
interface InternalRadioContextValue {
|
|
859
|
+
isSelected: () => boolean;
|
|
860
|
+
isPressed: () => boolean;
|
|
861
|
+
isDisabled: () => boolean;
|
|
862
|
+
labelProps: () => JSX.LabelHTMLAttributes<HTMLLabelElement>;
|
|
863
|
+
inputProps: () => JSX.InputHTMLAttributes<HTMLInputElement>;
|
|
864
|
+
setInputRef: (el: HTMLInputElement) => void;
|
|
865
|
+
defaultClassName: string;
|
|
866
|
+
}
|
|
867
|
+
const InternalRadioContext = createContext<InternalRadioContextValue | null>(null);
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* A RadioField represents an individual option within a radio group, containing a
|
|
871
|
+
* `RadioButton` and optional description. Must be rendered inside a `RadioGroup`.
|
|
872
|
+
* Per-option help text is wired through a TextContext description slot — render it
|
|
873
|
+
* with `<Text slot="description">`. (Radios have no per-option error slot; errors
|
|
874
|
+
* are reported at the group level.)
|
|
875
|
+
*
|
|
876
|
+
* @example
|
|
877
|
+
* ```tsx
|
|
878
|
+
* <RadioGroup>
|
|
879
|
+
* <RadioField value="a">
|
|
880
|
+
* <RadioButton>Option A</RadioButton>
|
|
881
|
+
* <Text slot="description">The first option</Text>
|
|
882
|
+
* </RadioField>
|
|
883
|
+
* </RadioGroup>
|
|
884
|
+
* ```
|
|
885
|
+
*/
|
|
886
|
+
export function RadioField(props: RadioFieldProps): JSX.Element {
|
|
887
|
+
const getState = createMemo(() => useContext(RadioGroupStateContext));
|
|
888
|
+
return (
|
|
889
|
+
<Show when={getState()} fallback={null} keyed>
|
|
890
|
+
{(state) => <RadioFieldImpl fieldProps={props} state={state} />}
|
|
891
|
+
</Show>
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
function RadioFieldImpl(props: {
|
|
896
|
+
fieldProps: RadioFieldProps;
|
|
897
|
+
state: RadioGroupState;
|
|
898
|
+
}): JSX.Element {
|
|
899
|
+
const [inputElement, setInputElement] = createSignal<HTMLInputElement | null>(null);
|
|
900
|
+
const { state } = props;
|
|
901
|
+
const contextProps = useContext(RadioFieldContext);
|
|
902
|
+
const contextSlotProps = contextProps?.slots?.[props.fieldProps.slot ?? "default"];
|
|
903
|
+
const contextBaseProps = createMemo<Partial<RadioFieldProps>>(() => {
|
|
904
|
+
if (!contextProps) return {};
|
|
905
|
+
const { slots: _slots, ...rest } = contextProps;
|
|
906
|
+
return rest;
|
|
907
|
+
});
|
|
908
|
+
const fieldProps = contextProps
|
|
909
|
+
? (mergeProps(contextBaseProps(), contextSlotProps ?? {}, props.fieldProps) as RadioFieldProps)
|
|
910
|
+
: props.fieldProps;
|
|
911
|
+
const inputRefs = createMemo(
|
|
912
|
+
() =>
|
|
913
|
+
[contextBaseProps().inputRef, contextSlotProps?.inputRef, props.fieldProps.inputRef].filter(
|
|
914
|
+
Boolean,
|
|
915
|
+
) as RefLike<HTMLInputElement>[],
|
|
916
|
+
);
|
|
917
|
+
|
|
918
|
+
// `children` is split out of ariaProps so neither the inputAriaProps key-copy
|
|
919
|
+
// loop nor the hook accessor spread eagerly reads it — reading a Solid
|
|
920
|
+
// `children` getter instantiates the nested RadioButton, and doing so OUTSIDE
|
|
921
|
+
// InternalRadioContext both breaks its binding and recurses.
|
|
922
|
+
const [local, ariaProps] = splitProps(fieldProps, [
|
|
923
|
+
"class",
|
|
924
|
+
"style",
|
|
925
|
+
"ref",
|
|
926
|
+
"inputRef",
|
|
927
|
+
"slot",
|
|
928
|
+
"children",
|
|
929
|
+
]);
|
|
930
|
+
const inputAriaProps = createMemo(() => {
|
|
931
|
+
const clean: Record<string, unknown> = {};
|
|
932
|
+
for (const key in ariaProps as Record<string, unknown>) {
|
|
933
|
+
if (!key.startsWith("data-")) {
|
|
934
|
+
clean[key] = (ariaProps as Record<string, unknown>)[key];
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
return clean as typeof ariaProps;
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
const radioAria = createRadio(
|
|
941
|
+
() => ({
|
|
942
|
+
...inputAriaProps(),
|
|
943
|
+
// The hook reads `children` only to decide if an aria-label is needed; the
|
|
944
|
+
// visible label lives in the RadioButton, so report presence as a literal.
|
|
945
|
+
children: true,
|
|
946
|
+
}),
|
|
947
|
+
state,
|
|
948
|
+
inputElement,
|
|
949
|
+
);
|
|
950
|
+
|
|
951
|
+
// The hook mints the description slot id and bakes the combined aria-describedby
|
|
952
|
+
// (own description + the group's shared description/error) into the input; the
|
|
953
|
+
// field exposes that id through TextContext so a `<Text slot="description">`
|
|
954
|
+
// child resolves it. Mirrors react-aria-components' RadioField Provider value
|
|
955
|
+
// list (description slot only — radios have no per-option error slot).
|
|
956
|
+
const textSlots = {
|
|
957
|
+
slots: {
|
|
958
|
+
get description() {
|
|
959
|
+
return radioAria.descriptionProps;
|
|
960
|
+
},
|
|
961
|
+
},
|
|
962
|
+
};
|
|
963
|
+
|
|
964
|
+
const setInputRef = (el: HTMLInputElement) => {
|
|
965
|
+
setInputElement(el);
|
|
966
|
+
el.addEventListener("invalid", (event) => {
|
|
967
|
+
state.updateValidation(getNativeValidation(el));
|
|
968
|
+
state.commitValidation();
|
|
969
|
+
el.focus();
|
|
970
|
+
event.preventDefault();
|
|
971
|
+
});
|
|
972
|
+
el.addEventListener("change", () => {
|
|
973
|
+
state.updateValidation(el.validity.valid ? validValidation : getNativeValidation(el));
|
|
974
|
+
state.commitValidation();
|
|
975
|
+
});
|
|
976
|
+
for (const ref of inputRefs()) {
|
|
977
|
+
assignRef(ref, el);
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
const setFieldRef = (el: HTMLDivElement) => {
|
|
981
|
+
assignRef(local.ref, el);
|
|
982
|
+
};
|
|
983
|
+
|
|
984
|
+
const internalContext: InternalRadioContextValue = {
|
|
985
|
+
isSelected: () => radioAria.isSelected(),
|
|
986
|
+
isPressed: () => radioAria.isPressed(),
|
|
987
|
+
isDisabled: () => radioAria.isDisabled,
|
|
988
|
+
labelProps: () => radioAria.labelProps,
|
|
989
|
+
inputProps: () => radioAria.inputProps,
|
|
990
|
+
setInputRef,
|
|
991
|
+
defaultClassName: "solidaria-RadioButton",
|
|
992
|
+
};
|
|
993
|
+
|
|
994
|
+
const selectionIndicatorContext = createMemo<SelectionIndicatorContextValue>(() => ({
|
|
995
|
+
isSelected: radioAria.isSelected,
|
|
996
|
+
}));
|
|
997
|
+
|
|
998
|
+
const renderValues = createMemo<RadioFieldRenderProps>(() => ({
|
|
999
|
+
isSelected: radioAria.isSelected(),
|
|
1000
|
+
isDisabled: radioAria.isDisabled,
|
|
1001
|
+
isReadOnly: state.isReadOnly,
|
|
1002
|
+
isInvalid: state.isInvalid,
|
|
1003
|
+
isRequired: state.isRequired,
|
|
1004
|
+
}));
|
|
1005
|
+
|
|
1006
|
+
const renderProps = useRenderProps(
|
|
1007
|
+
{
|
|
1008
|
+
children: fieldProps.children,
|
|
1009
|
+
class: local.class,
|
|
1010
|
+
style: local.style,
|
|
1011
|
+
defaultClassName: "solidaria-RadioField",
|
|
1012
|
+
},
|
|
1013
|
+
renderValues,
|
|
1014
|
+
);
|
|
1015
|
+
|
|
1016
|
+
const domProps = createMemo(() => {
|
|
1017
|
+
const filtered = filterDOMProps(ariaProps, { global: true });
|
|
1018
|
+
delete (filtered as Record<string, unknown>).id;
|
|
1019
|
+
delete (filtered as Record<string, unknown>).onClick;
|
|
1020
|
+
return filtered;
|
|
1021
|
+
});
|
|
1022
|
+
|
|
1023
|
+
// Children are accessed inside the providers (component-execution owner) so a
|
|
1024
|
+
// nested RadioButton's useContext binds to InternalRadioContext.
|
|
1025
|
+
const FieldChildren = () => {
|
|
1026
|
+
const childRenderValues: RadioFieldRenderProps = {
|
|
1027
|
+
get isSelected() {
|
|
1028
|
+
return radioAria.isSelected();
|
|
1029
|
+
},
|
|
1030
|
+
get isDisabled() {
|
|
1031
|
+
return radioAria.isDisabled;
|
|
1032
|
+
},
|
|
1033
|
+
get isReadOnly() {
|
|
1034
|
+
return state.isReadOnly;
|
|
1035
|
+
},
|
|
1036
|
+
get isInvalid() {
|
|
1037
|
+
return state.isInvalid;
|
|
1038
|
+
},
|
|
1039
|
+
get isRequired() {
|
|
1040
|
+
return state.isRequired;
|
|
1041
|
+
},
|
|
1042
|
+
};
|
|
1043
|
+
const renderedChildren = createMemo(() => {
|
|
1044
|
+
const children = fieldProps.children;
|
|
1045
|
+
return typeof children === "function" ? children(childRenderValues) : children;
|
|
1046
|
+
});
|
|
1047
|
+
return <>{renderedChildren()}</>;
|
|
1048
|
+
};
|
|
1049
|
+
|
|
1050
|
+
return (
|
|
1051
|
+
<div
|
|
1052
|
+
{...domProps()}
|
|
1053
|
+
ref={setFieldRef}
|
|
1054
|
+
class={renderProps.class()}
|
|
1055
|
+
style={renderProps.style()}
|
|
1056
|
+
slot={local.slot}
|
|
1057
|
+
data-selected={radioAria.isSelected() || undefined}
|
|
1058
|
+
data-disabled={radioAria.isDisabled || undefined}
|
|
1059
|
+
data-readonly={state.isReadOnly || undefined}
|
|
1060
|
+
data-invalid={state.isInvalid || undefined}
|
|
1061
|
+
data-required={state.isRequired || undefined}
|
|
1062
|
+
>
|
|
1063
|
+
<SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
|
|
1064
|
+
<InternalRadioContext.Provider value={internalContext}>
|
|
1065
|
+
<Provider values={[[TextContext, textSlots]] as Array<[Context<unknown>, unknown]>}>
|
|
1066
|
+
<FieldChildren />
|
|
1067
|
+
</Provider>
|
|
1068
|
+
</InternalRadioContext.Provider>
|
|
1069
|
+
</SelectionIndicatorContext.Provider>
|
|
1070
|
+
</div>
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
/**
|
|
1075
|
+
* A RadioButton is the clickable area of a radio, including the indicator and label.
|
|
1076
|
+
* Must be rendered inside a `RadioField` (or the legacy `Radio`).
|
|
1077
|
+
*/
|
|
1078
|
+
export function RadioButton(props: RadioButtonProps): JSX.Element {
|
|
1079
|
+
const getCtx = createMemo(() => useContext(InternalRadioContext));
|
|
1080
|
+
const getState = createMemo(() => useContext(RadioGroupStateContext));
|
|
1081
|
+
return (
|
|
1082
|
+
<Show when={getCtx()} fallback={null} keyed>
|
|
1083
|
+
{(ctx) => (
|
|
1084
|
+
<Show when={getState()} fallback={null} keyed>
|
|
1085
|
+
{(state) => <RadioButtonImpl buttonProps={props} ctx={ctx} state={state} />}
|
|
1086
|
+
</Show>
|
|
1087
|
+
)}
|
|
1088
|
+
</Show>
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
function RadioButtonImpl(props: {
|
|
1093
|
+
buttonProps: RadioButtonProps;
|
|
1094
|
+
ctx: InternalRadioContextValue;
|
|
1095
|
+
state: RadioGroupState;
|
|
1096
|
+
}): JSX.Element {
|
|
1097
|
+
const { ctx, state } = props;
|
|
1098
|
+
|
|
1099
|
+
const { isFocused, isFocusVisible, focusProps } = createFocusRing();
|
|
1100
|
+
const { isHovered, hoverProps } = createHover({
|
|
1101
|
+
get isDisabled() {
|
|
1102
|
+
return ctx.isDisabled() || state.isReadOnly;
|
|
1103
|
+
},
|
|
1104
|
+
onHoverStart: props.buttonProps.onHoverStart,
|
|
1105
|
+
onHoverEnd: props.buttonProps.onHoverEnd,
|
|
1106
|
+
onHoverChange: props.buttonProps.onHoverChange,
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
const renderValues = createMemo<RadioButtonRenderProps>(() => ({
|
|
1110
|
+
isSelected: ctx.isSelected(),
|
|
1111
|
+
isHovered: isHovered(),
|
|
1112
|
+
isPressed: ctx.isPressed(),
|
|
1113
|
+
isFocused: isFocused(),
|
|
1114
|
+
isFocusVisible: isFocusVisible(),
|
|
1115
|
+
isDisabled: ctx.isDisabled(),
|
|
1116
|
+
isReadOnly: state.isReadOnly,
|
|
1117
|
+
isInvalid: state.isInvalid,
|
|
1118
|
+
isRequired: state.isRequired,
|
|
1119
|
+
}));
|
|
1120
|
+
|
|
1121
|
+
const renderProps = useRenderProps(
|
|
1122
|
+
{
|
|
1123
|
+
children: props.buttonProps.children,
|
|
1124
|
+
class: props.buttonProps.class,
|
|
1125
|
+
style: props.buttonProps.style,
|
|
1126
|
+
defaultClassName: ctx.defaultClassName,
|
|
1127
|
+
},
|
|
1128
|
+
renderValues,
|
|
1129
|
+
);
|
|
1130
|
+
|
|
1131
|
+
const cleanLabelProps = () => {
|
|
1132
|
+
const { ref: _ref1, ...rest } = ctx.labelProps() as Record<string, unknown>;
|
|
1133
|
+
return rest;
|
|
1134
|
+
};
|
|
1135
|
+
const cleanHoverProps = () => {
|
|
1136
|
+
const { ref: _ref2, ...rest } = hoverProps as Record<string, unknown>;
|
|
1137
|
+
return rest;
|
|
1138
|
+
};
|
|
1139
|
+
const cleanInputProps = () => {
|
|
1140
|
+
const {
|
|
1141
|
+
ref: _ref3,
|
|
1142
|
+
onFocus: _onFocus,
|
|
1143
|
+
onBlur: _onBlur,
|
|
1144
|
+
...rest
|
|
1145
|
+
} = ctx.inputProps() as Record<string, unknown>;
|
|
1146
|
+
return rest;
|
|
1147
|
+
};
|
|
1148
|
+
const cleanFocusProps = () => {
|
|
1149
|
+
const {
|
|
1150
|
+
ref: _ref4,
|
|
1151
|
+
onFocus: _onFocus,
|
|
1152
|
+
onBlur: _onBlur,
|
|
1153
|
+
...rest
|
|
1154
|
+
} = focusProps as Record<string, unknown>;
|
|
1155
|
+
return rest;
|
|
1156
|
+
};
|
|
1157
|
+
const handleInputFocus: JSX.EventHandler<HTMLInputElement, FocusEvent> = (event) => {
|
|
1158
|
+
(
|
|
1159
|
+
ctx.inputProps() as unknown as { onFocus?: JSX.EventHandler<HTMLInputElement, FocusEvent> }
|
|
1160
|
+
).onFocus?.(event);
|
|
1161
|
+
(
|
|
1162
|
+
focusProps as unknown as { onFocus?: JSX.EventHandler<HTMLInputElement, FocusEvent> }
|
|
1163
|
+
).onFocus?.(event);
|
|
1164
|
+
};
|
|
1165
|
+
const handleInputBlur: JSX.EventHandler<HTMLInputElement, FocusEvent> = (event) => {
|
|
1166
|
+
(
|
|
1167
|
+
ctx.inputProps() as unknown as { onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent> }
|
|
1168
|
+
).onBlur?.(event);
|
|
1169
|
+
(focusProps as unknown as { onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent> }).onBlur?.(
|
|
1170
|
+
event,
|
|
1171
|
+
);
|
|
1172
|
+
};
|
|
1173
|
+
const handleInputClick: JSX.EventHandler<HTMLInputElement, MouseEvent> = (event) => {
|
|
1174
|
+
(
|
|
1175
|
+
ctx.inputProps() as unknown as { onClick?: JSX.EventHandler<HTMLInputElement, MouseEvent> }
|
|
1176
|
+
).onClick?.(event);
|
|
1177
|
+
};
|
|
1178
|
+
const handleInputInvalid: JSX.EventHandler<HTMLInputElement, Event> = (event) => {
|
|
1179
|
+
state.updateValidation(getNativeValidation(event.currentTarget));
|
|
1180
|
+
state.commitValidation();
|
|
1181
|
+
event.currentTarget.focus();
|
|
1182
|
+
event.preventDefault();
|
|
1183
|
+
};
|
|
1184
|
+
const handleInputChange: JSX.EventHandler<HTMLInputElement, Event> = (event) => {
|
|
1185
|
+
(
|
|
1186
|
+
ctx.inputProps() as unknown as { onChange?: JSX.EventHandler<HTMLInputElement, Event> }
|
|
1187
|
+
).onChange?.(event);
|
|
1188
|
+
state.updateValidation(
|
|
1189
|
+
event.currentTarget.validity.valid
|
|
1190
|
+
? validValidation
|
|
1191
|
+
: getNativeValidation(event.currentTarget),
|
|
1192
|
+
);
|
|
1193
|
+
state.commitValidation();
|
|
1194
|
+
};
|
|
1195
|
+
const setButtonRef = (el: HTMLLabelElement) => {
|
|
1196
|
+
assignRef(props.buttonProps.ref, el);
|
|
1197
|
+
};
|
|
1198
|
+
|
|
1199
|
+
return (
|
|
1200
|
+
<label
|
|
1201
|
+
{...cleanLabelProps()}
|
|
1202
|
+
{...cleanHoverProps()}
|
|
1203
|
+
ref={setButtonRef}
|
|
1204
|
+
class={renderProps.class()}
|
|
1205
|
+
style={renderProps.style()}
|
|
1206
|
+
slot={props.buttonProps.slot}
|
|
1207
|
+
data-selected={ctx.isSelected() || undefined}
|
|
1208
|
+
data-pressed={ctx.isPressed() || undefined}
|
|
1209
|
+
data-hovered={isHovered() || undefined}
|
|
1210
|
+
data-focused={isFocused() || undefined}
|
|
1211
|
+
data-focus-visible={isFocusVisible() || undefined}
|
|
1212
|
+
data-disabled={ctx.isDisabled() || undefined}
|
|
1213
|
+
data-readonly={state.isReadOnly || undefined}
|
|
1214
|
+
data-invalid={state.isInvalid || undefined}
|
|
1215
|
+
data-required={state.isRequired || undefined}
|
|
1216
|
+
>
|
|
1217
|
+
<VisuallyHidden>
|
|
1218
|
+
<input
|
|
1219
|
+
ref={ctx.setInputRef}
|
|
1220
|
+
{...cleanInputProps()}
|
|
1221
|
+
{...cleanFocusProps()}
|
|
1222
|
+
onFocus={handleInputFocus}
|
|
1223
|
+
onBlur={handleInputBlur}
|
|
1224
|
+
onInvalid={handleInputInvalid}
|
|
1225
|
+
onChange={handleInputChange}
|
|
1226
|
+
onClick={handleInputClick}
|
|
1227
|
+
/>
|
|
1228
|
+
</VisuallyHidden>
|
|
1229
|
+
{renderProps.renderChildren()}
|
|
1230
|
+
</label>
|
|
1231
|
+
);
|
|
1232
|
+
}
|
package/src/RangeCalendar.tsx
CHANGED
|
@@ -508,7 +508,9 @@ export function RangeCalendarCell(props: RangeCalendarCellProps): JSX.Element {
|
|
|
508
508
|
|
|
509
509
|
const renderProps = useRenderProps(
|
|
510
510
|
{
|
|
511
|
-
children
|
|
511
|
+
get children() {
|
|
512
|
+
return props.children;
|
|
513
|
+
},
|
|
512
514
|
class: props.class,
|
|
513
515
|
style: props.style,
|
|
514
516
|
defaultClassName: "solidaria-RangeCalendarCell",
|
package/src/SearchField.tsx
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
type JSX,
|
|
10
|
+
type Context,
|
|
10
11
|
createContext,
|
|
11
12
|
createMemo,
|
|
12
13
|
onCleanup,
|
|
@@ -38,7 +39,9 @@ import {
|
|
|
38
39
|
type SlotProps,
|
|
39
40
|
useRenderProps,
|
|
40
41
|
filterDOMProps,
|
|
42
|
+
Provider,
|
|
41
43
|
} from "./utils";
|
|
44
|
+
import { TextContext } from "./Text";
|
|
42
45
|
|
|
43
46
|
export interface SearchFieldRenderProps {
|
|
44
47
|
/** Whether the search field is empty. */
|
|
@@ -456,7 +459,9 @@ export function SearchField(props: SearchFieldProps): JSX.Element {
|
|
|
456
459
|
|
|
457
460
|
const renderProps = useRenderProps(
|
|
458
461
|
{
|
|
459
|
-
children
|
|
462
|
+
get children() {
|
|
463
|
+
return local.children;
|
|
464
|
+
},
|
|
460
465
|
class: local.class,
|
|
461
466
|
style: local.style,
|
|
462
467
|
defaultClassName: "solidaria-SearchField",
|
|
@@ -544,6 +549,21 @@ export function SearchField(props: SearchFieldProps): JSX.Element {
|
|
|
544
549
|
const children = local.children;
|
|
545
550
|
return typeof children === "function" ? children(childRenderValues) : children;
|
|
546
551
|
};
|
|
552
|
+
// Provide the description / errorMessage props as `TextContext` slots (mirrors
|
|
553
|
+
// react-aria-components' SearchField), so a `<Text slot="description">` /
|
|
554
|
+
// `<Text slot="errorMessage">` child picks up the `id` its `aria-describedby`
|
|
555
|
+
// references. Additive: existing consumers reading these off
|
|
556
|
+
// `SearchFieldContext` are unaffected.
|
|
557
|
+
const textSlots = {
|
|
558
|
+
slots: {
|
|
559
|
+
get description() {
|
|
560
|
+
return searchFieldAria.descriptionProps;
|
|
561
|
+
},
|
|
562
|
+
get errorMessage() {
|
|
563
|
+
return searchFieldAria.errorMessageProps;
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
};
|
|
547
567
|
|
|
548
568
|
return (
|
|
549
569
|
<FieldErrorContext.Provider value={fieldErrorContext}>
|
|
@@ -559,7 +579,9 @@ export function SearchField(props: SearchFieldProps): JSX.Element {
|
|
|
559
579
|
data-required={ariaProps.isRequired || undefined}
|
|
560
580
|
data-readonly={ariaProps.isReadOnly || undefined}
|
|
561
581
|
>
|
|
562
|
-
{
|
|
582
|
+
<Provider values={[[TextContext, textSlots]] as Array<[Context<unknown>, unknown]>}>
|
|
583
|
+
{fieldChildren()}
|
|
584
|
+
</Provider>
|
|
563
585
|
</div>
|
|
564
586
|
</SearchFieldContext.Provider>
|
|
565
587
|
</FieldErrorContext.Provider>
|
|
@@ -758,7 +780,9 @@ export function SearchFieldClearButton(props: SearchFieldClearButtonProps): JSX.
|
|
|
758
780
|
|
|
759
781
|
const renderProps = useRenderProps(
|
|
760
782
|
{
|
|
761
|
-
children
|
|
783
|
+
get children() {
|
|
784
|
+
return props.children;
|
|
785
|
+
},
|
|
762
786
|
class: local.class,
|
|
763
787
|
style: local.style,
|
|
764
788
|
defaultClassName: "solidaria-SearchField-clear",
|
package/src/Select.tsx
CHANGED
|
@@ -766,7 +766,9 @@ export function SelectTrigger(props: SelectTriggerProps): JSX.Element {
|
|
|
766
766
|
|
|
767
767
|
const renderProps = useRenderProps(
|
|
768
768
|
{
|
|
769
|
-
children
|
|
769
|
+
get children() {
|
|
770
|
+
return props.children;
|
|
771
|
+
},
|
|
770
772
|
class: local.class,
|
|
771
773
|
style: local.style,
|
|
772
774
|
defaultClassName: "solidaria-Select-trigger",
|
|
@@ -871,7 +873,9 @@ export function SelectValue<T>(props: SelectValueProps<T>): JSX.Element {
|
|
|
871
873
|
|
|
872
874
|
const renderProps = useRenderProps(
|
|
873
875
|
{
|
|
874
|
-
|
|
876
|
+
get children() {
|
|
877
|
+
return props.children ?? defaultSelectValueChildren;
|
|
878
|
+
},
|
|
875
879
|
class: local.class,
|
|
876
880
|
style: local.style,
|
|
877
881
|
defaultClassName: "solidaria-Select-value",
|
|
@@ -959,7 +963,9 @@ export function SelectListBox<T>(props: SelectListBoxProps<T>): JSX.Element {
|
|
|
959
963
|
);
|
|
960
964
|
|
|
961
965
|
const renderValues = createMemo<SelectListBoxRenderProps>(() => ({
|
|
962
|
-
|
|
966
|
+
// Focus within the listbox itself (the selection manager's focus state),
|
|
967
|
+
// not the select-level trigger focus.
|
|
968
|
+
isFocused: state.selectionManager.isFocused,
|
|
963
969
|
}));
|
|
964
970
|
|
|
965
971
|
const renderProps = useRenderProps(
|
|
@@ -1004,7 +1010,7 @@ export function SelectListBox<T>(props: SelectListBoxProps<T>): JSX.Element {
|
|
|
1004
1010
|
{...cleanListBoxProps()}
|
|
1005
1011
|
class={renderProps.class()}
|
|
1006
1012
|
style={renderProps.style()}
|
|
1007
|
-
data-focused={state.isFocused
|
|
1013
|
+
data-focused={state.selectionManager.isFocused || undefined}
|
|
1008
1014
|
data-empty={state.collection().size === 0 || undefined}
|
|
1009
1015
|
>
|
|
1010
1016
|
{state.collection().size === 0 && local.renderEmptyState ? (
|
|
@@ -1072,6 +1078,7 @@ export function SelectOption<T>(props: SelectOptionProps<T>): JSX.Element {
|
|
|
1072
1078
|
}
|
|
1073
1079
|
const state = context as SelectState<T>;
|
|
1074
1080
|
const selectContext = useContext(SelectContext) as SelectContextValue<T> | null;
|
|
1081
|
+
const [ref, setRef] = createSignal<HTMLLIElement | null>(null);
|
|
1075
1082
|
|
|
1076
1083
|
const optionAria = createOption<T>(
|
|
1077
1084
|
{
|
|
@@ -1126,6 +1133,7 @@ export function SelectOption<T>(props: SelectOptionProps<T>): JSX.Element {
|
|
|
1126
1133
|
}
|
|
1127
1134
|
},
|
|
1128
1135
|
},
|
|
1136
|
+
() => ref(),
|
|
1129
1137
|
);
|
|
1130
1138
|
const isOptionFocusVisible = () =>
|
|
1131
1139
|
optionAria.isFocused() && (selectContext?.isFocusVisible() ?? optionAria.isFocusVisible());
|
|
@@ -1141,7 +1149,9 @@ export function SelectOption<T>(props: SelectOptionProps<T>): JSX.Element {
|
|
|
1141
1149
|
|
|
1142
1150
|
const renderProps = useRenderProps(
|
|
1143
1151
|
{
|
|
1144
|
-
children
|
|
1152
|
+
get children() {
|
|
1153
|
+
return props.children;
|
|
1154
|
+
},
|
|
1145
1155
|
class: local.class,
|
|
1146
1156
|
style: local.style,
|
|
1147
1157
|
defaultClassName: "solidaria-Select-option",
|
|
@@ -1200,6 +1210,7 @@ export function SelectOption<T>(props: SelectOptionProps<T>): JSX.Element {
|
|
|
1200
1210
|
return (
|
|
1201
1211
|
<SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
|
|
1202
1212
|
<li
|
|
1213
|
+
ref={setRef}
|
|
1203
1214
|
{...cleanOptionProps()}
|
|
1204
1215
|
class={renderProps.class()}
|
|
1205
1216
|
style={renderProps.style()}
|
|
@@ -1254,8 +1265,12 @@ function createSelectListStateAdapter<T>(state: SelectState<T>): ListState<T> {
|
|
|
1254
1265
|
|
|
1255
1266
|
return {
|
|
1256
1267
|
collection: state.collection,
|
|
1257
|
-
|
|
1258
|
-
|
|
1268
|
+
selectionManager: state.selectionManager,
|
|
1269
|
+
// Collection-level focus (the selection manager's), not the select-level
|
|
1270
|
+
// trigger focus — upstream listbox internals only ever read
|
|
1271
|
+
// state.selectionManager.isFocused.
|
|
1272
|
+
isFocused: () => state.selectionManager.isFocused,
|
|
1273
|
+
setFocused: (isFocused) => state.selectionManager.setFocused(isFocused),
|
|
1259
1274
|
focusedKey: state.focusedKey,
|
|
1260
1275
|
setFocusedKey: (key) => state.setFocusedKey(key ?? null),
|
|
1261
1276
|
childFocusStrategy: () => null,
|