import { useState } from 'react'; import AnimateHeight from 'react-animate-height'; export interface AccordionProps { children: (args: AccordionChildProps) => JSX.Element; /** If true, only one accordion item can be open at any time */ single?: boolean; /** If true, at least one accordion item will always be open */ atLeastOne?: boolean; initialOpenIndexes?: number[]; } export interface AccordionChildProps { openIndexes: number[]; handleClick(index: number): void; AccordionContent: typeof AccordionContent; } type AccordionContentProps = { isOpen: boolean; children: React.ReactNode; }; export const AccordionContent = ({ isOpen, children, }: AccordionContentProps) => { return {children}; }; const Accordion = ({ single, atLeastOne, initialOpenIndexes, children, }: AccordionProps) => { const initialState = initialOpenIndexes || (atLeastOne && [0]) || []; const [openIndexes, setOpenIndexes] = useState(initialState); const close = (index: number) => { const openCount = openIndexes.length; const newListOfIndexes = atLeastOne && openCount === 1 && openIndexes.includes(index) ? openIndexes : openIndexes.filter((i) => i !== index); setOpenIndexes(newListOfIndexes); }; const open = (index: number) => { const newListOfIndexes = single ? [index] : [...openIndexes, index]; setOpenIndexes(newListOfIndexes); }; const handleItemClick = (index: number) => { const action = openIndexes.includes(index) ? 'closing' : 'opening'; if (action === 'closing') { close(index); } else { open(index); } }; return children({ openIndexes: openIndexes, handleClick: handleItemClick, AccordionContent, }); }; export default Accordion;