// Animated number counter const Counter = ({ end = 0, duration = 1600, decimals = 0, prefix = "", suffix = "", format = true }) => { const [val, setVal] = React.useState(0); const ref = React.useRef(null); React.useEffect(() => { const el = ref.current; if (!el) return; const io = new IntersectionObserver((entries) => { entries.forEach(e => { if (e.isIntersecting) { let start = null; const tick = (t) => { if (!start) start = t; const p = Math.min(1, (t - start) / duration); const eased = 1 - Math.pow(1 - p, 3); setVal(end * eased); if (p < 1) requestAnimationFrame(tick); }; requestAnimationFrame(tick); io.disconnect(); } }); }, { threshold: 0.3 }); io.observe(el); return () => io.disconnect(); }, [end, duration]); const fmt = (n) => { const fixed = n.toFixed(decimals); if (!format) return fixed; const [int, frac] = fixed.split("."); const withSep = int.replace(/\B(?=(\d{3})+(?!\d))/g, ","); return frac ? `${withSep}.${frac}` : withSep; }; return ( {prefix}{fmt(val)}{suffix} ); }; window.Counter = Counter;