import React from 'react'; import { BarChart3, GitBranch, MessageSquare, Code, Image, Link, Download, Table, FileText } from 'lucide-react'; export type CodeBlockType = 'chart' | 'mermaid' | 'proposal' | 'code' | 'image' | 'link' | 'expand' | 'table' | 'markdown' | 'fusion-fragment'; export interface CodeBlockPlaceholderProps { /** The type of content being loaded */ type: CodeBlockType; /** Optional error message to display */ error?: string; /** Callback to retry loading */ onRetry?: () => void; /** Optional custom message */ message?: string; /** Height hint for the placeholder (default varies by type) */ height?: number; } const TYPE_CONFIG: Record = { chart: { icon: BarChart3, label: 'chart', defaultHeight: 200 }, mermaid: { icon: GitBranch, label: 'diagram', defaultHeight: 150 }, proposal: { icon: MessageSquare, label: 'options', defaultHeight: 100 }, code: { icon: Code, label: 'code', defaultHeight: 80 }, image: { icon: Image, label: 'image', defaultHeight: 150 }, link: { icon: Link, label: 'link', defaultHeight: 24 }, expand: { icon: Download, label: 'content', defaultHeight: 100 }, table: { icon: Table, label: 'table', defaultHeight: 150 }, markdown: { icon: FileText, label: 'content', defaultHeight: 100 }, 'fusion-fragment': { icon: Code, label: 'fragment', defaultHeight: 150 }, }; /** * Placeholder component shown while code blocks are loading. * Provides visual feedback and error states with retry capability. */ export function CodeBlockPlaceholder({ type, error, onRetry, message, height, }: CodeBlockPlaceholderProps) { const config = TYPE_CONFIG[type]; const displayHeight = height ?? config.defaultHeight; const isInline = type === 'link'; if (error) { return (
Failed to load {config.label} {onRetry && ( )}
); } const IconComponent = config.icon; if (isInline) { return ( {message || `Loading ${config.label}...`} ); } return (
{message || `Loading ${config.label}...`}
{[...Array(3)].map((_, i) => (
))}
); } /** * Error boundary for code block rendering. * Catches rendering errors and displays a fallback UI. */ interface CodeBlockErrorBoundaryProps { children: React.ReactNode; type: CodeBlockType; fallbackCode?: string; onError?: (error: Error) => void; } interface CodeBlockErrorBoundaryState { hasError: boolean; error?: Error; } export class CodeBlockErrorBoundary extends React.Component< CodeBlockErrorBoundaryProps, CodeBlockErrorBoundaryState > { constructor(props: CodeBlockErrorBoundaryProps) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error: Error): CodeBlockErrorBoundaryState { return { hasError: true, error }; } componentDidCatch(error: Error, errorInfo: React.ErrorInfo) { console.error(`CodeBlock rendering error (${this.props.type}):`, error, errorInfo); this.props.onError?.(error); } handleRetry = () => { this.setState({ hasError: false, error: undefined }); }; render() { if (this.state.hasError) { const { type, fallbackCode } = this.props; return (
{fallbackCode && (
Show raw content
                                {fallbackCode}
                            
)}
); } return this.props.children; } }