import React, { type ChangeEventHandler } from 'react'; import { classNames } from '../../utils'; import { useFormFieldContext } from '../FormField/FormFieldContext'; import { Icon, type IconName } from '../Icon'; import styles from './OptionGroup.module.css'; import commonStyles from '../../theme/common.module.css'; type CommonProps = { /** * The name of the OptionGroup */ name: string; /** * The current value */ value: K | null; /** * Options contained within the OptionGroup * * * If the key iconName is provided then the associated icon will be displayed * instead of the label (and in this case the label will be used * as an accessible attribute to describe the icon) */ options: { label: string; value: K; iconName?: IconName }[]; /** * className for the element */ className?: string; /** * Whether the OptionGroup is invalid. */ isInvalid?: boolean; }; /** * `onChange` props is required only if `isDisabled` is false * `isDisabled` props is optional (will default to false) if `onChange` is given */ type DisabledProps = | { /** * Handler that is called when the value changes. */ onChange: ChangeEventHandler; /** * Whether the OptionGroup should be disabled. * @default false */ isDisabled?: false; } | { onChange?: ChangeEventHandler; isDisabled: true; }; export type OptionGroupProps = CommonProps & DisabledProps; export const OptionGroup = ({ value, options, name, onChange, isDisabled = false, className, isInvalid, ...rest }: OptionGroupProps) => { const context = useFormFieldContext(); const isInputInvalid = isInvalid === undefined ? context.isInvalid : isInvalid; const indexSelected = options.findIndex( (option) => `${option.value}` === `${value}`, ); return (
{isInputInvalid &&
} {options.map((option) => { const isChecked = `${option.value}` === `${value}`; return ( ); })}
); }; type IndicatorProps = { index: number; }; type IndicatorState = { transition?: string; display: string; }; const Indicator = ({ index }: IndicatorProps) => { const [style, setStyle] = React.useState({ transition: 'none', display: 'none', }); React.useEffect(() => { if (index >= 0) { setStyle((state) => { const isFirstSelection = state.display === 'none'; return { ...state, display: 'block', transition: isFirstSelection ? 'none' : undefined, ['--index' as string]: index, }; }); } }, [index]); return (
); };