"use client"; import { useEffect } from "react"; import { motion, stagger, useAnimate, useInView } from "framer-motion"; import { cn } from "@/lib/utils"; import { useRef } from "react"; export const TextGenerateEffect = ({ words, className, filter = true, duration = 1, }: { words: string; className?: string; filter?: boolean; duration?: number; }) => { const [scope, animate] = useAnimate(); const containerRef = useRef(null); const isInView = useInView(containerRef, { once: true }); let wordsArray = words.split(" "); useEffect(() => { if (isInView) { animate( "span", { opacity: 1, filter: filter ? "blur(0px)" : "none", }, { duration: duration ? duration : 1, delay: stagger(0.2), ease: "easeOut", // added an ease for smoother animation } ); } }, [isInView, scope.current, animate, filter, duration]); const renderWords = () => { return ( <> {wordsArray.map((word, idx) => { return ( <motion.span key={word + idx} className="text-gray-500 opacity-0 font-normal text-3xl italic" style={{ filter: filter ? "blur(10px)" : "none", }} > {word}{" "} </motion.span> ); })} </> ); }; return ( <div className={cn("font-bold", className)} ref={containerRef}> <div className="mt-4"> <motion.div ref={scope} className=" dark:text-white text-black text-2xl leading-snug tracking-wide"> {renderWords()} </motion.div> </div> </div> ); };