import { importShared } from "./__federation_fn_import-hlt2XzeI.js"; import { j as jsxRuntimeExports } from "./jsx-runtime-CvJTHeKY.js"; const { useState, useCallback, useMemo } = await importShared("react"); const { Card, CardContent, CardDescription, CardHeader, CardTitle, Tabs, TabsContent, TabsList, TabsTrigger, ScrollArea, Button, Input, Textarea, Label, Badge, Monaco, Loader2, Sparkles, Check, Code, History, Wand2, Send, Edit3, useAIGenerate, useAIAssist, } = await importShared("@block-ninja/ui"); function SmartBlockEditor({ content, onChange }) { const [activeTab, setActiveTab] = useState("generate"); const [prompt, setPrompt] = useState(""); const [assistPrompt, setAssistPrompt] = useState(""); const [lastExplanation, setLastExplanation] = useState(""); const { generate, isLoading: isGenerating } = useAIGenerate(); const { assist, isLoading: isAssisting } = useAIAssist(); const meta = useMemo(() => { return content._meta ?? { currentGenerationId: "", generations: [] }; }, [content._meta]); const currentGeneration = useMemo(() => meta.generations?.find((g) => g.id === meta.currentGenerationId), [meta]); const currentTemplate = currentGeneration?.template || ""; const contentFields = useMemo(() => { const fields = {}; for (const [key, value] of Object.entries(content)) { if (!key.startsWith("_")) { fields[key] = value; } } return fields; }, [content]); const handleGenerate = useCallback(async () => { if (!prompt.trim()) return; try { const result = await generate(prompt, currentTemplate); const newGeneration = { id: result.generationId, prompt, schema: result.schema, template: result.template, createdAt: /* @__PURE__ */ new Date().toISOString(), }; const updatedMeta = { currentGenerationId: result.generationId, generations: [...(meta.generations || []), newGeneration], }; const newContent = { _meta: updatedMeta }; if (result.schema?.properties) { for (const key of Object.keys(result.schema.properties)) { newContent[key] = ""; } } onChange(newContent); setLastExplanation(result.explanation); setPrompt(""); setActiveTab("content"); } catch (error) { console.error("Generation failed:", error); } }, [prompt, currentTemplate, meta, generate, onChange]); const handleAssist = useCallback(async () => { if (!assistPrompt.trim() || !currentTemplate) return; try { const result = await assist(assistPrompt, currentTemplate, currentGeneration?.schema ? JSON.stringify(currentGeneration.schema) : void 0); const updatedGenerations = (meta.generations || []).map((g) => (g.id === meta.currentGenerationId ? { ...g, template: result.template } : g)); onChange({ ...content, _meta: { ...meta, generations: updatedGenerations }, }); setLastExplanation(result.explanation); setAssistPrompt(""); } catch (error) { console.error("Assist failed:", error); } }, [assistPrompt, currentTemplate, currentGeneration, meta, content, assist, onChange]); const handleTemplateChange = useCallback( (newTemplate) => { if (!newTemplate || !currentGeneration) return; const updatedGenerations = (meta.generations || []).map((g) => (g.id === meta.currentGenerationId ? { ...g, template: newTemplate } : g)); onChange({ ...content, _meta: { ...meta, generations: updatedGenerations }, }); }, [currentGeneration, meta, content, onChange], ); const handleSwitchGeneration = useCallback( (generationId) => { const generation = meta.generations?.find((g) => g.id === generationId); if (!generation) return; const newContent = { _meta: { ...meta, currentGenerationId: generationId }, }; if (generation.schema?.properties) { for (const key of Object.keys(generation.schema.properties)) { newContent[key] = content[key] ?? ""; } } onChange(newContent); setActiveTab("content"); }, [meta, content, onChange], ); const handleFieldChange = useCallback( (fieldName, value) => { onChange({ ...content, [fieldName]: value }); }, [content, onChange], ); const renderContentFields = () => { const schema = currentGeneration?.schema; if (!schema?.properties) { return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center py-8 text-muted-foreground", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "Generate content structure first" }), }); } const properties = Object.entries(schema.properties); const requiredFields = new Set(schema.required || []); return /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-sm", children: "Content Fields" }), }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "space-y-4", children: properties.map(([name, prop]) => { const propObj = prop; const isRequired = requiredFields.has(name); const editor = propObj["x-editor"] || "text"; let inputType = "text"; if (editor === "number") { inputType = "number"; } else if (editor === "url") { inputType = "url"; } return /* @__PURE__ */ jsxRuntimeExports.jsxs( "div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(Label, { htmlFor: name, children: [ propObj.title || propObj.description || name, isRequired && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-destructive ml-1", children: "*" }), ], }), editor === "textarea" ? /* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, { id: name, value: contentFields[name] || "", onChange: (e) => handleFieldChange(name, e.target.value), placeholder: propObj.description, rows: 4, }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { id: name, type: inputType, value: contentFields[name] || "", onChange: (e) => handleFieldChange(name, e.target.value), placeholder: propObj.description, }), ], }, name, ); }), }), ], }); }; return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "grid w-full grid-cols-4", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "generate", className: "gap-2", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Wand2, { className: "h-4 w-4" }), "Generate"], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "content", className: "gap-2", disabled: !currentGeneration, children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Edit3, { className: "h-4 w-4" }), "Content"], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "html", className: "gap-2", disabled: !currentGeneration, children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Code, { className: "h-4 w-4" }), "HTML"], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsTrigger, { value: "history", className: "gap-2", disabled: (meta.generations?.length || 0) === 0, children: [/* @__PURE__ */ jsxRuntimeExports.jsx(History, { className: "h-4 w-4" }), "History"], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsContent, { value: "generate", className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "flex items-center gap-2", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-5 w-5 text-primary" }), "Generate Content Structure"], }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: "Describe the content you want to create. AI will generate both the form fields and HTML template.", }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Textarea, { placeholder: "E.g., Create a testimonial card with author photo, quote, name, title, and 5-star rating...", value: prompt, onChange: (e) => setPrompt(e.target.value), className: "min-h-[100px]", }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-center", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: currentGeneration ? "Generating will create a new version" : "Start by describing your content", }), /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { action: "create", entity: "smart-block-generation", onClick: handleGenerate, disabled: isGenerating || !prompt.trim(), children: isGenerating ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }), "Generating..."], }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Wand2, { className: "h-4 w-4 mr-2" }), "Generate"], }), }), ], }), ], }), ], }), lastExplanation && /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-sm", children: "AI Response" }), }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-muted-foreground", children: lastExplanation }), }), ], }), !currentGeneration && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center py-8 text-muted-foreground", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Wand2, { className: "h-12 w-12 mx-auto mb-4 opacity-50" }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { children: "No content structure generated yet" }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm", children: "Enter a prompt above to get started" }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "content", children: renderContentFields() }), /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsContent, { value: "html", className: "space-y-4", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "text-sm flex items-center justify-between", children: [ "HTML Template", /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "outline", children: [Object.keys(currentGeneration?.schema?.properties || {}).length, " fields"], }), ], }), }), /* @__PURE__ */ jsxRuntimeExports.jsxs(CardContent, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Monaco, { value: currentTemplate, onChange: handleTemplateChange, language: "html", height: "300px", theme: "vs-dark" }), /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-xs text-muted-foreground mt-2", children: ["Use ", "{{fieldName}}", " placeholders to insert content values"], }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(CardTitle, { className: "text-sm flex items-center gap-2", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-4 w-4" }), "AI Assistant"], }), }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { className: "space-y-2", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(Input, { placeholder: "E.g., Make the quote italic and add a shadow...", value: assistPrompt, onChange: (e) => setAssistPrompt(e.target.value), onKeyDown: (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); handleAssist(); } }, }), /* @__PURE__ */ jsxRuntimeExports.jsx(Button, { action: "edit", entity: "smart-block-template", onClick: handleAssist, disabled: isAssisting || !assistPrompt.trim(), size: "icon", children: isAssisting ? /* @__PURE__ */ jsxRuntimeExports.jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), }), ], }), }), ], }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "history", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Card, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs(CardHeader, { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx(CardTitle, { className: "text-sm", children: "Generation History" }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardDescription, { children: "Switch between previous generations or regenerate from a prompt" }), ], }), /* @__PURE__ */ jsxRuntimeExports.jsx(CardContent, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "h-[300px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-2", children: [...(meta.generations || [])].reverse().map((gen) => /* @__PURE__ */ jsxRuntimeExports.jsx( Button, { type: "button", variant: "ghost", action: "select", entity: "smart-block-generation", className: `w-full h-auto justify-start p-3 rounded-lg border text-left font-normal whitespace-normal transition-colors hover:text-foreground [&_svg]:size-3 ${gen.id === meta.currentGenerationId ? "bg-primary/10 border-primary hover:bg-primary/10" : "hover:bg-muted"}`, onClick: () => handleSwitchGeneration(gen.id), children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full flex items-start justify-between gap-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-medium truncate", children: gen.prompt }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground", children: new Date(gen.createdAt).toLocaleString(), }), ], }), gen.id === meta.currentGenerationId && /* @__PURE__ */ jsxRuntimeExports.jsxs(Badge, { variant: "default", className: "shrink-0", children: [/* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-3 w-3 mr-1" }), "Active"], }), ], }), }, gen.id, ), ), }), }), }), ], }), }), ], }), }); } export { SmartBlockEditor as default };