import { useCallback, useEffect, useState } from 'react'; import { DropdownPropsType } from './dropdown.component'; type UseDropdownType = [ boolean, (toggleState?: boolean) => void, string ]; export function useDropdown( dropdownEl: HTMLElement | null, triggerEl: HTMLElement | null, closeOnSelect = true, isOpen?: boolean, isChangeOutside?: boolean, positon?: DropdownPropsType['position'] ): UseDropdownType { const [ drop, setDrop ] = useState(false); const [ autoPosition, setAutoPosition ] = useState(''); const toggleDrop = useCallback((toggleState: any) => { setDrop(toggleState || !drop); }, [ drop ]); const onOuterClick = useCallback((e: any) => { e.preventDefault(); e.stopPropagation(); const clickOnTrigger = triggerEl && (e.target === triggerEl || triggerEl.contains(e.target)); if (clickOnTrigger) { return; } const clickOnContent = dropdownEl && (e.target === dropdownEl || dropdownEl.contains(e.target)); if (clickOnContent && !closeOnSelect) { return; } if (drop) { toggleDrop(false); } }, [ drop ]); useEffect(() => { if (drop) { document.addEventListener('click', onOuterClick); } if (isChangeOutside) { if (isOpen) { setDrop(true); } else { setDrop(false); } } if (positon && positon.split('-')[ 0 ] === 'auto') { if (dropdownEl && triggerEl) { const triggerHeight = triggerEl.getBoundingClientRect().height; const triggerTop = triggerEl.getBoundingClientRect().top; const dropHeight = dropdownEl.getBoundingClientRect().height; const windowHeight = window.innerHeight; if ((windowHeight - triggerTop - triggerHeight - dropHeight) > 8) { setAutoPosition(`bottom-${ positon.split('-')[ 2 ] }`); } else { setAutoPosition(`top-${ positon.split('-')[ 2 ] }`); } } } return () => document.removeEventListener('click', onOuterClick); }, [ isOpen, drop ]); return [ drop, toggleDrop, autoPosition ]; }