"use client" import { useEffect, useRef, useState } from "react" interface AnimatedNumberProps { value: number duration?: number format?: "number" | "currency" | "percent" className?: string } function formatValue(n: number, format: string) { if (format === "currency") return "$" + n.toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 0 }) if (format === "percent") return n + "%" return n.toLocaleString() } export function AnimatedNumber({ value, duration = 900, format = "number", className, }: AnimatedNumberProps) { const [display, setDisplay] = useState(0) const startRef = useRef(null) const frameRef = useRef(0) const prevRef = useRef(0) useEffect(() => { const from = prevRef.current const to = value prevRef.current = value if (from === to) { setDisplay(to) return } startRef.current = null function tick(ts: number) { if (!startRef.current) startRef.current = ts const elapsed = ts - startRef.current const progress = Math.min(elapsed / duration, 1) const eased = 1 - Math.pow(1 - progress, 3) setDisplay(Math.round(from + (to - from) * eased)) if (progress < 1) { frameRef.current = requestAnimationFrame(tick) } } frameRef.current = requestAnimationFrame(tick) return () => cancelAnimationFrame(frameRef.current) }, [value, duration]) return {formatValue(display, format)} }