"use client"; import { motion, useMotionValue, useSpring, useTransform } from "motion/react"; import { useEffect, useRef, useState } from "react"; import { cn } from "@/lib/utils"; interface TelemetryMetric { label: string; value: number; unit: string; precision?: number; min?: number; max?: number; } const METRICS_CONFIG: TelemetryMetric[] = [ { label: "UPTIME", value: 99.97, unit: "%", precision: 2, min: 99.9, max: 100, }, { label: "INTEGRAÇÕES", value: 12, unit: " ativas", precision: 0, min: 8, max: 16, }, { label: "BUILDS", value: 247, unit: " /dia", precision: 0, min: 200, max: 300, }, { label: "LATÊNCIA", value: 12, unit: " ms", precision: 0, min: 8, max: 28 }, ]; const UPDATE_INTERVAL = 3000; const springConfigs = [ { stiffness: 300, damping: 30, mass: 0.8 }, { stiffness: 200, damping: 25, mass: 1 }, { stiffness: 150, damping: 20, mass: 1.2 }, { stiffness: 150, damping: 20, mass: 1.2 }, ]; export function TelemetryStrip({ className, reducedMotion = false, }: { className?: string; reducedMotion?: boolean; }) { const [_metrics, setMetrics] = useState(METRICS_CONFIG); const pointerX = useMotionValue(0); const pointerY = useMotionValue(0); const isHovering = useRef(false); const intervalRef = useRef | null>(null); const metricValue0 = useSpring( useMotionValue(METRICS_CONFIG[0].value), springConfigs[0], ); const metricValue1 = useSpring( useMotionValue(METRICS_CONFIG[1].value), springConfigs[1], ); const metricValue2 = useSpring( useMotionValue(METRICS_CONFIG[2].value), springConfigs[2], ); const metricValue3 = useSpring( useMotionValue(METRICS_CONFIG[3].value), springConfigs[3], ); const metricValues = [metricValue0, metricValue1, metricValue2, metricValue3]; // Parallax sutil em px, sinal alternado por métrica — assinatura "reage ao ponteiro" const pointerShiftX = useTransform(pointerX, [-1, 1], [-8, 8]); const pointerShiftY = useTransform(pointerY, [-1, 1], [-5, 5]); const pointerShiftXNeg = useTransform(pointerShiftX, (v) => -v); const pointerShiftYNeg = useTransform(pointerShiftY, (v) => -v); const generateVariation = useRef((metric: TelemetryMetric): number => { const range = (metric.max ?? metric.value * 1.1) - (metric.min ?? metric.value * 0.9); const variation = (Math.random() - 0.5) * range * 0.15; const newValue = metric.value + variation; return Math.max( metric.min ?? -Infinity, Math.min(metric.max ?? Infinity, newValue), ); }); const updateMetrics = useRef(() => { setMetrics((prev) => prev.map((metric) => ({ ...metric, value: generateVariation.current(metric), })), ); }); useEffect(() => { if (reducedMotion) return; intervalRef.current = setInterval(updateMetrics.current, UPDATE_INTERVAL); return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; }, [reducedMotion]); useEffect(() => { const handlePointerMove = (e: MouseEvent) => { const x = (e.clientX / window.innerWidth) * 2 - 1; const y = -(e.clientY / window.innerHeight) * 2 + 1; pointerX.set(x); pointerY.set(y); }; window.addEventListener("pointermove", handlePointerMove); return () => window.removeEventListener("pointermove", handlePointerMove); }, [pointerX, pointerY]); return (
{ isHovering.current = true; }} onPointerLeave={() => { isHovering.current = false; }} > {METRICS_CONFIG.map((metric, index) => (
{metric.label}
); }