"use client"; import { animate, useInView, useMotionValue, useTransform } from "motion/react"; import { motion } from "motion/react"; import { useEffect, useRef } from "react"; import { formatNumber } from "@/lib/format"; type CounterProps = { from?: number; to: number; /** Seconds. Default 0.8. */ duration?: number; /** Seconds. Default 0.2 — system standard: 200 ms after slide enter. */ delay?: number; decimals?: number; suffix?: string; prefix?: string; /** When true uses linear easing — system convention for count-up. */ linear?: boolean; className?: string; }; export function Counter({ from = 0, to, duration = 0.8, delay = 0.2, decimals = 0, suffix = "", prefix = "", linear = true, className, }: CounterProps) { const ref = useRef(null); const inView = useInView(ref, { once: true, amount: 0.4 }); const value = useMotionValue(from); const rounded = useTransform( value, (latest) => `${prefix}${formatNumber(latest, decimals)}${suffix}`, ); useEffect(() => { if (!inView) return; const controls = animate(value, to, { duration, delay, ease: linear ? "linear" : [0.22, 1, 0.36, 1], }); return controls.stop; }, [inView, to, duration, delay, value, linear]); return ( {rounded} ); }