import { useEffect, useMemo, useState } from 'react'; /** * Renders a typewriter-style text that cycles through a list of strings. * It types each string character-by-character, pauses, clears, then proceeds to the next. * @param {string[]} strings - The list of sentences to cycle through. * @param {{ typingMs?: number; pauseMs?: number; resetMs?: number }} [options] - Timing options. * @returns {string} - The current text to display. */ export function useTypewriterText( strings: string[], options?: { typingMs?: number; pauseMs?: number; resetMs?: number } ): string { const typingMs = options?.typingMs ?? 40; const pauseMs = options?.pauseMs ?? 1200; const resetMs = options?.resetMs ?? 300; const [text, setText] = useState(''); const [listIndex, setListIndex] = useState(0); const [charIndex, setCharIndex] = useState(0); const [phase, setPhase] = useState<'typing' | 'pausing' | 'clearing'>('typing'); const key = useMemo(() => (strings && strings.length ? strings.join('|') : ''), [strings]); useEffect(() => { setText(''); setListIndex(0); setCharIndex(0); setPhase('typing'); }, [key]); useEffect(() => { const list = strings && strings.length ? strings : ['Describe the story you want to make...']; const full = list[listIndex % list.length] ?? ''; let timer: number | undefined; if (phase === 'typing') { if (charIndex <= full.length) { setText(full.slice(0, charIndex)); timer = window.setTimeout(() => setCharIndex(charIndex + 1), typingMs); } else { setPhase('pausing'); } } else if (phase === 'pausing') { timer = window.setTimeout(() => setPhase('clearing'), pauseMs); } else { setText(''); timer = window.setTimeout(() => { setListIndex((listIndex + 1) % list.length); setCharIndex(0); setPhase('typing'); }, resetMs); } return () => { if (timer) window.clearTimeout(timer); }; }, [strings, listIndex, charIndex, phase, typingMs, pauseMs, resetMs]); return text; }