import React, { ReactNode, useEffect, useMemo, useState } from 'react' import useTheme from '../use-theme' import FieldsetTitle from './fieldset-title' import FieldsetSubtitle from './fieldset-subtitle' import FieldsetFooter from './fieldset-footer' import FieldsetContent from './fieldset-content' import { hasChild, pickChild } from '../utils/collections' import { useFieldset } from './fieldset-context' import useWarning from '../utils/use-warning' import useScale, { withScale } from '../use-scale' import useClasses from '../use-classes' interface Props { value?: string label?: string title?: string | ReactNode subtitle?: string | ReactNode className?: string } const defaultProps = { value: '', label: '', disabled: false, title: '' as string | ReactNode, subtitle: '' as string | ReactNode, className: '' } type NativeAttrs = Omit, keyof Props> export type FieldsetProps = Props & NativeAttrs const FieldsetComponent: React.FC> = ({ className, title, subtitle, children, value, label, ...props }: React.PropsWithChildren & typeof defaultProps) => { const theme = useTheme() const { SCALES } = useScale() const { inGroup, currentValue, register } = useFieldset() const [hidden, setHidden] = useState(inGroup) const classes = useClasses('fieldset', className) const [withoutFooterChildren, FooterChildren] = pickChild(children, FieldsetFooter) const hasTitle = hasChild(withoutFooterChildren, FieldsetTitle) const hasSubtitle = hasChild(withoutFooterChildren, FieldsetSubtitle) const hasContent = hasChild(withoutFooterChildren, FieldsetContent) if (inGroup) { if (!label) { // eslint-disable-next-line react-hooks/rules-of-hooks useWarning('Props "label" is required when in a group.', 'Fieldset Group') } if (!value || value === '') { value = label } // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { register && register({ value, label }) }, []) // eslint-disable-next-line react-hooks/rules-of-hooks useEffect(() => { // In a few cases, the user will set Fieldset state manually. // If the user incorrectly set the state, Group component should ignore it. /* istanbul ignore if */ if (!currentValue || currentValue === '') return setHidden(currentValue !== value) }, [currentValue]) } const content = useMemo( () => ( <> {withoutFooterChildren} {!hasTitle && title && {title}} {!hasSubtitle && subtitle && {subtitle}} ), [withoutFooterChildren, hasTitle, hasSubtitle, title, subtitle] ) return (
{hasContent ? content : {content}} {FooterChildren && FooterChildren}
) } FieldsetComponent.defaultProps = defaultProps FieldsetComponent.displayName = 'HuiFieldset' const Fieldset = withScale(FieldsetComponent) export default Fieldset