"use client"; import { motion, useReducedMotion, type Variants } from "motion/react"; import { cn } from "@/lib/utils"; type AnimatedTextProps = { text: string; as?: "h1" | "h2" | "h3" | "h4" | "p" | "span"; className?: string; split?: "words" | "chars"; stagger?: number; delay?: number; duration?: number; once?: boolean; }; const container = (stagger: number, delay: number, reduce: boolean): Variants => ({ hidden: {}, show: { transition: { staggerChildren: reduce ? 0 : stagger, delayChildren: delay, }, }, }); const itemMotion = (duration: number): Variants => ({ hidden: { y: "115%", opacity: 0, filter: "blur(6px)" }, show: { y: "0%", opacity: 1, filter: "blur(0px)", transition: { duration, ease: [0.22, 1, 0.36, 1] }, }, }); const itemReduce: Variants = { hidden: { opacity: 0 }, show: { opacity: 1, transition: { duration: 0.25 } }, }; export function AnimatedText({ text, as: Tag = "h2", className, split = "words", stagger = 0.06, delay = 0, duration = 0.85, once = true, }: AnimatedTextProps) { const reduce = useReducedMotion() ?? false; const tokens = split === "words" ? text.split(" ") : Array.from(text); const MotionTag = motion[Tag] as typeof motion.div; const variants = reduce ? itemReduce : itemMotion(duration); return ( {tokens.map((token, index) => ( {token === " " ? " " : token} ))} ); }