'use client'; import { type JSX } from 'react'; import { motion, Transition } from 'motion/react'; import { cn } from '@/lib/utils'; export type TextShimmerWaveProps = { children: string; as?: React.ElementType; className?: string; duration?: number; zDistance?: number; xDistance?: number; yDistance?: number; spread?: number; scaleDistance?: number; rotateYDistance?: number; transition?: Transition; }; export function TextShimmerWave({ children, as: Component = 'p', className, duration = 1, zDistance = 10, xDistance = 2, yDistance = -2, spread = 1, scaleDistance = 1.1, rotateYDistance = 10, transition, }: TextShimmerWaveProps) { const MotionComponent = motion.create( Component as keyof JSX.IntrinsicElements ); return ( <MotionComponent className={cn( 'relative inline-block [perspective:500px]', '[--base-color:#a1a1aa] [--base-gradient-color:#000]', 'dark:[--base-color:#71717a] dark:[--base-gradient-color:#ffffff]', className )} style={{ color: 'var(--base-color)' }} > {children.split('').map((char, i) => { const delay = (i * duration * (1 / spread)) / children.length; return ( <motion.span key={i} className={cn( 'inline-block whitespace-pre [transform-style:preserve-3d]' )} initial={{ translateZ: 0, scale: 1, rotateY: 0, color: 'var(--base-color)', }} animate={{ translateZ: [0, zDistance, 0], translateX: [0, xDistance, 0], translateY: [0, yDistance, 0], scale: [1, scaleDistance, 1], rotateY: [0, rotateYDistance, 0], color: [ 'var(--base-color)', 'var(--base-gradient-color)', 'var(--base-color)', ], }} transition={{ duration: duration, repeat: Infinity, repeatDelay: (children.length * 0.05) / spread, delay, ease: 'easeInOut', ...transition, }} > {char} </motion.span> ); })} </MotionComponent> ); }