Initial commit
This commit is contained in:
commit
bcca176137
88 files changed
+8725
No files matched your search
@@ -0,0 +1,95 @@
|
||||
"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<string | null>(null);
|
||||
const [noTransition, setNoTransition] = useState(false);
|
||||
|
||||
const rafRef = useRef<number | null>(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,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user