import { useState, useRef, useEffect } from 'react' import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter' import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism' import { useCopyToClipboard } from '../hooks/useCopyToClipboard' const LANG_ALIASES = { jsx: 'jsx', tsx: 'tsx', js: 'javascript', javascript: 'javascript', ts: 'typescript', typescript: 'typescript', py: 'python', python: 'python', css: 'css', json: 'json', html: 'markup', sh: 'bash', bash: 'bash', } function ChevronIcon({ open }) { return ( ) } function StreamingDots() { return ( {[0, 150, 300].map(d => ( ))} ) } export default function CollapsibleCode({ filename, lang, code, streaming }) { // Auto-expand while streaming so the user can watch live; collapse when done. const [expanded, setExpanded] = useState(false) const wasStreaming = useRef(streaming) const codeRef = useRef(null) // Collapse the moment streaming finishes (auto-close polish). useEffect(() => { if (wasStreaming.current && !streaming) { setExpanded(false) } wasStreaming.current = streaming }, [streaming]) // Auto-scroll the code panel to the bottom while it's streaming and expanded. useEffect(() => { if (streaming && expanded && codeRef.current) { codeRef.current.scrollTop = codeRef.current.scrollHeight } }, [code, streaming, expanded]) const { copied, copy } = useCopyToClipboard() const language = LANG_ALIASES[(lang || '').toLowerCase()] || 'text' const label = streaming ? 'Writing' : 'Wrote' const accent = streaming ? 'var(--accent-hi)' : 'var(--text-dim)' return (
{expanded && (
{code || ''}
)}
) }