import { useState, type RefObject } from "react"; import { useMountEffect } from "../../hooks/useMountEffect"; export interface DomEditCompositionRect { left: number; top: number; width: number; height: number; scaleX: number; scaleY: number; } function sameRect(a: DomEditCompositionRect, b: DomEditCompositionRect): boolean { const d = (k: keyof DomEditCompositionRect) => Math.abs(a[k] - b[k]); return ( d("left") < 0.5 && d("top") < 0.5 && d("width") < 0.5 && d("height") < 0.5 && d("scaleX") < 0.001 && d("scaleY") < 0.001 ); } export function useDomEditCompositionRect({ iframeRef, overlayRef, }: { iframeRef: RefObject; overlayRef: RefObject; }): DomEditCompositionRect { const [compRect, setCompRect] = useState({ left: 0, top: 0, width: 0, height: 0, scaleX: 1, scaleY: 1, }); useMountEffect(() => { let frame = 0; // fallow-ignore-next-line complexity const update = () => { frame = requestAnimationFrame(update); const iframe = iframeRef.current; const overlayEl = overlayRef.current; if (!iframe || !overlayEl) return; const iRect = iframe.getBoundingClientRect(); const oRect = overlayEl.getBoundingClientRect(); const left = iRect.left - oRect.left; const top = iRect.top - oRect.top; if (iRect.width <= 0 || iRect.height <= 0) return; const doc = iframe.contentDocument; const root = doc?.querySelector("[data-composition-id]") ?? doc?.documentElement; const dw = Number.parseFloat(root?.getAttribute("data-width") ?? ""); const dh = Number.parseFloat(root?.getAttribute("data-height") ?? ""); const scaleX = dw > 0 ? iRect.width / dw : 1; const scaleY = dh > 0 ? iRect.height / dh : 1; const next = { left, top, width: iRect.width, height: iRect.height, scaleX, scaleY }; setCompRect((prev) => (sameRect(prev, next) ? prev : next)); }; frame = requestAnimationFrame(update); return () => cancelAnimationFrame(frame); }); return compRect; }