/** * ╔═══════════════════════════════════════════════════════════════════════════╗ * ║ SMART COMPONENT RENDERER ║ * ║═══════════════════════════════════════════════════════════════════════════║ * ║ Dynamic renderer that maps JSON component specifications to React ║ * ║ Part of the Liquid UI Arsenal ║ * ╚═══════════════════════════════════════════════════════════════════════════╝ */ import { Suspense, lazy, ComponentType, useMemo } from 'react'; import { Loader2, AlertTriangle } from 'lucide-react'; import { cn } from '@/lib/utils'; // Import all smart components import { LiveMetricGauge, LiveMetricGaugeProps } from './LiveMetricGauge'; import { CodeDiffViewer, CodeDiffViewerProps } from './CodeDiffViewer'; import { LogStreamViewer, LogStreamViewerProps } from './LogStreamViewer'; import { InteractiveForceGraph, InteractiveForceGraphProps } from './InteractiveForceGraph'; import { KnowledgeGapCard, KnowledgeGapCardProps } from './KnowledgeGapCard'; import { AgentProcessTracker, AgentProcessTrackerProps } from './AgentProcessTracker'; import { IdeaStickyNote, IdeaStickyNoteProps } from './IdeaStickyNote'; // Visual Cortex Components (Diagram Engine) import { MermaidDiagram, MermaidDiagramProps } from './MermaidDiagram'; import { ArchitectureView, ArchitectureViewProps } from './ArchitectureView'; import { SequenceDiagram, SequenceDiagramProps } from './SequenceDiagram'; import { FlowchartView, FlowchartViewProps } from './FlowchartView'; import { MindMapView, MindMapViewProps } from './MindMapView'; // Component type definitions export type SmartComponentName = | 'LiveMetricGauge' | 'CodeDiffViewer' | 'LogStreamViewer' | 'InteractiveForceGraph' | 'KnowledgeGapCard' | 'AgentProcessTracker' | 'IdeaStickyNote' // Visual Cortex (Diagram Engine) | 'MermaidDiagram' | 'ArchitectureView' | 'SequenceDiagram' | 'FlowchartView' | 'MindMapView'; // Props type mapping export type SmartComponentProps = { LiveMetricGauge: LiveMetricGaugeProps; CodeDiffViewer: CodeDiffViewerProps; LogStreamViewer: LogStreamViewerProps; InteractiveForceGraph: InteractiveForceGraphProps; KnowledgeGapCard: KnowledgeGapCardProps; AgentProcessTracker: AgentProcessTrackerProps; IdeaStickyNote: IdeaStickyNoteProps; // Visual Cortex MermaidDiagram: MermaidDiagramProps; ArchitectureView: ArchitectureViewProps; SequenceDiagram: SequenceDiagramProps; FlowchartView: FlowchartViewProps; MindMapView: MindMapViewProps; }; // Component registry const componentRegistry: Record> = { LiveMetricGauge, CodeDiffViewer, LogStreamViewer, InteractiveForceGraph, KnowledgeGapCard, AgentProcessTracker, IdeaStickyNote, // Visual Cortex MermaidDiagram, ArchitectureView, SequenceDiagram, FlowchartView, MindMapView, }; // UI_COMPONENT message format from backend export interface UIComponentMessage { type: 'UI_COMPONENT'; component: SmartComponentName; props: Record; id?: string; } export interface SmartComponentRendererProps { message: UIComponentMessage; onError?: (error: Error, componentName: string) => void; className?: string; } // Error boundary fallback function ComponentError({ componentName, error }: { componentName: string; error?: Error }) { return (

Failed to render: {componentName}

{error &&

{error.message}

}
); } // Loading state function ComponentLoading({ componentName }: { componentName: string }) { return (
Loading {componentName}...
); } /** * SmartComponentRenderer - Renders UI components based on JSON specification * * Usage: * ```tsx * * ``` */ export function SmartComponentRenderer({ message, onError, className, }: SmartComponentRendererProps) { const { component: componentName, props, id } = message; // Validate component exists const Component = componentRegistry[componentName]; if (!Component) { const error = new Error(`Unknown component: ${componentName}`); onError?.(error, componentName); return ; } // Render with error boundary try { return (
}>
); } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); onError?.(err, componentName); return ; } } /** * Helper to check if a message is a UI_COMPONENT message */ export function isUIComponentMessage(message: unknown): message is UIComponentMessage { if (!message || typeof message !== 'object') return false; const msg = message as Record; return msg.type === 'UI_COMPONENT' && typeof msg.component === 'string'; } /** * Parse assistant message content for embedded UI components * Supports format: ```ui:ComponentName {...props}``` */ export function parseMessageForComponents(content: string): Array { const parts: Array = []; const regex = /```ui:(\w+)\s*([\s\S]*?)```/g; let lastIndex = 0; let match; while ((match = regex.exec(content)) !== null) { // Add text before the component if (match.index > lastIndex) { parts.push(content.slice(lastIndex, match.index)); } // Parse the component const componentName = match[1] as SmartComponentName; let props = {}; try { if (match[2].trim()) { props = JSON.parse(match[2].trim()); } } catch { // If JSON parsing fails, try to interpret as simple key-value pairs console.warn(`Failed to parse props for ${componentName}:`, match[2]); } parts.push({ type: 'UI_COMPONENT', component: componentName, props, id: `${componentName}-${match.index}`, }); lastIndex = regex.lastIndex; } // Add remaining text if (lastIndex < content.length) { parts.push(content.slice(lastIndex)); } return parts.length > 0 ? parts : [content]; } /** * List all available component names */ export function getAvailableComponents(): SmartComponentName[] { return Object.keys(componentRegistry) as SmartComponentName[]; } /** * Component metadata for documentation */ export const componentMetadata: Record = { LiveMetricGauge: { description: 'Animated gauge for real-time metrics with thresholds', category: 'Observability', }, CodeDiffViewer: { description: 'Side-by-side or unified diff viewer for code changes', category: 'Builder', }, LogStreamViewer: { description: 'Real-time log streaming with filtering and levels', category: 'Observability', }, InteractiveForceGraph: { description: 'Force-directed knowledge graph visualization', category: 'Knowledge', }, KnowledgeGapCard: { description: 'Visual card for knowledge gaps and their status', category: 'Knowledge', }, AgentProcessTracker: { description: 'Real-time visualization of agent task execution', category: 'Builder', }, IdeaStickyNote: { description: 'Playful sticky note for incubated ideas', category: 'Creative', }, // Visual Cortex (Diagram Engine) MermaidDiagram: { description: 'Render any Mermaid diagram from DSL syntax', category: 'Visual', }, ArchitectureView: { description: 'System architecture visualization with typed nodes', category: 'Visual', }, SequenceDiagram: { description: 'Interaction sequences between actors/systems', category: 'Visual', }, FlowchartView: { description: 'Business process and decision flow visualization', category: 'Visual', }, MindMapView: { description: 'Hierarchical idea visualization and brainstorming', category: 'Visual', }, }; export default SmartComponentRenderer;