diff --git a/src/components/overlays/OverlayDisplay.tsx b/src/components/overlays/OverlayDisplay.tsx index 009e769d..2f21d0ac 100644 --- a/src/components/overlays/OverlayDisplay.tsx +++ b/src/components/overlays/OverlayDisplay.tsx @@ -3,7 +3,10 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { Transition } from "@/components/Transition"; -import { useInternalOverlayRouter } from "@/hooks/useOverlayRouter"; +import { + useInternalOverlayRouter, + useRouterAnchorUpdate, +} from "@/hooks/useOverlayRouter"; export interface OverlayProps { id: string; @@ -32,6 +35,9 @@ export function Overlay(props: OverlayProps) { const ref = useRef(null); const target = useRef(null); + // listen for anchor updates + useRouterAnchorUpdate(props.id); + useEffect(() => { function listen(e: MouseEvent) { target.current = e.target as Element; diff --git a/src/hooks/useOverlayRouter.ts b/src/hooks/useOverlayRouter.ts index 4ca89fca..33c31431 100644 --- a/src/hooks/useOverlayRouter.ts +++ b/src/hooks/useOverlayRouter.ts @@ -1,4 +1,4 @@ -import { useCallback } from "react"; +import { useCallback, useEffect, useMemo } from "react"; import { useQueryParam } from "@/hooks/useQueryParams"; import { useOverlayStore } from "@/stores/overlay/store"; @@ -12,11 +12,47 @@ function joinPath(path: string[]): string { return `/${path.join("/")}`; } +export function useRouterAnchorUpdate(id: string) { + const setAnchorPoint = useOverlayStore((s) => s.setAnchorPoint); + const [route] = useQueryParam("r"); + const routerActive = useMemo( + () => !!route && route.startsWith(`/${id}`), + [route, id] + ); + + const update = useCallback(() => { + if (!routerActive) return; + const anchor = document.getElementById(`__overlayRouter::${id}`); + if (anchor) { + const rect = anchor.getBoundingClientRect(); + setAnchorPoint({ + h: rect.height, + w: rect.width, + x: rect.x, + y: rect.y, + }); + } + }, [routerActive, setAnchorPoint, id]); + + useEffect(() => { + update(); + }, [routerActive, update]); + + useEffect(() => { + function resizeEvent() { + update(); + } + window.addEventListener("resize", resizeEvent); + return () => { + window.removeEventListener("resize", resizeEvent); + }; + }, [update]); +} + export function useInternalOverlayRouter(id: string) { const [route, setRoute] = useQueryParam("r"); const transition = useOverlayStore((s) => s.transition); const setTransition = useOverlayStore((s) => s.setTransition); - const setAnchorPoint = useOverlayStore((s) => s.setAnchorPoint); const routerActive = !!route && route.startsWith(`/${id}`); function makePath(path: string) { @@ -62,23 +98,10 @@ export function useInternalOverlayRouter(id: string) { const open = useCallback( (defaultRoute = "/") => { - const anchor = document.getElementById(`__overlayRouter::${id}`); - if (anchor) { - const rect = anchor.getBoundingClientRect(); - setAnchorPoint({ - h: rect.height, - w: rect.width, - x: rect.x, - y: rect.y, - }); - } else { - setAnchorPoint(null); - } - setTransition(null); setRoute(joinPath(splitPath(defaultRoute, id))); }, - [id, setRoute, setTransition, setAnchorPoint] + [id, setRoute, setTransition] ); const activeRoute = routerActive