import { useEffect, useRef, useState } from "react"; /** * Spuncin animated entrance logo (A1 · Comet Trail Classic). * * Plays once on mount: two rings "draw themselves" comet-style * (a leading dot trails a growing arc) rotating in opposite * directions, then the center dot pops in. Ends in a static state * matching the official static logo — does not loop. * * Usage: * * // for dark backgrounds * // change replayKey to replay * * Props: * size number — width/height in px (default 120) * onDark boolean — use the light-on-dark palette (default false) * duration number — animation duration in seconds (default 1.4) * replayKey any — change this value to force the animation to replay * className string — passed through to the wrapping */ export default function SpuncinLogoAnimated({ size = 120, onDark = false, duration = 1.4, replayKey, className = "", }) { const [id] = useState( () => `spuncin-logo-${Math.random().toString(36).slice(2, 9)}` ); const svgRef = useRef(null); // Colors const outerColor = onDark ? "#D1FAE5" : "#064E3B"; const innerColor = "#10B981"; const coreColor = onDark ? "#D1FAE5" : "#064E3B"; // Restart the CSS animation whenever replayKey changes, by toggling // the animation off and back on (forces reflow). useEffect(() => { const el = svgRef.current; if (!el) return; const animated = el.querySelectorAll( ".spuncin-outer-group, .spuncin-outer-path, .spuncin-inner-group, .spuncin-inner-path, .spuncin-core, .spuncin-outer-dot, .spuncin-inner-dot" ); animated.forEach((node) => { node.style.animation = "none"; // force reflow // eslint-disable-next-line no-unused-expressions node.offsetHeight; node.style.animation = ""; }); }, [replayKey]); const ease = "cubic-bezier(0.25, 0.1, 0.25, 1)"; const bounceEase = "cubic-bezier(0.34, 1.56, 0.64, 1)"; const coreDelay = duration - 0.3; return ( ); }