import classNames from "classnames"; import { ReactNode, useCallback, useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { Transition } from "@/components/Transition"; import { useInternalOverlayRouter } from "@/hooks/useOverlayRouter"; export interface OverlayProps { id: string; children?: ReactNode; darken?: boolean; } export function OverlayDisplay(props: { children: ReactNode }) { const router = useInternalOverlayRouter("hello world :)"); const refRouter = useRef(router); // close router on first mount, we dont want persist routes for overlays useEffect(() => { const r = refRouter.current; r.close(); return () => { r.close(); }; }, []); return
{props.children}
; } export function Overlay(props: OverlayProps) { const router = useInternalOverlayRouter(props.id); const [portalElement, setPortalElement] = useState(null); const ref = useRef(null); const target = useRef(null); useEffect(() => { function listen(e: MouseEvent) { target.current = e.target as Element; } document.addEventListener("mousedown", listen); return () => { document.removeEventListener("mousedown", listen); }; }); const click = useCallback( (e: React.MouseEvent) => { const startedTarget = target.current; target.current = null; if (e.currentTarget !== e.target) return; if (!startedTarget) return; if (!startedTarget.isEqualNode(e.currentTarget as Element)) return; router.close(); }, [router] ); useEffect(() => { const element = ref.current?.closest(".popout-location"); setPortalElement(element ?? document.body); }, []); return (
{portalElement ? createPortal(
{props.children}
, portalElement ) : null}
); }