"use client"; import { useCallback, useEffect, useRef, useState } from "react"; type Options = { supportsHover: boolean; desktopBp?: number; }; export function useNavToggleMenu({ desktopBp = 1024 }: Options) { const [menuOpen, setMenuOpen] = useState(false); const [openSubmenuId, setOpenSubmenuId] = useState(null); const [noTransition, setNoTransition] = useState(false); const rafRef = useRef(null); const clearRaf = useCallback(() => { if (rafRef.current != null) { cancelAnimationFrame(rafRef.current); rafRef.current = null; } }, []); const closeMenu = useCallback(() => { setMenuOpen(false); setOpenSubmenuId(null); }, []); const closeInstantNoAnim = useCallback(() => { clearRaf(); setNoTransition(true); closeMenu(); rafRef.current = requestAnimationFrame(() => { setNoTransition(false); rafRef.current = null; }); }, [clearRaf, closeMenu]); const toggleMenu = useCallback(() => { clearRaf(); setNoTransition(false); setMenuOpen((prev) => { const next = !prev; if (!next) { setOpenSubmenuId(null); } return next; }); }, [clearRaf]); const toggleSubmenu = useCallback((id: string) => { setOpenSubmenuId((cur) => (cur === id ? null : id)); }, []); useEffect(() => { const mql = window.matchMedia(`(min-width: ${desktopBp}px)`); const onChange = () => { clearRaf(); setNoTransition(true); closeMenu(); requestAnimationFrame(() => setNoTransition(false)); }; if (mql.addEventListener) { mql.addEventListener("change", onChange); } else { mql.addListener(onChange); } return () => { if (mql.removeEventListener) { mql.removeEventListener("change", onChange); } else { mql.removeListener(onChange); } }; }, [desktopBp, clearRaf, closeMenu]); useEffect(() => clearRaf, [clearRaf]); return { menuOpen, openSubmenuId, noTransition, setMenuOpen, setOpenSubmenuId, toggleMenu, toggleSubmenu, closeMenu, closeInstantNoAnim, }; }