'use client'; import { cn } from '@/lib/utils'; import { motion, AnimatePresence, Transition, Variants, AnimatePresenceProps, } from 'motion/react'; import { useState, useEffect, Children } from 'react'; export type TextLoopProps = { children: React.ReactNode[]; className?: string; interval?: number; transition?: Transition; variants?: Variants; onIndexChange?: (index: number) => void; trigger?: boolean; mode?: AnimatePresenceProps['mode']; }; export function TextLoop({ children, className, interval = 2, transition = { duration: 0.3 }, variants, onIndexChange, trigger = true, mode = 'popLayout', }: TextLoopProps) { const [currentIndex, setCurrentIndex] = useState(0); const items = Children.toArray(children); useEffect(() => { if (!trigger) return; const intervalMs = interval * 1000; const timer = setInterval(() => { setCurrentIndex((current) => { const next = (current + 1) % items.length; onIndexChange?.(next); return next; }); }, intervalMs); return () => clearInterval(timer); }, [items.length, interval, onIndexChange, trigger]); const motionVariants: Variants = { initial: { y: 20, opacity: 0 }, animate: { y: 0, opacity: 1 }, exit: { y: -20, opacity: 0 }, }; return ( <div className={cn('relative inline-block whitespace-nowrap', className)}> <AnimatePresence mode={mode} initial={false}> <motion.div key={currentIndex} initial='initial' animate='animate' exit='exit' transition={transition} variants={variants || motionVariants} > {items[currentIndex]} </motion.div> </AnimatePresence> </div> ); }