/** @jsxImportSource @emotion/react */ import React, { FunctionComponent } from 'react'; import { css } from 'twin.macro'; import useResizeObserver from '../hooks/useResizeObserver'; import CollapseExpandIcon from '../icons/CollapseExpandIcon'; import { AccordionContext } from './AccordionGroup'; import { TRANSITION_DURATION, TRANSITION_FUNCTION } from './constants'; import { AccordionBtn, AccordionBtnSummary, AccordionContent } from './styles'; import { AccordionProps, TransitionState } from './types'; export const Accordion: FunctionComponent = ({ summary, children, ...props }) => { const accordionId = React.useMemo( () => `accordion-${Math.random() .toString(16) .slice(2)}`, [], ); const [height, setHeight] = React.useState('0px'); const resizeRef = useResizeObserver( React.useCallback( (entries) => { for (const entry of entries) { const { height } = entry.contentRect; setHeight(`${height}px`); } }, [setHeight], ), ); const [isOpen, setIsOpen] = React.useState(false); const [transitionState, setTransitionState] = React.useState( isOpen ? 'opened' : 'closed', ); React.useEffect(() => { let timeout = setTimeout(() => { setTransitionState((transitionState) => { if (transitionState === 'opening') { return 'opened'; } if (transitionState === 'closing') { return 'closed'; } }); timeout = null; }, TRANSITION_DURATION); return () => { if (!timeout) return; clearTimeout(timeout); }; }, [isOpen, setTransitionState]); React.useEffect(() => { if (isOpen) { if (transitionState !== 'opened') setTransitionState('opening'); } else { if (transitionState !== 'closed') setTransitionState('closing'); } }, [isOpen, setTransitionState]); const handleToggle = React.useCallback( (e: React.MouseEvent) => { e.target.dispatchEvent( new CustomEvent('accordion', { bubbles: true, detail: accordionId }), ); setIsOpen((state) => !state); }, [setIsOpen], ); const activeAccordion = React.useContext(AccordionContext); React.useEffect(() => { if (!activeAccordion || !accordionId) return; if (activeAccordion === accordionId) return; setIsOpen(false); }, [activeAccordion, accordionId, setIsOpen]); return (
{summary}
{children}
); }; export default Accordion;