@spaced-out/ui-design-system
Version:
Sense UI components library
76 lines (62 loc) • 1.92 kB
Flow
// @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';