import { onMount, onCleanup } from "solid-js"; interface RingProps { target: () => HTMLElement | null; } export function Ring(props: RingProps) { let svgEl: SVGSVGElement | undefined; let rectEl: SVGRectElement | undefined; let fadeTimer: ReturnType; function calibrate() { const el = props.target(); if (!el || !svgEl || !rectEl) return; const { width, height } = el.getBoundingClientRect(); const r = 12; const perim = 2 * (width + height); svgEl.setAttribute("viewBox", `0 0 ${width} ${height}`); svgEl.setAttribute("width", String(width)); svgEl.setAttribute("height", String(height)); rectEl.setAttribute("width", String(width)); rectEl.setAttribute("height", String(height)); rectEl.setAttribute("rx", String(r)); rectEl.setAttribute("ry", String(r)); rectEl.style.setProperty("--perim", String(perim)); rectEl.style.strokeDasharray = String(perim); rectEl.style.strokeDashoffset = String(perim); } function trigger() { if (!rectEl) return; rectEl.style.animation = "none"; void (rectEl as unknown as HTMLElement).offsetWidth; rectEl.style.animation = "ringDraw 380ms ease-out both"; clearTimeout(fadeTimer); fadeTimer = setTimeout(beginFade, 380 + 1200); } function beginFade() { if (!rectEl) return; rectEl.style.transition = "opacity 600ms var(--retreat)"; rectEl.style.opacity = "0"; } onMount(() => { calibrate(); const ro = new ResizeObserver(calibrate); const el = props.target(); if (el) ro.observe(el); onCleanup(() => ro.disconnect()); }); (window as any).__peachRingTrigger = trigger; return ( ); }