import { useMemo, forwardRef, useRef } from 'react' import { motion, useInView, type HTMLMotionProps } from 'framer-motion' import { cn } from '../lib/utils' export interface ShimmeringTextProps extends Omit, 'children'> { /** Required. Text to display with shimmer effect */ text: string /** Animation duration in seconds. Default: 2 */ duration?: number /** Delay before starting animation in seconds. Default: 0 */ delay?: number /** Whether to repeat the animation. Default: true */ repeat?: boolean /** Pause duration between repeats in seconds. Default: 0.5 */ repeatDelay?: number /** Whether to start animation when entering viewport. Default: true */ startOnView?: boolean /** Whether to animate only once. Default: false */ once?: boolean /** Margin for viewport detection (e.g., "0px 0px -10%"). Default: undefined */ inViewMargin?: string /** Shimmer spread multiplier. Default: 2 */ spread?: number /** Base text color (CSS color value) */ color?: string /** Shimmer gradient color (CSS color value) */ shimmerColor?: string } const ShimmeringText = forwardRef( ( { text, duration = 2, delay = 0, repeat = true, repeatDelay = 0.5, startOnView = true, once = false, inViewMargin, spread = 2, color, shimmerColor, className, style, ...props }, ref ) => { const containerRef = useRef(null) const isInView = useInView(containerRef, { once: once, margin: inViewMargin as `${number}px ${number}px ${number}px ${number}px` | undefined, }) const shouldAnimate = startOnView ? isInView : true const dynamicSpread = useMemo(() => { return text.length * spread }, [text, spread]) const baseColor = color || 'var(--color-text-secondary)' const highlightColor = shimmerColor || 'var(--color-text)' const backgroundStyle = useMemo(() => { return { backgroundImage: `linear-gradient(90deg, transparent calc(50% - ${dynamicSpread}px), ${highlightColor}, transparent calc(50% + ${dynamicSpread}px)), linear-gradient(${baseColor}, ${baseColor})`, } }, [dynamicSpread, highlightColor, baseColor]) const combinedRef = (node: HTMLSpanElement | null) => { ;(containerRef as React.MutableRefObject).current = node if (typeof ref === 'function') { ref(node) } else if (ref) { ref.current = node } } return ( {text} ) } ) ShimmeringText.displayName = 'ShimmeringText' export { ShimmeringText }