UNPKG

@base-ui-components/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

86 lines (85 loc) 2.54 kB
'use client'; import * as React from 'react'; import { mergeReactProps } from '../../utils/mergeReactProps.js'; import { visuallyHidden } from '../../utils/visuallyHidden.js'; import { useRadioGroupContext } from '../../radio-group/RadioGroupContext.js'; import { useFieldRootContext } from '../../field/root/FieldRootContext.js'; export function useRadioRoot(params) { const { disabled, readOnly, value, required } = params; const { checkedValue, setCheckedValue, onValueChange, touched, setTouched } = useRadioGroupContext(); const { setDirty, validityData, setTouched: setFieldTouched } = useFieldRootContext(); const checked = checkedValue === value; const inputRef = React.useRef(null); const getRootProps = React.useCallback((externalProps = {}) => mergeReactProps(externalProps, { role: 'radio', type: 'button', 'aria-checked': checked, 'aria-required': required || undefined, 'aria-disabled': disabled || undefined, 'aria-readonly': readOnly || undefined, disabled, onKeyDown(event) { if (event.key === 'Enter') { event.preventDefault(); } }, onClick(event) { if (event.defaultPrevented || disabled || readOnly) { return; } event.preventDefault(); inputRef.current?.click(); }, onFocus(event) { if (event.defaultPrevented || disabled || readOnly || !touched) { return; } inputRef.current?.click(); setTouched(false); } }), [checked, disabled, readOnly, required, touched, setTouched]); const getInputProps = React.useCallback((externalProps = {}) => mergeReactProps(externalProps, { type: 'radio', ref: inputRef, tabIndex: -1, style: visuallyHidden, 'aria-hidden': true, disabled, checked, required, readOnly, onChange(event) { // Workaround for https://github.com/facebook/react/issues/9023 if (event.nativeEvent.defaultPrevented) { return; } if (disabled || readOnly || value == null) { return; } setFieldTouched(true); setDirty(value !== validityData.initialValue); setCheckedValue(value); onValueChange?.(value, event.nativeEvent); } }), [disabled, checked, required, readOnly, value, setFieldTouched, setDirty, validityData.initialValue, setCheckedValue, onValueChange]); return React.useMemo(() => ({ checked, getRootProps, getInputProps }), [checked, getRootProps, getInputProps]); }