'use client'; import { useEffect, useRef, useState, useCallback } from 'react'; import { motion, useSpring, useTransform, useInView } from 'framer-motion'; import { clsx } from 'clsx'; type NumberLocale = 'ar' | 'en'; interface StatsCounterProps { target: number; label: string; prefix?: string; suffix?: string; currency?: boolean; locale?: NumberLocale; duration?: number; className?: string; } function formatNumber(value: number, locale: NumberLocale, currency: boolean): string { const opts: Intl.NumberFormatOptions = currency ? { style: 'currency', currency: 'SAR', maximumFractionDigits: 0 } : { maximumFractionDigits: 0 }; const loc = locale === 'ar' ? 'ar-SA' : 'en-SA'; return new Intl.NumberFormat(loc, opts).format(value); } function AnimatedNumber({ target, locale, currency, duration, }: { target: number; locale: NumberLocale; currency: boolean; duration: number; }) { const ref = useRef(null); const isInView = useInView(ref, { once: true, margin: '-50px' }); const springValue = useSpring(0, { stiffness: 50, damping: 20, duration: duration * 1000, }); const display = useTransform(springValue, (v) => formatNumber(Math.round(v), locale, currency)); useEffect(() => { if (isInView) { springValue.set(target); } }, [isInView, target, springValue]); useEffect(() => { const unsubscribe = display.on('change', (v) => { if (ref.current) { ref.current.textContent = v; } }); return unsubscribe; }, [display]); return 0; } function StatsCounter({ target, label, prefix, suffix, currency = false, locale = 'ar', duration = 2, className, }: StatsCounterProps) { return (
{prefix && {prefix}} {suffix && {suffix}}

{label}

); } interface StatsGridProps { stats: StatsCounterProps[]; className?: string; } function StatsGrid({ stats, className }: StatsGridProps) { return (
{stats.map((stat) => ( ))}
); } export { StatsCounter, StatsGrid }; export type { StatsCounterProps, StatsGridProps, NumberLocale };