import React, { ReactNode, useEffect, useRef, useState } from "react"; import anime from "animejs/lib/anime.es.js"; import styles from "./typewritertext.module.css"; function Cursor() { const self = useRef(null); useEffect(() => { const blink = anime({ targets: self.current, loop: true, duration: 750, opacity: [{ value: [1, 1] }, { value: [0, 0] }], }); }, []); return () } function FadingLetter({ char }: { char: string }) { const letter = useRef(null); useEffect(() => { anime({ targets: letter.current, loop: false, //opacity: [{ value: [1, 1] }, { value: [0, 0] }], color: ['#ffffff', '#ffffff', '#ffffff', '#ffffff', '#eeeeee'], duration: 100, }); }, []); return ( {char == " " ? "\u00A0" : char} ); } function TypewriterLine( { text, cursor, lineFinished }: { text: string, cursor: boolean, lineFinished: () => any }) { const TYPE_AFTER_MS = 1_000; const JUMP_AFTER_MS = 80; const [index, setIndex] = useState(0); const [hasCursor, setHasCursor] = useState(true); const current = text.slice(0, index) || ""; const lettersHtml = (!current) ? (
) : current.split("").map((c, i) => { return (); }); const lineHtml = ( <>

{lettersHtml}{ (hasCursor || cursor) ? () : null }

); const text_animation_ref = useRef(null); useEffect(() => { const interval = setInterval(() => { setIndex(oldIndex => { if (oldIndex < text.length) { return oldIndex + 1; } else { clearInterval(interval); setHasCursor(false); //lineFinished(); // const cursorRemove = setInterval(() => { setHasCursor(false); return () => clearInterval(cursorRemove); }, 500); return oldIndex; } }) }, JUMP_AFTER_MS); //Clearing the interval return () => clearInterval(interval); }, [index, text.length]); if (current === "") return (

); return (
{lineHtml}
); } function TypewriterText({ text, lines }: { text: string[], lines: number }) { // IMPORTANT: This code chokes on an empty string. Logic needs to be refactored const len = text.length; return text.map((v, idx) => {}}>).slice(-lines); /* const TYPE_AFTER_MS = 1_000; const JUMP_AFTER_MS = 80; const [index, setIndex] = useState(0); const [hasCursor, setHasCursor] = useState(true); const current = text.slice(0, index) || ""; const lettersHtml: ReactNode[] = (!current) ? (
) : current.split("").map((c, i) => { return (); }); const lineHtml = ( <>
{lettersHtml}{ hasCursor ? () : null }
); const text_animation_ref = useRef(null); useEffect(() => { //Implementing the setInterval method const interval = setInterval(() => { setIndex(oldIndex => { if (oldIndex < text.length) { return oldIndex + 1; } else { clearInterval(interval); // const cursorRemove = setInterval(() => { setHasCursor(false); return () => clearInterval(cursorRemove); }, 500); return oldIndex; } }) }, 100); //Clearing the interval return () => clearInterval(interval); }, [index]); return (

{lineHtml}

); */ } export default TypewriterText;