// @flow strict import * as React from 'react'; import type {GroupAlign} from '../../types/common'; import classify from '../../utils/classify'; import css from './RadioButton.module.css'; /** * Note: * Do not wrap Radio in a label. For simplicity's sake, Radio uses an * internal label tag to handle click delegation to the hidden input, and * nesting labels is a bad idea. */ type ClassNames = $ReadOnly<{wrapper?: string, label?: string, radio?: string}>; export type RadioButtonProps = { children?: React.Node, value?: string, disabled?: boolean, focused?: boolean, name?: string, selectedValue?: string, align?: GroupAlign, classNames?: ClassNames, error?: boolean, onChange?: (newValue: string) => mixed, tabIndex?: number, ariaLabel?: string, }; export const RadioButton: React$AbstractComponent< RadioButtonProps, HTMLInputElement, > = React.forwardRef( ( { children, disabled = false, value = '', focused = false, name = 'radio', selectedValue, onChange, align = 'vertical', classNames, error = false, tabIndex = 0, ariaLabel = '', ...props }: RadioButtonProps, forwardRef, ): React.Node => { const radioInput = React.createRef(); React.useImperativeHandle(forwardRef, () => radioInput.current); const checked = selectedValue === value; React.useEffect(() => { if (radioInput.current && focused) { radioInput.current.focus(); } }, [focused]); const onWrapClickHandler = () => { radioInput.current?.click(); }; const onChangeHandler = (e) => { if (!disabled) { onChange && onChange(e?.target?.value); } }; const onKeyDownHandler = (e) => { if (e.key === 'Enter') { onChangeHandler(e); } }; return (
{React.Children.count(children) > 0 && (
{children}
)}
); }, );