From 8320b1d39ea6402c32e907dbb35082efc6af9f5a Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Tue, 31 May 2022 19:40:23 +0200 Subject: chore: replace the toggle component --- src/components/molecules/forms/radio-group.tsx | 81 ++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 12 deletions(-) (limited to 'src/components/molecules/forms/radio-group.tsx') diff --git a/src/components/molecules/forms/radio-group.tsx b/src/components/molecules/forms/radio-group.tsx index 68a8adf..45f585e 100644 --- a/src/components/molecules/forms/radio-group.tsx +++ b/src/components/molecules/forms/radio-group.tsx @@ -1,10 +1,21 @@ import Fieldset, { type FieldsetProps } from '@components/atoms/forms/fieldset'; -import { ChangeEvent, FC, useState } from 'react'; +import useStateChange from '@utils/hooks/use-state-change'; +import { ChangeEvent, FC, MouseEvent, SetStateAction, useState } from 'react'; import LabelledBooleanField, { type LabelledBooleanFieldProps, } from './labelled-boolean-field'; import styles from './radio-group.module.scss'; +export type RadioGroupCallbackProps = { + choices: { + new: string; + prev: string; + }; + updateChoice: (value: SetStateAction) => void; +}; + +export type RadioGroupCallback = (props: RadioGroupCallbackProps) => void; + export type RadioGroupOption = Pick< LabelledBooleanFieldProps, 'id' | 'label' | 'name' | 'value' @@ -15,14 +26,34 @@ export type RadioGroupProps = Pick< 'className' | 'legend' | 'legendClassName' > & Pick & { + /** + * Set additional classnames to the radio group wrapper when kind is toggle. + */ + groupClassName?: string; /** * The default option value. */ initialChoice: string; + /** + * The radio group kind. Default: regular. + */ + kind?: 'regular' | 'toggle'; /** * The legend position. Default: inline. */ legendPosition?: FieldsetProps['legendPosition']; + /** + * A callback function to execute when choice is changed. + */ + onChange?: RadioGroupCallback; + /** + * A callback function to execute when clicking on a choice. + */ + onClick?: RadioGroupCallback; + /** + * Set additional classnames to the labelled field wrapper. + */ + optionClassName?: string; /** * The options. */ @@ -36,23 +67,38 @@ export type RadioGroupProps = Pick< */ const RadioGroup: FC = ({ className, + groupClassName = '', initialChoice, + kind = 'regular', labelPosition, labelSize, legendPosition = 'inline', + onChange, + optionClassName = '', options, ...props }) => { - const [selectedChoice, setSelectedChoice] = useState(initialChoice); - const wrapperModifier = `wrapper--${legendPosition}`; + const [selectedChoice, setSelectedChoice] = + useStateChange(initialChoice); + const isToggle = kind === 'toggle'; + const alignmentModifier = `wrapper--${legendPosition}`; + const toggleModifier = isToggle ? 'wrapper--toggle' : 'wrapper--regular'; /** - * Update the selected choice based on the change event target. - * - * @param {ChangeEvent} e - The change event. + * Update the selected choice on click or change event. */ - const updateChoice = (e: ChangeEvent) => { - setSelectedChoice(e.target.value); + const updateChoice = ( + e: + | ChangeEvent + | MouseEvent + ) => { + const input = e.target as HTMLInputElement; + onChange && + onChange({ + choices: { new: input.value, prev: selectedChoice }, + updateChoice: setSelectedChoice, + }); + if (e.type === 'change') setSelectedChoice(input.value); }; /** @@ -65,10 +111,14 @@ const RadioGroup: FC = ({