@proyecto-viviana/solidaria-components 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +39 -272
- package/dist/ActionBar.d.ts +79 -0
- package/dist/ActionBar.d.ts.map +1 -0
- package/dist/ActionGroup.d.ts +74 -0
- package/dist/ActionGroup.d.ts.map +1 -0
- package/dist/Alert.d.ts +70 -0
- package/dist/Alert.d.ts.map +1 -0
- package/dist/Autocomplete.d.ts +5 -5
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Breadcrumbs.d.ts +27 -8
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +28 -5
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +51 -7
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +33 -8
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +130 -0
- package/dist/Collection.d.ts.map +1 -0
- package/dist/Color.d.ts +210 -9
- package/dist/Color.d.ts.map +1 -1
- package/dist/ColorEditor.d.ts +42 -0
- package/dist/ColorEditor.d.ts.map +1 -0
- package/dist/ComboBox.d.ts +146 -16
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +40 -0
- package/dist/ContextualHelpTrigger.d.ts.map +1 -0
- package/dist/DateField.d.ts +35 -8
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +101 -5
- package/dist/DatePicker.d.ts.map +1 -1
- package/dist/DateRangePickerContext.d.ts +30 -0
- package/dist/DateRangePickerContext.d.ts.map +1 -0
- package/dist/Dialog.d.ts +5 -5
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Disclosure.d.ts +25 -5
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/DragAndDrop.d.ts +80 -0
- package/dist/DragAndDrop.d.ts.map +1 -0
- package/dist/DragPreview.d.ts +14 -0
- package/dist/DragPreview.d.ts.map +1 -0
- package/dist/DropZone.d.ts +27 -0
- package/dist/DropZone.d.ts.map +1 -0
- package/dist/FieldError.d.ts +27 -0
- package/dist/FieldError.d.ts.map +1 -0
- package/dist/FileTrigger.d.ts +26 -0
- package/dist/FileTrigger.d.ts.map +1 -0
- package/dist/Focusable.d.ts +27 -0
- package/dist/Focusable.d.ts.map +1 -0
- package/dist/Form.d.ts +41 -0
- package/dist/Form.d.ts.map +1 -0
- package/dist/GridList.d.ts +69 -10
- package/dist/GridList.d.ts.map +1 -1
- package/dist/HiddenDateInput.d.ts +26 -0
- package/dist/HiddenDateInput.d.ts.map +1 -0
- package/dist/HiddenTimeInput.d.ts +25 -0
- package/dist/HiddenTimeInput.d.ts.map +1 -0
- package/dist/Icon.d.ts +57 -0
- package/dist/Icon.d.ts.map +1 -0
- package/dist/Keyboard.d.ts +13 -0
- package/dist/Keyboard.d.ts.map +1 -0
- package/dist/Landmark.d.ts +3 -3
- package/dist/Landmark.d.ts.map +1 -1
- package/dist/Link.d.ts +10 -4
- package/dist/Link.d.ts.map +1 -1
- package/dist/ListBox.d.ts +73 -11
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +38 -0
- package/dist/ListDropTargetDelegate.d.ts.map +1 -0
- package/dist/Menu.d.ts +79 -10
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +4 -4
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +6 -4
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +10 -12
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +32 -7
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Pressable.d.ts +27 -0
- package/dist/Pressable.d.ts.map +1 -0
- package/dist/ProgressBar.d.ts +6 -4
- package/dist/ProgressBar.d.ts.map +1 -1
- package/dist/RadioGroup.d.ts +43 -9
- package/dist/RadioGroup.d.ts.map +1 -1
- package/dist/RangeCalendar.d.ts +39 -7
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RouterProvider.d.ts +75 -0
- package/dist/RouterProvider.d.ts.map +1 -0
- package/dist/SearchField.d.ts +23 -21
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +48 -7
- package/dist/Select.d.ts.map +1 -1
- package/dist/SelectionIndicator.d.ts +30 -0
- package/dist/SelectionIndicator.d.ts.map +1 -0
- package/dist/Separator.d.ts +9 -3
- package/dist/Separator.d.ts.map +1 -1
- package/dist/SharedElementTransition.d.ts +41 -0
- package/dist/SharedElementTransition.d.ts.map +1 -0
- package/dist/Slider.d.ts +15 -8
- package/dist/Slider.d.ts.map +1 -1
- package/dist/StepList.d.ts +90 -0
- package/dist/StepList.d.ts.map +1 -0
- package/dist/Switch.d.ts +11 -5
- package/dist/Switch.d.ts.map +1 -1
- package/dist/Table.d.ts +222 -19
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +47 -10
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +22 -10
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/Text.d.ts +10 -0
- package/dist/Text.d.ts.map +1 -0
- package/dist/TextField.d.ts +19 -11
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +32 -7
- package/dist/TimeField.d.ts.map +1 -1
- package/dist/Toast.d.ts +29 -14
- package/dist/Toast.d.ts.map +1 -1
- package/dist/ToggleButton.d.ts +36 -0
- package/dist/ToggleButton.d.ts.map +1 -0
- package/dist/ToggleButtonGroup.d.ts +33 -0
- package/dist/ToggleButtonGroup.d.ts.map +1 -0
- package/dist/Toolbar.d.ts +7 -3
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +58 -7
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +102 -11
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Virtualizer.d.ts +61 -0
- package/dist/Virtualizer.d.ts.map +1 -0
- package/dist/VirtualizerLayouts.d.ts +82 -0
- package/dist/VirtualizerLayouts.d.ts.map +1 -0
- package/dist/VisuallyHidden.d.ts +4 -2
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +6 -1
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +73 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23342 -10644
- package/dist/index.js.map +1 -7
- package/dist/index.jsx +18110 -0
- package/dist/index.jsx.map +1 -0
- package/dist/useDragAndDrop.d.ts +93 -0
- package/dist/useDragAndDrop.d.ts.map +1 -0
- package/dist/utils.d.ts +8 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/virtualizer/Layout.d.ts +79 -0
- package/dist/virtualizer/Layout.d.ts.map +1 -0
- package/package.json +33 -32
- package/src/ActionBar.tsx +251 -0
- package/src/ActionGroup.tsx +277 -0
- package/src/Alert.tsx +152 -0
- package/src/Autocomplete.tsx +39 -44
- package/src/Breadcrumbs.tsx +227 -72
- package/src/Button.tsx +315 -74
- package/src/Calendar.tsx +347 -141
- package/src/Checkbox.tsx +414 -123
- package/src/Collection.tsx +350 -0
- package/src/Color.tsx +1325 -284
- package/src/ColorEditor.tsx +213 -0
- package/src/ComboBox.tsx +644 -245
- package/src/ContextualHelpTrigger.tsx +195 -0
- package/src/DateField.tsx +274 -106
- package/src/DatePicker.tsx +892 -111
- package/src/DateRangePickerContext.tsx +44 -0
- package/src/Dialog.tsx +173 -104
- package/src/Disclosure.tsx +158 -105
- package/src/DragAndDrop.tsx +340 -0
- package/src/DragPreview.tsx +47 -0
- package/src/DropZone.tsx +233 -0
- package/src/FieldError.tsx +89 -0
- package/src/FileTrigger.tsx +83 -0
- package/src/Focusable.tsx +103 -0
- package/src/Form.tsx +140 -0
- package/src/GridList.tsx +542 -128
- package/src/HiddenDateInput.tsx +153 -0
- package/src/HiddenTimeInput.tsx +133 -0
- package/src/Icon.tsx +133 -0
- package/src/Keyboard.tsx +26 -0
- package/src/Landmark.tsx +37 -63
- package/src/Link.tsx +132 -69
- package/src/ListBox.tsx +656 -106
- package/src/ListDropTargetDelegate.ts +283 -0
- package/src/Menu.tsx +1234 -132
- package/src/Meter.tsx +44 -58
- package/src/Modal.tsx +262 -166
- package/src/NumberField.tsx +267 -151
- package/src/Popover.tsx +452 -343
- package/src/Pressable.tsx +108 -0
- package/src/ProgressBar.tsx +54 -59
- package/src/RadioGroup.tsx +533 -121
- package/src/RangeCalendar.tsx +249 -150
- package/src/RouterProvider.tsx +223 -0
- package/src/SearchField.tsx +460 -133
- package/src/Select.tsx +804 -233
- package/src/SelectionIndicator.tsx +108 -0
- package/src/Separator.tsx +47 -49
- package/src/SharedElementTransition.tsx +264 -0
- package/src/Slider.tsx +148 -98
- package/src/StepList.tsx +272 -0
- package/src/Switch.tsx +93 -46
- package/src/Table.tsx +1551 -225
- package/src/Tabs.tsx +377 -123
- package/src/TagGroup.tsx +233 -135
- package/src/Text.tsx +18 -0
- package/src/TextField.tsx +413 -86
- package/src/TimeField.tsx +232 -222
- package/src/Toast.tsx +306 -160
- package/src/ToggleButton.tsx +169 -0
- package/src/ToggleButtonGroup.tsx +141 -0
- package/src/Toolbar.tsx +61 -70
- package/src/Tooltip.tsx +473 -116
- package/src/Tree.tsx +1514 -175
- package/src/Virtualizer.tsx +730 -0
- package/src/VirtualizerLayouts.ts +280 -0
- package/src/VisuallyHidden.tsx +32 -38
- package/src/contexts.ts +29 -36
- package/src/index.ts +972 -620
- package/src/useDragAndDrop.ts +367 -0
- package/src/utils.tsx +69 -50
- package/src/virtualizer/Layout.ts +192 -0
- package/dist/index.ssr.js +0 -9785
- package/dist/index.ssr.js.map +0 -7
package/src/RadioGroup.tsx
CHANGED
|
@@ -9,25 +9,35 @@ import {
|
|
|
9
9
|
type JSX,
|
|
10
10
|
type ParentProps,
|
|
11
11
|
createContext,
|
|
12
|
-
useContext,
|
|
13
12
|
createMemo,
|
|
13
|
+
createSignal,
|
|
14
|
+
createUniqueId,
|
|
14
15
|
splitProps,
|
|
16
|
+
useContext,
|
|
15
17
|
Show,
|
|
16
|
-
} from
|
|
18
|
+
} from "solid-js";
|
|
17
19
|
import {
|
|
18
20
|
createRadio,
|
|
19
21
|
createRadioGroup,
|
|
20
22
|
createFocusRing,
|
|
21
23
|
createHover,
|
|
24
|
+
mergeProps,
|
|
22
25
|
type AriaRadioProps,
|
|
23
26
|
type AriaRadioGroupProps,
|
|
24
|
-
} from
|
|
27
|
+
} from "@proyecto-viviana/solidaria";
|
|
25
28
|
import {
|
|
26
29
|
createRadioGroupState,
|
|
30
|
+
VALID_VALIDITY_STATE,
|
|
27
31
|
type RadioGroupState,
|
|
28
32
|
type RadioGroupProps as RadioGroupStateProps,
|
|
29
|
-
|
|
30
|
-
|
|
33
|
+
type ValidationResult,
|
|
34
|
+
} from "@proyecto-viviana/solid-stately";
|
|
35
|
+
import { FieldErrorContext, type FieldErrorContextValue } from "./FieldError";
|
|
36
|
+
import { VisuallyHidden } from "./VisuallyHidden";
|
|
37
|
+
import {
|
|
38
|
+
SelectionIndicatorContext,
|
|
39
|
+
type SelectionIndicatorContextValue,
|
|
40
|
+
} from "./SelectionIndicator";
|
|
31
41
|
import {
|
|
32
42
|
type RenderChildren,
|
|
33
43
|
type ClassNameOrFunction,
|
|
@@ -35,13 +45,46 @@ import {
|
|
|
35
45
|
type SlotProps,
|
|
36
46
|
useRenderProps,
|
|
37
47
|
filterDOMProps,
|
|
38
|
-
} from
|
|
48
|
+
} from "./utils";
|
|
49
|
+
|
|
50
|
+
type RefLike<T> = ((el: T) => void) | { current?: T | null } | undefined;
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
function assignRef<T>(ref: RefLike<T>, el: T): void {
|
|
53
|
+
if (!ref) return;
|
|
54
|
+
if (typeof ref === "function") {
|
|
55
|
+
ref(el);
|
|
56
|
+
} else {
|
|
57
|
+
ref.current = el;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
43
60
|
|
|
44
|
-
|
|
61
|
+
const validValidation: ValidationResult = {
|
|
62
|
+
isInvalid: false,
|
|
63
|
+
validationDetails: VALID_VALIDITY_STATE,
|
|
64
|
+
validationErrors: [],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function getNativeValidation(input: HTMLInputElement): ValidationResult {
|
|
68
|
+
return {
|
|
69
|
+
isInvalid: !input.validity.valid,
|
|
70
|
+
validationDetails: {
|
|
71
|
+
badInput: input.validity.badInput,
|
|
72
|
+
customError: input.validity.customError,
|
|
73
|
+
patternMismatch: input.validity.patternMismatch,
|
|
74
|
+
rangeOverflow: input.validity.rangeOverflow,
|
|
75
|
+
rangeUnderflow: input.validity.rangeUnderflow,
|
|
76
|
+
stepMismatch: input.validity.stepMismatch,
|
|
77
|
+
tooLong: input.validity.tooLong,
|
|
78
|
+
tooShort: input.validity.tooShort,
|
|
79
|
+
typeMismatch: input.validity.typeMismatch,
|
|
80
|
+
valueMissing: input.validity.valueMissing,
|
|
81
|
+
valid: input.validity.valid,
|
|
82
|
+
},
|
|
83
|
+
validationErrors: input.validationMessage ? [input.validationMessage] : [],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export type Orientation = "horizontal" | "vertical";
|
|
45
88
|
|
|
46
89
|
export interface RadioGroupRenderProps {
|
|
47
90
|
/** The orientation of the radio group. */
|
|
@@ -80,8 +123,12 @@ export interface RadioRenderProps {
|
|
|
80
123
|
}
|
|
81
124
|
|
|
82
125
|
export interface RadioGroupProps
|
|
83
|
-
extends
|
|
84
|
-
|
|
126
|
+
extends
|
|
127
|
+
Omit<AriaRadioGroupProps, "children" | "label" | "description" | "errorMessage">,
|
|
128
|
+
Pick<
|
|
129
|
+
RadioGroupStateProps,
|
|
130
|
+
"value" | "defaultValue" | "onChange" | "validationState" | "validate"
|
|
131
|
+
>,
|
|
85
132
|
SlotProps {
|
|
86
133
|
/** The children of the component. A function may be provided to receive render props. */
|
|
87
134
|
children?: RenderChildren<RadioGroupRenderProps>;
|
|
@@ -89,30 +136,56 @@ export interface RadioGroupProps
|
|
|
89
136
|
class?: ClassNameOrFunction<RadioGroupRenderProps>;
|
|
90
137
|
/** The inline style for the element. */
|
|
91
138
|
style?: StyleOrFunction<RadioGroupRenderProps>;
|
|
139
|
+
/** Custom renderer for the outer radio group element. */
|
|
140
|
+
render?: (
|
|
141
|
+
props: JSX.HTMLAttributes<HTMLDivElement>,
|
|
142
|
+
renderProps: RadioGroupRenderProps,
|
|
143
|
+
) => JSX.Element;
|
|
144
|
+
/** Ref for the radio group element. */
|
|
145
|
+
ref?: RefLike<HTMLDivElement>;
|
|
146
|
+
/** A description for the radio group. */
|
|
147
|
+
description?: JSX.Element;
|
|
148
|
+
/** An error message for the radio group. */
|
|
149
|
+
errorMessage?: JSX.Element;
|
|
92
150
|
}
|
|
93
151
|
|
|
94
|
-
export interface RadioProps
|
|
95
|
-
extends Omit<AriaRadioProps, 'children'>,
|
|
96
|
-
SlotProps {
|
|
152
|
+
export interface RadioProps extends Omit<AriaRadioProps, "children">, SlotProps {
|
|
97
153
|
/** The children of the component. A function may be provided to receive render props. */
|
|
98
154
|
children?: RenderChildren<RadioRenderProps>;
|
|
99
155
|
/** The CSS className for the element. */
|
|
100
156
|
class?: ClassNameOrFunction<RadioRenderProps>;
|
|
101
157
|
/** The inline style for the element. */
|
|
102
158
|
style?: StyleOrFunction<RadioRenderProps>;
|
|
159
|
+
/** Custom renderer for the outer radio label element. */
|
|
160
|
+
render?: (
|
|
161
|
+
props: JSX.LabelHTMLAttributes<HTMLLabelElement>,
|
|
162
|
+
renderProps: RadioRenderProps,
|
|
163
|
+
) => JSX.Element;
|
|
164
|
+
/** Ref for the outer label element. */
|
|
165
|
+
ref?: RefLike<HTMLLabelElement>;
|
|
166
|
+
/** Ref for the underlying input element. */
|
|
167
|
+
inputRef?: RefLike<HTMLInputElement>;
|
|
168
|
+
/** A description for the radio. */
|
|
169
|
+
description?: JSX.Element;
|
|
170
|
+
/** An error message for the radio. */
|
|
171
|
+
errorMessage?: JSX.Element;
|
|
172
|
+
/** Handler called when hover starts. */
|
|
173
|
+
onHoverStart?: () => void;
|
|
174
|
+
/** Handler called when hover ends. */
|
|
175
|
+
onHoverEnd?: () => void;
|
|
176
|
+
/** Handler called when hover state changes. */
|
|
177
|
+
onHoverChange?: (isHovered: boolean) => void;
|
|
103
178
|
}
|
|
104
179
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
export const RadioGroupContext = createContext<RadioGroupProps | null>(null);
|
|
180
|
+
export interface RadioGroupContextValue extends RadioGroupProps {
|
|
181
|
+
slots?: Record<string, RadioGroupProps>;
|
|
182
|
+
}
|
|
183
|
+
export const RadioGroupContext = createContext<RadioGroupContextValue | null>(null);
|
|
110
184
|
export const RadioGroupStateContext = createContext<RadioGroupState | null>(null);
|
|
111
|
-
export
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// ============================================
|
|
185
|
+
export interface RadioContextValue extends RadioProps {
|
|
186
|
+
slots?: Record<string, RadioProps>;
|
|
187
|
+
}
|
|
188
|
+
export const RadioContext = createContext<RadioContextValue | null>(null);
|
|
116
189
|
|
|
117
190
|
/**
|
|
118
191
|
* A radio group allows a user to select a single item from a list of mutually exclusive options.
|
|
@@ -126,111 +199,307 @@ export const RadioContext = createContext<RadioProps | null>(null);
|
|
|
126
199
|
* ```
|
|
127
200
|
*/
|
|
128
201
|
export function RadioGroup(props: ParentProps<RadioGroupProps>): JSX.Element {
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// Create radio group state
|
|
136
|
-
// We pass a function that returns props so that createRadioGroupState
|
|
137
|
-
// can access props reactively. The props object itself is a proxy in SolidJS,
|
|
138
|
-
// so accessing props.value inside a reactive context will track changes.
|
|
139
|
-
const state = createRadioGroupState({
|
|
140
|
-
get value() { return props.value; },
|
|
141
|
-
get defaultValue() { return props.defaultValue; },
|
|
142
|
-
get onChange() { return props.onChange; },
|
|
143
|
-
get isDisabled() { return props.isDisabled; },
|
|
144
|
-
get isReadOnly() { return props.isReadOnly; },
|
|
145
|
-
get isRequired() { return props.isRequired; },
|
|
146
|
-
get isInvalid() { return props.isInvalid; },
|
|
202
|
+
const contextProps = useContext(RadioGroupContext);
|
|
203
|
+
const contextSlotProps = contextProps?.slots?.[props.slot ?? "default"];
|
|
204
|
+
const contextBaseProps = createMemo<RadioGroupProps>(() => {
|
|
205
|
+
if (!contextProps) return {};
|
|
206
|
+
const { slots: _slots, ...rest } = contextProps;
|
|
207
|
+
return rest;
|
|
147
208
|
});
|
|
209
|
+
const mergedProps = contextProps
|
|
210
|
+
? (mergeProps(
|
|
211
|
+
contextBaseProps(),
|
|
212
|
+
contextSlotProps ?? {},
|
|
213
|
+
props,
|
|
214
|
+
) as ParentProps<RadioGroupProps>)
|
|
215
|
+
: props;
|
|
216
|
+
const [local, ariaProps] = splitProps(mergedProps, ["class", "style", "render", "ref", "slot"]);
|
|
217
|
+
|
|
218
|
+
const state = createRadioGroupState(() => ({
|
|
219
|
+
value: mergedProps.value,
|
|
220
|
+
defaultValue: mergedProps.defaultValue,
|
|
221
|
+
onChange: mergedProps.onChange,
|
|
222
|
+
isDisabled: mergedProps.isDisabled,
|
|
223
|
+
isReadOnly: mergedProps.isReadOnly,
|
|
224
|
+
isRequired: mergedProps.isRequired,
|
|
225
|
+
isInvalid: mergedProps.isInvalid,
|
|
226
|
+
validationState: mergedProps.validationState,
|
|
227
|
+
validate: mergedProps.validate,
|
|
228
|
+
validationBehavior: mergedProps.validationBehavior,
|
|
229
|
+
name: mergedProps.name,
|
|
230
|
+
form: mergedProps.form,
|
|
231
|
+
}));
|
|
148
232
|
|
|
149
233
|
// Create radio group aria props
|
|
150
|
-
const groupAria = createRadioGroup(
|
|
234
|
+
const groupAria = createRadioGroup(
|
|
235
|
+
() => ({
|
|
236
|
+
...ariaProps,
|
|
237
|
+
description: mergedProps.description,
|
|
238
|
+
errorMessage: mergedProps.errorMessage,
|
|
239
|
+
}),
|
|
240
|
+
state,
|
|
241
|
+
);
|
|
242
|
+
const isInvalid = createMemo(() => state.isInvalid);
|
|
243
|
+
const validation = createMemo(() => state.displayValidation());
|
|
244
|
+
const fallbackErrorMessageId = createUniqueId();
|
|
245
|
+
const errorMessageId = () => groupAria.errorMessageProps.id ?? fallbackErrorMessageId;
|
|
151
246
|
|
|
152
|
-
// Render props values
|
|
153
247
|
const renderValues = createMemo<RadioGroupRenderProps>(() => ({
|
|
154
|
-
orientation: (ariaProps.orientation as Orientation) ??
|
|
248
|
+
orientation: (ariaProps.orientation as Orientation) ?? "vertical",
|
|
155
249
|
isDisabled: state.isDisabled,
|
|
156
250
|
isReadOnly: state.isReadOnly,
|
|
157
251
|
isRequired: state.isRequired,
|
|
158
|
-
isInvalid:
|
|
252
|
+
isInvalid: isInvalid(),
|
|
159
253
|
state,
|
|
160
254
|
}));
|
|
161
255
|
|
|
162
|
-
// Resolve render props
|
|
163
256
|
const renderProps = useRenderProps(
|
|
164
257
|
{
|
|
165
258
|
children: props.children,
|
|
166
259
|
class: local.class,
|
|
167
260
|
style: local.style,
|
|
168
|
-
defaultClassName:
|
|
261
|
+
defaultClassName: "solidaria-RadioGroup",
|
|
169
262
|
},
|
|
170
|
-
renderValues
|
|
263
|
+
renderValues,
|
|
171
264
|
);
|
|
172
265
|
|
|
173
|
-
// Filter DOM props
|
|
174
266
|
const domProps = createMemo(() => filterDOMProps(ariaProps, { global: true }));
|
|
175
267
|
|
|
176
|
-
// Remove ref from spread props to avoid type conflicts
|
|
177
268
|
const cleanGroupProps = () => {
|
|
178
269
|
const { ref: _ref, ...rest } = groupAria.radioGroupProps as Record<string, unknown>;
|
|
179
270
|
return rest;
|
|
180
271
|
};
|
|
272
|
+
const handleGroupFocusIn: JSX.EventHandler<HTMLDivElement, FocusEvent> = (event) => {
|
|
273
|
+
(
|
|
274
|
+
groupAria.radioGroupProps as unknown as {
|
|
275
|
+
onFocus?: JSX.EventHandler<HTMLDivElement, FocusEvent>;
|
|
276
|
+
}
|
|
277
|
+
).onFocus?.(event);
|
|
278
|
+
};
|
|
279
|
+
const handleGroupFocusOut: JSX.EventHandler<HTMLDivElement, FocusEvent> = (event) => {
|
|
280
|
+
(
|
|
281
|
+
groupAria.radioGroupProps as unknown as {
|
|
282
|
+
onBlur?: JSX.EventHandler<HTMLDivElement, FocusEvent>;
|
|
283
|
+
}
|
|
284
|
+
).onBlur?.(event);
|
|
285
|
+
};
|
|
286
|
+
const handleGroupInvalidCapture: JSX.EventHandler<HTMLDivElement, Event> = (event) => {
|
|
287
|
+
const target = event.target;
|
|
288
|
+
if (!(target instanceof HTMLInputElement) || target.type !== "radio") {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
181
291
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
292
|
+
state.updateValidation(getNativeValidation(target));
|
|
293
|
+
state.commitValidation();
|
|
294
|
+
target.focus();
|
|
295
|
+
event.preventDefault();
|
|
296
|
+
};
|
|
297
|
+
const handleGroupChangeCapture: JSX.EventHandler<HTMLDivElement, Event> = (event) => {
|
|
298
|
+
const target = event.target;
|
|
299
|
+
if (!(target instanceof HTMLInputElement) || target.type !== "radio") {
|
|
300
|
+
return;
|
|
189
301
|
}
|
|
190
|
-
|
|
302
|
+
|
|
303
|
+
state.updateValidation(target.validity.valid ? validValidation : getNativeValidation(target));
|
|
304
|
+
state.commitValidation();
|
|
305
|
+
};
|
|
306
|
+
const setGroupRef = (el: HTMLDivElement) => {
|
|
307
|
+
assignRef(local.ref, el);
|
|
308
|
+
};
|
|
309
|
+
const groupDescribedBy = () => {
|
|
310
|
+
const ids = [
|
|
311
|
+
(cleanGroupProps() as { "aria-describedby"?: string })["aria-describedby"],
|
|
312
|
+
mergedProps.description ? groupAria.descriptionProps.id : undefined,
|
|
313
|
+
isInvalid() && (mergedProps.errorMessage || validation().validationErrors.length > 0)
|
|
314
|
+
? errorMessageId()
|
|
315
|
+
: undefined,
|
|
316
|
+
]
|
|
317
|
+
.filter(Boolean)
|
|
318
|
+
.join(" ")
|
|
319
|
+
.split(" ")
|
|
320
|
+
.filter(Boolean);
|
|
321
|
+
return ids.length ? Array.from(new Set(ids)).join(" ") : undefined;
|
|
191
322
|
};
|
|
323
|
+
const fieldErrorContext: FieldErrorContextValue = {
|
|
324
|
+
get validation() {
|
|
325
|
+
return validation();
|
|
326
|
+
},
|
|
327
|
+
get errorMessageProps() {
|
|
328
|
+
return {
|
|
329
|
+
...groupAria.errorMessageProps,
|
|
330
|
+
id: errorMessageId(),
|
|
331
|
+
} as JSX.HTMLAttributes<HTMLElement>;
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const GroupChildren = () => {
|
|
336
|
+
const childRenderValues: RadioGroupRenderProps = {
|
|
337
|
+
get orientation() {
|
|
338
|
+
return (ariaProps.orientation as Orientation) ?? "vertical";
|
|
339
|
+
},
|
|
340
|
+
get isDisabled() {
|
|
341
|
+
return state.isDisabled;
|
|
342
|
+
},
|
|
343
|
+
get isReadOnly() {
|
|
344
|
+
return state.isReadOnly;
|
|
345
|
+
},
|
|
346
|
+
get isRequired() {
|
|
347
|
+
return state.isRequired;
|
|
348
|
+
},
|
|
349
|
+
get isInvalid() {
|
|
350
|
+
return isInvalid();
|
|
351
|
+
},
|
|
352
|
+
get state() {
|
|
353
|
+
return state;
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
const renderedChildren = createMemo(() => {
|
|
357
|
+
const children = props.children;
|
|
358
|
+
if (typeof children === "function") {
|
|
359
|
+
return children.length > 0
|
|
360
|
+
? children(childRenderValues)
|
|
361
|
+
: (children as unknown as () => JSX.Element)();
|
|
362
|
+
}
|
|
363
|
+
return children;
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
return (
|
|
367
|
+
<>
|
|
368
|
+
{renderedChildren()}
|
|
369
|
+
<Show when={mergedProps.description}>
|
|
370
|
+
<div {...(groupAria.descriptionProps as unknown as JSX.HTMLAttributes<HTMLDivElement>)}>
|
|
371
|
+
{mergedProps.description}
|
|
372
|
+
</div>
|
|
373
|
+
</Show>
|
|
374
|
+
<Show when={isInvalid() && mergedProps.errorMessage}>
|
|
375
|
+
<div {...(groupAria.errorMessageProps as unknown as JSX.HTMLAttributes<HTMLDivElement>)}>
|
|
376
|
+
{mergedProps.errorMessage}
|
|
377
|
+
</div>
|
|
378
|
+
</Show>
|
|
379
|
+
</>
|
|
380
|
+
);
|
|
381
|
+
};
|
|
382
|
+
const groupEventProps = {
|
|
383
|
+
onInvalidCapture: handleGroupInvalidCapture,
|
|
384
|
+
onChangeCapture: handleGroupChangeCapture,
|
|
385
|
+
} as unknown as JSX.HTMLAttributes<HTMLDivElement>;
|
|
386
|
+
const customRootProps = () =>
|
|
387
|
+
({
|
|
388
|
+
...domProps(),
|
|
389
|
+
...cleanGroupProps(),
|
|
390
|
+
...groupEventProps,
|
|
391
|
+
ref: setGroupRef,
|
|
392
|
+
onFocusIn: handleGroupFocusIn,
|
|
393
|
+
onFocusOut: handleGroupFocusOut,
|
|
394
|
+
"aria-describedby": groupDescribedBy(),
|
|
395
|
+
class: renderProps.class(),
|
|
396
|
+
style: renderProps.style(),
|
|
397
|
+
slot: local.slot,
|
|
398
|
+
"data-orientation": ariaProps.orientation ?? "vertical",
|
|
399
|
+
"data-disabled": state.isDisabled || undefined,
|
|
400
|
+
"data-readonly": state.isReadOnly || undefined,
|
|
401
|
+
"data-required": state.isRequired || undefined,
|
|
402
|
+
"data-invalid": isInvalid() || undefined,
|
|
403
|
+
children: <GroupChildren />,
|
|
404
|
+
}) as unknown as JSX.HTMLAttributes<HTMLDivElement>;
|
|
192
405
|
|
|
193
406
|
return (
|
|
194
407
|
<RadioGroupStateContext.Provider value={state}>
|
|
195
|
-
<
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
408
|
+
<FieldErrorContext.Provider value={fieldErrorContext}>
|
|
409
|
+
{local.render ? (
|
|
410
|
+
local.render(customRootProps(), renderValues())
|
|
411
|
+
) : (
|
|
412
|
+
<div
|
|
413
|
+
{...domProps()}
|
|
414
|
+
{...cleanGroupProps()}
|
|
415
|
+
{...groupEventProps}
|
|
416
|
+
ref={setGroupRef}
|
|
417
|
+
onFocusIn={handleGroupFocusIn}
|
|
418
|
+
onFocusOut={handleGroupFocusOut}
|
|
419
|
+
aria-describedby={groupDescribedBy()}
|
|
420
|
+
class={renderProps.class()}
|
|
421
|
+
style={renderProps.style()}
|
|
422
|
+
slot={local.slot}
|
|
423
|
+
data-orientation={ariaProps.orientation ?? "vertical"}
|
|
424
|
+
data-disabled={state.isDisabled || undefined}
|
|
425
|
+
data-readonly={state.isReadOnly || undefined}
|
|
426
|
+
data-required={state.isRequired || undefined}
|
|
427
|
+
data-invalid={isInvalid() || undefined}
|
|
428
|
+
>
|
|
429
|
+
<GroupChildren />
|
|
430
|
+
</div>
|
|
431
|
+
)}
|
|
432
|
+
</FieldErrorContext.Provider>
|
|
208
433
|
</RadioGroupStateContext.Provider>
|
|
209
434
|
);
|
|
210
435
|
}
|
|
211
436
|
|
|
212
|
-
// ============================================
|
|
213
|
-
// RADIO COMPONENT
|
|
214
|
-
// ============================================
|
|
215
|
-
|
|
216
437
|
/**
|
|
217
438
|
* Internal Radio implementation that has access to RadioGroupStateContext.
|
|
218
439
|
* This is rendered inside the RadioGroup's context provider.
|
|
219
440
|
*/
|
|
220
441
|
function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): JSX.Element {
|
|
221
|
-
|
|
222
|
-
const {
|
|
442
|
+
const [inputElement, setInputElement] = createSignal<HTMLInputElement | null>(null);
|
|
443
|
+
const { state } = props;
|
|
444
|
+
const contextProps = useContext(RadioContext);
|
|
445
|
+
const contextSlotProps = contextProps?.slots?.[props.radioProps.slot ?? "default"];
|
|
446
|
+
const contextBaseProps = createMemo<RadioProps>(() => {
|
|
447
|
+
if (!contextProps) return {} as RadioProps;
|
|
448
|
+
const { slots: _slots, ...rest } = contextProps;
|
|
449
|
+
return rest as RadioProps;
|
|
450
|
+
});
|
|
451
|
+
const radioProps = contextProps
|
|
452
|
+
? (mergeProps(contextBaseProps(), contextSlotProps ?? {}, props.radioProps) as RadioProps)
|
|
453
|
+
: props.radioProps;
|
|
454
|
+
const inputRefs = createMemo(
|
|
455
|
+
() =>
|
|
456
|
+
[contextBaseProps().inputRef, contextSlotProps?.inputRef, props.radioProps.inputRef].filter(
|
|
457
|
+
Boolean,
|
|
458
|
+
) as RefLike<HTMLInputElement>[],
|
|
459
|
+
);
|
|
223
460
|
|
|
224
|
-
const [local, ariaProps] = splitProps(radioProps, [
|
|
461
|
+
const [local, ariaProps] = splitProps(radioProps, [
|
|
462
|
+
"class",
|
|
463
|
+
"style",
|
|
464
|
+
"render",
|
|
465
|
+
"ref",
|
|
466
|
+
"inputRef",
|
|
467
|
+
"slot",
|
|
468
|
+
"description",
|
|
469
|
+
"errorMessage",
|
|
470
|
+
"onHoverStart",
|
|
471
|
+
"onHoverEnd",
|
|
472
|
+
"onHoverChange",
|
|
473
|
+
]);
|
|
474
|
+
const descriptionId = createUniqueId();
|
|
475
|
+
const errorMessageId = createUniqueId();
|
|
476
|
+
const describedBy = () => {
|
|
477
|
+
const ids = [
|
|
478
|
+
ariaProps["aria-describedby"],
|
|
479
|
+
local.description ? descriptionId : undefined,
|
|
480
|
+
state.isInvalid && local.errorMessage ? errorMessageId : undefined,
|
|
481
|
+
].filter(Boolean);
|
|
482
|
+
return ids.length ? ids.join(" ") : undefined;
|
|
483
|
+
};
|
|
484
|
+
const inputAriaProps = createMemo(() => {
|
|
485
|
+
const clean: Record<string, unknown> = {};
|
|
486
|
+
for (const key in ariaProps as Record<string, unknown>) {
|
|
487
|
+
if (!key.startsWith("data-")) {
|
|
488
|
+
clean[key] = (ariaProps as Record<string, unknown>)[key];
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return clean as typeof ariaProps;
|
|
492
|
+
});
|
|
225
493
|
|
|
226
494
|
// Create radio aria props
|
|
227
495
|
const radioAria = createRadio(
|
|
228
496
|
() => ({
|
|
229
|
-
...
|
|
230
|
-
|
|
497
|
+
...inputAriaProps(),
|
|
498
|
+
"aria-describedby": describedBy(),
|
|
499
|
+
children: typeof radioProps.children === "function" ? true : radioProps.children,
|
|
231
500
|
}),
|
|
232
501
|
state,
|
|
233
|
-
|
|
502
|
+
inputElement,
|
|
234
503
|
);
|
|
235
504
|
|
|
236
505
|
// Create focus ring
|
|
@@ -241,9 +510,11 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
241
510
|
get isDisabled() {
|
|
242
511
|
return radioAria.isDisabled || state.isReadOnly;
|
|
243
512
|
},
|
|
513
|
+
onHoverStart: local.onHoverStart,
|
|
514
|
+
onHoverEnd: local.onHoverEnd,
|
|
515
|
+
onHoverChange: local.onHoverChange,
|
|
244
516
|
});
|
|
245
517
|
|
|
246
|
-
// Render props values
|
|
247
518
|
const renderValues = createMemo<RadioRenderProps>(() => ({
|
|
248
519
|
isSelected: radioAria.isSelected(),
|
|
249
520
|
isHovered: isHovered(),
|
|
@@ -256,18 +527,20 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
256
527
|
isRequired: state.isRequired,
|
|
257
528
|
}));
|
|
258
529
|
|
|
259
|
-
// Resolve render props
|
|
260
530
|
const renderProps = useRenderProps(
|
|
261
531
|
{
|
|
262
532
|
children: radioProps.children,
|
|
263
533
|
class: local.class,
|
|
264
534
|
style: local.style,
|
|
265
|
-
defaultClassName:
|
|
535
|
+
defaultClassName: "solidaria-Radio",
|
|
266
536
|
},
|
|
267
|
-
renderValues
|
|
537
|
+
renderValues,
|
|
268
538
|
);
|
|
269
539
|
|
|
270
|
-
|
|
540
|
+
const selectionIndicatorContext = createMemo<SelectionIndicatorContextValue>(() => ({
|
|
541
|
+
isSelected: radioAria.isSelected,
|
|
542
|
+
}));
|
|
543
|
+
|
|
271
544
|
const domProps = createMemo(() => {
|
|
272
545
|
const filtered = filterDOMProps(ariaProps, { global: true });
|
|
273
546
|
delete (filtered as Record<string, unknown>).id;
|
|
@@ -275,7 +548,6 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
275
548
|
return filtered;
|
|
276
549
|
});
|
|
277
550
|
|
|
278
|
-
// Remove ref from spread props to avoid type conflicts
|
|
279
551
|
const cleanLabelProps = () => {
|
|
280
552
|
const { ref: _ref1, ...rest } = radioAria.labelProps as Record<string, unknown>;
|
|
281
553
|
return rest;
|
|
@@ -285,40 +557,184 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
285
557
|
return rest;
|
|
286
558
|
};
|
|
287
559
|
const cleanInputProps = () => {
|
|
288
|
-
const {
|
|
560
|
+
const {
|
|
561
|
+
ref: _ref3,
|
|
562
|
+
onFocus: _onFocus,
|
|
563
|
+
onBlur: _onBlur,
|
|
564
|
+
...rest
|
|
565
|
+
} = radioAria.inputProps as Record<string, unknown>;
|
|
289
566
|
return rest;
|
|
290
567
|
};
|
|
291
568
|
const cleanFocusProps = () => {
|
|
292
|
-
const {
|
|
569
|
+
const {
|
|
570
|
+
ref: _ref4,
|
|
571
|
+
onFocus: _onFocus,
|
|
572
|
+
onBlur: _onBlur,
|
|
573
|
+
...rest
|
|
574
|
+
} = focusProps as Record<string, unknown>;
|
|
293
575
|
return rest;
|
|
294
576
|
};
|
|
577
|
+
const handleInputFocus: JSX.EventHandler<HTMLInputElement, FocusEvent> = (event) => {
|
|
578
|
+
(
|
|
579
|
+
radioAria.inputProps as unknown as {
|
|
580
|
+
onFocus?: JSX.EventHandler<HTMLInputElement, FocusEvent>;
|
|
581
|
+
}
|
|
582
|
+
).onFocus?.(event);
|
|
583
|
+
(
|
|
584
|
+
focusProps as unknown as { onFocus?: JSX.EventHandler<HTMLInputElement, FocusEvent> }
|
|
585
|
+
).onFocus?.(event);
|
|
586
|
+
};
|
|
587
|
+
const handleInputBlur: JSX.EventHandler<HTMLInputElement, FocusEvent> = (event) => {
|
|
588
|
+
(
|
|
589
|
+
radioAria.inputProps as unknown as { onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent> }
|
|
590
|
+
).onBlur?.(event);
|
|
591
|
+
(focusProps as unknown as { onBlur?: JSX.EventHandler<HTMLInputElement, FocusEvent> }).onBlur?.(
|
|
592
|
+
event,
|
|
593
|
+
);
|
|
594
|
+
};
|
|
595
|
+
const handleLabelClick: JSX.EventHandler<HTMLLabelElement, MouseEvent> = (event) => {
|
|
596
|
+
(ariaProps as unknown as { onClickCapture?: (event: MouseEvent) => void }).onClickCapture?.(
|
|
597
|
+
event as unknown as MouseEvent,
|
|
598
|
+
);
|
|
599
|
+
(
|
|
600
|
+
radioAria.labelProps as unknown as {
|
|
601
|
+
onClick?: JSX.EventHandler<HTMLLabelElement, MouseEvent>;
|
|
602
|
+
}
|
|
603
|
+
).onClick?.(event);
|
|
604
|
+
};
|
|
605
|
+
const handleLabelClickCapture: JSX.EventHandler<HTMLLabelElement, MouseEvent> = (event) => {
|
|
606
|
+
(ariaProps as unknown as { onClickCapture?: (event: MouseEvent) => void }).onClickCapture?.(
|
|
607
|
+
event as unknown as MouseEvent,
|
|
608
|
+
);
|
|
609
|
+
};
|
|
610
|
+
const handleInputClick: JSX.EventHandler<HTMLInputElement, MouseEvent> = (event) => {
|
|
611
|
+
(
|
|
612
|
+
radioAria.inputProps as unknown as {
|
|
613
|
+
onClick?: JSX.EventHandler<HTMLInputElement, MouseEvent>;
|
|
614
|
+
}
|
|
615
|
+
).onClick?.(event);
|
|
616
|
+
};
|
|
617
|
+
const handleInputInvalid: JSX.EventHandler<HTMLInputElement, Event> = (event) => {
|
|
618
|
+
state.updateValidation(getNativeValidation(event.currentTarget));
|
|
619
|
+
state.commitValidation();
|
|
620
|
+
event.currentTarget.focus();
|
|
621
|
+
event.preventDefault();
|
|
622
|
+
};
|
|
623
|
+
const handleInputChange: JSX.EventHandler<HTMLInputElement, Event> = (event) => {
|
|
624
|
+
(
|
|
625
|
+
radioAria.inputProps as unknown as { onChange?: JSX.EventHandler<HTMLInputElement, Event> }
|
|
626
|
+
).onChange?.(event);
|
|
627
|
+
state.updateValidation(
|
|
628
|
+
event.currentTarget.validity.valid
|
|
629
|
+
? validValidation
|
|
630
|
+
: getNativeValidation(event.currentTarget),
|
|
631
|
+
);
|
|
632
|
+
state.commitValidation();
|
|
633
|
+
};
|
|
634
|
+
const setLabelRef = (el: HTMLLabelElement) => {
|
|
635
|
+
assignRef(local.ref, el);
|
|
636
|
+
};
|
|
637
|
+
const setInputRef = (el: HTMLInputElement) => {
|
|
638
|
+
setInputElement(el);
|
|
639
|
+
el.addEventListener("invalid", (event) => {
|
|
640
|
+
state.updateValidation(getNativeValidation(el));
|
|
641
|
+
state.commitValidation();
|
|
642
|
+
el.focus();
|
|
643
|
+
event.preventDefault();
|
|
644
|
+
});
|
|
645
|
+
el.addEventListener("change", () => {
|
|
646
|
+
state.updateValidation(el.validity.valid ? validValidation : getNativeValidation(el));
|
|
647
|
+
state.commitValidation();
|
|
648
|
+
});
|
|
649
|
+
for (const ref of inputRefs()) {
|
|
650
|
+
assignRef(ref, el);
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
const hiddenInput = (
|
|
654
|
+
<VisuallyHidden>
|
|
655
|
+
<input
|
|
656
|
+
ref={setInputRef}
|
|
657
|
+
{...cleanInputProps()}
|
|
658
|
+
{...cleanFocusProps()}
|
|
659
|
+
onFocus={handleInputFocus}
|
|
660
|
+
onBlur={handleInputBlur}
|
|
661
|
+
onInvalid={handleInputInvalid}
|
|
662
|
+
onChange={handleInputChange}
|
|
663
|
+
onClick={handleInputClick}
|
|
664
|
+
/>
|
|
665
|
+
</VisuallyHidden>
|
|
666
|
+
);
|
|
667
|
+
const labelChildren = () => (
|
|
668
|
+
<>
|
|
669
|
+
{hiddenInput}
|
|
670
|
+
{renderProps.renderChildren()}
|
|
671
|
+
<Show when={local.description}>
|
|
672
|
+
<span id={descriptionId} slot="description">
|
|
673
|
+
{local.description}
|
|
674
|
+
</span>
|
|
675
|
+
</Show>
|
|
676
|
+
<Show when={state.isInvalid && local.errorMessage}>
|
|
677
|
+
<span id={errorMessageId} slot="errorMessage">
|
|
678
|
+
{local.errorMessage}
|
|
679
|
+
</span>
|
|
680
|
+
</Show>
|
|
681
|
+
</>
|
|
682
|
+
);
|
|
683
|
+
const customLabelProps = () =>
|
|
684
|
+
({
|
|
685
|
+
...domProps(),
|
|
686
|
+
...cleanLabelProps(),
|
|
687
|
+
...cleanHoverProps(),
|
|
688
|
+
ref: setLabelRef,
|
|
689
|
+
class: renderProps.class(),
|
|
690
|
+
style: renderProps.style(),
|
|
691
|
+
slot: local.slot,
|
|
692
|
+
onClick: handleLabelClick,
|
|
693
|
+
onClickCapture: handleLabelClickCapture,
|
|
694
|
+
"data-selected": radioAria.isSelected() || undefined,
|
|
695
|
+
"data-pressed": radioAria.isPressed() || undefined,
|
|
696
|
+
"data-hovered": isHovered() || undefined,
|
|
697
|
+
"data-focused": isFocused() || undefined,
|
|
698
|
+
"data-focus-visible": isFocusVisible() || undefined,
|
|
699
|
+
"data-disabled": radioAria.isDisabled || undefined,
|
|
700
|
+
"data-readonly": state.isReadOnly || undefined,
|
|
701
|
+
"data-invalid": state.isInvalid || undefined,
|
|
702
|
+
"data-required": state.isRequired || undefined,
|
|
703
|
+
children: labelChildren(),
|
|
704
|
+
}) as unknown as JSX.LabelHTMLAttributes<HTMLLabelElement>;
|
|
705
|
+
const labelCaptureProps = {
|
|
706
|
+
onClickCapture: handleLabelClickCapture,
|
|
707
|
+
} as unknown as JSX.LabelHTMLAttributes<HTMLLabelElement>;
|
|
295
708
|
|
|
296
709
|
return (
|
|
297
|
-
<
|
|
298
|
-
{
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
{
|
|
317
|
-
{
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
710
|
+
<SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
|
|
711
|
+
{local.render ? (
|
|
712
|
+
local.render(customLabelProps(), renderValues())
|
|
713
|
+
) : (
|
|
714
|
+
<label
|
|
715
|
+
{...domProps()}
|
|
716
|
+
{...cleanLabelProps()}
|
|
717
|
+
{...cleanHoverProps()}
|
|
718
|
+
ref={setLabelRef}
|
|
719
|
+
class={renderProps.class()}
|
|
720
|
+
style={renderProps.style()}
|
|
721
|
+
slot={local.slot}
|
|
722
|
+
onClick={handleLabelClick}
|
|
723
|
+
{...labelCaptureProps}
|
|
724
|
+
data-selected={radioAria.isSelected() || undefined}
|
|
725
|
+
data-pressed={radioAria.isPressed() || undefined}
|
|
726
|
+
data-hovered={isHovered() || undefined}
|
|
727
|
+
data-focused={isFocused() || undefined}
|
|
728
|
+
data-focus-visible={isFocusVisible() || undefined}
|
|
729
|
+
data-disabled={radioAria.isDisabled || undefined}
|
|
730
|
+
data-readonly={state.isReadOnly || undefined}
|
|
731
|
+
data-invalid={state.isInvalid || undefined}
|
|
732
|
+
data-required={state.isRequired || undefined}
|
|
733
|
+
>
|
|
734
|
+
{labelChildren()}
|
|
735
|
+
</label>
|
|
736
|
+
)}
|
|
737
|
+
</SelectionIndicatorContext.Provider>
|
|
322
738
|
);
|
|
323
739
|
}
|
|
324
740
|
|
|
@@ -345,11 +761,7 @@ export function Radio(props: RadioProps): JSX.Element {
|
|
|
345
761
|
const getState = createMemo(() => useContext(RadioGroupStateContext));
|
|
346
762
|
|
|
347
763
|
return (
|
|
348
|
-
<Show
|
|
349
|
-
when={getState()}
|
|
350
|
-
fallback={null}
|
|
351
|
-
keyed
|
|
352
|
-
>
|
|
764
|
+
<Show when={getState()} fallback={null} keyed>
|
|
353
765
|
{(state) => <RadioImpl radioProps={props} state={state} />}
|
|
354
766
|
</Show>
|
|
355
767
|
);
|