import { AnimatePresence, motion } from "motion/react"; import { type ReactNode, useEffect, useState } from "react"; import { Message } from "@/app/chat/components/message"; import DogIcon from "@/components/logo/dog-icon"; import { AnimatedProcessingIcon } from "@/components/ui/animated-processing-icon"; import { MarkdownRenderer } from "@/components/markdown-renderer"; import { cn } from "@/lib/utils"; interface OnboardingStepProps { text: string; children?: ReactNode; isVisible: boolean; isCompleted?: boolean; icon?: ReactNode; isMarkdown?: boolean; hideIcon?: boolean; isLoadingModels?: boolean; loadingStatus?: string[]; reserveSpaceForThinking?: boolean; } export function OnboardingStep({ text, children, isVisible, isCompleted = false, icon, isMarkdown = false, hideIcon = false, isLoadingModels = false, loadingStatus = [], reserveSpaceForThinking = false, }: OnboardingStepProps) { const [displayedText, setDisplayedText] = useState(""); const [showChildren, setShowChildren] = useState(false); const [currentStatusIndex, setCurrentStatusIndex] = useState(0); // Cycle through loading status messages once useEffect(() => { if (!isLoadingModels || loadingStatus.length === 0) { setCurrentStatusIndex(0); return; } const interval = setInterval(() => { setCurrentStatusIndex((prev) => { const nextIndex = prev + 1; // Stop at the last message if (nextIndex >= loadingStatus.length - 1) { clearInterval(interval); return loadingStatus.length - 1; } return nextIndex; }); }, 1500); // Change status every 1.5 seconds return () => clearInterval(interval); }, [isLoadingModels, loadingStatus]); useEffect(() => { if (!isVisible) { setDisplayedText(""); setShowChildren(false); return; } if (isCompleted) { setDisplayedText(text); setShowChildren(true); return; } let currentIndex = 0; setDisplayedText(""); setShowChildren(false); const interval = setInterval(() => { if (currentIndex < text.length) { setDisplayedText(text.slice(0, currentIndex + 1)); currentIndex++; } else { clearInterval(interval); setShowChildren(true); } }, 20); // 20ms per character return () => clearInterval(interval); }, [text, isVisible, isCompleted]); if (!isVisible) return null; return ( ) : ( icon || (
) ) } >
{isLoadingModels && loadingStatus.length > 0 ? (
Thinking
{loadingStatus[currentStatusIndex]}
) : isMarkdown ? ( ) : ( <>

{displayedText} {!showChildren && !isCompleted && ( )}

{reserveSpaceForThinking && (
)} )} {children && ( {((showChildren && !isCompleted) || isMarkdown) && (
{children}
)}
)}
); }