// fallow-ignore-file unused-file import { memo, useRef, type RefObject } from "react"; import { useMountEffect } from "../../hooks/useMountEffect"; import type { SnapGuide, SpacingGuide } from "./snapEngine"; export interface SnapGuidesState { guides: SnapGuide[]; spacingGuides: SpacingGuide[]; } const MAX_GUIDES = 6; const MAX_SPACING_GUIDES = 4; const GUIDE_COLOR = "rgba(255, 68, 204, 0.85)"; const SPACING_COLOR = "rgba(255, 68, 204, 0.6)"; const SPACING_BG = "rgba(255, 68, 204, 0.15)"; interface SnapGuideOverlayProps { snapGuidesRef: RefObject; overlayWidth: number; overlayHeight: number; } export const SnapGuideOverlay = memo(function SnapGuideOverlay({ snapGuidesRef, overlayWidth, overlayHeight, }: SnapGuideOverlayProps) { const guideElsRef = useRef<(HTMLDivElement | null)[]>([]); const spacingElsRef = useRef<(HTMLDivElement | null)[]>([]); const spacingLabelElsRef = useRef<(HTMLSpanElement | null)[]>([]); const overlayWidthRef = useRef(overlayWidth); overlayWidthRef.current = overlayWidth; const overlayHeightRef = useRef(overlayHeight); overlayHeightRef.current = overlayHeight; useMountEffect(() => { let frame = 0; // fallow-ignore-next-line complexity const update = () => { frame = requestAnimationFrame(update); const state = snapGuidesRef.current; const guides = state?.guides ?? []; const spacingGuides = state?.spacingGuides ?? []; const w = overlayWidthRef.current; const h = overlayHeightRef.current; for (let i = 0; i < MAX_GUIDES; i++) { const el = guideElsRef.current[i]; if (!el) continue; const guide = guides[i]; if (!guide) { el.style.display = "none"; continue; } el.style.display = ""; if (guide.axis === "x") { el.style.left = `${guide.position}px`; el.style.top = "0"; el.style.width = "1px"; el.style.height = `${h}px`; } else { el.style.left = "0"; el.style.top = `${guide.position}px`; el.style.width = `${w}px`; el.style.height = "1px"; } } for (let i = 0; i < MAX_SPACING_GUIDES; i++) { const el = spacingElsRef.current[i]; const label = spacingLabelElsRef.current[i]; if (!el) continue; const sg = spacingGuides[i]; if (!sg) { el.style.display = "none"; continue; } el.style.display = "flex"; el.style.alignItems = "center"; el.style.justifyContent = "center"; if (sg.axis === "x") { el.style.left = `${sg.position}px`; el.style.top = `${sg.from}px`; el.style.width = `${sg.size}px`; el.style.height = `${sg.to - sg.from}px`; el.style.borderLeft = `1px dashed ${SPACING_COLOR}`; el.style.borderRight = `1px dashed ${SPACING_COLOR}`; el.style.borderTop = "none"; el.style.borderBottom = "none"; } else { el.style.left = `${sg.from}px`; el.style.top = `${sg.position}px`; el.style.width = `${sg.to - sg.from}px`; el.style.height = `${sg.size}px`; el.style.borderTop = `1px dashed ${SPACING_COLOR}`; el.style.borderBottom = `1px dashed ${SPACING_COLOR}`; el.style.borderLeft = "none"; el.style.borderRight = "none"; } if (label) { label.textContent = `${Math.round(sg.size)}`; } } }; frame = requestAnimationFrame(update); return () => cancelAnimationFrame(frame); }); return (