1 import { Children, type FC, type ReactElement, type ReactNode, cloneElement } from 'react';
3 import { type FieldProps } from 'formik';
5 import { Icon, type IconName, InputButton, InputFieldTwo } from '@proton/components';
6 import { type InputFieldProps } from '@proton/components/components/v2/field/InputField';
7 import type { MaybeArray } from '@proton/pass/types';
8 import clsx from '@proton/utils/clsx';
10 import { useFieldControl } from '../../../hooks/useFieldControl';
11 import type { RadioValue } from './RadioGroupField';
13 import './RadioButtonGroupField.scss';
15 type BaseRadioProps<T> = {
20 onChange?: (value: T) => void;
24 type RadioButtonProps<T> = BaseRadioProps<T> & { color?: string; icon?: IconName };
26 export const RadioButton = <T,>({ onChange, id, checked, value, name, color, icon }: RadioButtonProps<T>) => {
33 onChange={(e) => e.target.checked && onChange?.(value)}
35 className: 'pass-radio-group--button',
36 style: { '--radio-button-background': color ? `rgb(${color})` : 'var(--background-weak)' },
39 {icon && <Icon name={icon} size={5} />}
44 type RadioLabelledButtonProps<T> = BaseRadioProps<T> & { children: MaybeArray<ReactNode> };
46 export const RadioLabelledButton = <T extends RadioValue>({
54 }: RadioLabelledButtonProps<T>) => {
59 'pass-radio-group--labelled-button w-full expand-click-area relative',
60 disabled && 'opacity-50 pointer-events-none',
70 onChange={(e) => e.target.checked && onChange?.(value)}
72 <div className="flex items-center gap-x-3 py-4">
74 {checked && <Icon name="checkmark" size={6} color="var(--interaction-norm)" />}
80 type RadioButtonGroupProps<T> = {
81 children: ReactElement<BaseRadioProps<T>>[];
84 onChange?: (value: T) => void;
88 export const RadioButtonGroup = <T extends RadioValue>(props: RadioButtonGroupProps<T>) => {
89 const radioButtons = Children.map(props.children, (child, id) => {
90 return cloneElement(child, {
91 checked: props.value === child.props.value,
92 id: `${props.name}-${id}`,
94 onChange: props.onChange,
98 return <div className={clsx('flex', props.className)}>{radioButtons}</div>;
101 type RadioButtonGroupFieldProps = FieldProps & InputFieldProps<typeof RadioButtonGroup>;
103 export const RadioButtonGroupField: FC<RadioButtonGroupFieldProps> = ({ field, form, meta, onChange, ...props }) => {
104 const { error } = useFieldControl({ field, form, meta });
107 <InputFieldTwo<typeof RadioButtonGroup>
108 as={RadioButtonGroup}
109 assistContainerClassName="empty:hidden"
113 onChange={async (value: RadioValue) => {
115 await form.setFieldValue(field.name, value);