@proyecto-viviana/solidaria-components 0.2.9 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -272
- package/dist/ActionBar.d.ts +21 -13
- package/dist/ActionBar.d.ts.map +1 -1
- package/dist/ActionGroup.d.ts +8 -8
- package/dist/ActionGroup.d.ts.map +1 -1
- package/dist/Alert.d.ts +5 -5
- package/dist/Alert.d.ts.map +1 -1
- package/dist/Autocomplete.d.ts +5 -5
- package/dist/Autocomplete.d.ts.map +1 -1
- package/dist/Breadcrumbs.d.ts +18 -7
- package/dist/Breadcrumbs.d.ts.map +1 -1
- package/dist/Button.d.ts +24 -5
- package/dist/Button.d.ts.map +1 -1
- package/dist/Calendar.d.ts +38 -7
- package/dist/Calendar.d.ts.map +1 -1
- package/dist/Checkbox.d.ts +32 -7
- package/dist/Checkbox.d.ts.map +1 -1
- package/dist/Collection.d.ts +19 -14
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Color.d.ts +103 -14
- package/dist/Color.d.ts.map +1 -1
- package/dist/ColorEditor.d.ts +6 -6
- package/dist/ColorEditor.d.ts.map +1 -1
- package/dist/ComboBox.d.ts +85 -19
- package/dist/ComboBox.d.ts.map +1 -1
- package/dist/ContextualHelpTrigger.d.ts +2 -2
- package/dist/ContextualHelpTrigger.d.ts.map +1 -1
- package/dist/DateField.d.ts +8 -6
- package/dist/DateField.d.ts.map +1 -1
- package/dist/DatePicker.d.ts +53 -22
- 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 +23 -5
- package/dist/Disclosure.d.ts.map +1 -1
- package/dist/DragAndDrop.d.ts +6 -6
- package/dist/DragAndDrop.d.ts.map +1 -1
- package/dist/DragPreview.d.ts +2 -2
- package/dist/DragPreview.d.ts.map +1 -1
- package/dist/DropZone.d.ts +4 -4
- package/dist/DropZone.d.ts.map +1 -1
- package/dist/FieldError.d.ts +9 -5
- package/dist/FieldError.d.ts.map +1 -1
- package/dist/FileTrigger.d.ts +3 -3
- package/dist/FileTrigger.d.ts.map +1 -1
- package/dist/Focusable.d.ts +2 -2
- package/dist/Focusable.d.ts.map +1 -1
- package/dist/Form.d.ts +18 -4
- package/dist/Form.d.ts.map +1 -1
- package/dist/GridList.d.ts +32 -12
- 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 +5 -5
- package/dist/Icon.d.ts.map +1 -1
- package/dist/Keyboard.d.ts +1 -1
- 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 +32 -12
- package/dist/ListBox.d.ts.map +1 -1
- package/dist/ListDropTargetDelegate.d.ts +6 -6
- package/dist/ListDropTargetDelegate.d.ts.map +1 -1
- package/dist/Menu.d.ts +65 -14
- package/dist/Menu.d.ts.map +1 -1
- package/dist/Meter.d.ts +3 -3
- package/dist/Meter.d.ts.map +1 -1
- package/dist/Modal.d.ts +5 -5
- package/dist/Modal.d.ts.map +1 -1
- package/dist/NumberField.d.ts +8 -12
- package/dist/NumberField.d.ts.map +1 -1
- package/dist/Popover.d.ts +28 -5
- package/dist/Popover.d.ts.map +1 -1
- package/dist/Pressable.d.ts +2 -2
- package/dist/Pressable.d.ts.map +1 -1
- package/dist/ProgressBar.d.ts +5 -3
- 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 +34 -7
- package/dist/RangeCalendar.d.ts.map +1 -1
- package/dist/RouterProvider.d.ts +2 -2
- package/dist/RouterProvider.d.ts.map +1 -1
- package/dist/SearchField.d.ts +23 -20
- package/dist/SearchField.d.ts.map +1 -1
- package/dist/Select.d.ts +41 -11
- package/dist/Select.d.ts.map +1 -1
- package/dist/SelectionIndicator.d.ts +3 -3
- package/dist/SelectionIndicator.d.ts.map +1 -1
- package/dist/Separator.d.ts +9 -3
- package/dist/Separator.d.ts.map +1 -1
- package/dist/SharedElementTransition.d.ts +6 -4
- package/dist/SharedElementTransition.d.ts.map +1 -1
- package/dist/Slider.d.ts +12 -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 +187 -23
- package/dist/Table.d.ts.map +1 -1
- package/dist/Tabs.d.ts +45 -9
- package/dist/Tabs.d.ts.map +1 -1
- package/dist/TagGroup.d.ts +12 -10
- package/dist/TagGroup.d.ts.map +1 -1
- package/dist/Text.d.ts +2 -2
- package/dist/TextField.d.ts +15 -11
- package/dist/TextField.d.ts.map +1 -1
- package/dist/TimeField.d.ts +6 -6
- 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 +11 -5
- package/dist/ToggleButton.d.ts.map +1 -1
- package/dist/ToggleButtonGroup.d.ts +7 -7
- package/dist/ToggleButtonGroup.d.ts.map +1 -1
- package/dist/Toolbar.d.ts +7 -3
- package/dist/Toolbar.d.ts.map +1 -1
- package/dist/Tooltip.d.ts +50 -8
- package/dist/Tooltip.d.ts.map +1 -1
- package/dist/Tree.d.ts +66 -17
- package/dist/Tree.d.ts.map +1 -1
- package/dist/Virtualizer.d.ts +12 -12
- package/dist/Virtualizer.d.ts.map +1 -1
- package/dist/VirtualizerLayouts.d.ts +2 -2
- package/dist/VirtualizerLayouts.d.ts.map +1 -1
- package/dist/VisuallyHidden.d.ts +1 -1
- package/dist/VisuallyHidden.d.ts.map +1 -1
- package/dist/contexts.d.ts +5 -1
- package/dist/contexts.d.ts.map +1 -1
- package/dist/index.d.ts +73 -71
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23247 -18564
- package/dist/index.js.map +1 -1
- package/dist/index.jsx +18110 -0
- package/dist/index.jsx.map +1 -0
- package/dist/useDragAndDrop.d.ts +13 -13
- package/dist/useDragAndDrop.d.ts.map +1 -1
- package/dist/utils.d.ts +2 -2
- package/dist/utils.d.ts.map +1 -1
- package/dist/virtualizer/Layout.d.ts +1 -1
- package/dist/virtualizer/Layout.d.ts.map +1 -1
- package/package.json +31 -32
- package/src/ActionBar.tsx +75 -72
- package/src/ActionGroup.tsx +53 -61
- package/src/Alert.tsx +17 -42
- package/src/Autocomplete.tsx +39 -44
- package/src/Breadcrumbs.tsx +149 -80
- package/src/Button.tsx +267 -70
- package/src/Calendar.tsx +218 -138
- package/src/Checkbox.tsx +413 -121
- package/src/Collection.tsx +67 -58
- package/src/Color.tsx +803 -380
- package/src/ColorEditor.tsx +131 -149
- package/src/ComboBox.tsx +414 -249
- package/src/ContextualHelpTrigger.tsx +86 -74
- package/src/DateField.tsx +185 -91
- package/src/DatePicker.tsx +524 -213
- package/src/DateRangePickerContext.tsx +44 -0
- package/src/Dialog.tsx +156 -118
- package/src/Disclosure.tsx +127 -80
- package/src/DragAndDrop.tsx +60 -54
- package/src/DragPreview.tsx +13 -11
- package/src/DropZone.tsx +42 -22
- package/src/FieldError.tsx +45 -23
- package/src/FileTrigger.tsx +19 -19
- package/src/Focusable.tsx +21 -24
- package/src/Form.tsx +71 -16
- package/src/GridList.tsx +273 -197
- package/src/HiddenDateInput.tsx +153 -0
- package/src/HiddenTimeInput.tsx +133 -0
- package/src/Icon.tsx +22 -43
- package/src/Keyboard.tsx +3 -3
- package/src/Landmark.tsx +37 -63
- package/src/Link.tsx +125 -75
- package/src/ListBox.tsx +332 -233
- package/src/ListDropTargetDelegate.ts +81 -80
- package/src/Menu.tsx +1023 -274
- package/src/Meter.tsx +38 -56
- package/src/Modal.tsx +243 -175
- package/src/NumberField.tsx +139 -143
- package/src/Popover.tsx +386 -233
- package/src/Pressable.tsx +21 -21
- package/src/ProgressBar.tsx +48 -57
- package/src/RadioGroup.tsx +524 -122
- package/src/RangeCalendar.tsx +157 -90
- package/src/RouterProvider.tsx +30 -47
- package/src/SearchField.tsx +362 -143
- package/src/Select.tsx +656 -233
- package/src/SelectionIndicator.tsx +18 -15
- package/src/Separator.tsx +47 -49
- package/src/SharedElementTransition.tsx +103 -97
- package/src/Slider.tsx +138 -98
- package/src/StepList.tsx +272 -0
- package/src/Switch.tsx +93 -46
- package/src/Table.tsx +1308 -342
- package/src/Tabs.tsx +324 -103
- package/src/TagGroup.tsx +139 -126
- package/src/Text.tsx +3 -3
- package/src/TextField.tsx +389 -79
- package/src/TimeField.tsx +136 -76
- package/src/Toast.tsx +209 -157
- package/src/ToggleButton.tsx +47 -37
- package/src/ToggleButtonGroup.tsx +39 -34
- package/src/Toolbar.tsx +54 -69
- package/src/Tooltip.tsx +387 -119
- package/src/Tree.tsx +651 -368
- package/src/Virtualizer.tsx +208 -180
- package/src/VirtualizerLayouts.ts +45 -30
- package/src/VisuallyHidden.tsx +19 -19
- package/src/contexts.ts +29 -37
- package/src/index.ts +110 -195
- package/src/useDragAndDrop.ts +87 -71
- package/src/utils.tsx +40 -55
- package/src/virtualizer/Layout.ts +14 -22
- package/dist/index.ssr.js +0 -16996
- package/dist/index.ssr.js.map +0 -1
package/src/RadioGroup.tsx
CHANGED
|
@@ -9,29 +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";
|
|
31
37
|
import {
|
|
32
38
|
SelectionIndicatorContext,
|
|
33
39
|
type SelectionIndicatorContextValue,
|
|
34
|
-
} from
|
|
40
|
+
} from "./SelectionIndicator";
|
|
35
41
|
import {
|
|
36
42
|
type RenderChildren,
|
|
37
43
|
type ClassNameOrFunction,
|
|
@@ -39,13 +45,46 @@ import {
|
|
|
39
45
|
type SlotProps,
|
|
40
46
|
useRenderProps,
|
|
41
47
|
filterDOMProps,
|
|
42
|
-
} from
|
|
48
|
+
} from "./utils";
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
type RefLike<T> = ((el: T) => void) | { current?: T | null } | undefined;
|
|
51
|
+
|
|
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
|
+
}
|
|
60
|
+
|
|
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
|
+
}
|
|
47
86
|
|
|
48
|
-
export type Orientation =
|
|
87
|
+
export type Orientation = "horizontal" | "vertical";
|
|
49
88
|
|
|
50
89
|
export interface RadioGroupRenderProps {
|
|
51
90
|
/** The orientation of the radio group. */
|
|
@@ -84,8 +123,12 @@ export interface RadioRenderProps {
|
|
|
84
123
|
}
|
|
85
124
|
|
|
86
125
|
export interface RadioGroupProps
|
|
87
|
-
extends
|
|
88
|
-
|
|
126
|
+
extends
|
|
127
|
+
Omit<AriaRadioGroupProps, "children" | "label" | "description" | "errorMessage">,
|
|
128
|
+
Pick<
|
|
129
|
+
RadioGroupStateProps,
|
|
130
|
+
"value" | "defaultValue" | "onChange" | "validationState" | "validate"
|
|
131
|
+
>,
|
|
89
132
|
SlotProps {
|
|
90
133
|
/** The children of the component. A function may be provided to receive render props. */
|
|
91
134
|
children?: RenderChildren<RadioGroupRenderProps>;
|
|
@@ -93,30 +136,56 @@ export interface RadioGroupProps
|
|
|
93
136
|
class?: ClassNameOrFunction<RadioGroupRenderProps>;
|
|
94
137
|
/** The inline style for the element. */
|
|
95
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;
|
|
96
150
|
}
|
|
97
151
|
|
|
98
|
-
export interface RadioProps
|
|
99
|
-
extends Omit<AriaRadioProps, 'children'>,
|
|
100
|
-
SlotProps {
|
|
152
|
+
export interface RadioProps extends Omit<AriaRadioProps, "children">, SlotProps {
|
|
101
153
|
/** The children of the component. A function may be provided to receive render props. */
|
|
102
154
|
children?: RenderChildren<RadioRenderProps>;
|
|
103
155
|
/** The CSS className for the element. */
|
|
104
156
|
class?: ClassNameOrFunction<RadioRenderProps>;
|
|
105
157
|
/** The inline style for the element. */
|
|
106
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;
|
|
107
178
|
}
|
|
108
179
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
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);
|
|
114
184
|
export const RadioGroupStateContext = createContext<RadioGroupState | null>(null);
|
|
115
|
-
export
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// ============================================
|
|
185
|
+
export interface RadioContextValue extends RadioProps {
|
|
186
|
+
slots?: Record<string, RadioProps>;
|
|
187
|
+
}
|
|
188
|
+
export const RadioContext = createContext<RadioContextValue | null>(null);
|
|
120
189
|
|
|
121
190
|
/**
|
|
122
191
|
* A radio group allows a user to select a single item from a list of mutually exclusive options.
|
|
@@ -130,111 +199,307 @@ export const RadioContext = createContext<RadioProps | null>(null);
|
|
|
130
199
|
* ```
|
|
131
200
|
*/
|
|
132
201
|
export function RadioGroup(props: ParentProps<RadioGroupProps>): JSX.Element {
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// Create radio group state
|
|
140
|
-
// We pass a function that returns props so that createRadioGroupState
|
|
141
|
-
// can access props reactively. The props object itself is a proxy in SolidJS,
|
|
142
|
-
// so accessing props.value inside a reactive context will track changes.
|
|
143
|
-
const state = createRadioGroupState({
|
|
144
|
-
get value() { return props.value; },
|
|
145
|
-
get defaultValue() { return props.defaultValue; },
|
|
146
|
-
get onChange() { return props.onChange; },
|
|
147
|
-
get isDisabled() { return props.isDisabled; },
|
|
148
|
-
get isReadOnly() { return props.isReadOnly; },
|
|
149
|
-
get isRequired() { return props.isRequired; },
|
|
150
|
-
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;
|
|
151
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
|
+
}));
|
|
152
232
|
|
|
153
233
|
// Create radio group aria props
|
|
154
|
-
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;
|
|
155
246
|
|
|
156
|
-
// Render props values
|
|
157
247
|
const renderValues = createMemo<RadioGroupRenderProps>(() => ({
|
|
158
|
-
orientation: (ariaProps.orientation as Orientation) ??
|
|
248
|
+
orientation: (ariaProps.orientation as Orientation) ?? "vertical",
|
|
159
249
|
isDisabled: state.isDisabled,
|
|
160
250
|
isReadOnly: state.isReadOnly,
|
|
161
251
|
isRequired: state.isRequired,
|
|
162
|
-
isInvalid:
|
|
252
|
+
isInvalid: isInvalid(),
|
|
163
253
|
state,
|
|
164
254
|
}));
|
|
165
255
|
|
|
166
|
-
// Resolve render props
|
|
167
256
|
const renderProps = useRenderProps(
|
|
168
257
|
{
|
|
169
258
|
children: props.children,
|
|
170
259
|
class: local.class,
|
|
171
260
|
style: local.style,
|
|
172
|
-
defaultClassName:
|
|
261
|
+
defaultClassName: "solidaria-RadioGroup",
|
|
173
262
|
},
|
|
174
|
-
renderValues
|
|
263
|
+
renderValues,
|
|
175
264
|
);
|
|
176
265
|
|
|
177
|
-
// Filter DOM props
|
|
178
266
|
const domProps = createMemo(() => filterDOMProps(ariaProps, { global: true }));
|
|
179
267
|
|
|
180
|
-
// Remove ref from spread props to avoid type conflicts
|
|
181
268
|
const cleanGroupProps = () => {
|
|
182
269
|
const { ref: _ref, ...rest } = groupAria.radioGroupProps as Record<string, unknown>;
|
|
183
270
|
return rest;
|
|
184
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
|
+
}
|
|
185
291
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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;
|
|
193
301
|
}
|
|
194
|
-
|
|
302
|
+
|
|
303
|
+
state.updateValidation(target.validity.valid ? validValidation : getNativeValidation(target));
|
|
304
|
+
state.commitValidation();
|
|
195
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;
|
|
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>;
|
|
196
405
|
|
|
197
406
|
return (
|
|
198
407
|
<RadioGroupStateContext.Provider value={state}>
|
|
199
|
-
<
|
|
200
|
-
{
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
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>
|
|
212
433
|
</RadioGroupStateContext.Provider>
|
|
213
434
|
);
|
|
214
435
|
}
|
|
215
436
|
|
|
216
|
-
// ============================================
|
|
217
|
-
// RADIO COMPONENT
|
|
218
|
-
// ============================================
|
|
219
|
-
|
|
220
437
|
/**
|
|
221
438
|
* Internal Radio implementation that has access to RadioGroupStateContext.
|
|
222
439
|
* This is rendered inside the RadioGroup's context provider.
|
|
223
440
|
*/
|
|
224
441
|
function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): JSX.Element {
|
|
225
|
-
|
|
226
|
-
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
|
+
);
|
|
227
460
|
|
|
228
|
-
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
|
+
});
|
|
229
493
|
|
|
230
494
|
// Create radio aria props
|
|
231
495
|
const radioAria = createRadio(
|
|
232
496
|
() => ({
|
|
233
|
-
...
|
|
234
|
-
|
|
497
|
+
...inputAriaProps(),
|
|
498
|
+
"aria-describedby": describedBy(),
|
|
499
|
+
children: typeof radioProps.children === "function" ? true : radioProps.children,
|
|
235
500
|
}),
|
|
236
501
|
state,
|
|
237
|
-
|
|
502
|
+
inputElement,
|
|
238
503
|
);
|
|
239
504
|
|
|
240
505
|
// Create focus ring
|
|
@@ -245,9 +510,11 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
245
510
|
get isDisabled() {
|
|
246
511
|
return radioAria.isDisabled || state.isReadOnly;
|
|
247
512
|
},
|
|
513
|
+
onHoverStart: local.onHoverStart,
|
|
514
|
+
onHoverEnd: local.onHoverEnd,
|
|
515
|
+
onHoverChange: local.onHoverChange,
|
|
248
516
|
});
|
|
249
517
|
|
|
250
|
-
// Render props values
|
|
251
518
|
const renderValues = createMemo<RadioRenderProps>(() => ({
|
|
252
519
|
isSelected: radioAria.isSelected(),
|
|
253
520
|
isHovered: isHovered(),
|
|
@@ -260,22 +527,20 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
260
527
|
isRequired: state.isRequired,
|
|
261
528
|
}));
|
|
262
529
|
|
|
263
|
-
// Resolve render props
|
|
264
530
|
const renderProps = useRenderProps(
|
|
265
531
|
{
|
|
266
532
|
children: radioProps.children,
|
|
267
533
|
class: local.class,
|
|
268
534
|
style: local.style,
|
|
269
|
-
defaultClassName:
|
|
535
|
+
defaultClassName: "solidaria-Radio",
|
|
270
536
|
},
|
|
271
|
-
renderValues
|
|
537
|
+
renderValues,
|
|
272
538
|
);
|
|
273
539
|
|
|
274
540
|
const selectionIndicatorContext = createMemo<SelectionIndicatorContextValue>(() => ({
|
|
275
541
|
isSelected: radioAria.isSelected,
|
|
276
542
|
}));
|
|
277
543
|
|
|
278
|
-
// Filter DOM props
|
|
279
544
|
const domProps = createMemo(() => {
|
|
280
545
|
const filtered = filterDOMProps(ariaProps, { global: true });
|
|
281
546
|
delete (filtered as Record<string, unknown>).id;
|
|
@@ -283,7 +548,6 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
283
548
|
return filtered;
|
|
284
549
|
});
|
|
285
550
|
|
|
286
|
-
// Remove ref from spread props to avoid type conflicts
|
|
287
551
|
const cleanLabelProps = () => {
|
|
288
552
|
const { ref: _ref1, ...rest } = radioAria.labelProps as Record<string, unknown>;
|
|
289
553
|
return rest;
|
|
@@ -293,41 +557,183 @@ function RadioImpl(props: { radioProps: RadioProps; state: RadioGroupState }): J
|
|
|
293
557
|
return rest;
|
|
294
558
|
};
|
|
295
559
|
const cleanInputProps = () => {
|
|
296
|
-
const {
|
|
560
|
+
const {
|
|
561
|
+
ref: _ref3,
|
|
562
|
+
onFocus: _onFocus,
|
|
563
|
+
onBlur: _onBlur,
|
|
564
|
+
...rest
|
|
565
|
+
} = radioAria.inputProps as Record<string, unknown>;
|
|
297
566
|
return rest;
|
|
298
567
|
};
|
|
299
568
|
const cleanFocusProps = () => {
|
|
300
|
-
const {
|
|
569
|
+
const {
|
|
570
|
+
ref: _ref4,
|
|
571
|
+
onFocus: _onFocus,
|
|
572
|
+
onBlur: _onBlur,
|
|
573
|
+
...rest
|
|
574
|
+
} = focusProps as Record<string, unknown>;
|
|
301
575
|
return rest;
|
|
302
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>;
|
|
303
708
|
|
|
304
709
|
return (
|
|
305
710
|
<SelectionIndicatorContext.Provider value={selectionIndicatorContext()}>
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
+
)}
|
|
331
737
|
</SelectionIndicatorContext.Provider>
|
|
332
738
|
);
|
|
333
739
|
}
|
|
@@ -355,11 +761,7 @@ export function Radio(props: RadioProps): JSX.Element {
|
|
|
355
761
|
const getState = createMemo(() => useContext(RadioGroupStateContext));
|
|
356
762
|
|
|
357
763
|
return (
|
|
358
|
-
<Show
|
|
359
|
-
when={getState()}
|
|
360
|
-
fallback={null}
|
|
361
|
-
keyed
|
|
362
|
-
>
|
|
764
|
+
<Show when={getState()} fallback={null} keyed>
|
|
363
765
|
{(state) => <RadioImpl radioProps={props} state={state} />}
|
|
364
766
|
</Show>
|
|
365
767
|
);
|