UNPKG

@spaced-out/ui-design-system

Version:
76 lines (62 loc) 1.92 kB
// @flow strict import * as React from 'react'; import classify from '../../utils/classify'; import css from './AccordionGroup.module.css'; export type AccordionGroupClassNames = $ReadOnly<{ wrapper?: string, }>; export type AccordionGroupPropsType = { children: React.Node, onAccordionClick?: (id: string, isOpen: boolean) => mixed, onToggle?: (id: string, checked?: boolean) => mixed, enabledToggleIds?: Array<string>, initialOpenId?: string, classNames?: AccordionGroupClassNames, }; export const AccordionGroup = ({ children, onAccordionClick, onToggle, enabledToggleIds = [], initialOpenId = '', classNames, }: AccordionGroupPropsType): React.Node => { const [openId, setOpenedId] = React.useState(initialOpenId); const [checks, setChecks] = React.useState(enabledToggleIds); const handleAccordionChange = (id, isOpen) => { setOpenedId(isOpen ? id : ''); onAccordionClick?.(id, isOpen); }; const handleToggle = (id, checked) => { setChecks((prev) => checked ? [...prev, id] : prev.filter((x) => x !== id), ); setOpenedId((prev) => (checked ? id : prev === id ? '' : prev)); onToggle?.(id, checked); }; const enhancedChildren = React.Children.map(children, (child) => { if (!React.isValidElement(child)) { return null; } const childId = child.props.id; const isDisabled = !checks.includes(childId); const isOpen = openId === childId; return React.cloneElement(child, { classNames: { headerWrapper: css.accordionHeaderWrapper, wrapper: css.accordionWrapper, }, onChange: handleAccordionChange, onToggle: handleToggle, showToggle: true, disabled: isDisabled, isOpen, }); }); return ( <div className={classify(css.wrapper, classNames?.wrapper)}> {enhancedChildren} </div> ); }; AccordionGroup.displayName = 'AccordionGroup';