'use client'; import { forwardRef, HTMLAttributes, useEffect, useState } from 'react'; export interface BreathingTextProps extends HTMLAttributes { /** The text to display with breathing effect */ children: string; /** Breathing intensity: subtle, medium, intense */ intensity?: 'subtle' | 'medium' | 'intense'; /** Animation speed in seconds */ duration?: number; /** Split text into words or keep as one unit */ splitWords?: boolean; /** Delay between each word (in seconds) */ wordDelay?: number; } const intensityClasses = { subtle: { base: 'animate-[breathe-in_1.2s_ease-out_forwards]', hover: 'hover:animate-[breathe-subtle_3s_ease-in-out_infinite]', }, medium: { base: 'animate-[breathe-in_0.8s_ease-out_forwards]', hover: 'hover:animate-[breathe-medium_2s_ease-in-out_infinite]', }, intense: { base: 'animate-[breathe-in_0.5s_ease-out_forwards]', hover: 'hover:animate-[breathe-intense_1.5s_ease-in-out_infinite]', }, }; export const BreathingText = forwardRef( ( { children, intensity = 'medium', duration = 2, splitWords = false, wordDelay = 0.15, className = '', ...props }, ref ) => { const [isVisible, setIsVisible] = useState(true); useEffect(() => { setIsVisible(true); }, [children]); const intensityStyle = intensityClasses[intensity]; if (splitWords) { const words = children.split(' '); return ( {words.map((word, index) => ( {word} {index < words.length - 1 && ' '} ))} ); } return ( {children} ); } ); BreathingText.displayName = 'BreathingText'; export default BreathingText;