"use client"; // Adapted from Magic UI (MIT). See THIRD_PARTY_NOTICES.md. import { type ComponentProps, type RefObject, useEffect, useState, } from "react"; export interface AnimatedBeamProps extends ComponentProps<"svg"> { containerRef: RefObject; fromRef: RefObject; toRef: RefObject; curvature?: number; reverse?: boolean; } export function AnimatedBeam({ containerRef, fromRef, toRef, curvature = 0, reverse = false, className = "", ...props }: AnimatedBeamProps) { const [geometry, setGeometry] = useState({ path: "", width: 1, height: 1 }); useEffect(() => { const container = containerRef.current, from = fromRef.current, to = toRef.current; if (!container || !from || !to) return; const update = () => { const box = container.getBoundingClientRect(), a = from.getBoundingClientRect(), b = to.getBoundingClientRect(); const x1 = a.left - box.left + a.width / 2 - container.clientLeft + container.scrollLeft; const y1 = a.top - box.top + a.height / 2 - container.clientTop + container.scrollTop; const x2 = b.left - box.left + b.width / 2 - container.clientLeft + container.scrollLeft; const y2 = b.top - box.top + b.height / 2 - container.clientTop + container.scrollTop; setGeometry({ path: `M ${x1} ${y1} Q ${(x1 + x2) / 2} ${(y1 + y2) / 2 - curvature} ${x2} ${y2}`, width: container.clientWidth || 1, height: container.clientHeight || 1, }); }; const observer = new ResizeObserver(update); [container, from, to].forEach((el) => observer.observe(el)); window.addEventListener("resize", update); update(); return () => { observer.disconnect(); window.removeEventListener("resize", update); }; }, [containerRef, fromRef, toRef, curvature]); return ( ); }