"use client"; import { Dispatch, SetStateAction, useCallback, useEffect, useRef, } from "react"; import FocusTrap from "focus-trap-react"; import { AnimatePresence, motion } from "framer-motion"; import Leaflet from "./leaflet"; import useWindowSize from "@/lib/hooks/useWindowSize"; export default function Modal({ children, showModal, setShowModal, }: { children: React.ReactNode; showModal: boolean; setShowModal: Dispatch<SetStateAction<boolean>>; }) { const desktopModalRef = useRef(null); const onKeyDown = useCallback( (e: KeyboardEvent) => { if (e.key === "Escape") { setShowModal(false); } }, [setShowModal], ); useEffect(() => { document.addEventListener("keydown", onKeyDown); return () => document.removeEventListener("keydown", onKeyDown); }, [onKeyDown]); const { isMobile, isDesktop } = useWindowSize(); useEffect(() => { if (showModal) { document.body.style.top = `-${window.scrollY}px`; document.body.style.position = "fixed"; } else { const scrollY = document.body.style.top; document.body.style.position = ""; document.body.style.top = ""; window.scrollTo(0, parseInt(scrollY || "0") * -1); } return () => { const scrollY = document.body.style.top; document.body.style.position = ""; document.body.style.top = ""; window.scrollTo(0, parseInt(scrollY || "0") * -1); }; }, [showModal]); return ( <AnimatePresence> {showModal && ( <> {isMobile && <Leaflet setShow={setShowModal}>{children}</Leaflet>} {isDesktop && ( <> <FocusTrap focusTrapOptions={{ initialFocus: false }} active={false} > <motion.div ref={desktopModalRef} key="desktop-modal" className="fixed inset-0 z-modal hidden min-h-screen items-center justify-center md:flex" initial={{ scale: 0.95 }} animate={{ scale: 1 }} exit={{ scale: 0.95 }} onMouseDown={(e) => { if (desktopModalRef.current === e.target) { setShowModal(false); } }} > <div className="center grow overflow-hidden">{children}</div> </motion.div> </FocusTrap> <motion.div key="desktop-backdrop" className="z-overlay fixed inset-0 bg-background/40 backdrop-blur" initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} onClick={() => setShowModal(false)} /> </> )} </> )} </AnimatePresence> ); }