"use client"; import { useEffect, useState } from "react"; import { cn } from "@/lib/utils"; import { MessageResponse } from "@/shared/ai-elements/message"; import { createStreamingMarkdownBufferState, resolveStreamingMarkdownDisplayContent, takeNextStreamingMarkdownChunk, } from "./streaming-token-response-state"; type StreamingTokenResponseProps = { content: string; streaming: boolean; streamDone?: boolean; className?: string; messageId?: string; }; const STREAMING_MARKDOWN_FRAME_MS = 45; export function StreamingTokenResponse({ content, streaming, streamDone = !streaming, className, messageId, }: StreamingTokenResponseProps) { const [displayContent, setDisplayContent] = useState(() => streamDone ? content : "" ); useEffect(() => { setDisplayContent((currentDisplayContent) => resolveStreamingMarkdownDisplayContent( content, currentDisplayContent, streamDone ) ); }, [content, messageId, streamDone]); useEffect(() => { if (streamDone || !streaming) { return; } const showNextChunk = () => { setDisplayContent((currentDisplayContent) => { const { chunk, state } = takeNextStreamingMarkdownChunk( createStreamingMarkdownBufferState(content, currentDisplayContent) ); if (chunk || state.displayContent !== currentDisplayContent) { return state.displayContent; } return currentDisplayContent; }); }; showNextChunk(); const timer = window.setInterval(showNextChunk, STREAMING_MARKDOWN_FRAME_MS); return () => window.clearInterval(timer); }, [content, streamDone, streaming]); if (!displayContent) { return null; } return ( {displayContent} ); }