"use client"; import { useInView, useMotionValue, useSpring } from "motion/react"; import { ComponentPropsWithoutRef, useEffect, useRef } from "react"; import { cn } from "@/lib/utils"; interface NumberTickerProps extends ComponentPropsWithoutRef<"span"> { value: number; startValue?: number; direction?: "up" | "down"; delay?: number; decimalPlaces?: number; } export function NumberTicker({ value, startValue = 0, direction = "up", delay = 0, className, decimalPlaces = 0, ...props }: NumberTickerProps) { const ref = useRef(null); const motionValue = useMotionValue(direction === "down" ? value : startValue); const springValue = useSpring(motionValue, { damping: 30, stiffness: 200, }); const isInView = useInView(ref, { once: true, margin: "0px" }); useEffect(() => { if (isInView) { const timer = setTimeout(() => { motionValue.set(direction === "down" ? startValue : value); }, delay * 1000); return () => clearTimeout(timer); } }, [motionValue, isInView, delay, value, direction, startValue]); useEffect( () => springValue.on("change", (latest) => { if (ref.current) { ref.current.textContent = Number(latest.toFixed(decimalPlaces)).toString(); } }), [springValue, decimalPlaces], ); return ( {startValue} ); }