@cdx-ui/primitives 0.0.1-beta.141 → 0.0.1-beta.142
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/lib/commonjs/checkbox/CheckboxRoot.web.js +91 -28
- package/lib/commonjs/checkbox/CheckboxRoot.web.js.map +1 -1
- package/lib/commonjs/checkbox/useCheckboxRoot.js +33 -19
- package/lib/commonjs/checkbox/useCheckboxRoot.js.map +1 -1
- package/lib/commonjs/radio/RadioGroup.js +65 -16
- package/lib/commonjs/radio/RadioGroup.js.map +1 -1
- package/lib/commonjs/radio/RadioRoot.web.js +114 -26
- package/lib/commonjs/radio/RadioRoot.web.js.map +1 -1
- package/lib/commonjs/radio/context.js.map +1 -1
- package/lib/commonjs/radio/useRadioGroupNavigation.js +79 -0
- package/lib/commonjs/radio/useRadioGroupNavigation.js.map +1 -0
- package/lib/commonjs/radio/useRadioRoot.js +14 -13
- package/lib/commonjs/radio/useRadioRoot.js.map +1 -1
- package/lib/module/checkbox/CheckboxRoot.web.js +92 -29
- package/lib/module/checkbox/CheckboxRoot.web.js.map +1 -1
- package/lib/module/checkbox/useCheckboxRoot.js +34 -20
- package/lib/module/checkbox/useCheckboxRoot.js.map +1 -1
- package/lib/module/radio/RadioGroup.js +68 -19
- package/lib/module/radio/RadioGroup.js.map +1 -1
- package/lib/module/radio/RadioRoot.web.js +117 -29
- package/lib/module/radio/RadioRoot.web.js.map +1 -1
- package/lib/module/radio/context.js.map +1 -1
- package/lib/module/radio/useRadioGroupNavigation.js +74 -0
- package/lib/module/radio/useRadioGroupNavigation.js.map +1 -0
- package/lib/module/radio/useRadioRoot.js +14 -13
- package/lib/module/radio/useRadioRoot.js.map +1 -1
- package/lib/typescript/checkbox/CheckboxRoot.web.d.ts +8 -0
- package/lib/typescript/checkbox/CheckboxRoot.web.d.ts.map +1 -1
- package/lib/typescript/checkbox/useCheckboxRoot.d.ts +7 -18
- package/lib/typescript/checkbox/useCheckboxRoot.d.ts.map +1 -1
- package/lib/typescript/radio/RadioGroup.d.ts.map +1 -1
- package/lib/typescript/radio/RadioRoot.web.d.ts +8 -0
- package/lib/typescript/radio/RadioRoot.web.d.ts.map +1 -1
- package/lib/typescript/radio/context.d.ts +6 -1
- package/lib/typescript/radio/context.d.ts.map +1 -1
- package/lib/typescript/radio/types.d.ts +7 -0
- package/lib/typescript/radio/types.d.ts.map +1 -1
- package/lib/typescript/radio/useRadioGroupNavigation.d.ts +17 -0
- package/lib/typescript/radio/useRadioGroupNavigation.d.ts.map +1 -0
- package/lib/typescript/radio/useRadioRoot.d.ts +4 -18
- package/lib/typescript/radio/useRadioRoot.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/checkbox/CheckboxRoot.web.tsx +105 -29
- package/src/checkbox/useCheckboxRoot.ts +37 -15
- package/src/radio/RadioGroup.tsx +84 -20
- package/src/radio/RadioRoot.web.tsx +136 -31
- package/src/radio/context.tsx +6 -1
- package/src/radio/types.ts +6 -0
- package/src/radio/useRadioGroupNavigation.ts +104 -0
- package/src/radio/useRadioRoot.ts +18 -11
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import { forwardRef } from 'react';
|
|
1
|
+
import { forwardRef, useContext, useEffect, useMemo, useRef } from 'react';
|
|
2
2
|
import { Pressable } from 'react-native';
|
|
3
3
|
import { VisuallyHidden } from '@react-aria/visually-hidden';
|
|
4
|
-
import {
|
|
4
|
+
import { composeEventHandlers, mergeRefs } from '@cdx-ui/utils';
|
|
5
5
|
import { useFocusRing } from '@react-native-aria/focus';
|
|
6
6
|
import { Slot } from '../slot';
|
|
7
7
|
import { dataAttributes, mergeDataAttributes } from '../utils/dataAttributes';
|
|
8
|
-
import { RadioProvider } from './context';
|
|
8
|
+
import { RadioGroupContext, RadioProvider } from './context';
|
|
9
9
|
import type { IRadioProps, IRadioContextValue } from './types';
|
|
10
10
|
import { useRadioRoot } from './useRadioRoot';
|
|
11
|
-
|
|
12
|
-
// TODO: Keyboard focus is not working as expected
|
|
11
|
+
import { getRovingFocusValue } from './useRadioGroupNavigation';
|
|
13
12
|
|
|
14
13
|
export interface RadioRootProps extends IRadioProps {
|
|
15
14
|
asChild?: boolean;
|
|
16
15
|
}
|
|
17
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Web Radio root.
|
|
19
|
+
*
|
|
20
|
+
* On web, `@react-native-aria/radio` re-exports `@react-aria/radio`'s `useRadio`,
|
|
21
|
+
* whose `inputProps` target a native `<input type="radio">` (selection via
|
|
22
|
+
* `onChange`). Selection must be applied explicitly on the Pressable —
|
|
23
|
+
* `inputProps.onPress` does **not** call `setSelectedValue`.
|
|
24
|
+
*/
|
|
18
25
|
export const RadioRoot = forwardRef<React.ComponentRef<typeof Pressable>, RadioRootProps>(
|
|
19
26
|
({ asChild, children, ...props }, ref) => {
|
|
20
27
|
const {
|
|
@@ -27,12 +34,13 @@ export const RadioRoot = forwardRef<React.ComponentRef<typeof Pressable>, RadioR
|
|
|
27
34
|
isPressed,
|
|
28
35
|
} = props;
|
|
29
36
|
|
|
37
|
+
const radioGroupContext = useContext(RadioGroupContext);
|
|
38
|
+
|
|
30
39
|
const {
|
|
31
40
|
combinedProps,
|
|
32
41
|
isInvalid,
|
|
33
42
|
isReadOnly,
|
|
34
43
|
inputProps,
|
|
35
|
-
labelProps,
|
|
36
44
|
isChecked,
|
|
37
45
|
isDisabled,
|
|
38
46
|
isHovered,
|
|
@@ -42,13 +50,80 @@ export const RadioRoot = forwardRef<React.ComponentRef<typeof Pressable>, RadioR
|
|
|
42
50
|
|
|
43
51
|
const { focusProps, isFocusVisible } = useFocusRing();
|
|
44
52
|
|
|
53
|
+
const nodeRef = useRef<React.ComponentRef<typeof Pressable> | null>(null);
|
|
54
|
+
const setRefs = mergeRefs(mergedRef, nodeRef);
|
|
55
|
+
|
|
56
|
+
// Strip native-input / internal props — they must not land on Pressable.
|
|
57
|
+
const {
|
|
58
|
+
onPress: _onPress,
|
|
59
|
+
onChange: _onChange,
|
|
60
|
+
role: _role,
|
|
61
|
+
tabIndex: _tabIndex,
|
|
62
|
+
disabled: _disabled,
|
|
63
|
+
checked: _checked,
|
|
64
|
+
value: _value,
|
|
65
|
+
type: _type,
|
|
66
|
+
name: _name,
|
|
67
|
+
form: _form,
|
|
68
|
+
required: _required,
|
|
69
|
+
...inputAriaProps
|
|
70
|
+
} = inputProps;
|
|
71
|
+
|
|
72
|
+
const resolvedDisabled = !!(isDisabled || isDisabledProp);
|
|
73
|
+
const resolvedReadOnly = !!(isReadOnly || isReadOnlyProp);
|
|
74
|
+
|
|
75
|
+
const selectThis = () => {
|
|
76
|
+
if (resolvedDisabled || resolvedReadOnly) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
radioGroupContext?.radioGroupState.setSelectedValue(combinedProps.value);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const selectedValue = radioGroupContext?.radioGroupState.selectedValue;
|
|
83
|
+
const focusedValue = radioGroupContext?.focusedValue;
|
|
84
|
+
const registerRadio = radioGroupContext?.registerRadio;
|
|
85
|
+
const unregisterRadio = radioGroupContext?.unregisterRadio;
|
|
86
|
+
const getRadios = radioGroupContext?.getRadios;
|
|
87
|
+
const groupName = radioGroupContext?.name;
|
|
88
|
+
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!registerRadio || !unregisterRadio) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
registerRadio(combinedProps.value, {
|
|
95
|
+
disabled: !!resolvedDisabled,
|
|
96
|
+
node: nodeRef.current as { focus?: () => void } | null,
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
return () => unregisterRadio(combinedProps.value);
|
|
100
|
+
}, [combinedProps.value, resolvedDisabled, registerRadio, unregisterRadio]);
|
|
101
|
+
|
|
102
|
+
const isRovingTabStop = useMemo(() => {
|
|
103
|
+
if (resolvedDisabled) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const enabledRadios = getRadios?.().filter(([, entry]) => !entry.disabled) ?? [];
|
|
108
|
+
const rovingValue = getRovingFocusValue(focusedValue, selectedValue, enabledRadios);
|
|
109
|
+
|
|
110
|
+
return combinedProps.value === rovingValue;
|
|
111
|
+
}, [combinedProps.value, focusedValue, getRadios, resolvedDisabled, selectedValue]);
|
|
112
|
+
|
|
113
|
+
const handleKeyDown = (event: { key: string; preventDefault: () => void }) => {
|
|
114
|
+
if (event.key === ' ' || event.key === 'Spacebar') {
|
|
115
|
+
event.preventDefault();
|
|
116
|
+
selectThis();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
45
120
|
const contextValue: IRadioContextValue = {
|
|
46
121
|
isChecked,
|
|
47
|
-
isDisabled:
|
|
122
|
+
isDisabled: resolvedDisabled,
|
|
48
123
|
isFocusVisible: isFocusVisible || isFocusVisibleProp,
|
|
49
124
|
isHovered: isHovered || isHoveredProp,
|
|
50
125
|
isInvalid: isInvalid || isInvalidProp,
|
|
51
|
-
isReadOnly:
|
|
126
|
+
isReadOnly: resolvedReadOnly,
|
|
52
127
|
isPressed,
|
|
53
128
|
isFocused,
|
|
54
129
|
};
|
|
@@ -57,31 +132,61 @@ export const RadioRoot = forwardRef<React.ComponentRef<typeof Pressable>, RadioR
|
|
|
57
132
|
|
|
58
133
|
return (
|
|
59
134
|
<RadioProvider value={contextValue}>
|
|
60
|
-
|
|
61
|
-
{...mergeProps(combinedProps as any, labelProps as any, focusProps as any)}
|
|
62
|
-
ref={mergedRef}
|
|
63
|
-
role="label"
|
|
64
|
-
// eslint-disable-next-line react-native-a11y/has-valid-accessibility-role
|
|
65
|
-
accessibilityRole="label"
|
|
66
|
-
{...mergeDataAttributes(
|
|
67
|
-
props,
|
|
68
|
-
dataAttributes({
|
|
69
|
-
checked: isChecked,
|
|
70
|
-
disabled: isDisabled || isDisabledProp,
|
|
71
|
-
hover: isHovered || isHoveredProp,
|
|
72
|
-
invalid: isInvalid || isInvalidProp,
|
|
73
|
-
readonly: isReadOnly || isReadOnlyProp,
|
|
74
|
-
active: isPressed,
|
|
75
|
-
focus: isFocused,
|
|
76
|
-
focusVisible: isFocusVisible || isFocusVisibleProp,
|
|
77
|
-
}),
|
|
78
|
-
)}
|
|
79
|
-
>
|
|
135
|
+
<>
|
|
80
136
|
<VisuallyHidden>
|
|
81
|
-
<input
|
|
137
|
+
<input
|
|
138
|
+
ref={inputRef as React.RefObject<HTMLInputElement>}
|
|
139
|
+
type="radio"
|
|
140
|
+
name={groupName}
|
|
141
|
+
value={combinedProps.value}
|
|
142
|
+
checked={!!isChecked}
|
|
143
|
+
disabled={resolvedDisabled}
|
|
144
|
+
tabIndex={-1}
|
|
145
|
+
aria-hidden
|
|
146
|
+
readOnly
|
|
147
|
+
// Decorative form mirror — pointer events must not steal clicks from Pressable.
|
|
148
|
+
style={{ pointerEvents: 'none' }}
|
|
149
|
+
/>
|
|
82
150
|
</VisuallyHidden>
|
|
83
|
-
|
|
84
|
-
|
|
151
|
+
<Comp
|
|
152
|
+
{...(combinedProps as object)}
|
|
153
|
+
{...inputAriaProps}
|
|
154
|
+
ref={setRefs}
|
|
155
|
+
role="radio"
|
|
156
|
+
aria-checked={isChecked}
|
|
157
|
+
aria-disabled={resolvedDisabled || undefined}
|
|
158
|
+
accessibilityRole="radio"
|
|
159
|
+
accessibilityState={{ checked: isChecked, disabled: resolvedDisabled }}
|
|
160
|
+
tabIndex={resolvedDisabled ? -1 : isRovingTabStop ? 0 : -1}
|
|
161
|
+
disabled={resolvedDisabled}
|
|
162
|
+
{...focusProps}
|
|
163
|
+
onPress={selectThis}
|
|
164
|
+
onClick={selectThis}
|
|
165
|
+
onKeyDown={composeEventHandlers(
|
|
166
|
+
(
|
|
167
|
+
combinedProps as {
|
|
168
|
+
onKeyDown?: (e: { key: string; preventDefault: () => void }) => void;
|
|
169
|
+
}
|
|
170
|
+
).onKeyDown,
|
|
171
|
+
handleKeyDown,
|
|
172
|
+
)}
|
|
173
|
+
{...mergeDataAttributes(
|
|
174
|
+
props,
|
|
175
|
+
dataAttributes({
|
|
176
|
+
checked: isChecked,
|
|
177
|
+
disabled: resolvedDisabled,
|
|
178
|
+
hover: isHovered || isHoveredProp,
|
|
179
|
+
invalid: isInvalid || isInvalidProp,
|
|
180
|
+
readonly: resolvedReadOnly,
|
|
181
|
+
active: isPressed,
|
|
182
|
+
focus: isFocused,
|
|
183
|
+
focusVisible: isFocusVisible || isFocusVisibleProp,
|
|
184
|
+
}),
|
|
185
|
+
)}
|
|
186
|
+
>
|
|
187
|
+
{children}
|
|
188
|
+
</Comp>
|
|
189
|
+
</>
|
|
85
190
|
</RadioProvider>
|
|
86
191
|
);
|
|
87
192
|
},
|
package/src/radio/context.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { createContext } from '@cdx-ui/utils';
|
|
3
3
|
import type { RadioGroupState } from '@react-stately/radio';
|
|
4
|
-
import type { IRadioContextValue } from './types';
|
|
4
|
+
import type { IRadioContextValue, RegisteredRadio } from './types';
|
|
5
5
|
|
|
6
6
|
export const [RadioProvider, useRadioContext] = createContext<IRadioContextValue>('RadioContext');
|
|
7
7
|
|
|
@@ -18,4 +18,9 @@ export const RadioGroupContext = React.createContext<{
|
|
|
18
18
|
state: IRadioGroupState;
|
|
19
19
|
radioGroupState: RadioGroupState;
|
|
20
20
|
name?: string;
|
|
21
|
+
focusedValue?: string | undefined;
|
|
22
|
+
setFocusedValue?: (value: string | undefined) => void;
|
|
23
|
+
registerRadio?: (value: string, entry: RegisteredRadio) => void;
|
|
24
|
+
unregisterRadio?: (value: string) => void;
|
|
25
|
+
getRadios?: () => [string, RegisteredRadio][];
|
|
21
26
|
} | null>(null);
|
package/src/radio/types.ts
CHANGED
|
@@ -43,3 +43,9 @@ export interface IRadioContextValue {
|
|
|
43
43
|
isHovered?: boolean;
|
|
44
44
|
isPressed?: boolean;
|
|
45
45
|
}
|
|
46
|
+
|
|
47
|
+
/** Web roving-focus registration entry for a single radio item. */
|
|
48
|
+
export interface RegisteredRadio {
|
|
49
|
+
disabled: boolean;
|
|
50
|
+
node: { focus?: () => void } | null;
|
|
51
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
import type { RegisteredRadio } from './types';
|
|
3
|
+
|
|
4
|
+
// Web-only — native platforms rely on OS-managed sequential focus (VoiceOver/TalkBack).
|
|
5
|
+
|
|
6
|
+
function isEnabledRadioValue(
|
|
7
|
+
value: string | null | undefined,
|
|
8
|
+
enabledRadios: [string, RegisteredRadio][],
|
|
9
|
+
): value is string {
|
|
10
|
+
return value != null && enabledRadios.some(([radioValue]) => radioValue === value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Resolves which radio value should hold the roving tab stop / keyboard focus anchor. */
|
|
14
|
+
export function getRovingFocusValue(
|
|
15
|
+
focusedValue: string | undefined,
|
|
16
|
+
selectedValue: string | null | undefined,
|
|
17
|
+
enabledRadios: [string, RegisteredRadio][],
|
|
18
|
+
): string | undefined {
|
|
19
|
+
const defaultFocusValue = isEnabledRadioValue(selectedValue, enabledRadios)
|
|
20
|
+
? selectedValue
|
|
21
|
+
: enabledRadios[0]?.[0];
|
|
22
|
+
|
|
23
|
+
const resolvedFocusedValue = isEnabledRadioValue(focusedValue, enabledRadios)
|
|
24
|
+
? focusedValue
|
|
25
|
+
: undefined;
|
|
26
|
+
|
|
27
|
+
return resolvedFocusedValue ?? defaultFocusValue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface UseRadioGroupNavigationOptions {
|
|
31
|
+
getRadios: () => [string, RegisteredRadio][];
|
|
32
|
+
focusedValue: string | undefined;
|
|
33
|
+
setFocusedValue: (value: string | undefined) => void;
|
|
34
|
+
selectedValue: string | null | undefined;
|
|
35
|
+
selectValue: (value: string) => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function useRadioGroupNavigation({
|
|
39
|
+
getRadios,
|
|
40
|
+
focusedValue,
|
|
41
|
+
setFocusedValue,
|
|
42
|
+
selectedValue,
|
|
43
|
+
selectValue,
|
|
44
|
+
}: UseRadioGroupNavigationOptions) {
|
|
45
|
+
const selectValueRef = useRef(selectValue);
|
|
46
|
+
selectValueRef.current = selectValue;
|
|
47
|
+
|
|
48
|
+
const getEnabledRadios = useCallback(
|
|
49
|
+
() => getRadios().filter(([, entry]) => !entry.disabled),
|
|
50
|
+
[getRadios],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const moveFocus = useCallback(
|
|
54
|
+
([targetValue, targetEntry]: [string, RegisteredRadio]) => {
|
|
55
|
+
setFocusedValue(targetValue);
|
|
56
|
+
targetEntry.node?.focus?.();
|
|
57
|
+
selectValueRef.current(targetValue);
|
|
58
|
+
},
|
|
59
|
+
[setFocusedValue],
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const handleKeyDown = useCallback(
|
|
63
|
+
(e: { key: string; preventDefault: () => void }) => {
|
|
64
|
+
const enabledRadios = getEnabledRadios();
|
|
65
|
+
if (enabledRadios.length === 0) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const currentValue = getRovingFocusValue(focusedValue, selectedValue, enabledRadios);
|
|
70
|
+
const idx = enabledRadios.findIndex(([value]) => value === currentValue);
|
|
71
|
+
|
|
72
|
+
switch (e.key) {
|
|
73
|
+
case 'ArrowDown':
|
|
74
|
+
case 'ArrowRight': {
|
|
75
|
+
e.preventDefault();
|
|
76
|
+
moveFocus(enabledRadios[idx < enabledRadios.length - 1 ? idx + 1 : 0]);
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
case 'ArrowUp':
|
|
80
|
+
case 'ArrowLeft': {
|
|
81
|
+
e.preventDefault();
|
|
82
|
+
moveFocus(enabledRadios[idx > 0 ? idx - 1 : enabledRadios.length - 1]);
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case 'Home': {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
moveFocus(enabledRadios[0]);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case 'End': {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
const last = enabledRadios.at(-1);
|
|
93
|
+
if (last) {
|
|
94
|
+
moveFocus(last);
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
[focusedValue, selectedValue, getEnabledRadios, moveFocus],
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return { handleKeyDown };
|
|
104
|
+
}
|
|
@@ -15,12 +15,6 @@ export function useRadioRoot(
|
|
|
15
15
|
{ useInputRefForAria = false }: UseRadioRootOptions = {},
|
|
16
16
|
) {
|
|
17
17
|
const formControlContext = useFormControlContext();
|
|
18
|
-
|
|
19
|
-
const { isInvalid, isReadOnly, ...combinedProps } = {
|
|
20
|
-
...formControlContext,
|
|
21
|
-
...props,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
18
|
const radioGroupContext = useContext(RadioGroupContext);
|
|
25
19
|
|
|
26
20
|
if (!radioGroupContext) {
|
|
@@ -29,17 +23,30 @@ export function useRadioRoot(
|
|
|
29
23
|
);
|
|
30
24
|
}
|
|
31
25
|
|
|
26
|
+
const isInvalid = props.isInvalid ?? formControlContext.isInvalid;
|
|
27
|
+
const isReadOnly =
|
|
28
|
+
props.isReadOnly ?? formControlContext.isReadOnly ?? radioGroupContext.state.isReadOnly;
|
|
29
|
+
const isDisabled =
|
|
30
|
+
props.isDisabled ?? formControlContext.isDisabled ?? radioGroupContext.state.isDisabled;
|
|
31
|
+
|
|
32
|
+
const combinedProps = {
|
|
33
|
+
...props,
|
|
34
|
+
isInvalid,
|
|
35
|
+
isReadOnly,
|
|
36
|
+
isDisabled,
|
|
37
|
+
};
|
|
38
|
+
|
|
32
39
|
const rootRef = useRef(null);
|
|
33
40
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
34
41
|
const mergedRootRef = mergeRefs(ref as any, rootRef as any);
|
|
35
|
-
const ariaLabel =
|
|
42
|
+
const ariaLabel = props['aria-label'] || props.value || 'Radio';
|
|
36
43
|
|
|
37
44
|
const radio = useRadio(
|
|
38
45
|
{
|
|
39
46
|
...combinedProps,
|
|
40
47
|
'aria-label': ariaLabel,
|
|
41
|
-
isReadOnly
|
|
42
|
-
isDisabled
|
|
48
|
+
isReadOnly,
|
|
49
|
+
isDisabled,
|
|
43
50
|
} as any,
|
|
44
51
|
radioGroupContext.radioGroupState,
|
|
45
52
|
(useInputRefForAria ? inputRef : rootRef) as any,
|
|
@@ -49,7 +56,7 @@ export function useRadioRoot(
|
|
|
49
56
|
labelProps?: Record<string, unknown>;
|
|
50
57
|
};
|
|
51
58
|
|
|
52
|
-
const { checked: isChecked, disabled:
|
|
59
|
+
const { checked: isChecked, disabled: isDisabledFromInput } = inputProps;
|
|
53
60
|
|
|
54
61
|
const { hoverProps, isHovered } = useHover({}, rootRef);
|
|
55
62
|
|
|
@@ -60,7 +67,7 @@ export function useRadioRoot(
|
|
|
60
67
|
inputProps,
|
|
61
68
|
labelProps: labelProps ?? {},
|
|
62
69
|
isChecked,
|
|
63
|
-
isDisabled,
|
|
70
|
+
isDisabled: isDisabledFromInput,
|
|
64
71
|
isHovered,
|
|
65
72
|
hoverProps,
|
|
66
73
|
mergedRef: mergedRootRef,
|