"use client"; import React, { useState, useEffect, useRef, memo } from "react"; import { MessageSquare, Send, Code2, Palette, Search, Trash2, Copy, Monitor, StopCircle, X, Zap, Ghost, Wand2, LayoutPanelLeft, Play, Orbit, Plus, Key } from "lucide-react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import rehypeHighlight from "rehype-highlight"; import { cn } from "@/lib/utils"; import { AIAssistMessage } from "@/types"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Input } from "@/components/ui/input"; import useStore from "@/lib/store"; import { translations } from "@/lib/i18n/translations"; import modelAdapter from "@/lib/services/adapter-instance"; // --- Types --- interface PreviewData { type: string; data: string; language?: string; isStreaming?: boolean; } // --- Specialized Components --- /** * A ultra-stable iframe wrapper that avoids hydration issues * and provides a WOW visual experience. */ // Error Boundary for Canvas crashes class CanvasErrorBoundary extends React.Component<{ children: React.ReactNode }, { hasError: boolean, error: string | null }> { constructor(props: { children: React.ReactNode }) { super(props); this.state = { hasError: false, error: null }; } static getDerivedStateFromError(error: Error) { return { hasError: true, error: error.message }; } render() { if (this.state.hasError) { return (

Canvas Crashed

{this.state.error}

); } return this.props.children; } } const BuildingArtifact = ({ type }: { type: string }) => { const [progress, setProgress] = useState(0); const steps = [ "Initializing neural links...", "Scaffolding architecture...", "Writing logic blocks...", "Injecting dynamic modules...", "Finalizing interactive layers..." ]; const [currentStep, setCurrentStep] = useState(0); useEffect(() => { const interval = setInterval(() => { setProgress(p => (p < 95 ? p + (100 - p) * 0.1 : p)); setCurrentStep(s => (s < steps.length - 1 ? s + 1 : s)); }, 2000); return () => clearInterval(interval); }, []); return (

Building {type}

{steps.map((step, idx) => (
{step} {idx < currentStep && }
))}
); }; const LiveCanvas = memo(({ data, type, isStreaming }: { data: string, type: string, isStreaming: boolean }) => { const iframeRef = useRef(null); const [renderError, setRenderError] = useState(null); useEffect(() => { if (!iframeRef.current || !data || isStreaming) return; setRenderError(null); // Decode HTML entities if present const isEncodedHtml = data.includes("<") && data.includes(">"); const normalized = isEncodedHtml ? data .replace(/</g, "<") .replace(/>/g, ">") .replace(/&/g, "&") .replace(/"/g, "\"") .replace(/'/g, "'") : data; // Check if the content is a full HTML document or a fragment const trimmed = normalized.trim(); const isFullDocument = /^]/i.test(normalized); const isReactLike = normalized.includes("import React") || normalized.includes("useState") || normalized.includes("useEffect") || /<[A-Z][\s\S]*>/.test(normalized); let doc: string; try { if (isFullDocument) { // If it's a full document, inject Tailwind CSS but keep the structure const reactScripts = isReactLike ? ` ` : ""; if (hasHeadTag) { doc = normalized.replace(//i, ` ${reactScripts} `); } else { doc = normalized.replace(/]*>/i, (match) => `${match} ${reactScripts} `); } } else if (isReactLike) { // Specialized React Runner for fragments/components const cleanedCode = normalized .replace(/import\s+(?:React\s*,\s*)?{?([\s\S]*?)}?\s+from\s+['"]react['"];?/g, "const { $1 } = React;") .replace(/import\s+React\s+from\s+['"]react['"];?/g, "/* React already global */") .replace(/import\s+[\s\S]*?from\s+['"]lucide-react['"];?/g, "const { ...lucide } = window.lucide || {};") .replace(/export\s+default\s+/g, "const MainComponent = "); // Try to find the component name to render const componentMatch = cleanedCode.match(/const\s+([A-Z]\w+)\s*=\s*\(\)\s*=>/); const mainComponent = componentMatch ? componentMatch[1] : (cleanedCode.includes("MainComponent") ? "MainComponent" : null); doc = `
`; } else { // Wrap fragments in a styled container doc = ` ${normalized} `; } if (iframeRef.current) { iframeRef.current.srcdoc = doc; } } catch (e) { console.error("Canvas Render Error:", e); setRenderError(e instanceof Error ? e.message : "Internal rendering failure"); } }, [data, type, isStreaming]); return (
{isStreaming && } {renderError ? (

Runtime Execution Error

{renderError}

) : (