import React, { useMemo, useRef, useLayoutEffect, useState } from 'react'; import AnsiToHtml from 'ansi-to-html'; interface TerminalPreviewProps { content: string; isLoading?: boolean; className?: string; } const ansiConverter = new AnsiToHtml({ fg: '#dcd6cc', bg: '#252320', newline: false, escapeXML: true, stream: false }); export function TerminalPreview({ content, isLoading = false, className = '' }: TerminalPreviewProps) { const preRef = useRef(null); const scrollTopRef = useRef(0); const [wordWrap, setWordWrap] = useState(true); const html = useMemo(() => { // Save scroll position before content changes if (preRef.current) { scrollTopRef.current = preRef.current.scrollTop; } if (!content) return ''; return ansiConverter.toHtml(content); }, [content]); // Restore scroll position after render useLayoutEffect(() => { if (preRef.current && scrollTopRef.current > 0) { preRef.current.scrollTop = scrollTopRef.current; } }, [html]); const preStyle: React.CSSProperties = { padding: '16px', margin: 0, fontFamily: 'var(--font-terminal)', fontSize: '12px', lineHeight: '1.6', overflow: 'auto', color: 'var(--color-text-primary)', backgroundColor: 'var(--color-bg-card)', whiteSpace: wordWrap ? 'pre-wrap' : 'pre', wordBreak: wordWrap ? 'break-word' : 'normal', position: 'absolute', inset: 0, }; return (
{/* Window chrome */}
{/* Content area */} {isLoading ? (
Loading preview...
) : (
        
)}
); }