import { useEffect, useState } from 'react' import { formatInt } from '../api' /** * Animated integer tick-up (900 ms ease-out cubic). * Respects prefers-reduced-motion by jumping straight to the value. */ export default function CountUp({ value }: { value: number }) { const [display, setDisplay] = useState(0) useEffect(() => { if ( typeof window.matchMedia === 'function' && window.matchMedia('(prefers-reduced-motion: reduce)').matches ) { setDisplay(value) return } let raf = 0 const duration = 900 const start = performance.now() const tick = (now: number) => { const p = Math.min(1, (now - start) / duration) const eased = 1 - Math.pow(1 - p, 3) setDisplay(Math.round(value * eased)) if (p < 1) raf = requestAnimationFrame(tick) } raf = requestAnimationFrame(tick) return () => cancelAnimationFrame(raf) }, [value]) return <>{formatInt(display)} }