import { ReactNode, useCallback, useEffect, useRef, useState } from "react"; import { createFloatingAnchorEvent } from "@/components/popout/FloatingAnchor"; interface AnchorPositionProps { children?: ReactNode; id: string; className?: string; } export function FloatingCardAnchorPosition(props: AnchorPositionProps) { const ref = useRef(null); const [left, setLeft] = useState(0); const [top, setTop] = useState(0); const [cardRect, setCardRect] = useState(null); const [anchorRect, setAnchorRect] = useState(null); const calculateAndSetCoords = useCallback( (anchor: DOMRect, card: DOMRect) => { const buttonCenter = anchor.left + anchor.width / 2; const bottomReal = window.innerHeight - anchor.bottom; setTop( window.innerHeight - bottomReal - anchor.height - card.height - 30 ); setLeft( Math.min( buttonCenter - card.width / 2, window.innerWidth - card.width - 30 ) ); }, [] ); useEffect(() => { if (!anchorRect || !cardRect) return; calculateAndSetCoords(anchorRect, cardRect); }, [anchorRect, calculateAndSetCoords, cardRect]); useEffect(() => { if (!ref.current) return; function checkBox() { const divRect = ref.current?.getBoundingClientRect(); setCardRect(divRect ?? null); } checkBox(); const observer = new ResizeObserver(checkBox); observer.observe(ref.current); return () => { observer.disconnect(); }; }, []); useEffect(() => { const evtStr = createFloatingAnchorEvent(props.id); if ((window as any)[evtStr]) setAnchorRect((window as any)[evtStr]); function listen(ev: CustomEvent) { setAnchorRect(ev.detail); } document.addEventListener(evtStr, listen as any); return () => { document.removeEventListener(evtStr, listen as any); }; }, [props.id]); return (
{props.children}
); }