@easybits.cloud/html-tailwind-generator 0.2.39 → 0.2.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -352,7 +352,8 @@ function FloatingToolbar({
|
|
|
352
352
|
onClose,
|
|
353
353
|
onViewCode,
|
|
354
354
|
onUpdateAttribute,
|
|
355
|
-
isRefining
|
|
355
|
+
isRefining,
|
|
356
|
+
hideStylePresets
|
|
356
357
|
}) {
|
|
357
358
|
const [prompt, setPrompt] = useState3("");
|
|
358
359
|
const [showCode, setShowCode] = useState3(false);
|
|
@@ -579,7 +580,7 @@ function FloatingToolbar({
|
|
|
579
580
|
}
|
|
580
581
|
)
|
|
581
582
|
] }),
|
|
582
|
-
selection.isSectionRoot && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50", children: [
|
|
583
|
+
selection.isSectionRoot && !hideStylePresets && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50", children: [
|
|
583
584
|
/* @__PURE__ */ jsx3("span", { className: "text-[10px] text-gray-500 uppercase tracking-wider mr-1 shrink-0", children: "Estilo" }),
|
|
584
585
|
STYLE_PRESETS.map((preset) => /* @__PURE__ */ jsxs3(
|
|
585
586
|
"button",
|
|
@@ -958,4 +959,4 @@ export {
|
|
|
958
959
|
CodeEditor,
|
|
959
960
|
ViewportToggle
|
|
960
961
|
};
|
|
961
|
-
//# sourceMappingURL=chunk-
|
|
962
|
+
//# sourceMappingURL=chunk-W7OJN3RE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Canvas.tsx","../src/components/SectionList.tsx","../src/components/FloatingToolbar.tsx","../src/components/CodeEditor.tsx","../src/components/ViewportToggle.tsx"],"sourcesContent":["import React, { useRef, useEffect, useCallback, useState, forwardRef, useImperativeHandle } from \"react\";\nimport type { Section3, IframeMessage } from \"../types\";\nimport { buildPreviewHtml } from \"../buildHtml\";\n\nexport interface CanvasHandle {\n scrollToSection: (id: string) => void;\n postMessage: (msg: Record<string, unknown>) => void;\n}\n\ninterface CanvasProps {\n sections: Section3[];\n theme?: string;\n onMessage: (msg: IframeMessage) => void;\n iframeRectRef: React.MutableRefObject<DOMRect | null>;\n onReady?: () => void;\n}\n\nexport const Canvas = forwardRef<CanvasHandle, CanvasProps>(function Canvas({ sections, theme, onMessage, iframeRectRef, onReady: onReadyProp }, ref) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const [ready, setReady] = useState(false);\n // Track what the iframe currently has so we can diff\n const knownSectionsRef = useRef<Map<string, string>>(new Map());\n const initializedRef = useRef(false);\n const onReadyRef = useRef(onReadyProp);\n onReadyRef.current = onReadyProp;\n\n // Post a message to the iframe\n const postToIframe = useCallback((msg: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(msg, \"*\");\n }, []);\n\n useImperativeHandle(ref, () => ({\n scrollToSection(id: string) {\n postToIframe({ action: \"scroll-to-section\", id });\n },\n postMessage(msg: Record<string, unknown>) {\n postToIframe(msg);\n },\n }), [postToIframe]);\n\n // Initial write: set up the iframe shell (empty body + script + tailwind)\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe || initializedRef.current) return;\n initializedRef.current = true;\n\n const html = buildPreviewHtml([]);\n const doc = iframe.contentDocument;\n if (!doc) return;\n doc.open();\n doc.write(html);\n doc.close();\n }, []);\n\n // Handle \"ready\" from iframe — then inject current sections\n const handleReady = useCallback(() => {\n setReady(true);\n // Inject all current sections\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n for (const s of sorted) {\n postToIframe({ action: \"add-section\", id: s.id, html: s.html, scroll: false });\n knownSectionsRef.current.set(s.id, s.html);\n }\n // Restore scroll position from sessionStorage\n const savedY = sessionStorage.getItem(\"landing-v3-iframe-scrollY\");\n if (savedY) {\n setTimeout(() => postToIframe({ action: \"restore-scroll\", y: Number(savedY) }), 100);\n }\n onReadyRef.current?.();\n }, [sections, postToIframe]);\n\n // Incremental diff: detect added/updated/removed sections\n useEffect(() => {\n if (!ready) return;\n\n const known = knownSectionsRef.current;\n const currentIds = new Set(sections.map((s) => s.id));\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n\n // Add new sections\n for (const s of sorted) {\n if (!known.has(s.id)) {\n postToIframe({ action: \"add-section\", id: s.id, html: s.html, scroll: true });\n known.set(s.id, s.html);\n } else if (known.get(s.id) !== s.html) {\n // Update changed sections\n postToIframe({ action: \"update-section\", id: s.id, html: s.html });\n known.set(s.id, s.html);\n }\n }\n\n // Remove deleted sections\n for (const id of known.keys()) {\n if (!currentIds.has(id)) {\n postToIframe({ action: \"remove-section\", id });\n known.delete(id);\n }\n }\n\n // Reorder if needed\n const knownOrder = [...known.keys()];\n const desiredOrder = sorted.map((s) => s.id);\n if (knownOrder.length !== desiredOrder.length || knownOrder.some((id, i) => id !== desiredOrder[i])) {\n postToIframe({ action: \"reorder-sections\", order: desiredOrder });\n }\n }, [sections, ready, postToIframe]);\n\n // Send theme changes to iframe\n useEffect(() => {\n if (!ready) return;\n postToIframe({ action: \"set-theme\", theme: theme || \"default\" });\n }, [theme, ready, postToIframe]);\n\n // Update iframe rect on resize/scroll\n const updateRect = useCallback(() => {\n if (iframeRef.current) {\n iframeRectRef.current = iframeRef.current.getBoundingClientRect();\n }\n }, [iframeRectRef]);\n\n useEffect(() => {\n updateRect();\n window.addEventListener(\"resize\", updateRect);\n window.addEventListener(\"scroll\", updateRect, true);\n return () => {\n window.removeEventListener(\"resize\", updateRect);\n window.removeEventListener(\"scroll\", updateRect, true);\n };\n }, [updateRect]);\n\n // Periodically save iframe scroll position\n useEffect(() => {\n if (!ready) return;\n const interval = setInterval(() => {\n postToIframe({ action: \"get-scroll\" });\n }, 2000);\n return () => clearInterval(interval);\n }, [ready, postToIframe]);\n\n // Listen for postMessage from iframe\n useEffect(() => {\n function handleMessage(e: MessageEvent) {\n const data = e.data;\n if (!data || typeof data.type !== \"string\") return;\n\n if (data.type === \"ready\") {\n handleReady();\n return;\n }\n\n if (data.type === \"scroll-position\") {\n sessionStorage.setItem(\"landing-v3-iframe-scrollY\", String(data.y));\n return;\n }\n\n if (\n [\"element-selected\", \"text-edited\", \"element-deselected\", \"section-html-updated\"].includes(\n data.type\n )\n ) {\n updateRect();\n onMessage(data as IframeMessage);\n }\n }\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [onMessage, updateRect, handleReady]);\n\n return (\n <div className=\"flex-1 overflow-hidden relative\">\n <iframe\n ref={iframeRef}\n title=\"Landing preview\"\n className=\"w-full h-full border-0\"\n sandbox=\"allow-scripts allow-same-origin\"\n style={{ minHeight: \"calc(100vh - 120px)\" }}\n />\n {!ready && sections.length > 0 && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/80\">\n <span className=\"w-6 h-6 border-2 border-gray-400 border-t-gray-800 rounded-full animate-spin\" />\n </div>\n )}\n <a href=\"https://www.easybits.cloud\" target=\"_blank\" rel=\"noopener noreferrer\"\n className=\"absolute bottom-2 right-3 text-xs text-gray-400 hover:text-gray-600 transition-colors\">\n Powered by easybits.cloud\n </a>\n </div>\n );\n});\n","import React, { useRef, useState } from \"react\";\nimport type { Section3 } from \"../types\";\nimport { LANDING_THEMES, type CustomColors } from \"../themes\";\n\ninterface SectionListProps {\n sections: Section3[];\n selectedSectionId: string | null;\n theme: string;\n customColors?: CustomColors;\n onThemeChange: (themeId: string) => void;\n onCustomColorChange?: (colors: Partial<CustomColors>) => void;\n onSelect: (id: string) => void;\n onOpenCode: (id: string) => void;\n onReorder: (fromIndex: number, toIndex: number) => void;\n onDelete: (id: string) => void;\n onRename: (id: string, label: string) => void;\n onAdd: () => void;\n}\n\nexport function SectionList({\n sections,\n selectedSectionId,\n theme,\n customColors,\n onThemeChange,\n onCustomColorChange,\n onSelect,\n onOpenCode,\n onReorder,\n onDelete,\n onRename,\n onAdd,\n}: SectionListProps) {\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n const colorInputRef = useRef<HTMLInputElement>(null);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingLabel, setEditingLabel] = useState(\"\");\n\n return (\n <div className=\"flex flex-col flex-1 overflow-hidden\">\n <div className=\"p-3 border-b border-gray-200\">\n <h3 className=\"text-xs font-black uppercase tracking-wider text-gray-500 mb-2\">\n Tema\n </h3>\n <div className=\"flex gap-1.5 flex-wrap\">\n {LANDING_THEMES.map((t) => (\n <button\n key={t.id}\n onClick={() => onThemeChange(t.id)}\n title={t.label}\n className={`w-6 h-6 rounded-full border-2 transition-all ${\n theme === t.id\n ? \"border-black scale-110 shadow-sm\"\n : \"border-gray-300 hover:border-gray-400\"\n }`}\n style={{ backgroundColor: t.colors.primary }}\n />\n ))}\n {/* Custom color picker */}\n <button\n onClick={() => colorInputRef.current?.click()}\n title=\"Color personalizado\"\n className={`w-6 h-6 rounded-full border-2 transition-all relative overflow-hidden ${\n theme === \"custom\"\n ? \"border-black scale-110 shadow-sm\"\n : \"border-gray-300 hover:border-gray-400\"\n }`}\n style={theme === \"custom\" && customColors?.primary ? { backgroundColor: customColors.primary } : undefined}\n >\n {theme !== \"custom\" && (\n <span className=\"absolute inset-0 rounded-full\"\n style={{ background: \"conic-gradient(#ef4444, #eab308, #22c55e, #3b82f6, #a855f7, #ef4444)\" }}\n />\n )}\n </button>\n <input\n ref={colorInputRef}\n type=\"color\"\n value={customColors?.primary || \"#6366f1\"}\n onChange={(e) => onCustomColorChange?.({ primary: e.target.value })}\n className=\"sr-only\"\n />\n </div>\n {/* Multi-color pickers when custom theme is active */}\n {theme === \"custom\" && (\n <div className=\"flex items-center gap-2 mt-2\">\n {([\n { key: \"primary\" as const, label: \"Pri\", fallback: \"#6366f1\" },\n { key: \"secondary\" as const, label: \"Sec\", fallback: \"#f59e0b\" },\n { key: \"accent\" as const, label: \"Acc\", fallback: \"#06b6d4\" },\n { key: \"surface\" as const, label: \"Sur\", fallback: \"#ffffff\" },\n ]).map((c) => (\n <label key={c.key} className=\"flex flex-col items-center gap-0.5 cursor-pointer\">\n <input\n type=\"color\"\n value={customColors?.[c.key] || c.fallback}\n onChange={(e) => onCustomColorChange?.({ [c.key]: e.target.value })}\n className=\"w-5 h-5 rounded border border-gray-300 cursor-pointer p-0 [&::-webkit-color-swatch-wrapper]:p-0 [&::-webkit-color-swatch]:border-none [&::-webkit-color-swatch]:rounded\"\n />\n <span className=\"text-[9px] font-bold text-gray-400 uppercase\">{c.label}</span>\n </label>\n ))}\n </div>\n )}\n </div>\n <div className=\"p-3 border-b border-gray-200\">\n <h3 className=\"text-xs font-black uppercase tracking-wider text-gray-500\">\n Secciones\n </h3>\n </div>\n\n <div className=\"flex-1 overflow-y-auto py-1\">\n {sorted.map((section, i) => (\n <div\n key={section.id}\n onClick={() => onSelect(section.id)}\n className={`group flex items-center gap-2 px-3 py-2 cursor-pointer transition-colors ${\n selectedSectionId === section.id\n ? \"bg-blue-50 border-l-2 border-blue-500\"\n : \"hover:bg-gray-50 border-l-2 border-transparent\"\n }`}\n >\n <span className=\"text-[10px] font-mono text-gray-400 w-4 text-right\">\n {i + 1}\n </span>\n {editingId === section.id ? (\n <input\n type=\"text\"\n value={editingLabel}\n onChange={(e) => setEditingLabel(e.target.value)}\n onBlur={() => {\n if (editingLabel.trim()) onRename(section.id, editingLabel.trim());\n setEditingId(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n if (editingLabel.trim()) onRename(section.id, editingLabel.trim());\n setEditingId(null);\n } else if (e.key === \"Escape\") {\n setEditingId(null);\n }\n }}\n className=\"text-sm font-bold flex-1 min-w-0 bg-transparent border-b border-blue-500 outline-none px-0 py-0\"\n autoFocus\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <span\n className=\"text-sm font-bold truncate flex-1\"\n onDoubleClick={(e) => {\n e.stopPropagation();\n setEditingId(section.id);\n setEditingLabel(section.label);\n }}\n >\n {section.label}\n </span>\n )}\n <div className=\"hidden group-hover:flex gap-0.5 shrink-0\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n onOpenCode(section.id);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-700 hover:bg-gray-200\"\n title=\"Editar HTML\"\n >\n <svg className=\"w-3 h-3\" viewBox=\"0 0 16 16\" fill=\"currentColor\"><path d=\"M5.854 4.854a.5.5 0 1 0-.708-.708l-3.5 3.5a.5.5 0 0 0 0 .708l3.5 3.5a.5.5 0 0 0 .708-.708L2.707 8l3.147-3.146zm4.292 0a.5.5 0 0 1 .708-.708l3.5 3.5a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708-.708L13.293 8l-3.147-3.146z\"/></svg>\n </button>\n {i > 0 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onReorder(i, i - 1);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-700 hover:bg-gray-200 text-[10px]\"\n >\n ↑\n </button>\n )}\n {i < sorted.length - 1 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onReorder(i, i + 1);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-700 hover:bg-gray-200 text-[10px]\"\n >\n ↓\n </button>\n )}\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete(section.id);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-red-600 hover:bg-red-50 text-[10px]\"\n title=\"Eliminar seccion\"\n >\n ✕\n </button>\n </div>\n </div>\n ))}\n </div>\n\n <div className=\"p-3 border-t border-gray-200\">\n <button\n onClick={onAdd}\n className=\"w-full text-center py-2 text-sm font-bold text-blue-600 hover:bg-blue-50 rounded-lg transition-colors\"\n >\n + Agregar seccion\n </button>\n </div>\n </div>\n );\n}\n","import React, { useState, useRef, useEffect } from \"react\";\nimport { HiSparkles } from \"react-icons/hi2\";\nimport type { IframeMessage } from \"../types\";\n\nconst STYLE_PRESETS = [\n { label: \"Minimal\", icon: \"○\", instruction: \"Redisena esta seccion con estetica minimal: mucho espacio en blanco, tipografia limpia, sin bordes ni sombras innecesarias. Manten el mismo contenido.\" },\n { label: \"Cards\", icon: \"▦\", instruction: \"Redisena esta seccion usando layout de cards en grid: cada item en su propia card con padding, sombra sutil y bordes redondeados. Manten el mismo contenido.\" },\n { label: \"Bold\", icon: \"■\", instruction: \"Redisena esta seccion con estilo bold/brutalist: tipografia grande y gruesa, colores de alto contraste, bordes solidos, sin gradientes. Manten el mismo contenido.\" },\n { label: \"Glass\", icon: \"◇\", instruction: \"Redisena esta seccion con glassmorphism: fondos translucidos con backdrop-blur, bordes sutiles blancos, sombras suaves. Usa un fondo oscuro o con gradiente detras. Manten el mismo contenido.\" },\n { label: \"Dark\", icon: \"●\", instruction: \"Redisena esta seccion con fondo oscuro (#111 o similar), texto claro, acentos de color vibrantes. Manten el mismo contenido.\" },\n];\n\ninterface FloatingToolbarProps {\n selection: IframeMessage | null;\n iframeRect: DOMRect | null;\n onRefine: (instruction: string, referenceImage?: string) => void;\n onMoveUp: () => void;\n onMoveDown: () => void;\n onDelete: () => void;\n onClose: () => void;\n onViewCode: () => void;\n onUpdateAttribute?: (sectionId: string, elementPath: string, attr: string, value: string) => void;\n isRefining: boolean;\n hideStylePresets?: boolean;\n}\n\nexport function FloatingToolbar({\n selection,\n iframeRect,\n onRefine,\n onMoveUp,\n onMoveDown,\n onDelete,\n onClose,\n onViewCode,\n onUpdateAttribute,\n isRefining,\n hideStylePresets,\n}: FloatingToolbarProps) {\n const [prompt, setPrompt] = useState(\"\");\n const [showCode, setShowCode] = useState(false);\n const [refImage, setRefImage] = useState<string | null>(null);\n const [refImageName, setRefImageName] = useState<string | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const toolbarRef = useRef<HTMLDivElement>(null);\n\n // Local attr editing state\n const [imgSrc, setImgSrc] = useState(\"\");\n const [imgAlt, setImgAlt] = useState(\"\");\n const [linkHref, setLinkHref] = useState(\"\");\n\n useEffect(() => {\n setPrompt(\"\");\n setShowCode(false);\n setRefImage(null);\n setRefImageName(null);\n }, [selection?.sectionId]);\n\n // Sync attr inputs when selection changes\n useEffect(() => {\n if (selection?.attrs) {\n setImgSrc(selection.attrs.src || \"\");\n setImgAlt(selection.attrs.alt || \"\");\n setLinkHref(selection.attrs.href || \"\");\n }\n }, [selection?.attrs, selection?.elementPath]);\n\n // ESC closes toolbar\n useEffect(() => {\n function handleKey(e: KeyboardEvent) {\n if (e.key === \"Escape\") onClose();\n }\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [onClose]);\n\n if (!selection || !selection.rect || !iframeRect) return null;\n\n const toolbarWidth = toolbarRef.current?.offsetWidth || 600;\n const toolbarHeight = toolbarRef.current?.offsetHeight || 60;\n const top = iframeRect.top + selection.rect.top + selection.rect.height + 8;\n const left = iframeRect.left + selection.rect.left;\n const clampedLeft = Math.max(8, Math.min(left, window.innerWidth - toolbarWidth - 8));\n const showAbove = top + toolbarHeight + 8 > window.innerHeight;\n const finalTop = Math.max(8, showAbove\n ? iframeRect.top + selection.rect.top - toolbarHeight - 8\n : top);\n\n function handleSubmit(e: React.FormEvent) {\n e.preventDefault();\n if (!prompt.trim() || isRefining) return;\n onRefine(prompt.trim(), refImage || undefined);\n setPrompt(\"\");\n setRefImage(null);\n setRefImageName(null);\n }\n\n function handleFileSelect(e: React.ChangeEvent<HTMLInputElement>) {\n const file = e.target.files?.[0];\n if (!file) return;\n setRefImageName(file.name);\n\n const img = new Image();\n img.onload = () => {\n const MAX = 1024;\n let { width, height } = img;\n if (width > MAX || height > MAX) {\n const ratio = Math.min(MAX / width, MAX / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n canvas.getContext(\"2d\")!.drawImage(img, 0, 0, width, height);\n canvas.toBlob(\n (blob) => {\n if (!blob) return;\n const reader = new FileReader();\n reader.onload = () => setRefImage(reader.result as string);\n reader.readAsDataURL(blob);\n },\n \"image/jpeg\",\n 0.7\n );\n URL.revokeObjectURL(img.src);\n };\n img.src = URL.createObjectURL(file);\n e.target.value = \"\";\n }\n\n function handleSetAttr(attr: string, value: string) {\n if (!selection?.sectionId || !selection?.elementPath || !onUpdateAttribute) return;\n onUpdateAttribute(selection.sectionId, selection.elementPath, attr, value);\n }\n\n const isImg = selection.tagName === \"IMG\";\n const isLink = selection.tagName === \"A\";\n const hasAttrEditing = (isImg || isLink) && onUpdateAttribute;\n\n return (\n <div\n ref={toolbarRef}\n className=\"fixed z-50 flex flex-col gap-1.5 bg-gray-900 text-white rounded-xl shadow-2xl px-2 py-1.5 border border-gray-700\"\n style={{ top: finalTop, left: clampedLeft, maxWidth: \"min(600px, calc(100vw - 16px))\" }}\n >\n {/* Main row */}\n <div className=\"flex items-center gap-1.5\">\n {/* Tag badge */}\n {selection.tagName && (\n <span className=\"px-2 py-0.5 rounded-md bg-blue-600 text-[10px] font-mono font-bold uppercase tracking-wider shrink-0\">\n {selection.tagName.toLowerCase()}\n </span>\n )}\n\n {/* AI prompt input */}\n <form onSubmit={handleSubmit} className=\"flex items-center gap-1 flex-1\">\n <input\n ref={inputRef}\n type=\"text\"\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder={refImage ? \"Instruccion + imagen...\" : \"Editar con AI...\"}\n disabled={isRefining}\n className=\"bg-transparent text-sm text-white placeholder:text-gray-500 outline-none min-w-[10rem] flex-1 px-2 py-1\"\n />\n {/* Submit button */}\n <button\n type=\"submit\"\n disabled={!prompt.trim() || isRefining}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg bg-blue-500 hover:bg-blue-600 disabled:opacity-30 transition-colors shrink-0\"\n >\n {isRefining ? (\n <span className=\"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n ) : (\n <HiSparkles className=\"w-3.5 h-3.5\" />\n )}\n </button>\n {/* Image attach button */}\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isRefining}\n className={`w-7 h-7 flex items-center justify-center rounded-lg transition-colors shrink-0 ${\n refImage\n ? \"bg-blue-600 text-white\"\n : \"hover:bg-gray-800 text-gray-400 hover:text-white\"\n }`}\n title={refImage ? `Imagen: ${refImageName}` : \"Adjuntar imagen de referencia\"}\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M1 5.25A2.25 2.25 0 013.25 3h13.5A2.25 2.25 0 0119 5.25v9.5A2.25 2.25 0 0116.75 17H3.25A2.25 2.25 0 011 14.75v-9.5zm1.5 5.81V14.75c0 .414.336.75.75.75h13.5a.75.75 0 00.75-.75v-2.06l-2.22-2.22a.75.75 0 00-1.06 0L8.56 16.1l-3.28-3.28a.75.75 0 00-1.06 0l-1.72 1.72zm12-4.06a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z\" clipRule=\"evenodd\"/>\n </svg>\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n className=\"hidden\"\n />\n </form>\n\n {/* Variante button */}\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={() => {\n const tag = selection.tagName?.toLowerCase();\n const text = selection.text?.substring(0, 80);\n const prompt = selection.isSectionRoot\n ? \"Genera una variante completamente diferente de esta seccion. Manten el mismo contenido/informacion pero cambia radicalmente el layout, la estructura visual, y el estilo. Sorprendeme con un diseno creativo e inesperado.\"\n : `Modifica SOLO el elemento <${tag}> que contiene \"${text}\". Genera una variante visual diferente de ESE elemento (diferente estilo, layout, tipografia). NO modifiques ningun otro elemento de la seccion.`;\n onRefine(prompt, refImage || undefined);\n }}\n disabled={isRefining}\n className=\"px-2.5 py-1 text-[11px] font-bold rounded-lg bg-blue-600 hover:bg-blue-500 disabled:opacity-30 transition-colors whitespace-nowrap shrink-0\"\n title=\"Generar variante\"\n >\n ✦ Variante\n </button>\n\n {/* Section-level actions (move/delete) */}\n {selection.isSectionRoot && (\n <>\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={onMoveUp}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 transition-colors text-xs\"\n title=\"Mover arriba\"\n >\n ↑\n </button>\n <button\n onClick={onMoveDown}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 transition-colors text-xs\"\n title=\"Mover abajo\"\n >\n ↓\n </button>\n </>\n )}\n\n {/* View code */}\n <button\n onClick={onViewCode}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 transition-colors text-xs font-mono text-gray-400 hover:text-white\"\n title=\"Ver codigo\"\n >\n </>\n </button>\n\n {selection.isSectionRoot && (\n <>\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={onDelete}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-red-900/50 text-red-400 transition-colors\"\n title=\"Eliminar seccion\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\" />\n </svg>\n </button>\n </>\n )}\n\n {/* Close button */}\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={onClose}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 text-gray-400 hover:text-white transition-colors\"\n title=\"Cerrar (ESC)\"\n >\n ✕\n </button>\n </div>\n\n {/* Reference image preview */}\n {refImage && (\n <div className=\"flex items-center gap-2 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <img src={refImage} alt=\"Referencia\" className=\"w-10 h-10 rounded object-cover border border-gray-600\" />\n <span className=\"text-[10px] text-gray-400 truncate flex-1\">{refImageName}</span>\n <button\n onClick={() => { setRefImage(null); setRefImageName(null); }}\n className=\"text-[10px] text-gray-500 hover:text-white px-1\"\n >\n ✕\n </button>\n </div>\n )}\n\n {/* Style presets row — only for section roots */}\n {selection.isSectionRoot && !hideStylePresets && (\n <div className=\"flex items-center gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider mr-1 shrink-0\">Estilo</span>\n {STYLE_PRESETS.map((preset) => (\n <button\n key={preset.label}\n onClick={() => onRefine(preset.instruction)}\n disabled={isRefining}\n className=\"px-2 py-0.5 text-[11px] font-medium rounded-md bg-gray-800 hover:bg-gray-700 disabled:opacity-30 transition-colors whitespace-nowrap\"\n title={preset.label}\n >\n <span className=\"mr-1\">{preset.icon}</span>\n {preset.label}\n </button>\n ))}\n </div>\n )}\n\n {/* Image attr editing */}\n {isImg && hasAttrEditing && (\n <div className=\"flex flex-col gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider w-8 shrink-0\">src</span>\n <input\n type=\"text\"\n value={imgSrc}\n onChange={(e) => setImgSrc(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") handleSetAttr(\"src\", imgSrc); }}\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1 outline-none min-w-0\"\n placeholder=\"URL de imagen...\"\n />\n <button\n onClick={() => handleSetAttr(\"src\", imgSrc)}\n className=\"px-2 py-1 text-[10px] font-bold rounded bg-blue-500 hover:bg-blue-600 transition-colors shrink-0\"\n >\n Set\n </button>\n </div>\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider w-8 shrink-0\">alt</span>\n <input\n type=\"text\"\n value={imgAlt}\n onChange={(e) => setImgAlt(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") handleSetAttr(\"alt\", imgAlt); }}\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1 outline-none min-w-0\"\n placeholder=\"Alt text...\"\n />\n <button\n onClick={() => handleSetAttr(\"alt\", imgAlt)}\n className=\"px-2 py-1 text-[10px] font-bold rounded bg-blue-500 hover:bg-blue-600 transition-colors shrink-0\"\n >\n Set\n </button>\n </div>\n </div>\n )}\n\n {/* Link attr editing */}\n {isLink && hasAttrEditing && (\n <div className=\"flex items-center gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider w-8 shrink-0\">href</span>\n <input\n type=\"text\"\n value={linkHref}\n onChange={(e) => setLinkHref(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") handleSetAttr(\"href\", linkHref); }}\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1 outline-none min-w-0\"\n placeholder=\"URL del enlace...\"\n />\n <button\n onClick={() => handleSetAttr(\"href\", linkHref)}\n className=\"px-2 py-1 text-[10px] font-bold rounded bg-blue-500 hover:bg-blue-600 transition-colors shrink-0\"\n >\n Set\n </button>\n </div>\n )}\n </div>\n );\n}\n","import React, { useEffect, useRef, useCallback, useState } from \"react\";\nimport { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, Decoration, type DecorationSet } from \"@codemirror/view\";\nimport { EditorState, StateField, StateEffect } from \"@codemirror/state\";\nimport { html } from \"@codemirror/lang-html\";\nimport { oneDark } from \"@codemirror/theme-one-dark\";\nimport { defaultKeymap, indentWithTab, history, historyKeymap } from \"@codemirror/commands\";\nimport { searchKeymap, highlightSelectionMatches } from \"@codemirror/search\";\nimport { bracketMatching, foldGutter, foldKeymap } from \"@codemirror/language\";\nimport { closeBrackets, closeBracketsKeymap } from \"@codemirror/autocomplete\";\n\ninterface CodeEditorProps {\n code: string;\n label: string;\n scrollToText?: string;\n onSave: (code: string) => void;\n onClose: () => void;\n}\n\nfunction formatHtml(html: string): string {\n let result = html.replace(/>\\s*</g, \">\\n<\");\n const lines = result.split(\"\\n\");\n const output: string[] = [];\n let indent = 0;\n for (const raw of lines) {\n const line = raw.trim();\n if (!line) continue;\n const isClosing = /^<\\//.test(line);\n const isSelfClosing =\n /\\/>$/.test(line) ||\n /^<(img|br|hr|input|meta|link|col|area|base|embed|source|track|wbr)\\b/i.test(line);\n const hasInlineClose = /^<[^/][^>]*>.*<\\//.test(line);\n if (isClosing) indent = Math.max(0, indent - 1);\n output.push(\" \".repeat(indent) + line);\n if (!isClosing && !isSelfClosing && !hasInlineClose && /^<[a-zA-Z]/.test(line)) {\n indent++;\n }\n }\n return output.join(\"\\n\");\n}\n\n// Flash highlight effect for scroll-to-code\nconst flashLineEffect = StateEffect.define<{ from: number; to: number }>();\nconst clearFlashEffect = StateEffect.define<null>();\n\nconst flashLineDeco = Decoration.line({ class: \"cm-flash-line\" });\n\nconst flashLineField = StateField.define<DecorationSet>({\n create: () => Decoration.none,\n update(decos, tr) {\n for (const e of tr.effects) {\n if (e.is(flashLineEffect)) {\n return Decoration.set([flashLineDeco.range(e.value.from)]);\n }\n if (e.is(clearFlashEffect)) {\n return Decoration.none;\n }\n }\n return decos;\n },\n provide: (f) => EditorView.decorations.from(f),\n});\n\n\nfunction scrollToTarget(view: EditorView, target?: string) {\n if (!target) return;\n const docText = view.state.doc.toString();\n const normalized = target.replace(/\"/g, \"'\");\n let idx = docText.indexOf(normalized);\n if (idx === -1) idx = docText.indexOf(target);\n\n // If exact match fails, extract tag+class and search line by line\n if (idx === -1) {\n const tagMatch = target.match(/^<(\\w+)/);\n const classMatch = target.match(/class=[\"']([^\"']*?)[\"']/);\n if (tagMatch) {\n const searchTag = tagMatch[0];\n const searchClass = classMatch ? classMatch[1].split(\" \")[0] : null;\n for (let i = 1; i <= view.state.doc.lines; i++) {\n const line = view.state.doc.line(i);\n if (line.text.includes(searchTag) && (!searchClass || line.text.includes(searchClass))) {\n idx = line.from;\n break;\n }\n }\n }\n }\n\n if (idx !== -1) {\n const line = view.state.doc.lineAt(idx);\n view.dispatch({\n selection: { anchor: line.from },\n effects: [\n EditorView.scrollIntoView(line.from, { y: \"center\" }),\n flashLineEffect.of({ from: line.from, to: line.to }),\n ],\n });\n // Clear flash after 2s\n setTimeout(() => {\n view.dispatch({ effects: clearFlashEffect.of(null) });\n }, 2000);\n }\n}\n\nexport function CodeEditor({ code, label, scrollToText, onSave, onClose }: CodeEditorProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const [stats, setStats] = useState({ lines: 0, kb: \"0.0\" });\n\n const onSaveRef = useRef(onSave);\n const onCloseRef = useRef(onClose);\n onSaveRef.current = onSave;\n onCloseRef.current = onClose;\n\n const updateStats = useCallback((doc: { length: number; lines: number }) => {\n setStats({ lines: doc.lines, kb: (doc.length / 1024).toFixed(1) });\n }, []);\n\n useEffect(() => {\n if (!containerRef.current) return;\n\n const initialDoc = code.includes(\"\\n\") ? code : formatHtml(code);\n\n const state = EditorState.create({\n doc: initialDoc,\n extensions: [\n lineNumbers(),\n highlightActiveLine(),\n highlightActiveLineGutter(),\n bracketMatching(),\n closeBrackets(),\n foldGutter(),\n highlightSelectionMatches(),\n html(),\n oneDark,\n history(),\n EditorView.lineWrapping,\n keymap.of([\n { key: \"Mod-s\", run: (v) => { onSaveRef.current(v.state.doc.toString()); return true; } },\n { key: \"Escape\", run: () => { onCloseRef.current(); return true; } },\n indentWithTab,\n ...closeBracketsKeymap,\n ...searchKeymap,\n ...foldKeymap,\n ...historyKeymap,\n ...defaultKeymap,\n ]),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n updateStats(update.state.doc);\n }\n }),\n flashLineField,\n EditorView.theme({\n \"&\": { height: \"100%\", fontSize: \"13px\" },\n \".cm-scroller\": { overflow: \"auto\", fontFamily: \"ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace\" },\n \".cm-content\": { padding: \"8px 0\" },\n \".cm-gutters\": { borderRight: \"1px solid #21262d\" },\n \".cm-flash-line\": { backgroundColor: \"rgba(250, 204, 21, 0.25)\", transition: \"background-color 2s ease-out\" },\n }),\n ],\n });\n\n const view = new EditorView({ state, parent: containerRef.current });\n viewRef.current = view;\n\n updateStats(view.state.doc);\n scrollToTarget(view, scrollToText);\n view.focus();\n\n return () => { view.destroy(); };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Re-scroll when scrollToText changes while editor is already open\n useEffect(() => {\n const view = viewRef.current;\n if (!view || !scrollToText) return;\n scrollToTarget(view, scrollToText);\n }, [scrollToText]);\n\n function handleFormat() {\n const view = viewRef.current;\n if (!view) return;\n const formatted = formatHtml(view.state.doc.toString());\n view.dispatch({\n changes: { from: 0, to: view.state.doc.length, insert: formatted },\n });\n }\n\n function handleSave() {\n const view = viewRef.current;\n if (!view) return;\n onSave(view.state.doc.toString());\n }\n\n return (\n <div className=\"flex flex-col h-full bg-[#0d1117]\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-800 shrink-0\">\n <div className=\"flex items-center gap-3\">\n <span className=\"px-2 py-0.5 rounded bg-orange-600/20 text-orange-400 text-[10px] font-mono font-bold uppercase tracking-wider\">\n HTML\n </span>\n <span className=\"text-sm font-bold text-gray-300\">{label}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={handleFormat}\n className=\"px-3 py-1.5 text-xs font-bold rounded-lg bg-gray-800 text-gray-400 hover:text-white hover:bg-gray-700 transition-colors\"\n >\n Formatear\n </button>\n <button\n onClick={handleSave}\n className=\"px-4 py-1.5 text-xs font-bold rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors\"\n >\n Guardar\n </button>\n <button\n onClick={onClose}\n className=\"px-3 py-1.5 text-xs font-bold rounded-lg bg-gray-800 text-gray-400 hover:text-white hover:bg-gray-700 transition-colors\"\n >\n Cerrar\n </button>\n </div>\n </div>\n\n {/* Editor */}\n <div ref={containerRef} className=\"flex-1 overflow-hidden\" />\n\n {/* Footer */}\n <div className=\"flex items-center justify-between px-4 py-1.5 border-t border-gray-800 text-[10px] text-gray-500 font-mono shrink-0\">\n <span>{stats.lines} lineas</span>\n <span>Tab = indentar · Cmd+S = guardar · Esc = cerrar</span>\n <span>{stats.kb} KB</span>\n </div>\n </div>\n );\n}\n","import React from \"react\";\n\nexport type Viewport = \"desktop\" | \"tablet\" | \"mobile\";\n\nconst VIEWPORTS: { id: Viewport; label: string; icon: React.ReactElement }[] = [\n {\n id: \"desktop\",\n label: \"Desktop\",\n icon: (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M2 4.25A2.25 2.25 0 014.25 2h11.5A2.25 2.25 0 0118 4.25v8.5A2.25 2.25 0 0115.75 15h-3.105a3.501 3.501 0 001.1 1.677A.75.75 0 0113.26 18H6.74a.75.75 0 01-.484-1.323A3.501 3.501 0 007.355 15H4.25A2.25 2.25 0 012 12.75v-8.5zm1.5 0a.75.75 0 01.75-.75h11.5a.75.75 0 01.75.75v8.5a.75.75 0 01-.75.75H4.25a.75.75 0 01-.75-.75v-8.5z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ),\n },\n {\n id: \"tablet\",\n label: \"Tablet\",\n icon: (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M5 1a2 2 0 00-2 2v14a2 2 0 002 2h10a2 2 0 002-2V3a2 2 0 00-2-2H5zm0 1.5h10a.5.5 0 01.5.5v14a.5.5 0 01-.5.5H5a.5.5 0 01-.5-.5V3a.5.5 0 01.5-.5zm4 14a1 1 0 112 0 1 1 0 01-2 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ),\n },\n {\n id: \"mobile\",\n label: \"Mobile\",\n icon: (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M6 2a2 2 0 00-2 2v12a2 2 0 002 2h8a2 2 0 002-2V4a2 2 0 00-2-2H6zm0 1.5h8a.5.5 0 01.5.5v12a.5.5 0 01-.5.5H6a.5.5 0 01-.5-.5V4a.5.5 0 01.5-.5zm3 13a1 1 0 112 0 1 1 0 01-2 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ),\n },\n];\n\nexport function ViewportToggle({\n value,\n onChange,\n activeClass = \"bg-blue-100 text-blue-700\",\n inactiveClass = \"text-gray-400 hover:text-gray-600 hover:bg-gray-100\",\n}: {\n value: Viewport;\n onChange: (v: Viewport) => void;\n activeClass?: string;\n inactiveClass?: string;\n}) {\n return (\n <div className=\"flex items-center justify-center gap-1 py-2 shrink-0 bg-gray-50 border-b border-gray-200\">\n {VIEWPORTS.map((v) => (\n <button\n key={v.id}\n type=\"button\"\n onClick={() => onChange(v.id)}\n title={v.label}\n className={`p-1.5 rounded-lg transition-colors ${\n value === v.id ? activeClass : inactiveClass\n }`}\n >\n {v.icon}\n </button>\n ))}\n </div>\n );\n}\n"],"mappings":"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","names":["Canvas","html","useRef","useState","jsx","jsxs","useRef","useState","useState","useRef","useEffect","jsx","jsxs","prompt","useEffect","useRef","useCallback","useState","jsx","jsxs","html","jsx"]}
|
package/dist/components.d.ts
CHANGED
|
@@ -43,8 +43,9 @@ interface FloatingToolbarProps {
|
|
|
43
43
|
onViewCode: () => void;
|
|
44
44
|
onUpdateAttribute?: (sectionId: string, elementPath: string, attr: string, value: string) => void;
|
|
45
45
|
isRefining: boolean;
|
|
46
|
+
hideStylePresets?: boolean;
|
|
46
47
|
}
|
|
47
|
-
declare function FloatingToolbar({ selection, iframeRect, onRefine, onMoveUp, onMoveDown, onDelete, onClose, onViewCode, onUpdateAttribute, isRefining, }: FloatingToolbarProps): react_jsx_runtime.JSX.Element | null;
|
|
48
|
+
declare function FloatingToolbar({ selection, iframeRect, onRefine, onMoveUp, onMoveDown, onDelete, onClose, onViewCode, onUpdateAttribute, isRefining, hideStylePresets, }: FloatingToolbarProps): react_jsx_runtime.JSX.Element | null;
|
|
48
49
|
|
|
49
50
|
interface CodeEditorProps {
|
|
50
51
|
code: string;
|
package/dist/components.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easybits.cloud/html-tailwind-generator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.40",
|
|
4
4
|
"description": "AI-powered landing page generator with Tailwind CSS — canvas editor, streaming generation, and one-click deploy",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"type": "module",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Canvas.tsx","../src/components/SectionList.tsx","../src/components/FloatingToolbar.tsx","../src/components/CodeEditor.tsx","../src/components/ViewportToggle.tsx"],"sourcesContent":["import React, { useRef, useEffect, useCallback, useState, forwardRef, useImperativeHandle } from \"react\";\nimport type { Section3, IframeMessage } from \"../types\";\nimport { buildPreviewHtml } from \"../buildHtml\";\n\nexport interface CanvasHandle {\n scrollToSection: (id: string) => void;\n postMessage: (msg: Record<string, unknown>) => void;\n}\n\ninterface CanvasProps {\n sections: Section3[];\n theme?: string;\n onMessage: (msg: IframeMessage) => void;\n iframeRectRef: React.MutableRefObject<DOMRect | null>;\n onReady?: () => void;\n}\n\nexport const Canvas = forwardRef<CanvasHandle, CanvasProps>(function Canvas({ sections, theme, onMessage, iframeRectRef, onReady: onReadyProp }, ref) {\n const iframeRef = useRef<HTMLIFrameElement>(null);\n const [ready, setReady] = useState(false);\n // Track what the iframe currently has so we can diff\n const knownSectionsRef = useRef<Map<string, string>>(new Map());\n const initializedRef = useRef(false);\n const onReadyRef = useRef(onReadyProp);\n onReadyRef.current = onReadyProp;\n\n // Post a message to the iframe\n const postToIframe = useCallback((msg: Record<string, unknown>) => {\n iframeRef.current?.contentWindow?.postMessage(msg, \"*\");\n }, []);\n\n useImperativeHandle(ref, () => ({\n scrollToSection(id: string) {\n postToIframe({ action: \"scroll-to-section\", id });\n },\n postMessage(msg: Record<string, unknown>) {\n postToIframe(msg);\n },\n }), [postToIframe]);\n\n // Initial write: set up the iframe shell (empty body + script + tailwind)\n useEffect(() => {\n const iframe = iframeRef.current;\n if (!iframe || initializedRef.current) return;\n initializedRef.current = true;\n\n const html = buildPreviewHtml([]);\n const doc = iframe.contentDocument;\n if (!doc) return;\n doc.open();\n doc.write(html);\n doc.close();\n }, []);\n\n // Handle \"ready\" from iframe — then inject current sections\n const handleReady = useCallback(() => {\n setReady(true);\n // Inject all current sections\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n for (const s of sorted) {\n postToIframe({ action: \"add-section\", id: s.id, html: s.html, scroll: false });\n knownSectionsRef.current.set(s.id, s.html);\n }\n // Restore scroll position from sessionStorage\n const savedY = sessionStorage.getItem(\"landing-v3-iframe-scrollY\");\n if (savedY) {\n setTimeout(() => postToIframe({ action: \"restore-scroll\", y: Number(savedY) }), 100);\n }\n onReadyRef.current?.();\n }, [sections, postToIframe]);\n\n // Incremental diff: detect added/updated/removed sections\n useEffect(() => {\n if (!ready) return;\n\n const known = knownSectionsRef.current;\n const currentIds = new Set(sections.map((s) => s.id));\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n\n // Add new sections\n for (const s of sorted) {\n if (!known.has(s.id)) {\n postToIframe({ action: \"add-section\", id: s.id, html: s.html, scroll: true });\n known.set(s.id, s.html);\n } else if (known.get(s.id) !== s.html) {\n // Update changed sections\n postToIframe({ action: \"update-section\", id: s.id, html: s.html });\n known.set(s.id, s.html);\n }\n }\n\n // Remove deleted sections\n for (const id of known.keys()) {\n if (!currentIds.has(id)) {\n postToIframe({ action: \"remove-section\", id });\n known.delete(id);\n }\n }\n\n // Reorder if needed\n const knownOrder = [...known.keys()];\n const desiredOrder = sorted.map((s) => s.id);\n if (knownOrder.length !== desiredOrder.length || knownOrder.some((id, i) => id !== desiredOrder[i])) {\n postToIframe({ action: \"reorder-sections\", order: desiredOrder });\n }\n }, [sections, ready, postToIframe]);\n\n // Send theme changes to iframe\n useEffect(() => {\n if (!ready) return;\n postToIframe({ action: \"set-theme\", theme: theme || \"default\" });\n }, [theme, ready, postToIframe]);\n\n // Update iframe rect on resize/scroll\n const updateRect = useCallback(() => {\n if (iframeRef.current) {\n iframeRectRef.current = iframeRef.current.getBoundingClientRect();\n }\n }, [iframeRectRef]);\n\n useEffect(() => {\n updateRect();\n window.addEventListener(\"resize\", updateRect);\n window.addEventListener(\"scroll\", updateRect, true);\n return () => {\n window.removeEventListener(\"resize\", updateRect);\n window.removeEventListener(\"scroll\", updateRect, true);\n };\n }, [updateRect]);\n\n // Periodically save iframe scroll position\n useEffect(() => {\n if (!ready) return;\n const interval = setInterval(() => {\n postToIframe({ action: \"get-scroll\" });\n }, 2000);\n return () => clearInterval(interval);\n }, [ready, postToIframe]);\n\n // Listen for postMessage from iframe\n useEffect(() => {\n function handleMessage(e: MessageEvent) {\n const data = e.data;\n if (!data || typeof data.type !== \"string\") return;\n\n if (data.type === \"ready\") {\n handleReady();\n return;\n }\n\n if (data.type === \"scroll-position\") {\n sessionStorage.setItem(\"landing-v3-iframe-scrollY\", String(data.y));\n return;\n }\n\n if (\n [\"element-selected\", \"text-edited\", \"element-deselected\", \"section-html-updated\"].includes(\n data.type\n )\n ) {\n updateRect();\n onMessage(data as IframeMessage);\n }\n }\n window.addEventListener(\"message\", handleMessage);\n return () => window.removeEventListener(\"message\", handleMessage);\n }, [onMessage, updateRect, handleReady]);\n\n return (\n <div className=\"flex-1 overflow-hidden relative\">\n <iframe\n ref={iframeRef}\n title=\"Landing preview\"\n className=\"w-full h-full border-0\"\n sandbox=\"allow-scripts allow-same-origin\"\n style={{ minHeight: \"calc(100vh - 120px)\" }}\n />\n {!ready && sections.length > 0 && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white/80\">\n <span className=\"w-6 h-6 border-2 border-gray-400 border-t-gray-800 rounded-full animate-spin\" />\n </div>\n )}\n <a href=\"https://www.easybits.cloud\" target=\"_blank\" rel=\"noopener noreferrer\"\n className=\"absolute bottom-2 right-3 text-xs text-gray-400 hover:text-gray-600 transition-colors\">\n Powered by easybits.cloud\n </a>\n </div>\n );\n});\n","import React, { useRef, useState } from \"react\";\nimport type { Section3 } from \"../types\";\nimport { LANDING_THEMES, type CustomColors } from \"../themes\";\n\ninterface SectionListProps {\n sections: Section3[];\n selectedSectionId: string | null;\n theme: string;\n customColors?: CustomColors;\n onThemeChange: (themeId: string) => void;\n onCustomColorChange?: (colors: Partial<CustomColors>) => void;\n onSelect: (id: string) => void;\n onOpenCode: (id: string) => void;\n onReorder: (fromIndex: number, toIndex: number) => void;\n onDelete: (id: string) => void;\n onRename: (id: string, label: string) => void;\n onAdd: () => void;\n}\n\nexport function SectionList({\n sections,\n selectedSectionId,\n theme,\n customColors,\n onThemeChange,\n onCustomColorChange,\n onSelect,\n onOpenCode,\n onReorder,\n onDelete,\n onRename,\n onAdd,\n}: SectionListProps) {\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n const colorInputRef = useRef<HTMLInputElement>(null);\n const [editingId, setEditingId] = useState<string | null>(null);\n const [editingLabel, setEditingLabel] = useState(\"\");\n\n return (\n <div className=\"flex flex-col flex-1 overflow-hidden\">\n <div className=\"p-3 border-b border-gray-200\">\n <h3 className=\"text-xs font-black uppercase tracking-wider text-gray-500 mb-2\">\n Tema\n </h3>\n <div className=\"flex gap-1.5 flex-wrap\">\n {LANDING_THEMES.map((t) => (\n <button\n key={t.id}\n onClick={() => onThemeChange(t.id)}\n title={t.label}\n className={`w-6 h-6 rounded-full border-2 transition-all ${\n theme === t.id\n ? \"border-black scale-110 shadow-sm\"\n : \"border-gray-300 hover:border-gray-400\"\n }`}\n style={{ backgroundColor: t.colors.primary }}\n />\n ))}\n {/* Custom color picker */}\n <button\n onClick={() => colorInputRef.current?.click()}\n title=\"Color personalizado\"\n className={`w-6 h-6 rounded-full border-2 transition-all relative overflow-hidden ${\n theme === \"custom\"\n ? \"border-black scale-110 shadow-sm\"\n : \"border-gray-300 hover:border-gray-400\"\n }`}\n style={theme === \"custom\" && customColors?.primary ? { backgroundColor: customColors.primary } : undefined}\n >\n {theme !== \"custom\" && (\n <span className=\"absolute inset-0 rounded-full\"\n style={{ background: \"conic-gradient(#ef4444, #eab308, #22c55e, #3b82f6, #a855f7, #ef4444)\" }}\n />\n )}\n </button>\n <input\n ref={colorInputRef}\n type=\"color\"\n value={customColors?.primary || \"#6366f1\"}\n onChange={(e) => onCustomColorChange?.({ primary: e.target.value })}\n className=\"sr-only\"\n />\n </div>\n {/* Multi-color pickers when custom theme is active */}\n {theme === \"custom\" && (\n <div className=\"flex items-center gap-2 mt-2\">\n {([\n { key: \"primary\" as const, label: \"Pri\", fallback: \"#6366f1\" },\n { key: \"secondary\" as const, label: \"Sec\", fallback: \"#f59e0b\" },\n { key: \"accent\" as const, label: \"Acc\", fallback: \"#06b6d4\" },\n { key: \"surface\" as const, label: \"Sur\", fallback: \"#ffffff\" },\n ]).map((c) => (\n <label key={c.key} className=\"flex flex-col items-center gap-0.5 cursor-pointer\">\n <input\n type=\"color\"\n value={customColors?.[c.key] || c.fallback}\n onChange={(e) => onCustomColorChange?.({ [c.key]: e.target.value })}\n className=\"w-5 h-5 rounded border border-gray-300 cursor-pointer p-0 [&::-webkit-color-swatch-wrapper]:p-0 [&::-webkit-color-swatch]:border-none [&::-webkit-color-swatch]:rounded\"\n />\n <span className=\"text-[9px] font-bold text-gray-400 uppercase\">{c.label}</span>\n </label>\n ))}\n </div>\n )}\n </div>\n <div className=\"p-3 border-b border-gray-200\">\n <h3 className=\"text-xs font-black uppercase tracking-wider text-gray-500\">\n Secciones\n </h3>\n </div>\n\n <div className=\"flex-1 overflow-y-auto py-1\">\n {sorted.map((section, i) => (\n <div\n key={section.id}\n onClick={() => onSelect(section.id)}\n className={`group flex items-center gap-2 px-3 py-2 cursor-pointer transition-colors ${\n selectedSectionId === section.id\n ? \"bg-blue-50 border-l-2 border-blue-500\"\n : \"hover:bg-gray-50 border-l-2 border-transparent\"\n }`}\n >\n <span className=\"text-[10px] font-mono text-gray-400 w-4 text-right\">\n {i + 1}\n </span>\n {editingId === section.id ? (\n <input\n type=\"text\"\n value={editingLabel}\n onChange={(e) => setEditingLabel(e.target.value)}\n onBlur={() => {\n if (editingLabel.trim()) onRename(section.id, editingLabel.trim());\n setEditingId(null);\n }}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n if (editingLabel.trim()) onRename(section.id, editingLabel.trim());\n setEditingId(null);\n } else if (e.key === \"Escape\") {\n setEditingId(null);\n }\n }}\n className=\"text-sm font-bold flex-1 min-w-0 bg-transparent border-b border-blue-500 outline-none px-0 py-0\"\n autoFocus\n onClick={(e) => e.stopPropagation()}\n />\n ) : (\n <span\n className=\"text-sm font-bold truncate flex-1\"\n onDoubleClick={(e) => {\n e.stopPropagation();\n setEditingId(section.id);\n setEditingLabel(section.label);\n }}\n >\n {section.label}\n </span>\n )}\n <div className=\"hidden group-hover:flex gap-0.5 shrink-0\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n onOpenCode(section.id);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-700 hover:bg-gray-200\"\n title=\"Editar HTML\"\n >\n <svg className=\"w-3 h-3\" viewBox=\"0 0 16 16\" fill=\"currentColor\"><path d=\"M5.854 4.854a.5.5 0 1 0-.708-.708l-3.5 3.5a.5.5 0 0 0 0 .708l3.5 3.5a.5.5 0 0 0 .708-.708L2.707 8l3.147-3.146zm4.292 0a.5.5 0 0 1 .708-.708l3.5 3.5a.5.5 0 0 1 0 .708l-3.5 3.5a.5.5 0 0 1-.708-.708L13.293 8l-3.147-3.146z\"/></svg>\n </button>\n {i > 0 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onReorder(i, i - 1);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-700 hover:bg-gray-200 text-[10px]\"\n >\n ↑\n </button>\n )}\n {i < sorted.length - 1 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onReorder(i, i + 1);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-gray-700 hover:bg-gray-200 text-[10px]\"\n >\n ↓\n </button>\n )}\n <button\n onClick={(e) => {\n e.stopPropagation();\n onDelete(section.id);\n }}\n className=\"w-5 h-5 flex items-center justify-center rounded text-gray-400 hover:text-red-600 hover:bg-red-50 text-[10px]\"\n title=\"Eliminar seccion\"\n >\n ✕\n </button>\n </div>\n </div>\n ))}\n </div>\n\n <div className=\"p-3 border-t border-gray-200\">\n <button\n onClick={onAdd}\n className=\"w-full text-center py-2 text-sm font-bold text-blue-600 hover:bg-blue-50 rounded-lg transition-colors\"\n >\n + Agregar seccion\n </button>\n </div>\n </div>\n );\n}\n","import React, { useState, useRef, useEffect } from \"react\";\nimport { HiSparkles } from \"react-icons/hi2\";\nimport type { IframeMessage } from \"../types\";\n\nconst STYLE_PRESETS = [\n { label: \"Minimal\", icon: \"○\", instruction: \"Redisena esta seccion con estetica minimal: mucho espacio en blanco, tipografia limpia, sin bordes ni sombras innecesarias. Manten el mismo contenido.\" },\n { label: \"Cards\", icon: \"▦\", instruction: \"Redisena esta seccion usando layout de cards en grid: cada item en su propia card con padding, sombra sutil y bordes redondeados. Manten el mismo contenido.\" },\n { label: \"Bold\", icon: \"■\", instruction: \"Redisena esta seccion con estilo bold/brutalist: tipografia grande y gruesa, colores de alto contraste, bordes solidos, sin gradientes. Manten el mismo contenido.\" },\n { label: \"Glass\", icon: \"◇\", instruction: \"Redisena esta seccion con glassmorphism: fondos translucidos con backdrop-blur, bordes sutiles blancos, sombras suaves. Usa un fondo oscuro o con gradiente detras. Manten el mismo contenido.\" },\n { label: \"Dark\", icon: \"●\", instruction: \"Redisena esta seccion con fondo oscuro (#111 o similar), texto claro, acentos de color vibrantes. Manten el mismo contenido.\" },\n];\n\ninterface FloatingToolbarProps {\n selection: IframeMessage | null;\n iframeRect: DOMRect | null;\n onRefine: (instruction: string, referenceImage?: string) => void;\n onMoveUp: () => void;\n onMoveDown: () => void;\n onDelete: () => void;\n onClose: () => void;\n onViewCode: () => void;\n onUpdateAttribute?: (sectionId: string, elementPath: string, attr: string, value: string) => void;\n isRefining: boolean;\n}\n\nexport function FloatingToolbar({\n selection,\n iframeRect,\n onRefine,\n onMoveUp,\n onMoveDown,\n onDelete,\n onClose,\n onViewCode,\n onUpdateAttribute,\n isRefining,\n}: FloatingToolbarProps) {\n const [prompt, setPrompt] = useState(\"\");\n const [showCode, setShowCode] = useState(false);\n const [refImage, setRefImage] = useState<string | null>(null);\n const [refImageName, setRefImageName] = useState<string | null>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const toolbarRef = useRef<HTMLDivElement>(null);\n\n // Local attr editing state\n const [imgSrc, setImgSrc] = useState(\"\");\n const [imgAlt, setImgAlt] = useState(\"\");\n const [linkHref, setLinkHref] = useState(\"\");\n\n useEffect(() => {\n setPrompt(\"\");\n setShowCode(false);\n setRefImage(null);\n setRefImageName(null);\n }, [selection?.sectionId]);\n\n // Sync attr inputs when selection changes\n useEffect(() => {\n if (selection?.attrs) {\n setImgSrc(selection.attrs.src || \"\");\n setImgAlt(selection.attrs.alt || \"\");\n setLinkHref(selection.attrs.href || \"\");\n }\n }, [selection?.attrs, selection?.elementPath]);\n\n // ESC closes toolbar\n useEffect(() => {\n function handleKey(e: KeyboardEvent) {\n if (e.key === \"Escape\") onClose();\n }\n document.addEventListener(\"keydown\", handleKey);\n return () => document.removeEventListener(\"keydown\", handleKey);\n }, [onClose]);\n\n if (!selection || !selection.rect || !iframeRect) return null;\n\n const toolbarWidth = toolbarRef.current?.offsetWidth || 600;\n const toolbarHeight = toolbarRef.current?.offsetHeight || 60;\n const top = iframeRect.top + selection.rect.top + selection.rect.height + 8;\n const left = iframeRect.left + selection.rect.left;\n const clampedLeft = Math.max(8, Math.min(left, window.innerWidth - toolbarWidth - 8));\n const showAbove = top + toolbarHeight + 8 > window.innerHeight;\n const finalTop = Math.max(8, showAbove\n ? iframeRect.top + selection.rect.top - toolbarHeight - 8\n : top);\n\n function handleSubmit(e: React.FormEvent) {\n e.preventDefault();\n if (!prompt.trim() || isRefining) return;\n onRefine(prompt.trim(), refImage || undefined);\n setPrompt(\"\");\n setRefImage(null);\n setRefImageName(null);\n }\n\n function handleFileSelect(e: React.ChangeEvent<HTMLInputElement>) {\n const file = e.target.files?.[0];\n if (!file) return;\n setRefImageName(file.name);\n\n const img = new Image();\n img.onload = () => {\n const MAX = 1024;\n let { width, height } = img;\n if (width > MAX || height > MAX) {\n const ratio = Math.min(MAX / width, MAX / height);\n width = Math.round(width * ratio);\n height = Math.round(height * ratio);\n }\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n canvas.getContext(\"2d\")!.drawImage(img, 0, 0, width, height);\n canvas.toBlob(\n (blob) => {\n if (!blob) return;\n const reader = new FileReader();\n reader.onload = () => setRefImage(reader.result as string);\n reader.readAsDataURL(blob);\n },\n \"image/jpeg\",\n 0.7\n );\n URL.revokeObjectURL(img.src);\n };\n img.src = URL.createObjectURL(file);\n e.target.value = \"\";\n }\n\n function handleSetAttr(attr: string, value: string) {\n if (!selection?.sectionId || !selection?.elementPath || !onUpdateAttribute) return;\n onUpdateAttribute(selection.sectionId, selection.elementPath, attr, value);\n }\n\n const isImg = selection.tagName === \"IMG\";\n const isLink = selection.tagName === \"A\";\n const hasAttrEditing = (isImg || isLink) && onUpdateAttribute;\n\n return (\n <div\n ref={toolbarRef}\n className=\"fixed z-50 flex flex-col gap-1.5 bg-gray-900 text-white rounded-xl shadow-2xl px-2 py-1.5 border border-gray-700\"\n style={{ top: finalTop, left: clampedLeft, maxWidth: \"min(600px, calc(100vw - 16px))\" }}\n >\n {/* Main row */}\n <div className=\"flex items-center gap-1.5\">\n {/* Tag badge */}\n {selection.tagName && (\n <span className=\"px-2 py-0.5 rounded-md bg-blue-600 text-[10px] font-mono font-bold uppercase tracking-wider shrink-0\">\n {selection.tagName.toLowerCase()}\n </span>\n )}\n\n {/* AI prompt input */}\n <form onSubmit={handleSubmit} className=\"flex items-center gap-1 flex-1\">\n <input\n ref={inputRef}\n type=\"text\"\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder={refImage ? \"Instruccion + imagen...\" : \"Editar con AI...\"}\n disabled={isRefining}\n className=\"bg-transparent text-sm text-white placeholder:text-gray-500 outline-none min-w-[10rem] flex-1 px-2 py-1\"\n />\n {/* Submit button */}\n <button\n type=\"submit\"\n disabled={!prompt.trim() || isRefining}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg bg-blue-500 hover:bg-blue-600 disabled:opacity-30 transition-colors shrink-0\"\n >\n {isRefining ? (\n <span className=\"w-3.5 h-3.5 border-2 border-white/30 border-t-white rounded-full animate-spin\" />\n ) : (\n <HiSparkles className=\"w-3.5 h-3.5\" />\n )}\n </button>\n {/* Image attach button */}\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n disabled={isRefining}\n className={`w-7 h-7 flex items-center justify-center rounded-lg transition-colors shrink-0 ${\n refImage\n ? \"bg-blue-600 text-white\"\n : \"hover:bg-gray-800 text-gray-400 hover:text-white\"\n }`}\n title={refImage ? `Imagen: ${refImageName}` : \"Adjuntar imagen de referencia\"}\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path fillRule=\"evenodd\" d=\"M1 5.25A2.25 2.25 0 013.25 3h13.5A2.25 2.25 0 0119 5.25v9.5A2.25 2.25 0 0116.75 17H3.25A2.25 2.25 0 011 14.75v-9.5zm1.5 5.81V14.75c0 .414.336.75.75.75h13.5a.75.75 0 00.75-.75v-2.06l-2.22-2.22a.75.75 0 00-1.06 0L8.56 16.1l-3.28-3.28a.75.75 0 00-1.06 0l-1.72 1.72zm12-4.06a1.5 1.5 0 11-3 0 1.5 1.5 0 013 0z\" clipRule=\"evenodd\"/>\n </svg>\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileSelect}\n className=\"hidden\"\n />\n </form>\n\n {/* Variante button */}\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={() => {\n const tag = selection.tagName?.toLowerCase();\n const text = selection.text?.substring(0, 80);\n const prompt = selection.isSectionRoot\n ? \"Genera una variante completamente diferente de esta seccion. Manten el mismo contenido/informacion pero cambia radicalmente el layout, la estructura visual, y el estilo. Sorprendeme con un diseno creativo e inesperado.\"\n : `Modifica SOLO el elemento <${tag}> que contiene \"${text}\". Genera una variante visual diferente de ESE elemento (diferente estilo, layout, tipografia). NO modifiques ningun otro elemento de la seccion.`;\n onRefine(prompt, refImage || undefined);\n }}\n disabled={isRefining}\n className=\"px-2.5 py-1 text-[11px] font-bold rounded-lg bg-blue-600 hover:bg-blue-500 disabled:opacity-30 transition-colors whitespace-nowrap shrink-0\"\n title=\"Generar variante\"\n >\n ✦ Variante\n </button>\n\n {/* Section-level actions (move/delete) */}\n {selection.isSectionRoot && (\n <>\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={onMoveUp}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 transition-colors text-xs\"\n title=\"Mover arriba\"\n >\n ↑\n </button>\n <button\n onClick={onMoveDown}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 transition-colors text-xs\"\n title=\"Mover abajo\"\n >\n ↓\n </button>\n </>\n )}\n\n {/* View code */}\n <button\n onClick={onViewCode}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 transition-colors text-xs font-mono text-gray-400 hover:text-white\"\n title=\"Ver codigo\"\n >\n </>\n </button>\n\n {selection.isSectionRoot && (\n <>\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={onDelete}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-red-900/50 text-red-400 transition-colors\"\n title=\"Eliminar seccion\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\" />\n <path d=\"M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\" />\n </svg>\n </button>\n </>\n )}\n\n {/* Close button */}\n <div className=\"w-px h-5 bg-gray-700\" />\n <button\n onClick={onClose}\n className=\"w-7 h-7 flex items-center justify-center rounded-lg hover:bg-gray-800 text-gray-400 hover:text-white transition-colors\"\n title=\"Cerrar (ESC)\"\n >\n ✕\n </button>\n </div>\n\n {/* Reference image preview */}\n {refImage && (\n <div className=\"flex items-center gap-2 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <img src={refImage} alt=\"Referencia\" className=\"w-10 h-10 rounded object-cover border border-gray-600\" />\n <span className=\"text-[10px] text-gray-400 truncate flex-1\">{refImageName}</span>\n <button\n onClick={() => { setRefImage(null); setRefImageName(null); }}\n className=\"text-[10px] text-gray-500 hover:text-white px-1\"\n >\n ✕\n </button>\n </div>\n )}\n\n {/* Style presets row — only for section roots */}\n {selection.isSectionRoot && (\n <div className=\"flex items-center gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider mr-1 shrink-0\">Estilo</span>\n {STYLE_PRESETS.map((preset) => (\n <button\n key={preset.label}\n onClick={() => onRefine(preset.instruction)}\n disabled={isRefining}\n className=\"px-2 py-0.5 text-[11px] font-medium rounded-md bg-gray-800 hover:bg-gray-700 disabled:opacity-30 transition-colors whitespace-nowrap\"\n title={preset.label}\n >\n <span className=\"mr-1\">{preset.icon}</span>\n {preset.label}\n </button>\n ))}\n </div>\n )}\n\n {/* Image attr editing */}\n {isImg && hasAttrEditing && (\n <div className=\"flex flex-col gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider w-8 shrink-0\">src</span>\n <input\n type=\"text\"\n value={imgSrc}\n onChange={(e) => setImgSrc(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") handleSetAttr(\"src\", imgSrc); }}\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1 outline-none min-w-0\"\n placeholder=\"URL de imagen...\"\n />\n <button\n onClick={() => handleSetAttr(\"src\", imgSrc)}\n className=\"px-2 py-1 text-[10px] font-bold rounded bg-blue-500 hover:bg-blue-600 transition-colors shrink-0\"\n >\n Set\n </button>\n </div>\n <div className=\"flex items-center gap-1\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider w-8 shrink-0\">alt</span>\n <input\n type=\"text\"\n value={imgAlt}\n onChange={(e) => setImgAlt(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") handleSetAttr(\"alt\", imgAlt); }}\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1 outline-none min-w-0\"\n placeholder=\"Alt text...\"\n />\n <button\n onClick={() => handleSetAttr(\"alt\", imgAlt)}\n className=\"px-2 py-1 text-[10px] font-bold rounded bg-blue-500 hover:bg-blue-600 transition-colors shrink-0\"\n >\n Set\n </button>\n </div>\n </div>\n )}\n\n {/* Link attr editing */}\n {isLink && hasAttrEditing && (\n <div className=\"flex items-center gap-1 pt-0.5 pb-0.5 border-t border-gray-700/50\">\n <span className=\"text-[10px] text-gray-500 uppercase tracking-wider w-8 shrink-0\">href</span>\n <input\n type=\"text\"\n value={linkHref}\n onChange={(e) => setLinkHref(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") handleSetAttr(\"href\", linkHref); }}\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1 outline-none min-w-0\"\n placeholder=\"URL del enlace...\"\n />\n <button\n onClick={() => handleSetAttr(\"href\", linkHref)}\n className=\"px-2 py-1 text-[10px] font-bold rounded bg-blue-500 hover:bg-blue-600 transition-colors shrink-0\"\n >\n Set\n </button>\n </div>\n )}\n </div>\n );\n}\n","import React, { useEffect, useRef, useCallback, useState } from \"react\";\nimport { EditorView, keymap, lineNumbers, highlightActiveLine, highlightActiveLineGutter, Decoration, type DecorationSet } from \"@codemirror/view\";\nimport { EditorState, StateField, StateEffect } from \"@codemirror/state\";\nimport { html } from \"@codemirror/lang-html\";\nimport { oneDark } from \"@codemirror/theme-one-dark\";\nimport { defaultKeymap, indentWithTab, history, historyKeymap } from \"@codemirror/commands\";\nimport { searchKeymap, highlightSelectionMatches } from \"@codemirror/search\";\nimport { bracketMatching, foldGutter, foldKeymap } from \"@codemirror/language\";\nimport { closeBrackets, closeBracketsKeymap } from \"@codemirror/autocomplete\";\n\ninterface CodeEditorProps {\n code: string;\n label: string;\n scrollToText?: string;\n onSave: (code: string) => void;\n onClose: () => void;\n}\n\nfunction formatHtml(html: string): string {\n let result = html.replace(/>\\s*</g, \">\\n<\");\n const lines = result.split(\"\\n\");\n const output: string[] = [];\n let indent = 0;\n for (const raw of lines) {\n const line = raw.trim();\n if (!line) continue;\n const isClosing = /^<\\//.test(line);\n const isSelfClosing =\n /\\/>$/.test(line) ||\n /^<(img|br|hr|input|meta|link|col|area|base|embed|source|track|wbr)\\b/i.test(line);\n const hasInlineClose = /^<[^/][^>]*>.*<\\//.test(line);\n if (isClosing) indent = Math.max(0, indent - 1);\n output.push(\" \".repeat(indent) + line);\n if (!isClosing && !isSelfClosing && !hasInlineClose && /^<[a-zA-Z]/.test(line)) {\n indent++;\n }\n }\n return output.join(\"\\n\");\n}\n\n// Flash highlight effect for scroll-to-code\nconst flashLineEffect = StateEffect.define<{ from: number; to: number }>();\nconst clearFlashEffect = StateEffect.define<null>();\n\nconst flashLineDeco = Decoration.line({ class: \"cm-flash-line\" });\n\nconst flashLineField = StateField.define<DecorationSet>({\n create: () => Decoration.none,\n update(decos, tr) {\n for (const e of tr.effects) {\n if (e.is(flashLineEffect)) {\n return Decoration.set([flashLineDeco.range(e.value.from)]);\n }\n if (e.is(clearFlashEffect)) {\n return Decoration.none;\n }\n }\n return decos;\n },\n provide: (f) => EditorView.decorations.from(f),\n});\n\n\nfunction scrollToTarget(view: EditorView, target?: string) {\n if (!target) return;\n const docText = view.state.doc.toString();\n const normalized = target.replace(/\"/g, \"'\");\n let idx = docText.indexOf(normalized);\n if (idx === -1) idx = docText.indexOf(target);\n\n // If exact match fails, extract tag+class and search line by line\n if (idx === -1) {\n const tagMatch = target.match(/^<(\\w+)/);\n const classMatch = target.match(/class=[\"']([^\"']*?)[\"']/);\n if (tagMatch) {\n const searchTag = tagMatch[0];\n const searchClass = classMatch ? classMatch[1].split(\" \")[0] : null;\n for (let i = 1; i <= view.state.doc.lines; i++) {\n const line = view.state.doc.line(i);\n if (line.text.includes(searchTag) && (!searchClass || line.text.includes(searchClass))) {\n idx = line.from;\n break;\n }\n }\n }\n }\n\n if (idx !== -1) {\n const line = view.state.doc.lineAt(idx);\n view.dispatch({\n selection: { anchor: line.from },\n effects: [\n EditorView.scrollIntoView(line.from, { y: \"center\" }),\n flashLineEffect.of({ from: line.from, to: line.to }),\n ],\n });\n // Clear flash after 2s\n setTimeout(() => {\n view.dispatch({ effects: clearFlashEffect.of(null) });\n }, 2000);\n }\n}\n\nexport function CodeEditor({ code, label, scrollToText, onSave, onClose }: CodeEditorProps) {\n const containerRef = useRef<HTMLDivElement>(null);\n const viewRef = useRef<EditorView | null>(null);\n const [stats, setStats] = useState({ lines: 0, kb: \"0.0\" });\n\n const onSaveRef = useRef(onSave);\n const onCloseRef = useRef(onClose);\n onSaveRef.current = onSave;\n onCloseRef.current = onClose;\n\n const updateStats = useCallback((doc: { length: number; lines: number }) => {\n setStats({ lines: doc.lines, kb: (doc.length / 1024).toFixed(1) });\n }, []);\n\n useEffect(() => {\n if (!containerRef.current) return;\n\n const initialDoc = code.includes(\"\\n\") ? code : formatHtml(code);\n\n const state = EditorState.create({\n doc: initialDoc,\n extensions: [\n lineNumbers(),\n highlightActiveLine(),\n highlightActiveLineGutter(),\n bracketMatching(),\n closeBrackets(),\n foldGutter(),\n highlightSelectionMatches(),\n html(),\n oneDark,\n history(),\n EditorView.lineWrapping,\n keymap.of([\n { key: \"Mod-s\", run: (v) => { onSaveRef.current(v.state.doc.toString()); return true; } },\n { key: \"Escape\", run: () => { onCloseRef.current(); return true; } },\n indentWithTab,\n ...closeBracketsKeymap,\n ...searchKeymap,\n ...foldKeymap,\n ...historyKeymap,\n ...defaultKeymap,\n ]),\n EditorView.updateListener.of((update) => {\n if (update.docChanged) {\n updateStats(update.state.doc);\n }\n }),\n flashLineField,\n EditorView.theme({\n \"&\": { height: \"100%\", fontSize: \"13px\" },\n \".cm-scroller\": { overflow: \"auto\", fontFamily: \"ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace\" },\n \".cm-content\": { padding: \"8px 0\" },\n \".cm-gutters\": { borderRight: \"1px solid #21262d\" },\n \".cm-flash-line\": { backgroundColor: \"rgba(250, 204, 21, 0.25)\", transition: \"background-color 2s ease-out\" },\n }),\n ],\n });\n\n const view = new EditorView({ state, parent: containerRef.current });\n viewRef.current = view;\n\n updateStats(view.state.doc);\n scrollToTarget(view, scrollToText);\n view.focus();\n\n return () => { view.destroy(); };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Re-scroll when scrollToText changes while editor is already open\n useEffect(() => {\n const view = viewRef.current;\n if (!view || !scrollToText) return;\n scrollToTarget(view, scrollToText);\n }, [scrollToText]);\n\n function handleFormat() {\n const view = viewRef.current;\n if (!view) return;\n const formatted = formatHtml(view.state.doc.toString());\n view.dispatch({\n changes: { from: 0, to: view.state.doc.length, insert: formatted },\n });\n }\n\n function handleSave() {\n const view = viewRef.current;\n if (!view) return;\n onSave(view.state.doc.toString());\n }\n\n return (\n <div className=\"flex flex-col h-full bg-[#0d1117]\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-gray-800 shrink-0\">\n <div className=\"flex items-center gap-3\">\n <span className=\"px-2 py-0.5 rounded bg-orange-600/20 text-orange-400 text-[10px] font-mono font-bold uppercase tracking-wider\">\n HTML\n </span>\n <span className=\"text-sm font-bold text-gray-300\">{label}</span>\n </div>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={handleFormat}\n className=\"px-3 py-1.5 text-xs font-bold rounded-lg bg-gray-800 text-gray-400 hover:text-white hover:bg-gray-700 transition-colors\"\n >\n Formatear\n </button>\n <button\n onClick={handleSave}\n className=\"px-4 py-1.5 text-xs font-bold rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors\"\n >\n Guardar\n </button>\n <button\n onClick={onClose}\n className=\"px-3 py-1.5 text-xs font-bold rounded-lg bg-gray-800 text-gray-400 hover:text-white hover:bg-gray-700 transition-colors\"\n >\n Cerrar\n </button>\n </div>\n </div>\n\n {/* Editor */}\n <div ref={containerRef} className=\"flex-1 overflow-hidden\" />\n\n {/* Footer */}\n <div className=\"flex items-center justify-between px-4 py-1.5 border-t border-gray-800 text-[10px] text-gray-500 font-mono shrink-0\">\n <span>{stats.lines} lineas</span>\n <span>Tab = indentar · Cmd+S = guardar · Esc = cerrar</span>\n <span>{stats.kb} KB</span>\n </div>\n </div>\n );\n}\n","import React from \"react\";\n\nexport type Viewport = \"desktop\" | \"tablet\" | \"mobile\";\n\nconst VIEWPORTS: { id: Viewport; label: string; icon: React.ReactElement }[] = [\n {\n id: \"desktop\",\n label: \"Desktop\",\n icon: (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M2 4.25A2.25 2.25 0 014.25 2h11.5A2.25 2.25 0 0118 4.25v8.5A2.25 2.25 0 0115.75 15h-3.105a3.501 3.501 0 001.1 1.677A.75.75 0 0113.26 18H6.74a.75.75 0 01-.484-1.323A3.501 3.501 0 007.355 15H4.25A2.25 2.25 0 012 12.75v-8.5zm1.5 0a.75.75 0 01.75-.75h11.5a.75.75 0 01.75.75v8.5a.75.75 0 01-.75.75H4.25a.75.75 0 01-.75-.75v-8.5z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ),\n },\n {\n id: \"tablet\",\n label: \"Tablet\",\n icon: (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M5 1a2 2 0 00-2 2v14a2 2 0 002 2h10a2 2 0 002-2V3a2 2 0 00-2-2H5zm0 1.5h10a.5.5 0 01.5.5v14a.5.5 0 01-.5.5H5a.5.5 0 01-.5-.5V3a.5.5 0 01.5-.5zm4 14a1 1 0 112 0 1 1 0 01-2 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ),\n },\n {\n id: \"mobile\",\n label: \"Mobile\",\n icon: (\n <svg className=\"w-4 h-4\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\n <path\n fillRule=\"evenodd\"\n d=\"M6 2a2 2 0 00-2 2v12a2 2 0 002 2h8a2 2 0 002-2V4a2 2 0 00-2-2H6zm0 1.5h8a.5.5 0 01.5.5v12a.5.5 0 01-.5.5H6a.5.5 0 01-.5-.5V4a.5.5 0 01.5-.5zm3 13a1 1 0 112 0 1 1 0 01-2 0z\"\n clipRule=\"evenodd\"\n />\n </svg>\n ),\n },\n];\n\nexport function ViewportToggle({\n value,\n onChange,\n activeClass = \"bg-blue-100 text-blue-700\",\n inactiveClass = \"text-gray-400 hover:text-gray-600 hover:bg-gray-100\",\n}: {\n value: Viewport;\n onChange: (v: Viewport) => void;\n activeClass?: string;\n inactiveClass?: string;\n}) {\n return (\n <div className=\"flex items-center justify-center gap-1 py-2 shrink-0 bg-gray-50 border-b border-gray-200\">\n {VIEWPORTS.map((v) => (\n <button\n key={v.id}\n type=\"button\"\n onClick={() => onChange(v.id)}\n title={v.label}\n className={`p-1.5 rounded-lg transition-colors ${\n value === v.id ? activeClass : inactiveClass\n }`}\n >\n {v.icon}\n </button>\n ))}\n </div>\n );\n}\n"],"mappings":"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","names":["Canvas","html","useRef","useState","jsx","jsxs","useRef","useState","useState","useRef","useEffect","jsx","jsxs","prompt","useEffect","useRef","useCallback","useState","jsx","jsxs","html","jsx"]}
|