"use client"; import { useEffect, useRef, useState } from "react"; import { useInView, useSpring, useTransform, motion } from "framer-motion"; interface AnimatedCounterProps { value: number; suffix?: string; prefix?: string; duration?: number; className?: string; } export default function AnimatedCounter({ value, suffix = "", prefix = "", duration = 2, className = "", }: AnimatedCounterProps) { const ref = useRef(null); const isInView = useInView(ref, { once: true, margin: "-50px" }); const [hasAnimated, setHasAnimated] = useState(false); const spring = useSpring(0, { stiffness: 50, damping: 30, duration: duration * 1000, }); const display = useTransform(spring, (current) => { return Math.round(current); }); const [displayValue, setDisplayValue] = useState(0); useEffect(() => { if (isInView && !hasAnimated) { setHasAnimated(true); spring.set(value); } }, [isInView, hasAnimated, spring, value]); useEffect(() => { const unsubscribe = display.on("change", (v) => { setDisplayValue(v); }); return unsubscribe; }, [display]); return ( {prefix} {displayValue} {suffix} ); }