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.

87 lines (86 loc) 2.79 kB
'use client'; import * as React from 'react'; import { contains } from '@floating-ui/react/utils'; import { mergeReactProps } from '../utils/mergeReactProps.js'; import { useControlled } from '../utils/useControlled.js'; import { useFieldRootContext } from '../field/root/FieldRootContext.js'; import { useBaseUiId } from '../utils/useBaseUiId.js'; import { useFieldControlValidation } from '../field/control/useFieldControlValidation.js'; import { useField } from '../field/useField.js'; export function useRadioGroup(params) { const { disabled = false, name, defaultValue, readOnly, value: externalValue } = params; const { labelId, setTouched: setFieldTouched } = useFieldRootContext(); const { getValidationProps, getInputValidationProps, inputRef: inputValidationRef, commitValidation } = useFieldControlValidation(); const id = useBaseUiId(); const [checkedValue, setCheckedValue] = useControlled({ controlled: externalValue, default: defaultValue, name: 'RadioGroup', state: 'value' }); useField({ id, commitValidation, value: checkedValue, controlRef: inputValidationRef }); const [touched, setTouched] = React.useState(false); const getRootProps = React.useCallback((externalProps = {}) => mergeReactProps(getValidationProps(externalProps), { role: 'radiogroup', 'aria-disabled': disabled || undefined, 'aria-readonly': readOnly || undefined, 'aria-labelledby': labelId, onBlur(event) { if (!contains(event.currentTarget, event.relatedTarget)) { setFieldTouched(true); commitValidation(checkedValue); } }, onKeyDownCapture(event) { if (event.key.startsWith('Arrow')) { setFieldTouched(true); setTouched(true); } } }), [checkedValue, commitValidation, disabled, getValidationProps, labelId, readOnly, setFieldTouched]); const serializedCheckedValue = React.useMemo(() => { if (checkedValue == null) { return ''; // avoid uncontrolled -> controlled error } if (typeof checkedValue === 'string') { return checkedValue; } return JSON.stringify(checkedValue); }, [checkedValue]); const getInputProps = React.useCallback((externalProps = {}) => mergeReactProps(getInputValidationProps(externalProps), { type: 'hidden', value: serializedCheckedValue, ref: inputValidationRef, id, name, disabled, readOnly }), [getInputValidationProps, serializedCheckedValue, inputValidationRef, id, name, disabled, readOnly]); return React.useMemo(() => ({ getRootProps, getInputProps, checkedValue, setCheckedValue, touched, setTouched }), [getRootProps, getInputProps, checkedValue, setCheckedValue, touched]); }