"use client"; import { cn } from "@/lib/utils"; import { motion, stagger, useAnimate, useInView } from "framer-motion"; import { useEffect } from "react"; type Word = { text: string; className?: string; }; type Props = { words: Word[]; className?: string; cursorClassName?: string; }; export function TypewriterEffect({ words, className, cursorClassName, }: Props) { const wordsArray = words.map((word) => ({ ...word, chars: word.text.split(""), })); const [scope, animate] = useAnimate(); const isInView = useInView(scope, { once: true }); useEffect(() => { if (isInView) { animate( "span.char", { opacity: 1 }, { duration: 0.25, delay: stagger(0.08), ease: "easeInOut", } ); } }, [isInView, animate]); return (
{wordsArray.map((word, wordIndex) => ( {word.chars.map((char, charIndex) => ( {char} ))} ))} {/* Cursor */}
); }