import { ChangeEvent, useCallback, useEffect, useState } from 'react'; import { usePrevious } from 'react-use'; import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { StringOrNumber } from '@gilbarbara/types'; import { Radio, RadioProps } from './CheckboxAndRadio'; import { getTheme } from './modules/helpers'; import { getStyledOptions } from './modules/system'; import { RadioItem, WithComponentSize } from './types'; export interface RadioGroupProps extends WithComponentSize, Omit { defaultValue?: StringOrNumber; inline?: boolean; items: RadioItem[]; } export const defaultProps = { disabled: false, inline: false, size: 'md', } satisfies Omit; const StyledRadioGroup = styled( 'div', getStyledOptions(), )>(props => { const { inline } = props; const { spacing } = getTheme(props); return css` display: flex; flex-direction: ${inline ? 'row' : 'column'}; ${inline && css` margin-top: 0; [data-component-name='Radio'] + [data-component-name='Radio'] { margin-left: ${spacing.xs}; } `}; `; }); export function RadioGroup(props: RadioGroupProps) { const { defaultValue, disabled, inline, items, name, onChange, size, value, ...rest } = { ...defaultProps, ...props, }; const [selectedValue, setSelectedValue] = useState(value ?? defaultValue); const previousProps = usePrevious(props); useEffect(() => { if (previousProps && value && previousProps.value !== value) { setSelectedValue(value); } }, [previousProps, value]); const handleChange = useCallback( (event: ChangeEvent) => { const { target } = event; const numericValue = Number(target.value); const currentValue = !Number.isNaN(numericValue) ? numericValue : target.value; /* istanbul ignore else */ if (onChange) { onChange(event); } if (!value && !disabled) { setSelectedValue(currentValue); } }, [disabled, onChange, value], ); if (!items || !items.length) { return null; } const currentValue = !!value && value !== selectedValue ? value : selectedValue; return ( {items.map(d => ( ))} ); } RadioGroup.displayName = 'RadioGroup';