import React, { createRef, useState, useEffect, ReactNode } from 'react'; import classnames from 'classnames'; import './Collapsible.scss'; interface Props { header?: React.ReactNode; collapsed?: boolean; children: ReactNode; collapseOnChildClick?: boolean; collapseOnOutsideClick?: boolean; onToggle?: (isCollapsed?: boolean) => void; disabled?: boolean; } export const Collapsible: React.FC = ({ collapsed = true, header = null, onToggle = (): void => {}, collapseOnChildClick = false, collapseOnOutsideClick = true, disabled = false, children, }) => { const collapsibleRef = createRef(); const [isCollapsed, setCollapsed] = useState(collapsed); const setHeight = (): void => { if (!isCollapsed) { collapsibleRef.current.style.maxHeight = `${collapsibleRef.current.scrollHeight}px`; } else { collapsibleRef.current.style.maxHeight = ''; } }; useEffect(() => { setHeight(); }, [isCollapsed, setHeight]); const handleClick = (): void => { if (!disabled) { setCollapsed(!isCollapsed); onToggle(!isCollapsed); } }; const handleClickOutside = (event: Event): void => { if ( collapseOnOutsideClick && !isCollapsed && collapsibleRef.current && collapsibleRef.current.parentNode && !collapsibleRef.current.parentNode.contains(event.target as Node) ) { handleClick(); } }; useEffect(() => { document.addEventListener('click', handleClickOutside, true); return () => { document.removeEventListener('click', handleClickOutside, true); }; }, [handleClickOutside]); return (
{header && header}
collapseOnChildClick && handleClick()} > {children}
); };