src/radio/radio-item.tsx (54 lines of code) (raw):
import {Component, createContext, forwardRef, type InputHTMLAttributes, type ReactNode} from 'react';
import classNames from 'classnames';
import getUID from '../global/get-uid';
import ControlHelp from '../control-help/control-help';
import styles from './radio.css';
export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
value?: string | undefined;
onChange?: ((value: string) => void) | null | undefined;
}
export const RadioContext = createContext<RadioProps>({});
export interface RadioItemInnerProps extends InputHTMLAttributes<HTMLInputElement> {
help?: ReactNode;
}
export class RadioItemInner extends Component<RadioItemInnerProps> {
uid = getUID('ring-radio-item-');
input?: HTMLElement | null;
inputRef = (el: HTMLElement | null) => {
this.input = el;
};
label?: HTMLElement | null;
labelRef = (el: HTMLElement | null) => {
this.label = el;
};
render() {
const {className, children, help, ...restProps} = this.props;
const classes = classNames(styles.radio, className);
return (
<label ref={this.labelRef} className={classes} htmlFor={this.uid}>
<input id={this.uid} {...restProps} ref={this.inputRef} className={styles.input} type='radio' />
<span className={styles.circle} />
<span className={styles.label}>
{children}
{help && <ControlHelp>{help}</ControlHelp>}
</span>
</label>
);
}
}
export interface RadioItemProps extends RadioItemInnerProps {
value: string;
}
const RadioItem = forwardRef<RadioItemInner, RadioItemProps>(function RadioItem(props, ref) {
return (
<RadioContext.Consumer>
{({value, onChange, ...restContext}) => (
<RadioItemInner
ref={ref}
{...restContext}
checked={value !== undefined ? value === props.value : undefined}
onChange={onChange ? () => onChange(props.value) : undefined}
{...props}
/>
)}
</RadioContext.Consumer>
);
});
export default RadioItem;