(function registerEcgLoader(global) { const ReactRef = global.React; if (!ReactRef) return; const { useId } = ReactRef; const ECG_PATH = "M10 64 H30 L36 58 L41 70 L46 46 L52 72 L61 30 L72 48 L84 31 L90 108 L102 59 L110 70 L118 62"; const PULSE_PAUSE_SECONDS = 1.5; const PULSE_DASH_DISTANCE = 100; function normalizePositiveNumber(value, fallback) { return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback; } function formatKeyframePercent(value) { return value.toFixed(4).replace(/\.?0+$/, ""); } function buildPulseKeyframes(animationName, travelDuration, cycleDuration) { const travelEndPercent = (travelDuration / cycleDuration) * 100; const fadeInPercent = Math.min(travelEndPercent * 0.2, (0.08 / cycleDuration) * 100); const hidePercent = Math.min(100, travelEndPercent + 0.01); return ` @keyframes ${animationName} { 0% { opacity: 0; stroke-dashoffset: 0; } ${formatKeyframePercent(fadeInPercent)}% { opacity: var(--ecg-loader-pulse-opacity); } ${formatKeyframePercent(travelEndPercent)}% { opacity: var(--ecg-loader-pulse-opacity); stroke-dashoffset: -${PULSE_DASH_DISTANCE}; } ${formatKeyframePercent(hidePercent)}% { opacity: 0; stroke-dashoffset: -${PULSE_DASH_DISTANCE}; } 100% { opacity: 0; stroke-dashoffset: -${PULSE_DASH_DISTANCE}; } }`; } function EcgLoader(props) { const { size = 64, speed = 2.16, className, pulseColor = "#FFFFFF", } = props || {}; const uniqueId = useId().replace(/:/g, ""); const gradientId = `ecg-loader-gradient-${uniqueId}`; const glowId = `ecg-loader-glow-${uniqueId}`; const animationName = `ecg-loader-pulse-${uniqueId}`; const normalizedSize = normalizePositiveNumber(size, 64); const normalizedDuration = normalizePositiveNumber(speed, 2.16); const cycleDuration = normalizedDuration + PULSE_PAUSE_SECONDS; const pulseKeyframes = buildPulseKeyframes(animationName, normalizedDuration, cycleDuration); const pulseAnimationStyle = { animationName }; const rootClassName = ["ecg-loader", className].filter(Boolean).join(" "); const style = { "--ecg-loader-size": `${normalizedSize}px`, "--ecg-loader-cycle-duration": `${cycleDuration}s`, "--ecg-loader-pulse-color": pulseColor, }; return ( ); } global.TanicUiComponents = global.TanicUiComponents || {}; global.TanicUiComponents.EcgLoader = EcgLoader; })(window);