@easybits.cloud/html-tailwind-generator 0.2.143 → 0.2.144

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildPreviewHtml
3
- } from "./chunk-7MGKYJTI.js";
3
+ } from "./chunk-XDJMUIKY.js";
4
4
  import {
5
5
  LANDING_THEMES
6
6
  } from "./chunk-DCAQAHSU.js";
@@ -1368,4 +1368,4 @@ export {
1368
1368
  ViewportToggle,
1369
1369
  useUndoStack
1370
1370
  };
1371
- //# sourceMappingURL=chunk-EP65R6DE.js.map
1371
+ //# sourceMappingURL=chunk-CZSPAIBQ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildDeployHtml
3
- } from "./chunk-7MGKYJTI.js";
3
+ } from "./chunk-XDJMUIKY.js";
4
4
 
5
5
  // src/deploy.ts
6
6
  async function deployToS3(options) {
@@ -39,4 +39,4 @@ export {
39
39
  deployToS3,
40
40
  deployToEasyBits
41
41
  };
42
- //# sourceMappingURL=chunk-SJJZEW5W.js.map
42
+ //# sourceMappingURL=chunk-FOTINBTC.js.map
@@ -70,9 +70,9 @@ function getIframeScript() {
70
70
 
71
71
  function emitElementSelected(el) {
72
72
  var rect = el.getBoundingClientRect();
73
- var attrs = {};
74
- if (el.tagName === 'IMG') attrs = { src: el.getAttribute('src') || '', alt: el.getAttribute('alt') || '' };
75
- if (el.tagName === 'A') attrs = { href: el.getAttribute('href') || '', target: el.getAttribute('target') || '' };
73
+ var attrs = { style: el.getAttribute('style') || '' };
74
+ if (el.tagName === 'IMG') { attrs.src = el.getAttribute('src') || ''; attrs.alt = el.getAttribute('alt') || ''; }
75
+ if (el.tagName === 'A') { attrs.href = el.getAttribute('href') || ''; attrs.target = el.getAttribute('target') || ''; }
76
76
  var ot = el.outerHTML.split('>')[0] + '>';
77
77
  if (ot.length > 200) ot = ot.substring(0, 200);
78
78
  window.parent.postMessage({
@@ -149,15 +149,18 @@ function getIframeScript() {
149
149
  el.style.boxShadow = SHADOW_SELECTED;
150
150
 
151
151
  var rect = el.getBoundingClientRect();
152
- var attrs = {};
152
+ var attrs = { style: el.getAttribute('style') || '' };
153
153
  if (el.tagName === 'IMG') {
154
- attrs = { src: el.getAttribute('src') || '', alt: el.getAttribute('alt') || '' };
154
+ attrs.src = el.getAttribute('src') || '';
155
+ attrs.alt = el.getAttribute('alt') || '';
155
156
  }
156
157
  if (el.tagName === 'A') {
157
- attrs = { href: el.getAttribute('href') || '', target: el.getAttribute('target') || '' };
158
+ attrs.href = el.getAttribute('href') || '';
159
+ attrs.target = el.getAttribute('target') || '';
158
160
  }
159
161
 
160
- window.parent.postMessage({
162
+ var clickClassName = (typeof el.className === 'string' ? el.className : '') || '';
163
+ var clickPayload = {
161
164
  type: 'element-selected',
162
165
  sectionId: getSectionId(el),
163
166
  tagName: el.tagName,
@@ -167,8 +170,10 @@ function getIframeScript() {
167
170
  elementPath: getElementPath(el),
168
171
  isSectionRoot: el.dataset && el.dataset.sectionId ? true : false,
169
172
  attrs: attrs,
170
- className: el.className || '',
171
- }, '*');
173
+ className: clickClassName,
174
+ };
175
+ console.log('[share/iframe] selected', { tag: el.tagName, className: clickClassName, path: clickPayload.elementPath });
176
+ window.parent.postMessage(clickPayload, '*');
172
177
  }, true);
173
178
 
174
179
  // Double-click \u2014 contentEditable for text
@@ -288,9 +293,13 @@ function getIframeScript() {
288
293
  }
289
294
  }
290
295
  }
296
+ console.log('[share/iframe] update-attribute', { sectionId: msg.sectionId, attr: msg.attr, value: msg.value, found: !!target });
291
297
  if (target) {
292
- if (msg.attr === 'style' && msg.value.indexOf(':') !== -1) {
293
- // Merge style property instead of replacing entire style
298
+ // For style: single-property values ("color: #abc") merge via setProperty so other
299
+ // inline styles survive (FloatingToolbar relies on this). Multi-prop or empty values
300
+ // replace the whole style attribute atomically (used by ShareInspector after stripInlineProps).
301
+ if (msg.attr === 'style' && typeof msg.value === 'string'
302
+ && msg.value.indexOf(':') !== -1 && msg.value.indexOf(';') === -1) {
294
303
  var parts = msg.value.split(':');
295
304
  var prop = parts[0].trim();
296
305
  var val = parts.slice(1).join(':').trim();
@@ -633,4 +642,4 @@ export {
633
642
  buildPreviewHtml,
634
643
  buildDeployHtml
635
644
  };
636
- //# sourceMappingURL=chunk-7MGKYJTI.js.map
645
+ //# sourceMappingURL=chunk-XDJMUIKY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/iframeScript.ts","../src/buildHtml.ts"],"sourcesContent":["/**\n * JavaScript injected into the landing v3 iframe.\n * Handles hover highlights, click selection, contentEditable text editing,\n * postMessage communication with the parent editor,\n * and incremental section injection from parent.\n */\nexport function getIframeScript(): string {\n return `\n(function() {\n let hoveredEl = null;\n let selectedEl = null;\n const SHADOW_HOVER = 'inset 0 0 0 2px #3B82F6';\n const SHADOW_SELECTED = 'inset 0 0 0 2px #8B5CF6';\n\n function getSectionId(el) {\n let node = el;\n while (node && node !== document.body) {\n if (node.dataset && node.dataset.sectionId) {\n return node.dataset.sectionId;\n }\n node = node.parentElement;\n }\n return null;\n }\n\n function getSectionElement(sectionId) {\n return document.querySelector('[data-section-id=\"' + sectionId + '\"]');\n }\n\n function getElementPath(el) {\n const parts = [];\n let node = el;\n while (node && node !== document.body) {\n let tag = node.tagName.toLowerCase();\n if (node.id) { tag += '#' + node.id; }\n const siblings = node.parentElement ? Array.from(node.parentElement.children).filter(function(c) { return c.tagName === node.tagName; }) : [];\n if (siblings.length > 1) { tag += ':nth(' + siblings.indexOf(node) + ')'; }\n parts.unshift(tag);\n node = node.parentElement;\n }\n return parts.join(' > ');\n }\n\n function getCleanSectionHtml(sectionEl) {\n var els = sectionEl.querySelectorAll('*');\n var saved = [];\n for (var i = 0; i < els.length; i++) {\n var s = els[i].style;\n saved.push({ boxShadow: s.boxShadow, ce: els[i].contentEditable });\n s.boxShadow = '';\n if (els[i].contentEditable === 'true') els[i].removeAttribute('contenteditable');\n }\n // Also clean the section root\n var rootShadow = sectionEl.style.boxShadow;\n sectionEl.style.boxShadow = '';\n var html = sectionEl.innerHTML;\n sectionEl.style.boxShadow = rootShadow;\n for (var i = 0; i < els.length; i++) {\n els[i].style.boxShadow = saved[i].boxShadow;\n if (saved[i].ce === 'true') els[i].contentEditable = 'true';\n }\n return html;\n }\n\n function isTextElement(el) {\n var textTags = ['H1','H2','H3','H4','H5','H6','P','DIV','SPAN','LI','A','BLOCKQUOTE','LABEL','TD','TH','FIGCAPTION','BUTTON'];\n return textTags.indexOf(el.tagName) !== -1;\n }\n\n function emitElementSelected(el) {\n var rect = el.getBoundingClientRect();\n var attrs = { style: el.getAttribute('style') || '' };\n if (el.tagName === 'IMG') { attrs.src = el.getAttribute('src') || ''; attrs.alt = el.getAttribute('alt') || ''; }\n if (el.tagName === 'A') { attrs.href = el.getAttribute('href') || ''; attrs.target = el.getAttribute('target') || ''; }\n var ot = el.outerHTML.split('>')[0] + '>';\n if (ot.length > 200) ot = ot.substring(0, 200);\n window.parent.postMessage({\n type: 'element-selected',\n sectionId: getSectionId(el),\n tagName: el.tagName,\n rect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n text: (el.textContent || '').substring(0, 200),\n openTag: ot,\n elementPath: getElementPath(el),\n isSectionRoot: el.dataset && el.dataset.sectionId ? true : false,\n attrs: attrs,\n className: (typeof el.className === 'string' ? el.className : '') || '',\n }, '*');\n }\n\n // Hover\n document.addEventListener('mouseover', function(e) {\n var el = e.target;\n while (el && el !== document.body && (el instanceof SVGElement) && el.tagName !== 'svg') {\n el = el.parentElement;\n }\n if (el && el.tagName === 'svg' && el.parentElement) el = el.parentElement;\n if (el === document.body || el === document.documentElement) return;\n if (el === selectedEl) return;\n if (hoveredEl && hoveredEl !== selectedEl) {\n hoveredEl.style.boxShadow = '';\n }\n hoveredEl = el;\n if (el !== selectedEl) {\n el.style.boxShadow = SHADOW_HOVER;\n }\n });\n\n document.addEventListener('mouseout', function(e) {\n if (hoveredEl && hoveredEl !== selectedEl) {\n hoveredEl.style.boxShadow = '';\n }\n hoveredEl = null;\n });\n\n // Click — select element\n document.addEventListener('click', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var el = e.target;\n\n // Bubble up from SVG internals to the nearest HTML element\n while (el && el !== document.body && (el instanceof SVGElement) && el.tagName !== 'svg') {\n el = el.parentElement;\n }\n // If we landed on an <svg>, bubble up to its HTML parent\n if (el && el.tagName === 'svg' && el.parentElement) {\n el = el.parentElement;\n }\n\n // Deselect previous\n if (selectedEl) {\n selectedEl.style.boxShadow = '';\n }\n\n if (selectedEl === el) {\n selectedEl = null;\n window.parent.postMessage({ type: 'element-deselected' }, '*');\n return;\n }\n\n selectedEl = el;\n\n // Clear hover styles BEFORE capturing openTag (so it matches source HTML)\n el.style.boxShadow = '';\n var openTag = el.outerHTML.substring(0, el.outerHTML.indexOf('>') + 1).substring(0, 120);\n\n el.style.boxShadow = SHADOW_SELECTED;\n\n var rect = el.getBoundingClientRect();\n var attrs = { style: el.getAttribute('style') || '' };\n if (el.tagName === 'IMG') {\n attrs.src = el.getAttribute('src') || '';\n attrs.alt = el.getAttribute('alt') || '';\n }\n if (el.tagName === 'A') {\n attrs.href = el.getAttribute('href') || '';\n attrs.target = el.getAttribute('target') || '';\n }\n\n var clickClassName = (typeof el.className === 'string' ? el.className : '') || '';\n var clickPayload = {\n type: 'element-selected',\n sectionId: getSectionId(el),\n tagName: el.tagName,\n rect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n text: (el.textContent || '').substring(0, 200),\n openTag: openTag,\n elementPath: getElementPath(el),\n isSectionRoot: el.dataset && el.dataset.sectionId ? true : false,\n attrs: attrs,\n className: clickClassName,\n };\n console.log('[share/iframe] selected', { tag: el.tagName, className: clickClassName, path: clickPayload.elementPath });\n window.parent.postMessage(clickPayload, '*');\n }, true);\n\n // Double-click — contentEditable for text\n document.addEventListener('dblclick', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var el = e.target;\n if (!isTextElement(el)) return;\n\n el.contentEditable = 'true';\n el.focus();\n el.style.boxShadow = 'inset 0 0 0 2px #F59E0B';\n\n function onBlur() {\n el.contentEditable = 'false';\n el.style.boxShadow = '';\n el.removeEventListener('blur', onBlur);\n el.removeEventListener('keydown', onKeydown);\n\n var sid = getSectionId(el);\n var sectionEl = sid ? getSectionElement(sid) : null;\n window.parent.postMessage({\n type: 'text-edited',\n sectionId: sid,\n elementPath: getElementPath(el),\n newText: el.innerHTML,\n sectionHtml: sectionEl ? getCleanSectionHtml(sectionEl) : null,\n }, '*');\n\n selectedEl = null;\n }\n\n function onKeydown(ev) {\n if (ev.key === 'Escape') {\n el.blur();\n }\n }\n\n el.addEventListener('blur', onBlur);\n el.addEventListener('keydown', onKeydown);\n }, true);\n\n // Listen for messages FROM parent (incremental section injection)\n window.addEventListener('message', function(e) {\n var msg = e.data;\n if (!msg || !msg.action) return;\n\n if (msg.action === 'add-section') {\n var wrapper = document.createElement('div');\n wrapper.setAttribute('data-section-id', msg.id);\n wrapper.innerHTML = msg.html;\n wrapper.style.animation = 'fadeInUp 0.4s ease-out';\n document.body.appendChild(wrapper);\n if (msg.scroll) {\n wrapper.scrollIntoView({ behavior: 'smooth', block: 'end' });\n }\n }\n\n if (msg.action === 'update-section') {\n var el = getSectionElement(msg.id);\n if (el && typeof window.morphdom === 'function') {\n var tmp = document.createElement('div');\n tmp.innerHTML = msg.html;\n window.morphdom(el, tmp, {\n childrenOnly: true,\n onBeforeElUpdated: function(fromEl, toEl) {\n if (fromEl.isEqualNode(toEl)) return false;\n return true;\n }\n });\n } else if (el) {\n el.innerHTML = msg.html;\n }\n }\n\n if (msg.action === 'rename-section') {\n var el = getSectionElement(msg.oldId);\n if (el) {\n el.setAttribute('data-section-id', msg.newId);\n if (msg.html) {\n if (typeof window.morphdom === 'function') {\n var tmp = document.createElement('div');\n tmp.innerHTML = msg.html;\n window.morphdom(el, tmp, { childrenOnly: true, onBeforeElUpdated: function(f,t){ return !f.isEqualNode(t); } });\n } else {\n el.innerHTML = msg.html;\n }\n }\n }\n }\n\n if (msg.action === 'remove-section') {\n var el = getSectionElement(msg.id);\n if (el) { el.remove(); }\n }\n\n if (msg.action === 'reorder-sections') {\n // msg.order = [id1, id2, id3, ...]\n var order = msg.order;\n for (var i = 0; i < order.length; i++) {\n var el = getSectionElement(order[i]);\n if (el) { document.body.appendChild(el); }\n }\n }\n\n if (msg.action === 'update-attribute') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl) {\n var target = null;\n if (msg.elementPath) {\n // Find element by matching path\n var allEls = sectionEl.querySelectorAll(msg.tagName || '*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n }\n console.log('[share/iframe] update-attribute', { sectionId: msg.sectionId, attr: msg.attr, value: msg.value, found: !!target });\n if (target) {\n // For style: single-property values (\"color: #abc\") merge via setProperty so other\n // inline styles survive (FloatingToolbar relies on this). Multi-prop or empty values\n // replace the whole style attribute atomically (used by ShareInspector after stripInlineProps).\n if (msg.attr === 'style' && typeof msg.value === 'string'\n && msg.value.indexOf(':') !== -1 && msg.value.indexOf(';') === -1) {\n var parts = msg.value.split(':');\n var prop = parts[0].trim();\n var val = parts.slice(1).join(':').trim();\n target.style.setProperty(prop, val);\n } else {\n target.setAttribute(msg.attr, msg.value);\n }\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n emitElementSelected(target);\n }\n }\n }\n\n if (msg.action === 'replace-class') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath) {\n var target = null;\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n if (target) {\n // Remove classes matching prefixes (supports responsive variants like md:p-4)\n var prefixes = msg.removePrefixes || [];\n var toRemove = [];\n for (var ci = 0; ci < target.classList.length; ci++) {\n var cls = target.classList[ci];\n var bare = cls.indexOf(':') !== -1 ? cls.substring(cls.lastIndexOf(':') + 1) : cls;\n for (var pi = 0; pi < prefixes.length; pi++) {\n if (bare === prefixes[pi] || bare.indexOf(prefixes[pi]) === 0) {\n toRemove.push(cls);\n break;\n }\n }\n }\n for (var ri = 0; ri < toRemove.length; ri++) {\n target.classList.remove(toRemove[ri]);\n }\n // Add new class\n if (msg.addClass && !target.classList.contains(msg.addClass)) {\n target.classList.add(msg.addClass);\n }\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n emitElementSelected(target);\n }\n }\n }\n\n if (msg.action === 'delete-element') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath) {\n var target = null;\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n if (target && target.parentNode) {\n target.parentNode.removeChild(target);\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n window.parent.postMessage({ type: 'element-deselected' }, '*');\n }\n }\n }\n\n if (msg.action === 'change-tag') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath && msg.newTag) {\n var target = null;\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n if (target && target.parentNode) {\n var newEl = document.createElement(msg.newTag);\n for (var a = 0; a < target.attributes.length; a++) {\n newEl.setAttribute(target.attributes[a].name, target.attributes[a].value);\n }\n while (target.firstChild) newEl.appendChild(target.firstChild);\n target.parentNode.replaceChild(newEl, target);\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n emitElementSelected(newEl);\n }\n }\n }\n\n if (msg.action === 'set-theme') {\n if (msg.theme && msg.theme !== 'default') {\n document.documentElement.setAttribute('data-theme', msg.theme);\n } else {\n document.documentElement.removeAttribute('data-theme');\n }\n }\n\n if (msg.action === 'set-custom-css') {\n var customStyle = document.getElementById('custom-theme-css');\n if (!customStyle) {\n customStyle = document.createElement('style');\n customStyle.id = 'custom-theme-css';\n document.head.appendChild(customStyle);\n }\n customStyle.textContent = msg.css || '';\n }\n\n if (msg.action === 'scroll-to-section') {\n var el = getSectionElement(msg.id);\n if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }\n }\n\n if (msg.action === 'get-scroll') {\n window.parent.postMessage({ type: 'scroll-position', y: window.scrollY }, '*');\n }\n\n if (msg.action === 'restore-scroll') {\n window.scrollTo(0, msg.y);\n }\n\n if (msg.action === 'element-loading') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath) {\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n var el = allEls[i];\n el.style.position = 'relative';\n el.style.overflow = 'hidden';\n var overlay = document.createElement('div');\n overlay.setAttribute('data-loading-overlay', 'true');\n overlay.style.cssText = 'position:absolute;inset:0;z-index:999;border-radius:inherit;background:linear-gradient(90deg,rgba(255,255,255,0) 0%,rgba(255,255,255,0.6) 50%,rgba(255,255,255,0) 100%);background-size:200% 100%;animation:shimmer 1.5s infinite;pointer-events:none;';\n el.appendChild(overlay);\n break;\n }\n }\n }\n }\n\n if (msg.action === 'element-loading-clear') {\n var overlays = document.querySelectorAll('[data-loading-overlay]');\n for (var i = 0; i < overlays.length; i++) {\n overlays[i].remove();\n }\n }\n\n if (msg.action === 'preview-version') {\n var el = getSectionElement(msg.sectionId);\n if (el) {\n // Store original html if not already stored\n if (!el.dataset.originalHtml) {\n el.dataset.originalHtml = el.innerHTML;\n }\n el.innerHTML = msg.html;\n el.style.outline = '2px dashed #8B5CF6';\n el.style.outlineOffset = '-2px';\n el.style.opacity = '0.85';\n }\n }\n\n if (msg.action === 'exit-preview') {\n var el = getSectionElement(msg.sectionId);\n if (el && el.dataset.originalHtml) {\n el.innerHTML = el.dataset.originalHtml;\n delete el.dataset.originalHtml;\n el.style.outline = '';\n el.style.outlineOffset = '';\n el.style.opacity = '';\n }\n }\n\n if (msg.action === 'full-rewrite') {\n // Fallback: rewrite everything\n document.body.innerHTML = msg.html;\n }\n });\n\n // Forward Cmd/Ctrl+Z undo/redo to parent (iframe captures keyboard focus)\n document.addEventListener('keydown', function(e) {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'z') {\n e.preventDefault();\n window.parent.postMessage({ type: e.shiftKey ? 'redo' : 'undo' }, '*');\n }\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'y') {\n e.preventDefault();\n window.parent.postMessage({ type: 'redo' }, '*');\n }\n });\n\n // Image loading placeholders\n function setupImagePlaceholder(img) {\n if (img.complete && img.naturalWidth > 0) return;\n img.style.background = 'linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%)';\n img.style.backgroundSize = '200% 100%';\n img.style.animation = 'shimmer 1.5s infinite';\n if (!img.style.minHeight && !img.getAttribute('height')) img.style.minHeight = '120px';\n function onDone() {\n img.style.background = '';\n img.style.backgroundSize = '';\n img.style.animation = '';\n if (img.style.minHeight === '120px') img.style.minHeight = '';\n img.removeEventListener('load', onDone);\n img.removeEventListener('error', onDone);\n }\n img.addEventListener('load', onDone);\n img.addEventListener('error', onDone);\n }\n // Observe new/changed images\n var imgObserver = new MutationObserver(function(mutations) {\n for (var m = 0; m < mutations.length; m++) {\n // New nodes\n for (var n = 0; n < mutations[m].addedNodes.length; n++) {\n var node = mutations[m].addedNodes[n];\n if (node.tagName === 'IMG') setupImagePlaceholder(node);\n if (node.querySelectorAll) {\n var imgs = node.querySelectorAll('img');\n for (var i = 0; i < imgs.length; i++) setupImagePlaceholder(imgs[i]);\n }\n }\n // src attribute changed\n if (mutations[m].type === 'attributes' && mutations[m].attributeName === 'src' && mutations[m].target.tagName === 'IMG') {\n setupImagePlaceholder(mutations[m].target);\n }\n }\n });\n imgObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });\n // Initial images\n var existingImgs = document.querySelectorAll('img');\n for (var ii = 0; ii < existingImgs.length; ii++) setupImagePlaceholder(existingImgs[ii]);\n\n // Inject animation keyframes\n var style = document.createElement('style');\n style.textContent = '@keyframes fadeInUp { from { opacity:0; transform:translateY(20px); } to { opacity:1; transform:translateY(0); } } @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }';\n document.head.appendChild(style);\n\n // Notify parent we're ready\n window.parent.postMessage({ type: 'ready' }, '*');\n})();\n`;\n}\n","import type { Section3 } from \"./types\";\nimport { getIframeScript } from \"./iframeScript\";\nimport { buildThemeCss, buildSingleThemeCss, buildCustomTheme, type CustomColors } from \"./themes\";\n\n/**\n * Build the full HTML for the iframe preview (with editing script).\n */\nexport function buildPreviewHtml(sections: Section3[], theme?: string): string {\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n const body = sorted\n .map((s) => `<div data-section-id=\"${s.id}\">${s.html}</div>`)\n .join(\"\\n\");\n\n const dataTheme = theme && theme !== \"default\" ? ` data-theme=\"${theme}\"` : \"\";\n const { css, tailwindConfig } = buildThemeCss();\n\n return `<!DOCTYPE html>\n<html lang=\"es\"${dataTheme}>\n<head>\n<meta charset=\"UTF-8\"/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n<script src=\"https://cdn.tailwindcss.com\"></script>\n<script src=\"https://unpkg.com/morphdom@2.7.4/dist/morphdom-umd.min.js\"></script>\n<script>tailwind.config = ${tailwindConfig}</script>\n<style>\n${css}\n*{margin:0;padding:0;box-sizing:border-box}\nhtml{scroll-behavior:smooth}\nbody{font-family:system-ui,-apple-system,sans-serif;background-color:var(--color-surface);color:var(--color-on-surface)}\nimg{max-width:100%}\nsection{width:100%}\nsection>*{max-width:80rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem}\n[contenteditable=\"true\"]{cursor:text}\n</style>\n</head>\n<body class=\"bg-surface text-on-surface\">\n${body}\n<script>${getIframeScript()}</script>\n</body>\n</html>`;\n}\n\n/**\n * Build the deploy HTML (no editing script, clean output).\n */\n/**\n * Remove editor artifacts (outline, outlineOffset, contenteditable) from HTML before deploy.\n */\nfunction stripEditorArtifacts(html: string): string {\n return html\n .replace(/\\s*outline:\\s*[^;\"]+;?/gi, \"\")\n .replace(/\\s*outline-offset:\\s*[^;\"]+;?/gi, \"\")\n .replace(/\\s*style=\"\\s*\"/gi, \"\")\n .replace(/\\s+contenteditable=\"[^\"]*\"/gi, \"\")\n .replace(/\\s+data-section-id=\"[^\"]*\"/gi, \"\")\n}\n\nexport function buildDeployHtml(sections: Section3[], theme?: string, customColors?: CustomColors, showBranding = true): string {\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n const body = sorted.map((s) => stripEditorArtifacts(s.html)).join(\"\\n\");\n\n const isCustom = theme === \"custom\" && customColors;\n const dataTheme = theme && theme !== \"default\" && !isCustom ? ` data-theme=\"${theme}\"` : \"\";\n\n // For custom theme, build CSS from the custom colors directly (no data-theme needed, inject as :root)\n const { css: baseCss, tailwindConfig } = isCustom\n ? (() => {\n const ct = buildCustomTheme(customColors);\n const vars = Object.entries(ct.colors).map(([k, v]) => ` --color-${k}: ${v};`).join(\"\\n\");\n return { css: `:root {\\n${vars}\\n}`, tailwindConfig: buildSingleThemeCss(\"default\").tailwindConfig };\n })()\n : buildSingleThemeCss(theme || \"default\");\n\n return `<!DOCTYPE html>\n<html lang=\"es\"${dataTheme}>\n<head>\n<meta charset=\"UTF-8\"/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n<title>Landing Page</title>\n<script src=\"https://cdn.tailwindcss.com\"></script>\n<script>tailwind.config = ${tailwindConfig}</script>\n<style>\n${baseCss}\n*{margin:0;padding:0;box-sizing:border-box}\nhtml{scroll-behavior:smooth}\nbody{font-family:system-ui,-apple-system,sans-serif;background-color:var(--color-surface);color:var(--color-on-surface)}\nsection{width:100%}\nsection>*{max-width:80rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem}\n</style>\n</head>\n<body class=\"bg-surface text-on-surface\">\n${body}\n${showBranding ? `<div style=\"text-align:center;padding:16px 0 12px;font-size:12px\">\n <a href=\"https://www.easybits.cloud\" target=\"_blank\" rel=\"noopener\"\n style=\"color:#9ca3af;text-decoration:none\">\n Powered by easybits.cloud\n </a>\n</div>` : \"\"}\n</body>\n</html>`;\n}\n"],"mappings":";;;;;;;AAMO,SAAS,kBAA0B;AACxC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0iBT;;;AC1iBO,SAAS,iBAAiB,UAAsB,OAAwB;AAC7E,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC7D,QAAM,OAAO,OACV,IAAI,CAAC,MAAM,yBAAyB,EAAE,EAAE,KAAK,EAAE,IAAI,QAAQ,EAC3D,KAAK,IAAI;AAEZ,QAAM,YAAY,SAAS,UAAU,YAAY,gBAAgB,KAAK,MAAM;AAC5E,QAAM,EAAE,KAAK,eAAe,IAAI,cAAc;AAE9C,SAAO;AAAA,iBACQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAME,cAAc;AAAA;AAAA,EAExC,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWH,IAAI;AAAA,UACI,gBAAgB,CAAC;AAAA;AAAA;AAG3B;AAQA,SAAS,qBAAqB,MAAsB;AAClD,SAAO,KACJ,QAAQ,4BAA4B,EAAE,EACtC,QAAQ,mCAAmC,EAAE,EAC7C,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,gCAAgC,EAAE,EAC1C,QAAQ,gCAAgC,EAAE;AAC/C;AAEO,SAAS,gBAAgB,UAAsB,OAAgB,cAA6B,eAAe,MAAc;AAC9H,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC7D,QAAM,OAAO,OAAO,IAAI,CAAC,MAAM,qBAAqB,EAAE,IAAI,CAAC,EAAE,KAAK,IAAI;AAEtE,QAAM,WAAW,UAAU,YAAY;AACvC,QAAM,YAAY,SAAS,UAAU,aAAa,CAAC,WAAW,gBAAgB,KAAK,MAAM;AAGzF,QAAM,EAAE,KAAK,SAAS,eAAe,IAAI,YACpC,MAAM;AACL,UAAM,KAAK,iBAAiB,YAAY;AACxC,UAAM,OAAO,OAAO,QAAQ,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI;AACzF,WAAO,EAAE,KAAK;AAAA,EAAY,IAAI;AAAA,IAAO,gBAAgB,oBAAoB,SAAS,EAAE,eAAe;AAAA,EACrG,GAAG,IACH,oBAAoB,SAAS,SAAS;AAE1C,SAAO;AAAA,iBACQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAME,cAAc;AAAA;AAAA,EAExC,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASP,IAAI;AAAA,EACJ,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,UAKP,EAAE;AAAA;AAAA;AAGZ;","names":[]}
@@ -5,8 +5,8 @@ import {
5
5
  SectionList,
6
6
  ViewportToggle,
7
7
  useUndoStack
8
- } from "./chunk-EP65R6DE.js";
9
- import "./chunk-7MGKYJTI.js";
8
+ } from "./chunk-CZSPAIBQ.js";
9
+ import "./chunk-XDJMUIKY.js";
10
10
  import "./chunk-DCAQAHSU.js";
11
11
  export {
12
12
  Canvas,
@@ -31,6 +31,8 @@ interface GrapesEditorHandle {
31
31
  setZoom: (value: number) => void;
32
32
  /** Get current canvas zoom level */
33
33
  getZoom: () => number;
34
+ /** Container element wrapping the GrapesJS canvas — useful to measure available width for fit-zoom calculations. */
35
+ getCanvasContainer: () => HTMLElement | null;
34
36
  }
35
37
  interface BrandKitItem {
36
38
  id: string;
@@ -73,6 +75,8 @@ interface Props$2 {
73
75
  }[];
74
76
  /** Called when the most visible section changes due to canvas scroll */
75
77
  onVisibleSectionChange?: (sectionId: string) => void;
78
+ /** Called once the canvas iframe has loaded — useful to apply auto-fit zoom based on document format. */
79
+ onCanvasReady?: () => void;
76
80
  /**
77
81
  * Editor UI variant. Default `"classic"` preserves the original EasyBits look
78
82
  * (dark sidebar `w-80`, hierarchical block grid, black canvas). Set to
@@ -1490,7 +1490,7 @@ function getPanelTabs(variant) {
1490
1490
  ];
1491
1491
  }
1492
1492
  var GrapesEditor = forwardRef(
1493
- ({ initialHtml, theme = "minimal", customColors: rawCustomColors, brandKits, onChange, onAiAction, onThemeChange, onBrandKitChange, initialBrandKitId, hiddenTabs = [], canvasStyles, devices, panelSide = "left", blocks: customBlocks, onVisibleSectionChange, editorVariant = "classic" }, ref) => {
1493
+ ({ initialHtml, theme = "minimal", customColors: rawCustomColors, brandKits, onChange, onAiAction, onThemeChange, onBrandKitChange, initialBrandKitId, hiddenTabs = [], canvasStyles, devices, panelSide = "left", blocks: customBlocks, onVisibleSectionChange, onCanvasReady, editorVariant = "classic" }, ref) => {
1494
1494
  useEffect3(() => {
1495
1495
  injectDarkCss(editorVariant);
1496
1496
  }, [editorVariant]);
@@ -1505,6 +1505,8 @@ var GrapesEditor = forwardRef(
1505
1505
  onAiActionRef.current = onAiAction;
1506
1506
  const onVisibleSectionChangeRef = useRef3(onVisibleSectionChange);
1507
1507
  onVisibleSectionChangeRef.current = onVisibleSectionChange;
1508
+ const onCanvasReadyRef = useRef3(onCanvasReady);
1509
+ onCanvasReadyRef.current = onCanvasReady;
1508
1510
  const onThemeChangeRef = useRef3(onThemeChange);
1509
1511
  onThemeChangeRef.current = onThemeChange;
1510
1512
  const onBrandKitChangeRef = useRef3(onBrandKitChange);
@@ -1624,7 +1626,8 @@ ${html}` : html;
1624
1626
  },
1625
1627
  getZoom: () => {
1626
1628
  return editorRef.current?.Canvas.getZoom() ?? 100;
1627
- }
1629
+ },
1630
+ getCanvasContainer: () => editorContainerRef.current
1628
1631
  }));
1629
1632
  function getThemeCss() {
1630
1633
  try {
@@ -1823,6 +1826,7 @@ ${vars}
1823
1826
  extraStyle.textContent = canvasStyles;
1824
1827
  doc.head.appendChild(extraStyle);
1825
1828
  }
1829
+ requestAnimationFrame(() => onCanvasReadyRef.current?.());
1826
1830
  doc.addEventListener("keydown", (e) => {
1827
1831
  if (e.key !== " ") return;
1828
1832
  const el = e.target;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components4/GrapesEditor.tsx","../src/components4/blocks.ts","../src/components4/TailwindClassEditor.tsx","../src/components4/ImageSrcEditor.tsx","../src/components4/grapesDarkCss.ts"],"sourcesContent":["import { useEffect, useRef, useState, forwardRef, useImperativeHandle } from \"react\";\nimport type { Editor } from \"grapesjs\";\nimport { LANDING_BLOCKS } from \"./blocks\";\nimport { buildSingleThemeCss, buildCustomTheme, LANDING_THEMES } from \"../themes\";\nimport TailwindClassEditor from \"./TailwindClassEditor\";\nimport ImageSrcEditor from \"./ImageSrcEditor\";\nimport { getGrapesCss, type EditorVariant } from \"./grapesDarkCss\";\n\n/** Inject GrapesJS theme CSS once per variant at runtime */\nconst injectedVariants = new Set<EditorVariant>();\nfunction injectDarkCss(variant: EditorVariant) {\n if (typeof document === \"undefined\") return;\n if (injectedVariants.has(variant)) return;\n injectedVariants.add(variant);\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-grapes-css\", variant);\n style.textContent = getGrapesCss(variant);\n document.head.appendChild(style);\n}\n\n/** Flatten brand kit colors: keep string entries and convert extras array to named colors */\nfunction flattenColors(colors: Record<string, any> | undefined): Record<string, string> | undefined {\n if (!colors) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(colors)) {\n if (typeof v === \"string\") {\n out[k] = v;\n } else if (k === \"extras\" && Array.isArray(v)) {\n v.forEach((extra: { name?: string; hex?: string }, i: number) => {\n if (extra?.hex) {\n out[extra.name || `extra-${i + 1}`] = extra.hex;\n }\n });\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nexport interface AiAction {\n type: \"refine-element\";\n componentId: string;\n html: string;\n sectionHtml?: string;\n sectionComponentId?: string;\n isSection?: boolean;\n}\n\nexport interface GrapesEditorHandle {\n getEditor: () => Editor | null;\n getHtml: () => string;\n setHtml: (html: string) => void;\n /** Replace a component's HTML by its GrapesJS ID */\n replaceComponent: (componentId: string, newHtml: string) => void;\n /** Toggle preview mode, returns new state */\n togglePreview: () => boolean;\n /** Toggle sw-visibility (component border guides), returns new state */\n toggleSwVisibility: () => boolean;\n /** Scroll the canvas iframe to a section by data-section-id. Falls back to iframe DOM query if the component model lost the attribute. */\n scrollToSection: (sectionId: string) => void;\n /** Scroll the canvas to the N-th content section (skips __grapes_css__ style). Index-based is robust even when GrapesJS strips data-* attributes during parse. */\n scrollToIndex: (index: number) => void;\n /** Set canvas zoom level (percentage, e.g. 50 = 50%) */\n setZoom: (value: number) => void;\n /** Get current canvas zoom level */\n getZoom: () => number;\n}\n\ninterface BrandKitItem {\n id: string;\n name: string;\n colors: Record<string, string>;\n fonts?: { heading?: string; body?: string } | null;\n mood?: string | null;\n logoUrl?: string | null;\n isDefault?: boolean;\n}\n\ninterface Props {\n initialHtml: string;\n theme?: string;\n customColors?: Record<string, string>;\n brandKits?: BrandKitItem[];\n onChange?: (html: string) => void;\n onAiAction?: (action: AiAction) => void;\n onThemeChange?: (themeId: string, customColors?: Record<string, string>, brandKitId?: string) => void;\n onBrandKitChange?: (brandKit: BrandKitItem | null) => void;\n /** Persisted brand kit ID — restored from metadata on load */\n initialBrandKitId?: string;\n /** Hide specific panel tabs (e.g. [\"blocks\"] for documents) */\n hiddenTabs?: PanelId[];\n /** Extra CSS injected into the canvas iframe (e.g. document page sizing) */\n canvasStyles?: string;\n /** Set to false to hide device switcher (always single viewport) */\n devices?: false;\n /** Which side to render the panel sidebar — default \"left\" */\n panelSide?: \"left\" | \"right\";\n /** Override default blocks (LANDING_BLOCKS). Pass custom blocks for different editors (e.g. presentations). */\n blocks?: { id: string; label: string; category: string; content: string | object; media?: string }[];\n /** Called when the most visible section changes due to canvas scroll */\n onVisibleSectionChange?: (sectionId: string) => void;\n /**\n * Editor UI variant. Default `\"classic\"` preserves the original EasyBits look\n * (dark sidebar `w-80`, hierarchical block grid, black canvas). Set to\n * `\"denik\"` for the Denik look (sidebar `w-60 #11151A` with pill tabs, flat\n * block list with 24×24 icon boxes, white canvas with 32px margin, label\n * \"+ Sección\" on the blocks tab).\n */\n editorVariant?: EditorVariant;\n}\n\nexport type PanelId = \"blocks\" | \"layers\" | \"styles\" | \"themes\";\n\ninterface PanelTab { id: PanelId; label: string; icon: string }\n\nfunction getPanelTabs(variant: EditorVariant): readonly PanelTab[] {\n if (variant === \"denik\") {\n return [\n { id: \"blocks\", label: \"+ Sección\", icon: \"⊞\" },\n { id: \"layers\", label: \"Capas\", icon: \"◇\" },\n { id: \"styles\", label: \"Estilos\", icon: \"◑\" },\n { id: \"themes\", label: \"Temas\", icon: \"◈\" },\n ] as const;\n }\n return [\n { id: \"blocks\", label: \"Bloques\", icon: \"⊞\" },\n { id: \"layers\", label: \"Capas\", icon: \"☰\" },\n { id: \"styles\", label: \"Estilos\", icon: \"◑\" },\n { id: \"themes\", label: \"Temas\", icon: \"◈\" },\n ] as const;\n}\n\nconst GrapesEditor = forwardRef<GrapesEditorHandle, Props>(\n ({ initialHtml, theme = \"minimal\", customColors: rawCustomColors, brandKits, onChange, onAiAction, onThemeChange, onBrandKitChange, initialBrandKitId, hiddenTabs = [], canvasStyles, devices, panelSide = \"left\", blocks: customBlocks, onVisibleSectionChange, editorVariant = \"classic\" }, ref) => {\n // Inject theme CSS on first render (per-variant)\n useEffect(() => { injectDarkCss(editorVariant); }, [editorVariant]);\n\n // Strip non-string entries (e.g. extras array from brand kits)\n const customColors = flattenColors(rawCustomColors);\n const editorContainerRef = useRef<HTMLDivElement>(null);\n const blocksRef = useRef<HTMLDivElement>(null);\n const layersRef = useRef<HTMLDivElement>(null);\n const editorRef = useRef<Editor | null>(null);\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const onAiActionRef = useRef(onAiAction);\n onAiActionRef.current = onAiAction;\n const onVisibleSectionChangeRef = useRef(onVisibleSectionChange);\n onVisibleSectionChangeRef.current = onVisibleSectionChange;\n const onThemeChangeRef = useRef(onThemeChange);\n onThemeChangeRef.current = onThemeChange;\n const onBrandKitChangeRef = useRef(onBrandKitChange);\n onBrandKitChangeRef.current = onBrandKitChange;\n const themeRef = useRef(theme);\n themeRef.current = theme;\n const customColorsRef = useRef(customColors);\n customColorsRef.current = customColors;\n const [activeBrandKitId, setActiveBrandKitId] = useState<string | null>(initialBrandKitId || null);\n const visibleTabs = getPanelTabs(editorVariant).filter((t) => !hiddenTabs.includes(t.id));\n const [activePanel, setActivePanel] = useState<PanelId>(() =>\n visibleTabs.find((t) => t.id === \"styles\")?.id ?? visibleTabs[0]?.id ?? \"styles\"\n );\n const [ready, setReady] = useState(false);\n const [themeVersion, setThemeVersion] = useState(0);\n\n useImperativeHandle(ref, () => ({\n getEditor: () => editorRef.current,\n getHtml: () => {\n const ed = editorRef.current;\n if (!ed) return \"\";\n const html = ed.getHtml();\n const css = ed.getCss();\n return css ? `<style>${css}</style>\\n${html}` : html;\n },\n setHtml: (html: string) => editorRef.current?.setComponents(html),\n togglePreview: () => {\n const ed = editorRef.current;\n if (!ed) return false;\n const cmd = ed.Commands;\n if (cmd.isActive(\"preview\")) {\n cmd.stop(\"preview\");\n if (!cmd.isActive(\"sw-visibility\")) cmd.run(\"sw-visibility\");\n return false;\n } else {\n if (cmd.isActive(\"sw-visibility\")) cmd.stop(\"sw-visibility\");\n ed.select();\n cmd.run(\"preview\");\n return true;\n }\n },\n toggleSwVisibility: () => {\n const ed = editorRef.current;\n if (!ed) return false;\n const cmd = ed.Commands;\n if (cmd.isActive(\"sw-visibility\")) {\n cmd.stop(\"sw-visibility\");\n return false;\n } else {\n cmd.run(\"sw-visibility\");\n return true;\n }\n },\n scrollToSection: (sectionId: string) => {\n const ed = editorRef.current;\n if (!ed) return;\n const wrapper = ed.DomComponents.getWrapper();\n if (!wrapper) return;\n const comps = wrapper.components().models || [];\n\n // (a) Try the GrapesJS model. This is the fast path when attributes were preserved.\n const target = comps.find((c: any) => c.getAttributes()[\"data-section-id\"] === sectionId);\n if (target) {\n ed.select(target);\n (ed.Canvas as any).scrollTo?.(target, { behavior: \"smooth\", block: \"start\", force: true });\n return;\n }\n\n // (b) GrapesJS sometimes discards custom `data-*` attributes from the model\n // while keeping them on the rendered DOM. Scroll via the iframe element directly —\n // Canvas.scrollTo accepts an HTMLElement too.\n const doc = ed.Canvas.getDocument();\n const el = doc?.querySelector(`[data-section-id=\"${sectionId}\"]`) as HTMLElement | null;\n if (el) {\n (ed.Canvas as any).scrollTo?.(el, { behavior: \"smooth\", block: \"start\", force: true });\n return;\n }\n\n console.warn(\"[scrollToSection] Section not found:\", sectionId, \"Model attrs:\", comps.map((c: any) => c.getAttributes()[\"data-section-id\"]), \"DOM has [data-section-id]?\", !!doc?.querySelector(\"[data-section-id]\"));\n },\n\n scrollToIndex: (index: number) => {\n const ed = editorRef.current;\n if (!ed) return;\n const wrapper = ed.DomComponents.getWrapper();\n if (!wrapper) return;\n const comps = wrapper.components().models || [];\n // Skip head-like tags that importers (splitIntoPages) prepend per page:\n // <link>, <style>, <script>, <meta>, <title>, <base>. Without this filter,\n // `contentComps[N]` can land on a zero-height <link> instead of the target\n // <section>, which makes every click scroll to the same place.\n const HEAD_TAGS = new Set([\"style\", \"script\", \"link\", \"meta\", \"title\", \"base\"]);\n const contentComps = comps.filter((c: any) => {\n const tag = (c.get(\"tagName\") || \"\").toLowerCase();\n return tag && !HEAD_TAGS.has(tag);\n });\n const target = contentComps[index];\n if (!target) return;\n ed.select(target);\n const el = target.getEl() as HTMLElement | undefined;\n if (index === 0) {\n ed.Canvas.getDocument()?.documentElement?.scrollTo({ top: 0, behavior: \"smooth\" });\n return;\n }\n el?.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n },\n replaceComponent: (componentId: string, newHtml: string) => {\n const ed = editorRef.current;\n if (!ed) return;\n function findById(parent: any): any {\n if (parent.getId() === componentId) return parent;\n for (const child of parent.components().models || []) {\n const found = findById(child);\n if (found) return found;\n }\n return null;\n }\n const wrapper = ed.DomComponents.getWrapper();\n if (!wrapper) return;\n const comp = findById(wrapper);\n if (comp) {\n comp.replaceWith(newHtml);\n } else {\n console.warn(\"[replaceComponent] Component not found:\", componentId);\n }\n },\n setZoom: (value: number) => {\n editorRef.current?.Canvas.setZoom(value);\n },\n getZoom: () => {\n return editorRef.current?.Canvas.getZoom() ?? 100;\n },\n }));\n\n function getThemeCss() {\n try {\n const cc = customColorsRef.current;\n if (cc && Object.keys(cc).length) {\n if (!cc[\"on-primary\"] && cc.primary) {\n const full = buildCustomTheme(cc as any);\n const vars = Object.entries(full.colors)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n return `:root {\\n${vars}\\n}`;\n }\n const vars = Object.entries(cc)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n return `:root {\\n${vars}\\n}`;\n }\n return buildSingleThemeCss(themeRef.current).css || \"\";\n } catch {\n return \"\";\n }\n }\n\n function findSectionAncestor(comp: any): any {\n let current = comp;\n while (current) {\n if (current.get(\"tagName\") === \"section\") return current;\n current = current.parent();\n }\n return null;\n }\n\n useEffect(() => {\n if (!editorContainerRef.current || editorRef.current) return;\n let mounted = true;\n\n (async () => {\n const grapesjs = (await import(\"grapesjs\")).default;\n if (!mounted || !editorContainerRef.current) return;\n\n // Inject grapesjs base CSS\n if (!document.querySelector('link[href*=\"grapes.min.css\"]')) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = \"https://unpkg.com/grapesjs/dist/css/grapes.min.css\";\n document.head.appendChild(link);\n }\n\n const initialThemeCss = getThemeCss();\n const COLORS_MAP: Record<string, string> = {\n primary: \"--color-primary\", \"primary-light\": \"--color-primary-light\", \"primary-dark\": \"--color-primary-dark\",\n secondary: \"--color-secondary\", accent: \"--color-accent\",\n surface: \"--color-surface\", \"surface-alt\": \"--color-surface-alt\",\n \"on-primary\": \"--color-on-primary\", \"on-secondary\": \"--color-on-secondary\", \"on-accent\": \"--color-on-accent\",\n \"on-surface\": \"--color-on-surface\", \"on-surface-muted\": \"--color-on-surface-muted\",\n };\n const fallbackRules: string[] = [];\n for (const [name, cssVar] of Object.entries(COLORS_MAP)) {\n fallbackRules.push(`.bg-${name} { background-color: var(${cssVar}) !important }`);\n fallbackRules.push(`.text-${name} { color: var(${cssVar}) !important }`);\n fallbackRules.push(`.border-${name} { border-color: var(${cssVar}) !important }`);\n fallbackRules.push(`.from-${name} { --tw-gradient-from: var(${cssVar}) }`);\n fallbackRules.push(`.to-${name} { --tw-gradient-to: var(${cssVar}) }`);\n fallbackRules.push(`.hover\\\\:bg-${name}:hover { background-color: var(${cssVar}) !important }`);\n fallbackRules.push(`.hover\\\\:text-${name}:hover { color: var(${cssVar}) !important }`);\n }\n\n const editor = grapesjs.init({\n container: editorContainerRef.current,\n height: \"100%\",\n width: \"auto\",\n fromElement: false,\n storageManager: false,\n panels: { defaults: [] },\n canvas: {\n scripts: [\n `data:text/javascript,window.tailwind=${encodeURIComponent(JSON.stringify({config:{\n theme: { extend: { colors: {\n primary: \"var(--color-primary)\",\n \"primary-light\": \"var(--color-primary-light)\",\n \"primary-dark\": \"var(--color-primary-dark)\",\n secondary: \"var(--color-secondary)\",\n accent: \"var(--color-accent)\",\n surface: \"var(--color-surface)\",\n \"surface-alt\": \"var(--color-surface-alt)\",\n \"on-primary\": \"var(--color-on-primary)\",\n \"on-secondary\": \"var(--color-on-secondary)\",\n \"on-accent\": \"var(--color-on-accent)\",\n \"on-surface\": \"var(--color-on-surface)\",\n \"on-surface-muted\": \"var(--color-on-surface-muted)\",\n }}}}\n }))}`,\n \"https://cdn.tailwindcss.com\",\n ],\n styles: [\n `data:text/css,${encodeURIComponent(initialThemeCss + \"\\n\" + fallbackRules.join(\"\\n\") + (canvasStyles ? \"\\n\" + canvasStyles : \"\"))}`,\n ],\n },\n deviceManager: devices === false ? false as any : {\n devices: [\n { name: \"Desktop\", width: \"\" },\n { name: \"Tablet\", width: \"768px\" },\n { name: \"Mobile\", width: \"375px\" },\n ],\n },\n styleManager: false as any,\n layerManager: {\n appendTo: layersRef.current!,\n },\n blockManager: hiddenTabs.includes(\"blocks\") ? false as any : {\n appendTo: blocksRef.current!,\n blocks: (customBlocks || LANDING_BLOCKS).map((b) => ({\n id: b.id,\n label: b.label,\n category: b.category,\n content: b.content,\n media: b.media,\n })),\n },\n allowScripts: 1,\n } as any);\n\n // ─── AI Commands ────────────────────────────────\n editor.Commands.add(\"ai-open-menu\", {\n run(ed: Editor) {\n const selected = ed.getSelected();\n if (!selected) return;\n const section = findSectionAncestor(selected);\n const isSection = selected.get(\"tagName\") === \"section\";\n onAiActionRef.current?.({\n type: \"refine-element\",\n componentId: selected.getId(),\n html: selected.toHTML(),\n sectionHtml: section ? section.toHTML() : undefined,\n sectionComponentId: section ? section.getId() : undefined,\n isSection,\n } as any);\n },\n });\n\n // ─── Switch to Styles tab on selection (only if not hidden) ───\n editor.on(\"component:selected\", () => {\n if (!hiddenTabs.includes(\"styles\")) setActivePanel(\"styles\");\n });\n editor.on(\"component:deselected\", () => {\n // Stay on current panel\n });\n\n // ─── Inject AI buttons into component toolbar on selection ───\n editor.on(\"component:selected\", (component: any) => {\n const toolbar = component.get(\"toolbar\") || [];\n const hasAi = toolbar.some((t: any) => t.id === \"ai-refine\");\n if (hasAi) return;\n\n const aiButtons: any[] = [\n {\n id: \"ai-menu\",\n label: `<svg title=\"AI\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"#9870ED\" style=\"vertical-align:middle;cursor:pointer\"><path d=\"M12 2l2.09 6.26L20.18 10l-6.09 1.74L12 18l-2.09-6.26L3.82 10l6.09-1.74z\"/><path d=\"M19 2l.75 2.25L22 5l-2.25.75L19 8l-.75-2.25L16 5l2.25-.75z\" opacity=\".7\"/><path d=\"M5 16l.5 1.5L7 18l-1.5.5L5 20l-.5-1.5L3 18l1.5-.5z\" opacity=\".5\"/></svg>`,\n command: \"ai-open-menu\",\n },\n ];\n\n component.set(\"toolbar\", [...toolbar, ...aiButtons]);\n });\n\n // ─── Theme + extras in iframe ────────────────────\n editor.on(\"canvas:frame:load\", ({ window: fw }: { window: Window }) => {\n const doc = fw.document;\n\n const style = doc.createElement(\"style\");\n style.id = \"easybits-theme\";\n style.textContent = getThemeCss();\n doc.head.appendChild(style);\n\n const shimmerStyle = doc.createElement(\"style\");\n shimmerStyle.textContent = `\n .easybits-refining { position: relative; overflow: hidden; }\n .easybits-refining::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, transparent 0%, rgba(152,112,237,0.08) 50%, transparent 100%);\n animation: easybits-shimmer 1.5s infinite;\n pointer-events: none;\n z-index: 9999;\n }\n @keyframes easybits-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n `;\n doc.head.appendChild(shimmerStyle);\n\n const swStyle = doc.createElement(\"style\");\n swStyle.textContent = `\n .gjs-dashed *[data-gjs-type] {\n outline: 1px dashed rgba(152,112,237,0.35) !important;\n outline-offset: -1px;\n }\n .gjs-dashed *[data-gjs-type]:hover {\n outline-color: rgba(152,112,237,0.7) !important;\n }\n `;\n doc.head.appendChild(swStyle);\n\n if (canvasStyles) {\n const extraStyle = doc.createElement(\"style\");\n extraStyle.id = \"easybits-canvas-styles\";\n extraStyle.textContent = canvasStyles;\n doc.head.appendChild(extraStyle);\n }\n\n doc.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (e.key !== \" \") return;\n const el = e.target as HTMLElement;\n if (!el?.isContentEditable) return;\n const tag = el.tagName?.toLowerCase();\n if (tag === \"a\" || tag === \"button\" || el.closest(\"a\") || el.closest(\"button\")) {\n e.preventDefault();\n doc.execCommand(\"insertText\", false, \" \");\n }\n });\n\n if (!doc.getElementById(\"easybits-semantic-fallback\")) {\n const fallback = doc.createElement(\"style\");\n fallback.id = \"easybits-semantic-fallback\";\n const rules: string[] = [];\n for (const [name, cssVar] of Object.entries(COLORS_MAP)) {\n rules.push(`.bg-${name} { background-color: var(${cssVar}) !important }`);\n rules.push(`.text-${name} { color: var(${cssVar}) !important }`);\n rules.push(`.border-${name} { border-color: var(${cssVar}) !important }`);\n rules.push(`.from-${name} { --tw-gradient-from: var(${cssVar}) }`);\n rules.push(`.to-${name} { --tw-gradient-to: var(${cssVar}) }`);\n rules.push(`.hover\\\\:bg-${name}:hover { background-color: var(${cssVar}) !important }`);\n rules.push(`.hover\\\\:text-${name}:hover { color: var(${cssVar}) !important }`);\n }\n fallback.textContent = rules.join(\"\\n\");\n doc.head.appendChild(fallback);\n }\n\n const applyTwConfig = () => {\n if ((fw as any).tailwind) {\n (fw as any).tailwind.config = {\n theme: { extend: { colors: Object.fromEntries(\n Object.keys(COLORS_MAP).map(name => [name, `var(${COLORS_MAP[name]})`])\n )}}\n };\n }\n };\n applyTwConfig();\n const twScript = doc.querySelector('script[src*=\"tailwindcss\"]');\n if (twScript) {\n twScript.addEventListener(\"load\", () => {\n applyTwConfig();\n doc.body.style.display = \"none\";\n doc.body.offsetHeight;\n doc.body.style.display = \"\";\n });\n }\n\n // Scroll-spy\n {\n let scrollRaf = 0;\n const onScroll = () => {\n cancelAnimationFrame(scrollRaf);\n scrollRaf = requestAnimationFrame(() => {\n if (!onVisibleSectionChangeRef.current) return;\n const sectionEls = doc.querySelectorAll(\"[data-section-id]\");\n if (!sectionEls.length) return;\n const viewH = fw.innerHeight;\n let bestId = \"\";\n let bestVisible = 0;\n sectionEls.forEach((el) => {\n const rect = el.getBoundingClientRect();\n const top = Math.max(0, rect.top);\n const bottom = Math.min(viewH, rect.bottom);\n const visible = Math.max(0, bottom - top);\n if (visible > bestVisible) {\n bestVisible = visible;\n bestId = el.getAttribute(\"data-section-id\") || \"\";\n }\n });\n if (bestId) onVisibleSectionChangeRef.current(bestId);\n });\n };\n fw.addEventListener(\"scroll\", onScroll, { passive: true });\n }\n });\n\n if (initialHtml) editor.setComponents(initialHtml);\n\n // ─── Name layers based on content ───\n function nameLayers() {\n const wrapper = editor.DomComponents.getWrapper();\n if (!wrapper) return;\n wrapper.components().forEach((comp: any, i: number) => {\n if (comp.get(\"custom-name\")) return;\n const tag = (comp.get(\"tagName\") || \"\").toLowerCase();\n if (tag !== \"section\") return;\n const html = comp.toHTML().toLowerCase();\n let name = `Section ${i + 1}`;\n if (html.includes(\"hero\") || (i === 0 && html.includes(\"<h1\"))) name = \"Hero\";\n else if (html.includes(\"pricing\") || html.includes(\"precio\") || html.includes(\"inversión\")) name = \"Pricing\";\n else if (html.includes(\"testimonial\") || html.includes(\"dicen\") || html.includes(\"quote\")) name = \"Testimonials\";\n else if (html.includes(\"faq\") || html.includes(\"pregunt\") || html.includes(\"<details\")) name = \"FAQ\";\n else if (html.includes(\"footer\") || html.includes(\"©\") || html.includes(\"derechos\")) name = \"Footer\";\n else if (html.includes(\"feature\") || html.includes(\"palanca\") || html.includes(\"servicio\")) name = \"Features\";\n else if (html.includes(\"stat\") || html.includes(\"número\") || html.includes(\"+%\")) name = \"Stats\";\n else if (html.includes(\"team\") || html.includes(\"equipo\")) name = \"Team\";\n else if (html.includes(\"cta\") || html.includes(\"listo\") || html.includes(\"empez\")) name = \"CTA\";\n else if (html.includes(\"newsletter\") || html.includes(\"suscri\") || html.includes(\"email\")) name = \"Newsletter\";\n else if (html.includes(\"proceso\") || html.includes(\"step\") || html.includes(\"cómo func\")) name = \"Process\";\n else if (html.includes(\"problema\") || html.includes(\"pain\")) name = \"Problem\";\n else if (html.includes(\"logo\") || html.includes(\"trusted\") || html.includes(\"brand\")) name = \"Logo Cloud\";\n comp.set(\"custom-name\", name);\n });\n }\n editor.on(\"load\", nameLayers);\n editor.on(\"component:add\", () => setTimeout(nameLayers, 200));\n\n let userHasInteracted = false;\n const interactionEvents = [\n \"canvas:drop\", \"block:drag:stop\", \"component:drag:end\",\n \"component:input\", \"undo\", \"redo\",\n ];\n const markInteracted = () => { userHasInteracted = true; };\n interactionEvents.forEach((evt) => editor.on(evt, markInteracted));\n editor.on(\"sidebar:change\", markInteracted);\n\n const notify = () => {\n if (!userHasInteracted) return;\n const html = editor.getHtml();\n if (!html || !html.trim()) return;\n const css = editor.getCss();\n const fullHtml = css ? `<style>${css}</style>\\n${html}` : html;\n onChangeRef.current?.(fullHtml);\n };\n\n [\n \"component:update\", \"component:add\", \"component:remove\",\n \"component:drag:end\", \"component:input\", \"canvas:drop\",\n \"block:drag:stop\", \"undo\", \"redo\", \"sidebar:change\",\n ].forEach((evt) => editor.on(evt, notify));\n\n // Collapse all block categories except CTA\n try {\n const bm = editor.BlockManager;\n const cats = bm.getCategories?.();\n if (cats && cats.forEach) {\n cats.forEach((cat: any) => {\n try {\n const name = (typeof cat.get === \"function\" ? cat.get(\"id\") || cat.get(\"label\") : cat.id || cat.label) || \"\";\n if (name !== \"CTA\") {\n if (typeof cat.set === \"function\") cat.set(\"open\", false);\n }\n } catch { /* skip */ }\n });\n }\n } catch { /* skip */ }\n\n editorRef.current = editor;\n editor.on(\"load\", () => {\n setReady(true);\n let attempts = 0;\n const interval = setInterval(() => {\n attempts++;\n try {\n const active = editor.Commands?.getActive();\n if (!active) { clearInterval(interval); return; }\n for (const cmd of Object.keys(active)) {\n if (cmd === \"show-offset\") {\n editor.stopCommand(cmd);\n }\n }\n } catch {}\n if (attempts >= 30) clearInterval(interval);\n }, 100);\n if (editor.Commands.isActive(\"sw-visibility\")) {\n editor.Commands.stop(\"sw-visibility\");\n }\n });\n })().catch((err) => {\n console.error(\"GrapesJS init failed:\", err);\n });\n\n return () => {\n mounted = false;\n editorRef.current?.destroy();\n editorRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Update theme CSS dynamically\n useEffect(() => {\n const ed = editorRef.current;\n if (!ed) return;\n const doc = ed.Canvas.getDocument();\n if (!doc) return;\n\n const old = doc.getElementById(\"easybits-theme\");\n if (old) old.remove();\n const style = doc.createElement(\"style\");\n style.id = \"easybits-theme\";\n style.textContent = getThemeCss();\n doc.head.appendChild(style);\n\n const oldFallback = doc.getElementById(\"easybits-semantic-fallback\");\n if (oldFallback) {\n const content = oldFallback.textContent;\n oldFallback.remove();\n const fb = doc.createElement(\"style\");\n fb.id = \"easybits-semantic-fallback\";\n fb.textContent = content;\n doc.head.appendChild(fb);\n }\n\n setTimeout(() => setThemeVersion((v) => v + 1), 100);\n }, [theme, customColors]);\n\n const sidebarBorder = panelSide === \"right\" ? \"border-l\" : \"border-r\";\n\n const sidebarContainerClass = editorVariant === \"denik\"\n ? `w-60 shrink-0 flex flex-col bg-[#11151A] ${sidebarBorder} border-gray-700 overflow-hidden`\n : `w-80 shrink-0 flex flex-col bg-black ${sidebarBorder} border-gray-700 overflow-hidden`;\n const tabsRowClass = editorVariant === \"denik\"\n ? \"flex gap-0 px-3 py-3\"\n : \"flex border-b border-gray-700\";\n const tabButtonClass = (isActive: boolean) => {\n if (editorVariant === \"denik\") {\n return `px-4 py-2 text-sm font-medium transition-colors flex items-center gap-2 rounded-full ${\n isActive ? \"bg-[#2A2B31] text-white\" : \"text-gray-400 hover:text-gray-200\"\n }`;\n }\n return `flex-1 py-2.5 text-xs font-bold transition-colors ${\n isActive\n ? \"bg-gray-800 text-white border-b-2 border-brand-500\"\n : \"text-gray-400 hover:text-gray-200 hover:bg-gray-800/50\"\n }`;\n };\n\n const sidebar = (\n <div className={sidebarContainerClass}>\n <div className={tabsRowClass}>\n {visibleTabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => setActivePanel(tab.id)}\n className={tabButtonClass(activePanel === tab.id)}\n title={tab.label}\n >\n {editorVariant === \"denik\" ? (\n <span className=\"text-sm\">{tab.icon}</span>\n ) : (\n <span className=\"block text-base mb-0.5\">{tab.icon}</span>\n )}\n {tab.label}\n </button>\n ))}\n </div>\n\n {!hiddenTabs.includes(\"blocks\") && <div\n ref={blocksRef}\n className={`flex-1 overflow-auto p-2 ${activePanel === \"blocks\" ? \"\" : \"hidden\"}`}\n />}\n <div\n ref={layersRef}\n className={`flex-1 overflow-auto ${activePanel === \"layers\" ? \"\" : \"hidden\"}`}\n />\n {!hiddenTabs.includes(\"styles\") && <div className={`flex-1 overflow-auto ${activePanel === \"styles\" ? \"\" : \"hidden\"}`}>\n {ready && <ImageSrcEditor editor={editorRef.current} />}\n {ready && <TailwindClassEditor\n editor={editorRef.current}\n themeVersion={themeVersion}\n themeColors={(() => {\n if (customColors && Object.keys(customColors).length) return customColors;\n const t = LANDING_THEMES.find((t) => t.id === theme);\n return t?.colors || {};\n })()}\n />}\n </div>}\n {!hiddenTabs.includes(\"themes\") && <div className={`flex-1 overflow-auto p-3 ${activePanel === \"themes\" ? \"\" : \"hidden\"}`}>\n <p className=\"text-xs text-gray-400 font-bold uppercase tracking-wider mb-3\">Temas</p>\n <div className=\"grid grid-cols-2 gap-2\">\n {LANDING_THEMES.map((t) => {\n const isActive = theme === t.id;\n const displayColors = isActive && customColors && Object.keys(customColors).length\n ? { ...t.colors, ...customColors }\n : t.colors;\n return (\n <button\n key={t.id}\n onClick={() => {\n onThemeChangeRef.current?.(t.id);\n setActiveBrandKitId(null);\n onBrandKitChangeRef.current?.(null);\n }}\n className={`flex flex-col items-center gap-1.5 p-2.5 rounded-xl border-2 transition-all ${\n isActive\n ? \"border-brand-500 bg-brand-500/10\"\n : \"border-gray-700 hover:border-gray-500\"\n }`}\n >\n <div className=\"flex gap-1\">\n <div className=\"w-5 h-5 rounded-full border border-gray-600\" style={{ background: displayColors.primary }} title=\"Primary\" />\n <div className=\"w-5 h-5 rounded-full border border-gray-600\" style={{ background: displayColors.surface }} title=\"Surface\" />\n <div className=\"w-5 h-5 rounded-full border border-gray-600\" style={{ background: displayColors.accent }} title=\"Accent\" />\n </div>\n <span className=\"text-[10px] font-bold text-gray-300\">{t.label}</span>\n </button>\n );\n })}\n </div>\n\n {(() => {\n const active = LANDING_THEMES.find((t) => t.id === theme);\n const baseColors: Record<string, string> = active?.colors ? { ...active.colors } : {};\n const currentColors: Record<string, string> = customColors && Object.keys(customColors).length\n ? { ...baseColors, ...customColors }\n : baseColors;\n if (!Object.keys(currentColors).length) return null;\n const COLOR_LABELS: Record<string, string> = {\n primary: \"Primary\", \"primary-light\": \"Primary Light\", \"primary-dark\": \"Primary Dark\",\n secondary: \"Secondary\", accent: \"Accent\", surface: \"Surface\",\n \"surface-alt\": \"Surface Alt\", \"on-surface\": \"On Surface\",\n \"on-surface-muted\": \"On Surface Muted\", \"on-primary\": \"On Primary\",\n \"on-secondary\": \"On Secondary\", \"on-accent\": \"On Accent\",\n };\n return (\n <div className=\"mt-3 space-y-1\">\n {Object.entries(currentColors).map(([key, hex]) => (\n <label\n key={key}\n className=\"flex items-center gap-2 w-full px-2 py-1 rounded-lg hover:bg-gray-800 transition-colors group text-left cursor-pointer\"\n >\n <input\n type=\"color\"\n value={hex}\n onChange={(e) => {\n const updated = { ...currentColors, [key]: e.target.value };\n onThemeChangeRef.current?.(themeRef.current, updated);\n }}\n className=\"w-4 h-4 rounded border border-gray-600 shrink-0 cursor-pointer p-0 bg-transparent [&::-webkit-color-swatch-wrapper]:p-0 [&::-webkit-color-swatch]:border-none [&::-webkit-color-swatch]:rounded\"\n />\n <span className=\"text-[10px] text-gray-400 flex-1 truncate\">{COLOR_LABELS[key] || key}</span>\n <code className=\"text-[10px] text-gray-500 group-hover:text-gray-300 font-mono\">{hex}</code>\n </label>\n ))}\n </div>\n );\n })()}\n\n {brandKits && brandKits.length > 0 && (\n <>\n <p className=\"text-xs text-gray-400 font-bold uppercase tracking-wider mt-5 mb-3\">Brand Kits</p>\n <div className=\"grid grid-cols-2 gap-2\">\n {brandKits.map((bk) => {\n const bkBase = flattenColors(bk.colors as Record<string, any>) || {};\n const displayColors = activeBrandKitId === bk.id && customColors && Object.keys(customColors).length\n ? { ...bkBase, ...customColors }\n : bkBase;\n return (\n <button\n key={bk.id}\n onClick={() => {\n onThemeChangeRef.current?.(\"custom\", bkBase, bk.id);\n setActiveBrandKitId(bk.id);\n onBrandKitChangeRef.current?.(bk);\n }}\n className={`flex flex-col items-center gap-1.5 p-2.5 rounded-xl border-2 transition-all ${\n activeBrandKitId === bk.id\n ? \"border-brand-500 bg-brand-500/10\"\n : \"border-gray-700 hover:border-gray-500\"\n }`}\n >\n <div className=\"flex gap-1\">\n {[\"primary\", \"surface\", \"accent\"].map((key) => (\n <div\n key={key}\n className=\"w-5 h-5 rounded-full border border-gray-600\"\n style={{ background: displayColors[key] || \"#888\" }}\n />\n ))}\n </div>\n <span className=\"text-[10px] font-bold text-gray-300 truncate max-w-full\">{bk.name}</span>\n </button>\n );\n })}\n </div>\n {activeBrandKitId && (() => {\n const bk = brandKits?.find((b) => b.id === activeBrandKitId);\n if (!bk) return null;\n const baseColors = flattenColors(bk.colors as Record<string, any>) || {};\n const colors = customColors && Object.keys(customColors).length\n ? { ...baseColors, ...customColors }\n : baseColors;\n return (\n <div className=\"mt-3 space-y-1\">\n {Object.entries(colors).map(([key, hex]) => (\n <label\n key={key}\n className=\"flex items-center gap-2 w-full px-2 py-1 rounded-lg hover:bg-gray-800 transition-colors group text-left cursor-pointer\"\n >\n <input\n type=\"color\"\n value={hex}\n onChange={(e) => {\n const updated = { ...colors, [key]: e.target.value };\n onThemeChangeRef.current?.(\"custom\", updated, activeBrandKitId || undefined);\n }}\n className=\"w-4 h-4 rounded border border-gray-600 shrink-0 cursor-pointer p-0 bg-transparent [&::-webkit-color-swatch-wrapper]:p-0 [&::-webkit-color-swatch]:border-none [&::-webkit-color-swatch]:rounded\"\n />\n <span className=\"text-[10px] text-gray-400 flex-1 truncate\">{key}</span>\n <code className=\"text-[10px] text-gray-500 group-hover:text-gray-300 font-mono\">{hex}</code>\n </label>\n ))}\n </div>\n );\n })()}\n </>\n )}\n </div>}\n </div>\n );\n\n const canvasClass = editorVariant === \"denik\"\n ? \"flex-1 h-full bg-white relative\"\n : \"flex-1 h-full bg-black\";\n const canvas = <div ref={editorContainerRef} className={canvasClass} />;\n\n return (\n <div className=\"flex h-full w-full relative\">\n {panelSide === \"right\" ? <>{canvas}{sidebar}</> : <>{sidebar}{canvas}</>}\n\n {/* Glass overlay while GrapesJS loads */}\n <div\n className={`absolute inset-0 z-50 pointer-events-none bg-gray-950/40 backdrop-blur-[2px] transition-all duration-500 ${\n ready ? \"opacity-0 invisible\" : \"opacity-100\"\n }`}\n />\n </div>\n );\n }\n);\n\nGrapesEditor.displayName = \"GrapesEditor\";\nexport default GrapesEditor;\n","/**\n * Predefined blocks for GrapesJS editor.\n * All section blocks use semantic colors (bg-primary, text-on-surface, etc.)\n */\nexport const LANDING_BLOCKS = [\n // ─── Basic Elements ───────────────────────────────────\n {\n id: \"text-block\",\n label: \"Text\",\n category: \"Basic\",\n content: `<p class=\"text-base text-on-surface\">Edit this text. Double click to start typing.</p>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M4 7V4h16v3\"/><path d=\"M9 20h6\"/><path d=\"M12 4v16\"/></svg>`,\n },\n {\n id: \"heading-block\",\n label: \"Heading\",\n category: \"Basic\",\n content: `<h2 class=\"text-4xl font-black text-on-surface\">Your Heading Here</h2>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M4 12h16\"/><path d=\"M4 4v16\"/><path d=\"M20 4v16\"/></svg>`,\n },\n {\n id: \"image-block\",\n label: \"Image\",\n category: \"Basic\",\n content: { type: \"image\" },\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><path d=\"m21 15-5-5L5 21\"/></svg>`,\n },\n {\n id: \"button-block\",\n label: \"Button\",\n category: \"Basic\",\n content: `<a href=\"#\" class=\"inline-block px-8 py-3 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Click Me</a>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"8\" width=\"18\" height=\"8\" rx=\"4\"/><path d=\"M8 12h8\"/></svg>`,\n },\n {\n id: \"link-block\",\n label: \"Link\",\n category: \"Basic\",\n content: `<a href=\"#\" class=\"text-primary font-bold underline hover:text-primary-dark transition\">Your Link</a>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`,\n },\n {\n id: \"video-block\",\n label: \"Video\",\n category: \"Basic\",\n content: { type: \"video\" },\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polygon points=\"5 3 19 12 5 21 5 3\"/></svg>`,\n },\n {\n id: \"divider-block\",\n label: \"Divider\",\n category: \"Basic\",\n content: `<hr class=\"border-t-2 border-gray-200 my-8\" />`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M3 12h18\"/></svg>`,\n },\n {\n id: \"spacer-block\",\n label: \"Spacer\",\n category: \"Basic\",\n content: `<div class=\"h-16\"></div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 5v14\"/><path d=\"M5 5h14\"/><path d=\"M5 19h14\"/></svg>`,\n },\n // ─── Layout ───────────────────────────────────────────\n {\n id: \"container-block\",\n label: \"Container\",\n category: \"Layout\",\n content: `<div class=\"max-w-6xl mx-auto px-6 py-12\"></div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/></svg>`,\n },\n {\n id: \"two-columns\",\n label: \"2 Columns\",\n category: \"Layout\",\n content: `<div class=\"grid grid-cols-2 gap-8 px-6 py-12 max-w-6xl mx-auto\">\n <div class=\"bg-surface-alt rounded-xl p-8 min-h-[120px]\"></div>\n <div class=\"bg-surface-alt rounded-xl p-8 min-h-[120px]\"></div>\n</div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"2\" y=\"3\" width=\"9\" height=\"18\" rx=\"1\"/><rect x=\"13\" y=\"3\" width=\"9\" height=\"18\" rx=\"1\"/></svg>`,\n },\n {\n id: \"three-columns\",\n label: \"3 Columns\",\n category: \"Layout\",\n content: `<div class=\"grid grid-cols-3 gap-6 px-6 py-12 max-w-6xl mx-auto\">\n <div class=\"bg-surface-alt rounded-xl p-6 min-h-[120px]\"></div>\n <div class=\"bg-surface-alt rounded-xl p-6 min-h-[120px]\"></div>\n <div class=\"bg-surface-alt rounded-xl p-6 min-h-[120px]\"></div>\n</div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"1\" y=\"3\" width=\"6\" height=\"18\" rx=\"1\"/><rect x=\"9\" y=\"3\" width=\"6\" height=\"18\" rx=\"1\"/><rect x=\"17\" y=\"3\" width=\"6\" height=\"18\" rx=\"1\"/></svg>`,\n },\n // ─── Heroes ───────────────────────────────────────────\n {\n id: \"hero-centered\",\n label: \"Hero Centered\",\n category: \"Heroes\",\n content: `<section class=\"bg-primary py-24 px-6 text-center\">\n <div class=\"max-w-4xl mx-auto\">\n <h1 class=\"text-5xl md:text-7xl font-black text-on-primary mb-6\">Your Amazing Headline</h1>\n <p class=\"text-xl text-on-primary/80 mb-10 max-w-2xl mx-auto\">A compelling subtitle that explains your value proposition in one or two sentences.</p>\n <div class=\"flex gap-4 justify-center flex-wrap\">\n <a href=\"#\" class=\"px-8 py-4 bg-accent text-on-accent font-bold rounded-xl hover:opacity-90 transition\">Get Started</a>\n <a href=\"#\" class=\"px-8 py-4 border-2 border-on-primary text-on-primary font-bold rounded-xl hover:bg-on-primary/10 transition\">Learn More</a>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"6\" y=\"2\" width=\"12\" height=\"2\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"8\" y=\"5\" width=\"8\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"9\" y=\"8\" width=\"3\" height=\"1.5\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"13\" y=\"8\" width=\"3\" height=\"1.5\" rx=\".5\" fill=\"#d1d5db\"/></svg>`,\n },\n {\n id: \"hero-split\",\n label: \"Hero Split\",\n category: \"Heroes\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto grid md:grid-cols-2 gap-12 items-center\">\n <div>\n <h1 class=\"text-5xl font-black text-on-surface mb-6\">Build Something Amazing</h1>\n <p class=\"text-lg text-on-surface/70 mb-8\">Describe your product or service. Focus on the benefits and what makes you different.</p>\n <a href=\"#\" class=\"inline-block px-8 py-4 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Start Now</a>\n </div>\n <img src=\"https://placehold.co/600x400/e2e8f0/64748b?text=Your+Image\" alt=\"Hero image\" class=\"rounded-2xl w-full\" />\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"2\" width=\"10\" height=\"2\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"1\" y=\"5\" width=\"8\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"1\" y=\"8\" width=\"4\" height=\"1.5\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"13\" y=\"1\" width=\"10\" height=\"10\" rx=\"1\" fill=\"#e5e7eb\"/></svg>`,\n },\n {\n id: \"hero-image-bg\",\n label: \"Hero Image BG\",\n category: \"Heroes\",\n content: `<section class=\"relative bg-primary-dark py-32 px-6 text-center overflow-hidden\">\n <img src=\"https://placehold.co/1920x800/1f2937/374151?text=Background\" alt=\"\" class=\"absolute inset-0 w-full h-full object-cover opacity-40\" />\n <div class=\"relative max-w-4xl mx-auto\">\n <h1 class=\"text-5xl md:text-7xl font-black text-on-primary mb-6\">Bold Statement Here</h1>\n <p class=\"text-xl text-on-primary/80 mb-10 max-w-2xl mx-auto\">A powerful subtitle on top of a beautiful background image.</p>\n <a href=\"#\" class=\"inline-block px-10 py-4 bg-accent text-on-accent font-bold rounded-xl text-lg hover:opacity-90 transition\">Get Started</a>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#374151\"/><rect x=\"6\" y=\"2\" width=\"12\" height=\"2\" rx=\".5\" fill=\"#fff\"/><rect x=\"8\" y=\"5\" width=\"8\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"9\" y=\"8\" width=\"6\" height=\"1.5\" rx=\".5\" fill=\"#fff\"/></svg>`,\n },\n // ─── Features ─────────────────────────────────────────\n {\n id: \"features-grid\",\n label: \"Features Grid\",\n category: \"Features\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-4\">Features</h2>\n <p class=\"text-center text-on-surface/60 mb-12 max-w-2xl mx-auto\">Everything you need to succeed.</p>\n <div class=\"grid md:grid-cols-3 gap-8\">\n <div class=\"bg-primary/5 rounded-2xl p-8\">\n <div class=\"w-12 h-12 bg-primary rounded-xl flex items-center justify-center text-on-primary text-xl mb-4\">⚡</div>\n <h3 class=\"text-xl font-black text-on-surface mb-2\">Lightning Fast</h3>\n <p class=\"text-on-surface/60\">Built for speed from the ground up.</p>\n </div>\n <div class=\"bg-primary/5 rounded-2xl p-8\">\n <div class=\"w-12 h-12 bg-secondary rounded-xl flex items-center justify-center text-on-secondary text-xl mb-4\">🔒</div>\n <h3 class=\"text-xl font-black text-on-surface mb-2\">Secure</h3>\n <p class=\"text-on-surface/60\">Enterprise-grade security by default.</p>\n </div>\n <div class=\"bg-primary/5 rounded-2xl p-8\">\n <div class=\"w-12 h-12 bg-accent rounded-xl flex items-center justify-center text-on-accent text-xl mb-4\">🎨</div>\n <h3 class=\"text-xl font-black text-on-surface mb-2\">Beautiful</h3>\n <p class=\"text-on-surface/60\">Pixel-perfect designs that stand out.</p>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"9\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n {\n id: \"features-bento\",\n label: \"Bento Grid\",\n category: \"Features\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">Why Choose Us</h2>\n <div class=\"grid md:grid-cols-3 gap-4\">\n <div class=\"md:col-span-2 bg-primary rounded-2xl p-10 text-on-primary\">\n <h3 class=\"text-2xl font-black mb-3\">All-in-one Platform</h3>\n <p class=\"text-on-primary/80\">Everything you need under one roof. No more juggling between tools.</p>\n </div>\n <div class=\"bg-secondary rounded-2xl p-10 text-on-secondary\">\n <h3 class=\"text-2xl font-black mb-3\">Fast Setup</h3>\n <p class=\"text-on-secondary/80\">Get started in under 5 minutes.</p>\n </div>\n <div class=\"bg-accent rounded-2xl p-10 text-on-accent\">\n <h3 class=\"text-2xl font-black mb-3\">24/7 Support</h3>\n <p class=\"text-on-accent/80\">Always here when you need us.</p>\n </div>\n <div class=\"md:col-span-2 bg-on-surface/5 rounded-2xl p-10\">\n <h3 class=\"text-2xl font-black text-on-surface mb-3\">Analytics Dashboard</h3>\n <p class=\"text-on-surface/60\">Track everything that matters with beautiful real-time charts.</p>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"14\" height=\"4\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#10b981\"/><rect x=\"1\" y=\"7\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#f59e0b\"/><rect x=\"9\" y=\"7\" width=\"14\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n // ─── Testimonials ─────────────────────────────────────\n {\n id: \"testimonials-cards\",\n label: \"Testimonials\",\n category: \"Social Proof\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">What People Say</h2>\n <div class=\"grid md:grid-cols-3 gap-8\">\n <div class=\"bg-on-surface/5 rounded-2xl p-8\">\n <p class=\"text-on-surface/80 mb-6\">\"This product changed how we work. Absolutely incredible results in just weeks.\"</p>\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 bg-primary rounded-full flex items-center justify-center text-on-primary font-bold\">A</div>\n <div><p class=\"font-bold text-on-surface text-sm\">Alex Johnson</p><p class=\"text-xs text-on-surface/50\">CEO, TechCo</p></div>\n </div>\n </div>\n <div class=\"bg-on-surface/5 rounded-2xl p-8\">\n <p class=\"text-on-surface/80 mb-6\">\"The best tool I've used in my career. Support team is amazing.\"</p>\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 bg-secondary rounded-full flex items-center justify-center text-on-secondary font-bold\">M</div>\n <div><p class=\"font-bold text-on-surface text-sm\">Maria Garcia</p><p class=\"text-xs text-on-surface/50\">Designer, StudioX</p></div>\n </div>\n </div>\n <div class=\"bg-on-surface/5 rounded-2xl p-8\">\n <p class=\"text-on-surface/80 mb-6\">\"10x improvement in productivity. I recommend it to everyone.\"</p>\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 bg-accent rounded-full flex items-center justify-center text-on-accent font-bold\">S</div>\n <div><p class=\"font-bold text-on-surface text-sm\">Sam Lee</p><p class=\"text-xs text-on-surface/50\">CTO, BuildIt</p></div>\n </div>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"9\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n {\n id: \"logo-cloud\",\n label: \"Logo Cloud\",\n category: \"Social Proof\",\n content: `<section class=\"bg-surface py-16 px-6\">\n <div class=\"max-w-4xl mx-auto text-center\">\n <p class=\"text-sm font-bold text-on-surface/40 uppercase tracking-wider mb-8\">Trusted by industry leaders</p>\n <div class=\"flex flex-wrap justify-center items-center gap-12 opacity-50\">\n <span class=\"text-2xl font-black text-on-surface\">Brand</span>\n <span class=\"text-2xl font-black text-on-surface\">Company</span>\n <span class=\"text-2xl font-black text-on-surface\">Startup</span>\n <span class=\"text-2xl font-black text-on-surface\">Agency</span>\n <span class=\"text-2xl font-black text-on-surface\">Studio</span>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"2\" y=\"5\" width=\"4\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/><rect x=\"8\" y=\"5\" width=\"4\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/><rect x=\"14\" y=\"5\" width=\"4\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/><rect x=\"20\" y=\"5\" width=\"3\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/></svg>`,\n },\n // ─── Pricing ──────────────────────────────────────────\n {\n id: \"pricing-cards\",\n label: \"Pricing Cards\",\n category: \"Pricing\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-5xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-4\">Pricing</h2>\n <p class=\"text-center text-on-surface/60 mb-12\">Simple, transparent pricing.</p>\n <div class=\"grid md:grid-cols-3 gap-8\">\n <div class=\"border-2 border-on-surface/10 rounded-2xl p-8 bg-surface\">\n <h3 class=\"text-lg font-bold text-on-surface mb-2\">Basic</h3>\n <div class=\"text-4xl font-black text-on-surface mb-6\">$9<span class=\"text-lg font-normal text-on-surface/50\">/mo</span></div>\n <ul class=\"space-y-3 text-on-surface/70 mb-8\"><li>✓ 5 Projects</li><li>✓ Basic Support</li><li>✓ 1 GB Storage</li></ul>\n <a href=\"#\" class=\"block text-center px-6 py-3 border-2 border-primary text-primary font-bold rounded-xl hover:bg-primary/5 transition\">Choose Plan</a>\n </div>\n <div class=\"border-2 border-primary rounded-2xl p-8 bg-primary/5 relative\">\n <span class=\"absolute -top-3 left-1/2 -translate-x-1/2 bg-primary text-on-primary text-xs font-bold px-3 py-1 rounded-full\">Popular</span>\n <h3 class=\"text-lg font-bold text-on-surface mb-2\">Pro</h3>\n <div class=\"text-4xl font-black text-on-surface mb-6\">$29<span class=\"text-lg font-normal text-on-surface/50\">/mo</span></div>\n <ul class=\"space-y-3 text-on-surface/70 mb-8\"><li>✓ Unlimited Projects</li><li>✓ Priority Support</li><li>✓ 50 GB Storage</li></ul>\n <a href=\"#\" class=\"block text-center px-6 py-3 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Choose Plan</a>\n </div>\n <div class=\"border-2 border-on-surface/10 rounded-2xl p-8 bg-surface\">\n <h3 class=\"text-lg font-bold text-on-surface mb-2\">Enterprise</h3>\n <div class=\"text-4xl font-black text-on-surface mb-6\">$99<span class=\"text-lg font-normal text-on-surface/50\">/mo</span></div>\n <ul class=\"space-y-3 text-on-surface/70 mb-8\"><li>✓ Everything in Pro</li><li>✓ Dedicated Support</li><li>✓ Unlimited Storage</li></ul>\n <a href=\"#\" class=\"block text-center px-6 py-3 border-2 border-primary text-primary font-bold rounded-xl hover:bg-primary/5 transition\">Contact Sales</a>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"9\" y=\"0\" width=\"6\" height=\"11\" rx=\".5\" fill=\"#ddd6fe\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n // ─── FAQ ──────────────────────────────────────────────\n {\n id: \"faq-section\",\n label: \"FAQ\",\n category: \"Content\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-3xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">Frequently Asked Questions</h2>\n <div class=\"space-y-6\">\n <details class=\"bg-on-surface/5 rounded-xl p-6 group\" open>\n <summary class=\"font-bold text-on-surface cursor-pointer list-none flex justify-between items-center\">\n What is included in the free plan?\n <span class=\"text-on-surface/40 group-open:rotate-180 transition-transform\">▼</span>\n </summary>\n <p class=\"text-on-surface/60 mt-4\">The free plan includes up to 3 projects, basic analytics, and community support.</p>\n </details>\n <details class=\"bg-on-surface/5 rounded-xl p-6 group\">\n <summary class=\"font-bold text-on-surface cursor-pointer list-none flex justify-between items-center\">\n Can I upgrade at any time?\n <span class=\"text-on-surface/40 group-open:rotate-180 transition-transform\">▼</span>\n </summary>\n <p class=\"text-on-surface/60 mt-4\">Yes! You can upgrade or downgrade your plan at any time. Changes take effect immediately.</p>\n </details>\n <details class=\"bg-on-surface/5 rounded-xl p-6 group\">\n <summary class=\"font-bold text-on-surface cursor-pointer list-none flex justify-between items-center\">\n Do you offer refunds?\n <span class=\"text-on-surface/40 group-open:rotate-180 transition-transform\">▼</span>\n </summary>\n <p class=\"text-on-surface/60 mt-4\">We offer a 30-day money-back guarantee. No questions asked.</p>\n </details>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"3\" y=\"1\" width=\"18\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"3\" y=\"5\" width=\"18\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"3\" y=\"9\" width=\"18\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n // ─── Stats ────────────────────────────────────────────\n {\n id: \"stats-section\",\n label: \"Stats\",\n category: \"Content\",\n content: `<section class=\"bg-primary py-16 px-6\">\n <div class=\"max-w-5xl mx-auto grid grid-cols-2 md:grid-cols-4 gap-8 text-center\">\n <div><div class=\"text-4xl font-black text-on-primary\">10K+</div><p class=\"text-on-primary/70 mt-1 text-sm\">Customers</p></div>\n <div><div class=\"text-4xl font-black text-on-primary\">99.9%</div><p class=\"text-on-primary/70 mt-1 text-sm\">Uptime</p></div>\n <div><div class=\"text-4xl font-black text-on-primary\">50M+</div><p class=\"text-on-primary/70 mt-1 text-sm\">Requests/day</p></div>\n <div><div class=\"text-4xl font-black text-on-primary\">150+</div><p class=\"text-on-primary/70 mt-1 text-sm\">Countries</p></div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#6366f1\"/><rect x=\"2\" y=\"3\" width=\"4\" height=\"3\" rx=\".5\" fill=\"#fff\"/><rect x=\"8\" y=\"3\" width=\"4\" height=\"3\" rx=\".5\" fill=\"#fff\"/><rect x=\"14\" y=\"3\" width=\"4\" height=\"3\" rx=\".5\" fill=\"#fff\"/><rect x=\"20\" y=\"3\" width=\"3\" height=\"3\" rx=\".5\" fill=\"#fff\"/></svg>`,\n },\n // ─── Team ─────────────────────────────────────────────\n {\n id: \"team-section\",\n label: \"Team\",\n category: \"Content\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-5xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">Our Team</h2>\n <div class=\"grid md:grid-cols-4 gap-8 text-center\">\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">Jane Smith</h3>\n <p class=\"text-sm text-on-surface/50\">CEO</p>\n </div>\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">John Doe</h3>\n <p class=\"text-sm text-on-surface/50\">CTO</p>\n </div>\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">Lisa Park</h3>\n <p class=\"text-sm text-on-surface/50\">Designer</p>\n </div>\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">Mike Chen</h3>\n <p class=\"text-sm text-on-surface/50\">Engineer</p>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><circle cx=\"4\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/><circle cx=\"10\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/><circle cx=\"16\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/><circle cx=\"22\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/></svg>`,\n },\n // ─── CTA ──────────────────────────────────────────────\n {\n id: \"cta-section\",\n label: \"Call to Action\",\n category: \"CTA\",\n content: `<section class=\"bg-primary py-20 px-6\">\n <div class=\"max-w-3xl mx-auto text-center\">\n <h2 class=\"text-4xl font-black text-on-primary mb-4\">Ready to get started?</h2>\n <p class=\"text-lg text-on-primary/80 mb-8\">Join thousands of happy customers and start building today.</p>\n <a href=\"#\" class=\"inline-block px-10 py-4 bg-accent text-on-accent font-bold rounded-xl text-lg hover:opacity-90 transition\">Start Free Trial</a>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#6366f1\"/><rect x=\"6\" y=\"3\" width=\"12\" height=\"2\" rx=\".5\" fill=\"#fff\"/><rect x=\"8\" y=\"7\" width=\"8\" height=\"2\" rx=\".5\" fill=\"#f59e0b\"/></svg>`,\n },\n {\n id: \"newsletter-section\",\n label: \"Newsletter\",\n category: \"CTA\",\n content: `<section class=\"bg-on-surface/5 py-20 px-6\">\n <div class=\"max-w-xl mx-auto text-center\">\n <h2 class=\"text-3xl font-black text-on-surface mb-4\">Stay Updated</h2>\n <p class=\"text-on-surface/60 mb-8\">Get the latest news and updates straight to your inbox.</p>\n <form class=\"flex gap-3 max-w-md mx-auto\">\n <input type=\"email\" placeholder=\"your@email.com\" class=\"flex-1 px-4 py-3 rounded-xl border-2 border-on-surface/20 bg-surface focus:border-primary focus:outline-none\" />\n <button class=\"px-6 py-3 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Subscribe</button>\n </form>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"5\" y=\"6\" width=\"10\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"16\" y=\"6\" width=\"4\" height=\"2.5\" rx=\".5\" fill=\"#6366f1\"/></svg>`,\n },\n // ─── Footer ───────────────────────────────────────────\n {\n id: \"footer\",\n label: \"Footer\",\n category: \"Footer\",\n content: `<section class=\"bg-on-surface py-12 px-6\">\n <div class=\"max-w-6xl mx-auto flex flex-col md:flex-row justify-between items-center gap-6\">\n <div class=\"text-surface font-black text-xl\">YourBrand</div>\n <nav class=\"flex gap-6 text-surface/70 text-sm\">\n <a href=\"#\" class=\"hover:text-surface transition\">About</a>\n <a href=\"#\" class=\"hover:text-surface transition\">Features</a>\n <a href=\"#\" class=\"hover:text-surface transition\">Pricing</a>\n <a href=\"#\" class=\"hover:text-surface transition\">Contact</a>\n </nav>\n <p class=\"text-surface/50 text-xs\">© 2026 YourBrand. All rights reserved.</p>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#1f2937\"/><rect x=\"1\" y=\"5\" width=\"6\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"10\" y=\"5\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#6b7280\"/><rect x=\"16\" y=\"5\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#6b7280\"/></svg>`,\n },\n {\n id: \"footer-columns\",\n label: \"Footer Columns\",\n category: \"Footer\",\n content: `<section class=\"bg-on-surface py-16 px-6\">\n <div class=\"max-w-6xl mx-auto grid md:grid-cols-4 gap-8\">\n <div>\n <h4 class=\"text-surface font-black text-lg mb-4\">YourBrand</h4>\n <p class=\"text-surface/50 text-sm\">Building the future, one pixel at a time.</p>\n </div>\n <div>\n <h4 class=\"text-surface font-bold text-sm mb-4\">Product</h4>\n <ul class=\"space-y-2 text-surface/60 text-sm\"><li><a href=\"#\" class=\"hover:text-surface transition\">Features</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Pricing</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Changelog</a></li></ul>\n </div>\n <div>\n <h4 class=\"text-surface font-bold text-sm mb-4\">Company</h4>\n <ul class=\"space-y-2 text-surface/60 text-sm\"><li><a href=\"#\" class=\"hover:text-surface transition\">About</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Blog</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Careers</a></li></ul>\n </div>\n <div>\n <h4 class=\"text-surface font-bold text-sm mb-4\">Legal</h4>\n <ul class=\"space-y-2 text-surface/60 text-sm\"><li><a href=\"#\" class=\"hover:text-surface transition\">Privacy</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Terms</a></li></ul>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#1f2937\"/><rect x=\"1\" y=\"2\" width=\"5\" height=\"1\" rx=\".25\" fill=\"#fff\"/><rect x=\"8\" y=\"2\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"8\" y=\"4\" width=\"3\" height=\".5\" rx=\".25\" fill=\"#6b7280\"/><rect x=\"8\" y=\"5.5\" width=\"3\" height=\".5\" rx=\".25\" fill=\"#6b7280\"/><rect x=\"14\" y=\"2\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"20\" y=\"2\" width=\"3\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/></svg>`,\n },\n];\n","import { useEffect, useState, useRef, useCallback } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport type { Editor } from \"grapesjs\";\n\ninterface Props {\n editor: Editor | null;\n /** Bumped when theme/customColors change — forces color preview re-resolve */\n themeVersion?: number;\n /** Resolved theme colors keyed by semantic name (e.g. \"primary\" → \"#6366f1\") */\n themeColors?: Record<string, string>;\n}\n\ninterface ClassCategory {\n label: string;\n classes: string[];\n}\n\nconst CATEGORIES: { id: string; label: string; test: (c: string) => boolean }[] = [\n { id: \"layout\", label: \"Layout\", test: (c) => /^(flex|grid|block|inline|hidden|col-|row-|justify-|items-|self-|overflow-|order-|relative|absolute|fixed|sticky|inset-|top-|right-|bottom-|left-|z-|container)/.test(c) },\n { id: \"spacing\", label: \"Spacing\", test: (c) => /^(p-|px-|py-|pt-|pr-|pb-|pl-|m-|mx-|my-|mt-|mr-|mb-|ml-|gap-|space-)/.test(c) },\n { id: \"sizing\", label: \"Sizing\", test: (c) => /^(w-|h-|min-w-|max-w-|min-h-|max-h-|size-)/.test(c) },\n { id: \"typography\", label: \"Typography\", test: (c) => /^(text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|left|center|right|justify|wrap|nowrap|ellipsis|balance)|font-|leading-|tracking-|uppercase|lowercase|capitalize|italic|not-italic|truncate|line-clamp|whitespace-)/.test(c) },\n { id: \"colors\", label: \"Colors\", test: (c) => /^(bg-|text-(?!xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|left|center|right|justify|wrap|nowrap|ellipsis|balance)|from-|to-|via-|decoration-)/.test(c) },\n { id: \"borders\", label: \"Borders\", test: (c) => /^(border|rounded|ring-|divide-|outline-)/.test(c) },\n { id: \"effects\", label: \"Effects\", test: (c) => /^(shadow|opacity-|blur-|transition|duration-|ease-|animate-|transform|scale-|rotate-|translate-|hover:|focus:|active:|group-)/.test(c) },\n];\n\nfunction categorize(classes: string[]): ClassCategory[] {\n const buckets: Record<string, string[]> = {};\n const other: string[] = [];\n\n for (const cls of classes) {\n let matched = false;\n for (const cat of CATEGORIES) {\n // Strip responsive prefix for matching\n const bare = cls.replace(/^(sm:|md:|lg:|xl:|2xl:)/, \"\");\n if (cat.test(bare)) {\n (buckets[cat.id] ??= []).push(cls);\n matched = true;\n break;\n }\n }\n if (!matched) other.push(cls);\n }\n\n const result: ClassCategory[] = [];\n for (const cat of CATEGORIES) {\n if (buckets[cat.id]?.length) {\n result.push({ label: cat.label, classes: buckets[cat.id] });\n }\n }\n if (other.length) result.push({ label: \"Other\", classes: other });\n return result;\n}\n\n// Semantic theme color hints — grouped by property\nconst THEME_HINTS: { label: string; prefix: string; colors: { cls: string; name: string }[] }[] = [\n {\n label: \"Texto\", prefix: \"text-\",\n colors: [\n { cls: \"text-on-primary\", name: \"on-primary\" }, { cls: \"text-on-secondary\", name: \"on-secondary\" },\n { cls: \"text-on-accent\", name: \"on-accent\" }, { cls: \"text-on-surface\", name: \"on-surface\" },\n { cls: \"text-on-surface-muted\", name: \"on-surface-muted\" },\n ],\n },\n {\n label: \"Fondo\", prefix: \"bg-\",\n colors: [\n { cls: \"bg-primary\", name: \"primary\" }, { cls: \"bg-primary-light\", name: \"primary-light\" },\n { cls: \"bg-primary-dark\", name: \"primary-dark\" }, { cls: \"bg-secondary\", name: \"secondary\" },\n { cls: \"bg-accent\", name: \"accent\" }, { cls: \"bg-surface\", name: \"surface\" },\n { cls: \"bg-surface-alt\", name: \"surface-alt\" },\n ],\n },\n {\n label: \"Borde\", prefix: \"border-\",\n colors: [\n { cls: \"border-primary\", name: \"primary\" }, { cls: \"border-secondary\", name: \"secondary\" },\n { cls: \"border-accent\", name: \"accent\" }, { cls: \"border-surface-alt\", name: \"surface-alt\" },\n ],\n },\n];\n\n// Curated autocomplete list\nconst COMMON_CLASSES = [\n // Layout\n \"flex\", \"flex-col\", \"flex-row\", \"flex-wrap\", \"grid\", \"grid-cols-2\", \"grid-cols-3\", \"grid-cols-4\",\n \"block\", \"inline-block\", \"hidden\", \"relative\", \"absolute\", \"fixed\", \"sticky\",\n \"justify-start\", \"justify-center\", \"justify-end\", \"justify-between\", \"justify-around\",\n \"items-start\", \"items-center\", \"items-end\", \"items-stretch\",\n \"overflow-hidden\", \"overflow-auto\", \"z-10\", \"z-20\", \"z-50\",\n // Spacing\n \"p-0\", \"p-1\", \"p-2\", \"p-3\", \"p-4\", \"p-6\", \"p-8\", \"p-10\", \"p-12\", \"p-16\", \"p-20\",\n \"px-2\", \"px-4\", \"px-6\", \"px-8\", \"px-10\", \"px-12\", \"px-16\",\n \"py-2\", \"py-4\", \"py-6\", \"py-8\", \"py-10\", \"py-12\", \"py-16\", \"py-20\", \"py-24\",\n \"m-0\", \"m-auto\", \"mx-auto\", \"my-2\", \"my-4\", \"my-6\", \"my-8\",\n \"mt-2\", \"mt-4\", \"mt-6\", \"mt-8\", \"mb-2\", \"mb-4\", \"mb-6\", \"mb-8\",\n \"gap-1\", \"gap-2\", \"gap-3\", \"gap-4\", \"gap-6\", \"gap-8\", \"gap-10\", \"gap-12\",\n \"space-x-2\", \"space-x-4\", \"space-y-2\", \"space-y-4\", \"space-y-6\",\n // Sizing\n \"w-full\", \"w-auto\", \"w-1/2\", \"w-1/3\", \"w-2/3\", \"w-1/4\", \"w-3/4\", \"w-screen\",\n \"w-8\", \"w-10\", \"w-12\", \"w-16\", \"w-20\", \"w-24\", \"w-32\", \"w-48\", \"w-64\",\n \"h-full\", \"h-auto\", \"h-screen\", \"h-8\", \"h-10\", \"h-12\", \"h-16\", \"h-20\", \"h-24\", \"h-32\", \"h-48\", \"h-64\",\n \"max-w-sm\", \"max-w-md\", \"max-w-lg\", \"max-w-xl\", \"max-w-2xl\", \"max-w-4xl\", \"max-w-6xl\", \"max-w-7xl\", \"max-w-full\",\n \"min-h-screen\", \"min-h-0\",\n // Typography\n \"text-xs\", \"text-sm\", \"text-base\", \"text-lg\", \"text-xl\", \"text-2xl\", \"text-3xl\", \"text-4xl\", \"text-5xl\", \"text-6xl\",\n \"font-thin\", \"font-light\", \"font-normal\", \"font-medium\", \"font-semibold\", \"font-bold\", \"font-extrabold\", \"font-black\",\n \"text-left\", \"text-center\", \"text-right\", \"leading-tight\", \"leading-normal\", \"leading-relaxed\",\n \"tracking-tight\", \"tracking-normal\", \"tracking-wide\", \"uppercase\", \"lowercase\", \"capitalize\", \"italic\", \"truncate\",\n // Colors (semantic)\n \"bg-primary\", \"bg-primary-light\", \"bg-primary-dark\", \"bg-secondary\", \"bg-accent\", \"bg-surface\", \"bg-surface-alt\",\n \"text-on-primary\", \"text-on-secondary\", \"text-on-accent\", \"text-on-surface\", \"text-on-surface-muted\",\n // Colors (common)\n \"bg-white\", \"bg-black\", \"bg-transparent\", \"bg-gray-50\", \"bg-gray-100\", \"bg-gray-200\", \"bg-gray-800\", \"bg-gray-900\",\n \"text-white\", \"text-black\", \"text-gray-300\", \"text-gray-400\", \"text-gray-500\", \"text-gray-600\", \"text-gray-700\", \"text-gray-900\",\n // Borders\n \"border\", \"border-0\", \"border-2\", \"border-4\", \"border-t\", \"border-b\",\n \"border-gray-200\", \"border-gray-300\", \"border-gray-700\",\n \"rounded\", \"rounded-md\", \"rounded-lg\", \"rounded-xl\", \"rounded-2xl\", \"rounded-3xl\", \"rounded-full\", \"rounded-none\",\n \"ring-1\", \"ring-2\", \"ring-4\",\n // Effects\n \"shadow-sm\", \"shadow\", \"shadow-md\", \"shadow-lg\", \"shadow-xl\", \"shadow-2xl\", \"shadow-none\",\n \"opacity-0\", \"opacity-50\", \"opacity-75\", \"opacity-100\",\n \"transition\", \"transition-all\", \"transition-colors\", \"duration-150\", \"duration-200\", \"duration-300\",\n \"hover:opacity-80\", \"hover:scale-105\", \"hover:shadow-lg\",\n \"animate-pulse\", \"animate-bounce\",\n // Misc\n \"cursor-pointer\", \"select-none\", \"object-cover\", \"object-contain\", \"aspect-square\", \"aspect-video\",\n];\n\nexport default function TailwindClassEditor({ editor, themeVersion = 0, themeColors = {} }: Props) {\n const [classes, setClasses] = useState<string[]>([]);\n const [search, setSearch] = useState(\"\");\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [highlightIdx, setHighlightIdx] = useState(-1);\n const [selectedComponent, setSelectedComponent] = useState<any>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const suggestionsRef = useRef<HTMLDivElement>(null);\n\n const readClasses = useCallback((component: any) => {\n if (!component) return [];\n const attrs = component.getAttributes?.() || {};\n const modelClass = attrs.class || \"\";\n if (modelClass) {\n return modelClass.split(/\\s+/).filter((c: string) => c && !c.startsWith(\"gjs-\"));\n }\n const el = component.getEl?.();\n if (!el) return [];\n const raw = typeof el.className === \"string\" ? el.className : el.className?.baseVal || \"\";\n return raw.split(/\\s+/).filter((c: string) => c && !c.startsWith(\"gjs-\"));\n }, []);\n\n const writeClasses = useCallback((component: any, newClasses: string[]) => {\n if (!component) return;\n const merged = twMerge(newClasses.join(\" \"));\n const newClassList = merged.split(/\\s+/).filter(Boolean);\n\n const el = component.getEl();\n if (el) {\n const raw = typeof el.className === \"string\" ? el.className : el.className?.baseVal || \"\";\n const gjsClasses = raw.split(/\\s+/).filter((c: string) => c.startsWith(\"gjs-\"));\n el.className = [...gjsClasses, ...newClassList].join(\" \");\n }\n\n const currentClasses = component.getClasses();\n currentClasses.forEach((cls: string) => {\n if (!cls.startsWith(\"gjs-\")) component.removeClass(cls);\n });\n newClassList.forEach((cls: string) => component.addClass(cls));\n\n editor?.trigger(\"sidebar:change\");\n\n setClasses(newClassList);\n }, [editor]);\n\n useEffect(() => {\n if (!editor) return;\n const onSelected = (component: any) => {\n setSelectedComponent(component);\n setClasses(readClasses(component));\n setSearch(\"\");\n };\n const onDeselected = () => {\n setSelectedComponent(null);\n setClasses([]);\n };\n const onUpdate = (component: any) => {\n if (component === selectedComponent || editor.getSelected() === component) {\n setClasses(readClasses(component));\n }\n };\n\n editor.on(\"component:selected\", onSelected);\n editor.on(\"component:deselected\", onDeselected);\n editor.on(\"component:update\", onUpdate);\n\n const current = editor.getSelected();\n if (current) onSelected(current);\n\n return () => {\n editor.off(\"component:selected\", onSelected);\n editor.off(\"component:deselected\", onDeselected);\n editor.off(\"component:update\", onUpdate);\n };\n }, [editor, readClasses, selectedComponent]);\n\n const removeClass = (cls: string) => {\n if (!selectedComponent) return;\n writeClasses(selectedComponent, classes.filter((c) => c !== cls));\n };\n\n const addClass = (cls: string) => {\n if (!selectedComponent || !cls.trim()) return;\n writeClasses(selectedComponent, [...classes, cls.trim()]);\n setSearch(\"\");\n setShowSuggestions(false);\n inputRef.current?.focus();\n };\n\n const filteredSuggestions = search.trim()\n ? COMMON_CLASSES.filter(\n (c) => c.includes(search.trim().toLowerCase()) && !classes.includes(c)\n ).slice(0, 20)\n : [];\n\n const categories = categorize(classes);\n\n const getColorPreview = (cls: string): string | null => {\n if (!editor || !selectedComponent) return null;\n const bare = cls.replace(/^(sm:|md:|lg:|xl:|2xl:)/, \"\");\n if (!/^(bg-|text-|from-|to-|via-|border-)/.test(bare)) return null;\n if (/^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|left|center|right)/.test(bare)) return null;\n try {\n const doc = editor.Canvas.getDocument();\n const win = doc?.defaultView;\n if (!win) return null;\n const tmp = doc.createElement(\"div\");\n tmp.className = cls;\n tmp.style.position = \"absolute\";\n tmp.style.visibility = \"hidden\";\n doc.body.appendChild(tmp);\n const computed = win.getComputedStyle(tmp);\n const color = bare.startsWith(\"text-\") || bare.startsWith(\"decoration-\")\n ? computed.color\n : bare.startsWith(\"border-\")\n ? computed.borderColor\n : computed.backgroundColor;\n doc.body.removeChild(tmp);\n if (color && color !== \"rgba(0, 0, 0, 0)\" && color !== \"transparent\") return color;\n } catch { /* ignore */ }\n return null;\n };\n\n if (!selectedComponent) {\n return (\n <div className=\"p-4 text-center text-gray-500 text-xs\">\n <p className=\"mb-1 text-base\">◎</p>\n Selecciona un elemento para editar sus clases Tailwind\n </div>\n );\n }\n\n const tagName = selectedComponent.get?.(\"tagName\") || \"div\";\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"px-3 py-2 border-b border-gray-700 flex items-center gap-2\">\n <code className=\"text-[11px] bg-gray-800 text-brand-400 px-1.5 py-0.5 rounded font-mono\">\n &lt;{tagName}&gt;\n </code>\n <span className=\"text-[10px] text-gray-500\">{classes.length} clases</span>\n </div>\n\n <div className=\"px-3 py-2 border-b border-gray-700 relative\">\n <input\n ref={inputRef}\n type=\"text\"\n value={search}\n onChange={(e) => {\n setSearch(e.target.value);\n setShowSuggestions(true);\n setHighlightIdx(-1);\n }}\n onFocus={() => setShowSuggestions(true)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\" && showSuggestions && filteredSuggestions.length > 0) {\n e.preventDefault();\n setHighlightIdx((i) => Math.min(i + 1, filteredSuggestions.length - 1));\n } else if (e.key === \"ArrowUp\" && showSuggestions && filteredSuggestions.length > 0) {\n e.preventDefault();\n setHighlightIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === \"Enter\" && search.trim()) {\n e.preventDefault();\n if (showSuggestions && filteredSuggestions.length > 0) {\n addClass(filteredSuggestions[highlightIdx >= 0 ? highlightIdx : 0]);\n } else {\n addClass(search.trim());\n }\n } else if (e.key === \"Escape\") {\n setShowSuggestions(false);\n setSearch(\"\");\n setHighlightIdx(-1);\n }\n }}\n placeholder=\"Agregar clase...\"\n className=\"w-full bg-gray-800 border border-gray-600 rounded-lg px-3 py-1.5 text-xs text-gray-200 placeholder-gray-500 focus:border-brand-500 focus:outline-none\"\n />\n\n {showSuggestions && filteredSuggestions.length > 0 && (\n <div\n ref={suggestionsRef}\n className=\"absolute left-3 right-3 top-full mt-1 bg-gray-800 border border-gray-600 rounded-lg shadow-xl z-50 max-h-48 overflow-auto\"\n >\n {filteredSuggestions.map((s, i) => (\n <button\n key={s}\n ref={(el) => { if (i === highlightIdx && el) el.scrollIntoView({ block: \"nearest\" }); }}\n onMouseDown={(e) => {\n e.preventDefault();\n addClass(s);\n }}\n onMouseEnter={() => setHighlightIdx(i)}\n className={`w-full text-left px-3 py-1.5 text-xs transition-colors font-mono ${\n i === highlightIdx ? \"bg-brand-500/20 text-white\" : \"text-gray-300 hover:bg-gray-700 hover:text-white\"\n }`}\n >\n {s}\n </button>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"flex-1 overflow-auto p-3 space-y-3\">\n {categories.length === 0 && (\n <p className=\"text-xs text-gray-500 text-center py-4\">Sin clases Tailwind</p>\n )}\n {categories.map((cat) => (\n <div key={cat.label}>\n <p className=\"text-[10px] text-gray-500 font-bold uppercase tracking-wider mb-1.5\">\n {cat.label}\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {cat.classes.map((cls) => {\n const color = getColorPreview(cls);\n return (\n <span\n key={cls}\n className=\"inline-flex items-center gap-1 bg-gray-800 border border-gray-600 rounded-md px-2 py-0.5 text-[11px] font-mono text-gray-300 hover:border-gray-400 group\"\n >\n {color && (\n <span\n className=\"w-2.5 h-2.5 rounded-full border border-gray-500 shrink-0\"\n style={{ backgroundColor: color }}\n />\n )}\n {cls}\n <button\n onClick={() => removeClass(cls)}\n className=\"text-gray-600 hover:text-red-400 transition-colors ml-0.5 opacity-0 group-hover:opacity-100\"\n title=\"Eliminar\"\n >\n ×\n </button>\n </span>\n );\n })}\n </div>\n </div>\n ))}\n\n <div className=\"border-t border-gray-700 pt-3 mt-1 space-y-2.5\">\n <p className=\"text-[10px] text-gray-500 font-bold uppercase tracking-wider\">Colores del tema</p>\n {THEME_HINTS.map((group) => (\n <div key={group.label}>\n <p className=\"text-[10px] text-gray-600 mb-1\">{group.label}</p>\n <div className=\"flex flex-wrap gap-1\">\n {group.colors.map(({ cls, name }) => {\n const semanticName = cls.replace(/^(bg-|text-|border-)/, \"\");\n const color = themeColors[semanticName] || getColorPreview(cls);\n const isActive = classes.includes(cls);\n return (\n <button\n key={cls}\n onClick={() => isActive ? removeClass(cls) : addClass(cls)}\n className={`inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] font-mono transition-all ${\n isActive\n ? \"bg-brand-500/20 border border-brand-500 text-brand-300\"\n : \"bg-gray-800/60 border border-gray-700 text-gray-500 hover:border-gray-500 hover:text-gray-300\"\n }`}\n title={cls}\n >\n <span\n className=\"w-2.5 h-2.5 rounded-full border border-gray-600 shrink-0\"\n style={{ backgroundColor: color || \"#666\" }}\n />\n {name}\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import { useEffect, useRef, useState, useCallback } from \"react\";\nimport type { Editor } from \"grapesjs\";\n\ninterface Props {\n editor: Editor | null;\n}\n\nfunction readSrc(component: any): string {\n if (!component) return \"\";\n const attrs = component.getAttributes?.() || {};\n return attrs.src || \"\";\n}\n\nfunction readAlt(component: any): string {\n if (!component) return \"\";\n const attrs = component.getAttributes?.() || {};\n return attrs.alt || \"\";\n}\n\nfunction isImageComponent(component: any): boolean {\n if (!component) return false;\n if (component.get?.(\"type\") === \"image\") return true;\n const el = component.getEl?.();\n return el?.tagName === \"IMG\";\n}\n\nfunction isValidHttpUrl(value: string): boolean {\n if (!value) return false;\n try {\n const u = new URL(value);\n return u.protocol === \"http:\" || u.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nexport default function ImageSrcEditor({ editor }: Props) {\n const [selectedComponent, setSelectedComponent] = useState<any>(null);\n const [isImg, setIsImg] = useState(false);\n const [src, setSrc] = useState(\"\");\n const [alt, setAlt] = useState(\"\");\n const [previewError, setPreviewError] = useState(false);\n\n const apply = useCallback((next: { src?: string; alt?: string }) => {\n if (!selectedComponent) return;\n selectedComponent.addAttributes?.(next);\n if (next.src !== undefined) selectedComponent.set?.(\"src\", next.src);\n const el = selectedComponent.getEl?.();\n if (el) {\n if (next.src !== undefined) el.setAttribute(\"src\", next.src);\n if (next.alt !== undefined) el.setAttribute(\"alt\", next.alt);\n }\n editor?.trigger(\"sidebar:change\");\n }, [editor, selectedComponent]);\n\n const applySrc = useCallback(() => {\n if (!isValidHttpUrl(src)) return;\n apply({ src });\n }, [apply, src]);\n\n const applyAlt = useCallback(() => {\n apply({ alt });\n }, [apply, alt]);\n\n const prevCidRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!editor) return;\n\n const onSelected = (component: any) => {\n const cid: string | null = component?.cid ?? component?.getId?.() ?? null;\n const isSame = cid !== null && cid === prevCidRef.current;\n prevCidRef.current = cid;\n setSelectedComponent(component);\n const img = isImageComponent(component);\n setIsImg(img);\n if (isSame) return;\n if (img) {\n setSrc(readSrc(component));\n setAlt(readAlt(component));\n setPreviewError(false);\n } else {\n setSrc(\"\");\n setAlt(\"\");\n }\n };\n const onDeselected = () => {\n prevCidRef.current = null;\n setSelectedComponent(null);\n setIsImg(false);\n setSrc(\"\");\n setAlt(\"\");\n };\n\n editor.on(\"component:selected\", onSelected);\n editor.on(\"component:deselected\", onDeselected);\n\n const current = editor.getSelected();\n if (current) onSelected(current);\n\n return () => {\n editor.off(\"component:selected\", onSelected);\n editor.off(\"component:deselected\", onDeselected);\n };\n }, [editor]);\n\n if (!isImg) return null;\n\n const urlValid = isValidHttpUrl(src);\n\n return (\n <div className=\"p-3 border-b border-gray-800 bg-gray-900/50\">\n <p className=\"text-[10px] text-gray-400 font-bold uppercase tracking-wider mb-2\">Imagen</p>\n\n {src && !previewError && (\n <div className=\"mb-2 rounded-md overflow-hidden border border-gray-700 bg-gray-950\" style={{ aspectRatio: \"16 / 9\" }}>\n <img\n src={src}\n alt=\"\"\n className=\"w-full h-full object-cover\"\n onError={() => setPreviewError(true)}\n onLoad={() => setPreviewError(false)}\n />\n </div>\n )}\n\n <label className=\"block text-[10px] text-gray-500 uppercase tracking-wider mb-1\">URL</label>\n <div className=\"flex items-center gap-1 mb-2\">\n <input\n type=\"text\"\n value={src}\n onChange={(e) => { setSrc(e.target.value); setPreviewError(false); }}\n onKeyDown={(e) => { if (e.key === \"Enter\") applySrc(); }}\n placeholder=\"https://...\"\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1.5 outline-none border border-transparent focus:border-brand-500 min-w-0\"\n />\n <button\n onClick={applySrc}\n disabled={!urlValid}\n title=\"Aplicar URL\"\n className=\"w-7 h-7 flex items-center justify-center rounded bg-brand-500 hover:bg-brand-600 transition-colors shrink-0 disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n </button>\n </div>\n {src && !urlValid && (\n <p className=\"text-[10px] text-amber-500 mb-2\">URL inválida — debe empezar con http:// o https://</p>\n )}\n {previewError && urlValid && (\n <p className=\"text-[10px] text-red-400 mb-2\">No se pudo cargar la imagen desde esa URL.</p>\n )}\n\n <label className=\"block text-[10px] text-gray-500 uppercase tracking-wider mb-1\">Alt</label>\n <div className=\"flex items-center gap-1\">\n <input\n type=\"text\"\n value={alt}\n onChange={(e) => setAlt(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") applyAlt(); }}\n placeholder=\"Descripción...\"\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1.5 outline-none border border-transparent focus:border-brand-500 min-w-0\"\n />\n <button\n onClick={applyAlt}\n title=\"Aplicar alt\"\n className=\"w-7 h-7 flex items-center justify-center rounded bg-gray-700 hover:bg-gray-600 transition-colors shrink-0\"\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n </button>\n </div>\n </div>\n );\n}\n","/** GrapesJS theme CSS — injected at runtime to avoid CSS bundling. */\n\nexport type EditorVariant = \"classic\" | \"denik\";\n\n/** Classic dark theme — original EasyBits editor look (dark sidebar, black canvas, hierarchical block grid). */\nexport const GRAPES_DARK_CSS_CLASSIC = `\n/* Dark theme for GrapesJS editor — matches EasyBits dark sidebar */\n\n/* Main editor background */\n.gjs-one-bg { background-color: #111827 !important; }\n.gjs-two-color { color: #e5e7eb !important; }\n.gjs-three-bg { background-color: #1f2937 !important; }\n.gjs-four-color, .gjs-four-color-h:hover { color: #9ca3af !important; }\n\n/* Editor chrome */\n.gjs-editor { background-color: #000000 !important; }\n\n/* Block manager */\n.gjs-blocks-cs { background-color: #111827 !important; }\n.gjs-block { background-color: #1f2937 !important; color: #e5e7eb !important; border: 1px solid #374151 !important; border-radius: 8px !important; }\n.gjs-block:hover { border-color: #9870ED !important; }\n.gjs-block-label { color: #d1d5db !important; }\n.gjs-block svg { fill: #9ca3af !important; }\n\n/* Block categories */\n.gjs-block-categories { background-color: #111827 !important; }\n.gjs-block-category { background-color: #111827 !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-block-category .gjs-title { background-color: #111827 !important; color: #e5e7eb !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-block-category .gjs-title:hover { background-color: #1f2937 !important; }\n.gjs-block-category .gjs-caret-icon { color: #9ca3af !important; }\n\n/* Layer manager */\n.gjs-layers { background-color: #111827 !important; }\n.gjs-layer { background-color: #111827 !important; color: #e5e7eb !important; }\n.gjs-layer:hover { background-color: #1f2937 !important; }\n.gjs-layer-title { color: #e5e7eb !important; }\n.gjs-layer-title-inn { background-color: transparent !important; }\n.gjs-layer.gjs-selected .gjs-layer-title { background-color: rgba(152, 112, 237, 0.15) !important; }\n.gjs-layer-name { color: #e5e7eb !important; }\n.gjs-layer-vis { color: #9ca3af !important; }\n.gjs-layer-caret { color: #9ca3af !important; }\n\n/* Style manager */\n.gjs-sm-sectors { background-color: #111827 !important; }\n.gjs-sm-sector { background-color: #111827 !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-sm-sector .gjs-sm-sector-title { background-color: #111827 !important; color: #e5e7eb !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-sm-sector .gjs-sm-sector-title:hover { background-color: #1f2937 !important; }\n.gjs-sm-sector .gjs-sm-properties { background-color: #111827 !important; }\n.gjs-sm-label { color: #9ca3af !important; }\n.gjs-field { background-color: #1f2937 !important; border: 1px solid #374151 !important; color: #e5e7eb !important; }\n.gjs-field input, .gjs-field select, .gjs-field textarea { color: #e5e7eb !important; background-color: transparent !important; }\n.gjs-field .gjs-input-holder { color: #e5e7eb !important; }\n.gjs-field-arrows { color: #9ca3af !important; }\n.gjs-sm-composite { background-color: #111827 !important; }\n.gjs-sm-stack #gjs-sm-add { color: #9ca3af !important; }\n\n/* Trait manager */\n.gjs-trt-traits { background-color: #111827 !important; }\n.gjs-trt-trait { color: #e5e7eb !important; }\n\n/* Panels */\n.gjs-pn-panel { background-color: #111827 !important; }\n.gjs-pn-btn { color: #9ca3af !important; }\n.gjs-pn-btn:hover { color: #e5e7eb !important; }\n.gjs-pn-btn.gjs-pn-active { color: #9870ED !important; }\n\n/* Canvas — full width, no padding */\n.gjs-cv-canvas { background-color: #000000 !important; }\n.gjs-frame-wrapper { padding: 0 !important; }\n.gjs-frame { width: 100% !important; left: 0 !important; }\n\n/* Toolbar on selected component */\n.gjs-toolbar { background-color: #9870ED !important; }\n.gjs-toolbar-item { color: white !important; }\n\n/* Selection highlight */\n.gjs-selected { outline: 2px solid #9870ED !important; outline-offset: -2px; }\n.gjs-highlighter { outline: 2px solid #9870ED !important; }\n\n/* Scrollbars */\n.gjs-editor ::-webkit-scrollbar { width: 6px; }\n.gjs-editor ::-webkit-scrollbar-track { background: #111827; }\n.gjs-editor ::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }\n.gjs-editor ::-webkit-scrollbar-thumb:hover { background: #4b5563; }\n\n/* Hide native GrapesJS panel buttons (preview eye, etc.) but keep panel system functional */\n.gjs-pn-btn {\n display: none !important;\n}\n/* The panels container that holds the buttons row */\n.gjs-pn-commands,\n.gjs-pn-options,\n.gjs-pn-views {\n height: 0 !important;\n overflow: hidden !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n/* Rich text editor */\n.gjs-rte-toolbar { background-color: #1f2937 !important; border: 1px solid #374151 !important; }\n.gjs-rte-actionbar { background-color: #1f2937 !important; }\n.gjs-rte-action { color: #e5e7eb !important; }\n`;\n\n/**\n * Denik variant overrides — applied on top of CLASSIC.\n *\n * Differences vs classic:\n * - Editor chrome: white instead of black.\n * - Block manager: flat horizontal list (icon-box + label) instead of hierarchical grid.\n * Categories: \"Básicos\" first category always expanded (non-collapsible); other categories\n * collapsible with colored cube icons.\n * - Canvas: white frame floating with 32px margin inside a white canvas.\n */\nconst DENIK_OVERRIDES = `\n/* ═══ Denik variant overrides ═══ */\n\n/* Editor chrome */\n.gjs-editor { background-color: white !important; }\n\n/* Block manager — flat list */\n.gjs-blocks-cs { background: transparent !important; }\n.gjs-block-categories { background: transparent !important; padding: 0 !important; }\n\n/* All blocks: horizontal row — [icon-box] [label] */\n.gjs-blocks-c .gjs-block.gjs-block {\n background: transparent !important;\n color: #e5e7eb !important;\n border: none !important;\n border-radius: 6px !important;\n display: flex !important;\n flex-direction: row !important;\n align-items: center !important;\n justify-content: flex-start !important;\n text-align: left !important;\n gap: 10px !important;\n padding: 0 10px !important;\n margin: 0 !important;\n width: 100% !important;\n min-height: unset !important;\n height: 24px !important;\n box-shadow: none !important;\n cursor: grab !important;\n}\n.gjs-blocks-c .gjs-block.gjs-block:hover { background: rgba(255,255,255,0.06) !important; }\n\n/* Icon box: 24x24 rounded square #2D2D2D — target BOTH class variants */\n.gjs-block .gjs-block__media,\n.gjs-block .gjs-block-media {\n width: 24px !important;\n height: 24px !important;\n min-width: 24px !important;\n max-width: 24px !important;\n min-height: 24px !important;\n max-height: 24px !important;\n line-height: 0 !important;\n background: #2D2D2D !important;\n border-radius: 5px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n padding: 4px !important;\n flex-shrink: 0 !important;\n}\n.gjs-block .gjs-block__media svg,\n.gjs-block .gjs-block-media svg {\n width: 14px !important;\n height: 14px !important;\n display: block !important;\n}\n.gjs-block svg { fill: #9ca3af !important; stroke: #9ca3af !important; }\n\n/* Label: 14px, left-aligned */\n.gjs-blocks-c .gjs-block .gjs-block-label {\n color: #d1d5db !important;\n font-size: 14px !important;\n font-weight: 400 !important;\n text-align: left !important;\n padding: 0 !important;\n width: auto !important;\n flex: 1 !important;\n line-height: 24px !important;\n}\n\n/* Blocks container: vertical single-column list */\n.gjs-block-category:first-child .gjs-blocks-c { display: flex !important; gap: 12px !important; }\n.gjs-blocks-c {\n flex-direction: column !important;\n flex-wrap: nowrap !important;\n gap: 8px !important;\n padding: 4px 0 !important;\n width: 100% !important;\n}\n/* Respect GrapesJS collapse: when inline style has display:none, honor it */\n.gjs-blocks-c[style*=\"none\"] { display: none !important; }\n\n/* All categories: no border, transparent */\n.gjs-block-category {\n background: transparent !important;\n border: none !important;\n border-bottom: none !important;\n}\n\n/* ─── Básicos (first category): NOT collapsible, always open, flat ─── */\n.gjs-block-category:first-child .gjs-title {\n background: transparent !important;\n color: #9ca3af !important;\n font-size: 11px !important;\n font-weight: 600 !important;\n text-transform: uppercase !important;\n letter-spacing: 0.05em !important;\n padding: 14px 10px 6px !important;\n border: none !important;\n cursor: default !important;\n pointer-events: none !important;\n}\n.gjs-block-category:first-child .gjs-caret-icon { display: none !important; }\n/* Force always open even if GrapesJS collapsed it */\n.gjs-block-category:first-child .gjs-blocks-c { display: flex !important; }\n\n/* ─── Secciones (all other categories): collapsible ─── */\n.gjs-block-category:not(:first-child) .gjs-title {\n background: transparent !important;\n color: #e5e7eb !important;\n font-size: 14px !important;\n font-weight: 500 !important;\n padding: 8px 10px !important;\n border: none !important;\n display: flex !important;\n align-items: center !important;\n gap: 10px !important;\n cursor: pointer !important;\n}\n.gjs-block-category:not(:first-child) .gjs-title:hover { background: rgba(255,255,255,0.04) !important; }\n.gjs-block-category:not(:first-child) .gjs-caret-icon { color: #6b7280 !important; margin-left: auto !important; font-size: 12px !important; }\n\n/* \"Secciones\" label above the section categories */\n.gjs-block-category:nth-child(2)::before {\n content: 'Secciones';\n display: block;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #9ca3af;\n padding: 18px 10px 6px;\n}\n\n/* Section category title icons: colored cubes (override the title text with an icon prefix) */\n.gjs-block-category:not(:first-child) .gjs-title::before {\n content: '';\n display: inline-block;\n width: 24px;\n height: 24px;\n min-width: 24px;\n border-radius: 5px;\n background: #ec4899;\n}\n/* Per-category colors for the title icon */\n.gjs-block-category:nth-child(2) .gjs-title::before { background: #f472b6; }\n.gjs-block-category:nth-child(3) .gjs-title::before { background: #fb923c; }\n.gjs-block-category:nth-child(4) .gjs-title::before { background: #f87171; }\n.gjs-block-category:nth-child(5) .gjs-title::before { background: #facc15; }\n.gjs-block-category:nth-child(6) .gjs-title::before { background: #4ade80; }\n.gjs-block-category:nth-child(7) .gjs-title::before { background: #60a5fa; }\n.gjs-block-category:nth-child(8) .gjs-title::before { background: #c084fc; }\n.gjs-block-category:nth-child(9) .gjs-title::before { background: #a8a29e; }\n\n/* Section title: [icon] [text] ... [arrow] */\n.gjs-block-category:not(:first-child) .gjs-title { justify-content: flex-start !important; }\n.gjs-block-category:not(:first-child) .gjs-caret-icon { order: 99 !important; margin-left: auto !important; }\n\n/* Canvas — white floating frame with 32px margin */\n.gjs-cv-canvas { background-color: white !important; width: 100% !important; height: 100% !important; top: 0 !important; left: 0 !important; }\n.gjs-frame-wrapper { background: white !important; top: 32px !important; left: 32px !important; right: 32px !important; bottom: 32px !important; width: auto !important; height: auto !important; padding: 0 !important; }\n.gjs-frame { left: 0 !important; }\n`;\n\nexport const GRAPES_DARK_CSS_DENIK = GRAPES_DARK_CSS_CLASSIC + DENIK_OVERRIDES;\n\nexport function getGrapesCss(variant: EditorVariant = \"classic\"): string {\n return variant === \"denik\" ? GRAPES_DARK_CSS_DENIK : GRAPES_DARK_CSS_CLASSIC;\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useEffect","useRef","useState","useCallback","jsx","jsxs","jsx","jsxs","useEffect","useRef","useState","vars","t"]}
1
+ {"version":3,"sources":["../src/components4/GrapesEditor.tsx","../src/components4/blocks.ts","../src/components4/TailwindClassEditor.tsx","../src/components4/ImageSrcEditor.tsx","../src/components4/grapesDarkCss.ts"],"sourcesContent":["import { useEffect, useRef, useState, forwardRef, useImperativeHandle } from \"react\";\nimport type { Editor } from \"grapesjs\";\nimport { LANDING_BLOCKS } from \"./blocks\";\nimport { buildSingleThemeCss, buildCustomTheme, LANDING_THEMES } from \"../themes\";\nimport TailwindClassEditor from \"./TailwindClassEditor\";\nimport ImageSrcEditor from \"./ImageSrcEditor\";\nimport { getGrapesCss, type EditorVariant } from \"./grapesDarkCss\";\n\n/** Inject GrapesJS theme CSS once per variant at runtime */\nconst injectedVariants = new Set<EditorVariant>();\nfunction injectDarkCss(variant: EditorVariant) {\n if (typeof document === \"undefined\") return;\n if (injectedVariants.has(variant)) return;\n injectedVariants.add(variant);\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-grapes-css\", variant);\n style.textContent = getGrapesCss(variant);\n document.head.appendChild(style);\n}\n\n/** Flatten brand kit colors: keep string entries and convert extras array to named colors */\nfunction flattenColors(colors: Record<string, any> | undefined): Record<string, string> | undefined {\n if (!colors) return undefined;\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(colors)) {\n if (typeof v === \"string\") {\n out[k] = v;\n } else if (k === \"extras\" && Array.isArray(v)) {\n v.forEach((extra: { name?: string; hex?: string }, i: number) => {\n if (extra?.hex) {\n out[extra.name || `extra-${i + 1}`] = extra.hex;\n }\n });\n }\n }\n return Object.keys(out).length ? out : undefined;\n}\n\nexport interface AiAction {\n type: \"refine-element\";\n componentId: string;\n html: string;\n sectionHtml?: string;\n sectionComponentId?: string;\n isSection?: boolean;\n}\n\nexport interface GrapesEditorHandle {\n getEditor: () => Editor | null;\n getHtml: () => string;\n setHtml: (html: string) => void;\n /** Replace a component's HTML by its GrapesJS ID */\n replaceComponent: (componentId: string, newHtml: string) => void;\n /** Toggle preview mode, returns new state */\n togglePreview: () => boolean;\n /** Toggle sw-visibility (component border guides), returns new state */\n toggleSwVisibility: () => boolean;\n /** Scroll the canvas iframe to a section by data-section-id. Falls back to iframe DOM query if the component model lost the attribute. */\n scrollToSection: (sectionId: string) => void;\n /** Scroll the canvas to the N-th content section (skips __grapes_css__ style). Index-based is robust even when GrapesJS strips data-* attributes during parse. */\n scrollToIndex: (index: number) => void;\n /** Set canvas zoom level (percentage, e.g. 50 = 50%) */\n setZoom: (value: number) => void;\n /** Get current canvas zoom level */\n getZoom: () => number;\n /** Container element wrapping the GrapesJS canvas — useful to measure available width for fit-zoom calculations. */\n getCanvasContainer: () => HTMLElement | null;\n}\n\ninterface BrandKitItem {\n id: string;\n name: string;\n colors: Record<string, string>;\n fonts?: { heading?: string; body?: string } | null;\n mood?: string | null;\n logoUrl?: string | null;\n isDefault?: boolean;\n}\n\ninterface Props {\n initialHtml: string;\n theme?: string;\n customColors?: Record<string, string>;\n brandKits?: BrandKitItem[];\n onChange?: (html: string) => void;\n onAiAction?: (action: AiAction) => void;\n onThemeChange?: (themeId: string, customColors?: Record<string, string>, brandKitId?: string) => void;\n onBrandKitChange?: (brandKit: BrandKitItem | null) => void;\n /** Persisted brand kit ID — restored from metadata on load */\n initialBrandKitId?: string;\n /** Hide specific panel tabs (e.g. [\"blocks\"] for documents) */\n hiddenTabs?: PanelId[];\n /** Extra CSS injected into the canvas iframe (e.g. document page sizing) */\n canvasStyles?: string;\n /** Set to false to hide device switcher (always single viewport) */\n devices?: false;\n /** Which side to render the panel sidebar — default \"left\" */\n panelSide?: \"left\" | \"right\";\n /** Override default blocks (LANDING_BLOCKS). Pass custom blocks for different editors (e.g. presentations). */\n blocks?: { id: string; label: string; category: string; content: string | object; media?: string }[];\n /** Called when the most visible section changes due to canvas scroll */\n onVisibleSectionChange?: (sectionId: string) => void;\n /** Called once the canvas iframe has loaded — useful to apply auto-fit zoom based on document format. */\n onCanvasReady?: () => void;\n /**\n * Editor UI variant. Default `\"classic\"` preserves the original EasyBits look\n * (dark sidebar `w-80`, hierarchical block grid, black canvas). Set to\n * `\"denik\"` for the Denik look (sidebar `w-60 #11151A` with pill tabs, flat\n * block list with 24×24 icon boxes, white canvas with 32px margin, label\n * \"+ Sección\" on the blocks tab).\n */\n editorVariant?: EditorVariant;\n}\n\nexport type PanelId = \"blocks\" | \"layers\" | \"styles\" | \"themes\";\n\ninterface PanelTab { id: PanelId; label: string; icon: string }\n\nfunction getPanelTabs(variant: EditorVariant): readonly PanelTab[] {\n if (variant === \"denik\") {\n return [\n { id: \"blocks\", label: \"+ Sección\", icon: \"⊞\" },\n { id: \"layers\", label: \"Capas\", icon: \"◇\" },\n { id: \"styles\", label: \"Estilos\", icon: \"◑\" },\n { id: \"themes\", label: \"Temas\", icon: \"◈\" },\n ] as const;\n }\n return [\n { id: \"blocks\", label: \"Bloques\", icon: \"⊞\" },\n { id: \"layers\", label: \"Capas\", icon: \"☰\" },\n { id: \"styles\", label: \"Estilos\", icon: \"◑\" },\n { id: \"themes\", label: \"Temas\", icon: \"◈\" },\n ] as const;\n}\n\nconst GrapesEditor = forwardRef<GrapesEditorHandle, Props>(\n ({ initialHtml, theme = \"minimal\", customColors: rawCustomColors, brandKits, onChange, onAiAction, onThemeChange, onBrandKitChange, initialBrandKitId, hiddenTabs = [], canvasStyles, devices, panelSide = \"left\", blocks: customBlocks, onVisibleSectionChange, onCanvasReady, editorVariant = \"classic\" }, ref) => {\n // Inject theme CSS on first render (per-variant)\n useEffect(() => { injectDarkCss(editorVariant); }, [editorVariant]);\n\n // Strip non-string entries (e.g. extras array from brand kits)\n const customColors = flattenColors(rawCustomColors);\n const editorContainerRef = useRef<HTMLDivElement>(null);\n const blocksRef = useRef<HTMLDivElement>(null);\n const layersRef = useRef<HTMLDivElement>(null);\n const editorRef = useRef<Editor | null>(null);\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const onAiActionRef = useRef(onAiAction);\n onAiActionRef.current = onAiAction;\n const onVisibleSectionChangeRef = useRef(onVisibleSectionChange);\n onVisibleSectionChangeRef.current = onVisibleSectionChange;\n const onCanvasReadyRef = useRef(onCanvasReady);\n onCanvasReadyRef.current = onCanvasReady;\n const onThemeChangeRef = useRef(onThemeChange);\n onThemeChangeRef.current = onThemeChange;\n const onBrandKitChangeRef = useRef(onBrandKitChange);\n onBrandKitChangeRef.current = onBrandKitChange;\n const themeRef = useRef(theme);\n themeRef.current = theme;\n const customColorsRef = useRef(customColors);\n customColorsRef.current = customColors;\n const [activeBrandKitId, setActiveBrandKitId] = useState<string | null>(initialBrandKitId || null);\n const visibleTabs = getPanelTabs(editorVariant).filter((t) => !hiddenTabs.includes(t.id));\n const [activePanel, setActivePanel] = useState<PanelId>(() =>\n visibleTabs.find((t) => t.id === \"styles\")?.id ?? visibleTabs[0]?.id ?? \"styles\"\n );\n const [ready, setReady] = useState(false);\n const [themeVersion, setThemeVersion] = useState(0);\n\n useImperativeHandle(ref, () => ({\n getEditor: () => editorRef.current,\n getHtml: () => {\n const ed = editorRef.current;\n if (!ed) return \"\";\n const html = ed.getHtml();\n const css = ed.getCss();\n return css ? `<style>${css}</style>\\n${html}` : html;\n },\n setHtml: (html: string) => editorRef.current?.setComponents(html),\n togglePreview: () => {\n const ed = editorRef.current;\n if (!ed) return false;\n const cmd = ed.Commands;\n if (cmd.isActive(\"preview\")) {\n cmd.stop(\"preview\");\n if (!cmd.isActive(\"sw-visibility\")) cmd.run(\"sw-visibility\");\n return false;\n } else {\n if (cmd.isActive(\"sw-visibility\")) cmd.stop(\"sw-visibility\");\n ed.select();\n cmd.run(\"preview\");\n return true;\n }\n },\n toggleSwVisibility: () => {\n const ed = editorRef.current;\n if (!ed) return false;\n const cmd = ed.Commands;\n if (cmd.isActive(\"sw-visibility\")) {\n cmd.stop(\"sw-visibility\");\n return false;\n } else {\n cmd.run(\"sw-visibility\");\n return true;\n }\n },\n scrollToSection: (sectionId: string) => {\n const ed = editorRef.current;\n if (!ed) return;\n const wrapper = ed.DomComponents.getWrapper();\n if (!wrapper) return;\n const comps = wrapper.components().models || [];\n\n // (a) Try the GrapesJS model. This is the fast path when attributes were preserved.\n const target = comps.find((c: any) => c.getAttributes()[\"data-section-id\"] === sectionId);\n if (target) {\n ed.select(target);\n (ed.Canvas as any).scrollTo?.(target, { behavior: \"smooth\", block: \"start\", force: true });\n return;\n }\n\n // (b) GrapesJS sometimes discards custom `data-*` attributes from the model\n // while keeping them on the rendered DOM. Scroll via the iframe element directly —\n // Canvas.scrollTo accepts an HTMLElement too.\n const doc = ed.Canvas.getDocument();\n const el = doc?.querySelector(`[data-section-id=\"${sectionId}\"]`) as HTMLElement | null;\n if (el) {\n (ed.Canvas as any).scrollTo?.(el, { behavior: \"smooth\", block: \"start\", force: true });\n return;\n }\n\n console.warn(\"[scrollToSection] Section not found:\", sectionId, \"Model attrs:\", comps.map((c: any) => c.getAttributes()[\"data-section-id\"]), \"DOM has [data-section-id]?\", !!doc?.querySelector(\"[data-section-id]\"));\n },\n\n scrollToIndex: (index: number) => {\n const ed = editorRef.current;\n if (!ed) return;\n const wrapper = ed.DomComponents.getWrapper();\n if (!wrapper) return;\n const comps = wrapper.components().models || [];\n // Skip head-like tags that importers (splitIntoPages) prepend per page:\n // <link>, <style>, <script>, <meta>, <title>, <base>. Without this filter,\n // `contentComps[N]` can land on a zero-height <link> instead of the target\n // <section>, which makes every click scroll to the same place.\n const HEAD_TAGS = new Set([\"style\", \"script\", \"link\", \"meta\", \"title\", \"base\"]);\n const contentComps = comps.filter((c: any) => {\n const tag = (c.get(\"tagName\") || \"\").toLowerCase();\n return tag && !HEAD_TAGS.has(tag);\n });\n const target = contentComps[index];\n if (!target) return;\n ed.select(target);\n const el = target.getEl() as HTMLElement | undefined;\n if (index === 0) {\n ed.Canvas.getDocument()?.documentElement?.scrollTo({ top: 0, behavior: \"smooth\" });\n return;\n }\n el?.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n },\n replaceComponent: (componentId: string, newHtml: string) => {\n const ed = editorRef.current;\n if (!ed) return;\n function findById(parent: any): any {\n if (parent.getId() === componentId) return parent;\n for (const child of parent.components().models || []) {\n const found = findById(child);\n if (found) return found;\n }\n return null;\n }\n const wrapper = ed.DomComponents.getWrapper();\n if (!wrapper) return;\n const comp = findById(wrapper);\n if (comp) {\n comp.replaceWith(newHtml);\n } else {\n console.warn(\"[replaceComponent] Component not found:\", componentId);\n }\n },\n setZoom: (value: number) => {\n editorRef.current?.Canvas.setZoom(value);\n },\n getZoom: () => {\n return editorRef.current?.Canvas.getZoom() ?? 100;\n },\n getCanvasContainer: () => editorContainerRef.current,\n }));\n\n function getThemeCss() {\n try {\n const cc = customColorsRef.current;\n if (cc && Object.keys(cc).length) {\n if (!cc[\"on-primary\"] && cc.primary) {\n const full = buildCustomTheme(cc as any);\n const vars = Object.entries(full.colors)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n return `:root {\\n${vars}\\n}`;\n }\n const vars = Object.entries(cc)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n return `:root {\\n${vars}\\n}`;\n }\n return buildSingleThemeCss(themeRef.current).css || \"\";\n } catch {\n return \"\";\n }\n }\n\n function findSectionAncestor(comp: any): any {\n let current = comp;\n while (current) {\n if (current.get(\"tagName\") === \"section\") return current;\n current = current.parent();\n }\n return null;\n }\n\n useEffect(() => {\n if (!editorContainerRef.current || editorRef.current) return;\n let mounted = true;\n\n (async () => {\n const grapesjs = (await import(\"grapesjs\")).default;\n if (!mounted || !editorContainerRef.current) return;\n\n // Inject grapesjs base CSS\n if (!document.querySelector('link[href*=\"grapes.min.css\"]')) {\n const link = document.createElement(\"link\");\n link.rel = \"stylesheet\";\n link.href = \"https://unpkg.com/grapesjs/dist/css/grapes.min.css\";\n document.head.appendChild(link);\n }\n\n const initialThemeCss = getThemeCss();\n const COLORS_MAP: Record<string, string> = {\n primary: \"--color-primary\", \"primary-light\": \"--color-primary-light\", \"primary-dark\": \"--color-primary-dark\",\n secondary: \"--color-secondary\", accent: \"--color-accent\",\n surface: \"--color-surface\", \"surface-alt\": \"--color-surface-alt\",\n \"on-primary\": \"--color-on-primary\", \"on-secondary\": \"--color-on-secondary\", \"on-accent\": \"--color-on-accent\",\n \"on-surface\": \"--color-on-surface\", \"on-surface-muted\": \"--color-on-surface-muted\",\n };\n const fallbackRules: string[] = [];\n for (const [name, cssVar] of Object.entries(COLORS_MAP)) {\n fallbackRules.push(`.bg-${name} { background-color: var(${cssVar}) !important }`);\n fallbackRules.push(`.text-${name} { color: var(${cssVar}) !important }`);\n fallbackRules.push(`.border-${name} { border-color: var(${cssVar}) !important }`);\n fallbackRules.push(`.from-${name} { --tw-gradient-from: var(${cssVar}) }`);\n fallbackRules.push(`.to-${name} { --tw-gradient-to: var(${cssVar}) }`);\n fallbackRules.push(`.hover\\\\:bg-${name}:hover { background-color: var(${cssVar}) !important }`);\n fallbackRules.push(`.hover\\\\:text-${name}:hover { color: var(${cssVar}) !important }`);\n }\n\n const editor = grapesjs.init({\n container: editorContainerRef.current,\n height: \"100%\",\n width: \"auto\",\n fromElement: false,\n storageManager: false,\n panels: { defaults: [] },\n canvas: {\n scripts: [\n `data:text/javascript,window.tailwind=${encodeURIComponent(JSON.stringify({config:{\n theme: { extend: { colors: {\n primary: \"var(--color-primary)\",\n \"primary-light\": \"var(--color-primary-light)\",\n \"primary-dark\": \"var(--color-primary-dark)\",\n secondary: \"var(--color-secondary)\",\n accent: \"var(--color-accent)\",\n surface: \"var(--color-surface)\",\n \"surface-alt\": \"var(--color-surface-alt)\",\n \"on-primary\": \"var(--color-on-primary)\",\n \"on-secondary\": \"var(--color-on-secondary)\",\n \"on-accent\": \"var(--color-on-accent)\",\n \"on-surface\": \"var(--color-on-surface)\",\n \"on-surface-muted\": \"var(--color-on-surface-muted)\",\n }}}}\n }))}`,\n \"https://cdn.tailwindcss.com\",\n ],\n styles: [\n `data:text/css,${encodeURIComponent(initialThemeCss + \"\\n\" + fallbackRules.join(\"\\n\") + (canvasStyles ? \"\\n\" + canvasStyles : \"\"))}`,\n ],\n },\n deviceManager: devices === false ? false as any : {\n devices: [\n { name: \"Desktop\", width: \"\" },\n { name: \"Tablet\", width: \"768px\" },\n { name: \"Mobile\", width: \"375px\" },\n ],\n },\n styleManager: false as any,\n layerManager: {\n appendTo: layersRef.current!,\n },\n blockManager: hiddenTabs.includes(\"blocks\") ? false as any : {\n appendTo: blocksRef.current!,\n blocks: (customBlocks || LANDING_BLOCKS).map((b) => ({\n id: b.id,\n label: b.label,\n category: b.category,\n content: b.content,\n media: b.media,\n })),\n },\n allowScripts: 1,\n } as any);\n\n // ─── AI Commands ────────────────────────────────\n editor.Commands.add(\"ai-open-menu\", {\n run(ed: Editor) {\n const selected = ed.getSelected();\n if (!selected) return;\n const section = findSectionAncestor(selected);\n const isSection = selected.get(\"tagName\") === \"section\";\n onAiActionRef.current?.({\n type: \"refine-element\",\n componentId: selected.getId(),\n html: selected.toHTML(),\n sectionHtml: section ? section.toHTML() : undefined,\n sectionComponentId: section ? section.getId() : undefined,\n isSection,\n } as any);\n },\n });\n\n // ─── Switch to Styles tab on selection (only if not hidden) ───\n editor.on(\"component:selected\", () => {\n if (!hiddenTabs.includes(\"styles\")) setActivePanel(\"styles\");\n });\n editor.on(\"component:deselected\", () => {\n // Stay on current panel\n });\n\n // ─── Inject AI buttons into component toolbar on selection ───\n editor.on(\"component:selected\", (component: any) => {\n const toolbar = component.get(\"toolbar\") || [];\n const hasAi = toolbar.some((t: any) => t.id === \"ai-refine\");\n if (hasAi) return;\n\n const aiButtons: any[] = [\n {\n id: \"ai-menu\",\n label: `<svg title=\"AI\" width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"#9870ED\" style=\"vertical-align:middle;cursor:pointer\"><path d=\"M12 2l2.09 6.26L20.18 10l-6.09 1.74L12 18l-2.09-6.26L3.82 10l6.09-1.74z\"/><path d=\"M19 2l.75 2.25L22 5l-2.25.75L19 8l-.75-2.25L16 5l2.25-.75z\" opacity=\".7\"/><path d=\"M5 16l.5 1.5L7 18l-1.5.5L5 20l-.5-1.5L3 18l1.5-.5z\" opacity=\".5\"/></svg>`,\n command: \"ai-open-menu\",\n },\n ];\n\n component.set(\"toolbar\", [...toolbar, ...aiButtons]);\n });\n\n // ─── Theme + extras in iframe ────────────────────\n editor.on(\"canvas:frame:load\", ({ window: fw }: { window: Window }) => {\n const doc = fw.document;\n\n const style = doc.createElement(\"style\");\n style.id = \"easybits-theme\";\n style.textContent = getThemeCss();\n doc.head.appendChild(style);\n\n const shimmerStyle = doc.createElement(\"style\");\n shimmerStyle.textContent = `\n .easybits-refining { position: relative; overflow: hidden; }\n .easybits-refining::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(90deg, transparent 0%, rgba(152,112,237,0.08) 50%, transparent 100%);\n animation: easybits-shimmer 1.5s infinite;\n pointer-events: none;\n z-index: 9999;\n }\n @keyframes easybits-shimmer {\n 0% { transform: translateX(-100%); }\n 100% { transform: translateX(100%); }\n }\n `;\n doc.head.appendChild(shimmerStyle);\n\n const swStyle = doc.createElement(\"style\");\n swStyle.textContent = `\n .gjs-dashed *[data-gjs-type] {\n outline: 1px dashed rgba(152,112,237,0.35) !important;\n outline-offset: -1px;\n }\n .gjs-dashed *[data-gjs-type]:hover {\n outline-color: rgba(152,112,237,0.7) !important;\n }\n `;\n doc.head.appendChild(swStyle);\n\n if (canvasStyles) {\n const extraStyle = doc.createElement(\"style\");\n extraStyle.id = \"easybits-canvas-styles\";\n extraStyle.textContent = canvasStyles;\n doc.head.appendChild(extraStyle);\n }\n\n // Notify parent the canvas is ready so it can apply auto-fit zoom etc.\n // Defer one frame so the container has its final layout dimensions.\n requestAnimationFrame(() => onCanvasReadyRef.current?.());\n\n doc.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n if (e.key !== \" \") return;\n const el = e.target as HTMLElement;\n if (!el?.isContentEditable) return;\n const tag = el.tagName?.toLowerCase();\n if (tag === \"a\" || tag === \"button\" || el.closest(\"a\") || el.closest(\"button\")) {\n e.preventDefault();\n doc.execCommand(\"insertText\", false, \" \");\n }\n });\n\n if (!doc.getElementById(\"easybits-semantic-fallback\")) {\n const fallback = doc.createElement(\"style\");\n fallback.id = \"easybits-semantic-fallback\";\n const rules: string[] = [];\n for (const [name, cssVar] of Object.entries(COLORS_MAP)) {\n rules.push(`.bg-${name} { background-color: var(${cssVar}) !important }`);\n rules.push(`.text-${name} { color: var(${cssVar}) !important }`);\n rules.push(`.border-${name} { border-color: var(${cssVar}) !important }`);\n rules.push(`.from-${name} { --tw-gradient-from: var(${cssVar}) }`);\n rules.push(`.to-${name} { --tw-gradient-to: var(${cssVar}) }`);\n rules.push(`.hover\\\\:bg-${name}:hover { background-color: var(${cssVar}) !important }`);\n rules.push(`.hover\\\\:text-${name}:hover { color: var(${cssVar}) !important }`);\n }\n fallback.textContent = rules.join(\"\\n\");\n doc.head.appendChild(fallback);\n }\n\n const applyTwConfig = () => {\n if ((fw as any).tailwind) {\n (fw as any).tailwind.config = {\n theme: { extend: { colors: Object.fromEntries(\n Object.keys(COLORS_MAP).map(name => [name, `var(${COLORS_MAP[name]})`])\n )}}\n };\n }\n };\n applyTwConfig();\n const twScript = doc.querySelector('script[src*=\"tailwindcss\"]');\n if (twScript) {\n twScript.addEventListener(\"load\", () => {\n applyTwConfig();\n doc.body.style.display = \"none\";\n doc.body.offsetHeight;\n doc.body.style.display = \"\";\n });\n }\n\n // Scroll-spy\n {\n let scrollRaf = 0;\n const onScroll = () => {\n cancelAnimationFrame(scrollRaf);\n scrollRaf = requestAnimationFrame(() => {\n if (!onVisibleSectionChangeRef.current) return;\n const sectionEls = doc.querySelectorAll(\"[data-section-id]\");\n if (!sectionEls.length) return;\n const viewH = fw.innerHeight;\n let bestId = \"\";\n let bestVisible = 0;\n sectionEls.forEach((el) => {\n const rect = el.getBoundingClientRect();\n const top = Math.max(0, rect.top);\n const bottom = Math.min(viewH, rect.bottom);\n const visible = Math.max(0, bottom - top);\n if (visible > bestVisible) {\n bestVisible = visible;\n bestId = el.getAttribute(\"data-section-id\") || \"\";\n }\n });\n if (bestId) onVisibleSectionChangeRef.current(bestId);\n });\n };\n fw.addEventListener(\"scroll\", onScroll, { passive: true });\n }\n });\n\n if (initialHtml) editor.setComponents(initialHtml);\n\n // ─── Name layers based on content ───\n function nameLayers() {\n const wrapper = editor.DomComponents.getWrapper();\n if (!wrapper) return;\n wrapper.components().forEach((comp: any, i: number) => {\n if (comp.get(\"custom-name\")) return;\n const tag = (comp.get(\"tagName\") || \"\").toLowerCase();\n if (tag !== \"section\") return;\n const html = comp.toHTML().toLowerCase();\n let name = `Section ${i + 1}`;\n if (html.includes(\"hero\") || (i === 0 && html.includes(\"<h1\"))) name = \"Hero\";\n else if (html.includes(\"pricing\") || html.includes(\"precio\") || html.includes(\"inversión\")) name = \"Pricing\";\n else if (html.includes(\"testimonial\") || html.includes(\"dicen\") || html.includes(\"quote\")) name = \"Testimonials\";\n else if (html.includes(\"faq\") || html.includes(\"pregunt\") || html.includes(\"<details\")) name = \"FAQ\";\n else if (html.includes(\"footer\") || html.includes(\"©\") || html.includes(\"derechos\")) name = \"Footer\";\n else if (html.includes(\"feature\") || html.includes(\"palanca\") || html.includes(\"servicio\")) name = \"Features\";\n else if (html.includes(\"stat\") || html.includes(\"número\") || html.includes(\"+%\")) name = \"Stats\";\n else if (html.includes(\"team\") || html.includes(\"equipo\")) name = \"Team\";\n else if (html.includes(\"cta\") || html.includes(\"listo\") || html.includes(\"empez\")) name = \"CTA\";\n else if (html.includes(\"newsletter\") || html.includes(\"suscri\") || html.includes(\"email\")) name = \"Newsletter\";\n else if (html.includes(\"proceso\") || html.includes(\"step\") || html.includes(\"cómo func\")) name = \"Process\";\n else if (html.includes(\"problema\") || html.includes(\"pain\")) name = \"Problem\";\n else if (html.includes(\"logo\") || html.includes(\"trusted\") || html.includes(\"brand\")) name = \"Logo Cloud\";\n comp.set(\"custom-name\", name);\n });\n }\n editor.on(\"load\", nameLayers);\n editor.on(\"component:add\", () => setTimeout(nameLayers, 200));\n\n let userHasInteracted = false;\n const interactionEvents = [\n \"canvas:drop\", \"block:drag:stop\", \"component:drag:end\",\n \"component:input\", \"undo\", \"redo\",\n ];\n const markInteracted = () => { userHasInteracted = true; };\n interactionEvents.forEach((evt) => editor.on(evt, markInteracted));\n editor.on(\"sidebar:change\", markInteracted);\n\n const notify = () => {\n if (!userHasInteracted) return;\n const html = editor.getHtml();\n if (!html || !html.trim()) return;\n const css = editor.getCss();\n const fullHtml = css ? `<style>${css}</style>\\n${html}` : html;\n onChangeRef.current?.(fullHtml);\n };\n\n [\n \"component:update\", \"component:add\", \"component:remove\",\n \"component:drag:end\", \"component:input\", \"canvas:drop\",\n \"block:drag:stop\", \"undo\", \"redo\", \"sidebar:change\",\n ].forEach((evt) => editor.on(evt, notify));\n\n // Collapse all block categories except CTA\n try {\n const bm = editor.BlockManager;\n const cats = bm.getCategories?.();\n if (cats && cats.forEach) {\n cats.forEach((cat: any) => {\n try {\n const name = (typeof cat.get === \"function\" ? cat.get(\"id\") || cat.get(\"label\") : cat.id || cat.label) || \"\";\n if (name !== \"CTA\") {\n if (typeof cat.set === \"function\") cat.set(\"open\", false);\n }\n } catch { /* skip */ }\n });\n }\n } catch { /* skip */ }\n\n editorRef.current = editor;\n editor.on(\"load\", () => {\n setReady(true);\n let attempts = 0;\n const interval = setInterval(() => {\n attempts++;\n try {\n const active = editor.Commands?.getActive();\n if (!active) { clearInterval(interval); return; }\n for (const cmd of Object.keys(active)) {\n if (cmd === \"show-offset\") {\n editor.stopCommand(cmd);\n }\n }\n } catch {}\n if (attempts >= 30) clearInterval(interval);\n }, 100);\n if (editor.Commands.isActive(\"sw-visibility\")) {\n editor.Commands.stop(\"sw-visibility\");\n }\n });\n })().catch((err) => {\n console.error(\"GrapesJS init failed:\", err);\n });\n\n return () => {\n mounted = false;\n editorRef.current?.destroy();\n editorRef.current = null;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Update theme CSS dynamically\n useEffect(() => {\n const ed = editorRef.current;\n if (!ed) return;\n const doc = ed.Canvas.getDocument();\n if (!doc) return;\n\n const old = doc.getElementById(\"easybits-theme\");\n if (old) old.remove();\n const style = doc.createElement(\"style\");\n style.id = \"easybits-theme\";\n style.textContent = getThemeCss();\n doc.head.appendChild(style);\n\n const oldFallback = doc.getElementById(\"easybits-semantic-fallback\");\n if (oldFallback) {\n const content = oldFallback.textContent;\n oldFallback.remove();\n const fb = doc.createElement(\"style\");\n fb.id = \"easybits-semantic-fallback\";\n fb.textContent = content;\n doc.head.appendChild(fb);\n }\n\n setTimeout(() => setThemeVersion((v) => v + 1), 100);\n }, [theme, customColors]);\n\n const sidebarBorder = panelSide === \"right\" ? \"border-l\" : \"border-r\";\n\n const sidebarContainerClass = editorVariant === \"denik\"\n ? `w-60 shrink-0 flex flex-col bg-[#11151A] ${sidebarBorder} border-gray-700 overflow-hidden`\n : `w-80 shrink-0 flex flex-col bg-black ${sidebarBorder} border-gray-700 overflow-hidden`;\n const tabsRowClass = editorVariant === \"denik\"\n ? \"flex gap-0 px-3 py-3\"\n : \"flex border-b border-gray-700\";\n const tabButtonClass = (isActive: boolean) => {\n if (editorVariant === \"denik\") {\n return `px-4 py-2 text-sm font-medium transition-colors flex items-center gap-2 rounded-full ${\n isActive ? \"bg-[#2A2B31] text-white\" : \"text-gray-400 hover:text-gray-200\"\n }`;\n }\n return `flex-1 py-2.5 text-xs font-bold transition-colors ${\n isActive\n ? \"bg-gray-800 text-white border-b-2 border-brand-500\"\n : \"text-gray-400 hover:text-gray-200 hover:bg-gray-800/50\"\n }`;\n };\n\n const sidebar = (\n <div className={sidebarContainerClass}>\n <div className={tabsRowClass}>\n {visibleTabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => setActivePanel(tab.id)}\n className={tabButtonClass(activePanel === tab.id)}\n title={tab.label}\n >\n {editorVariant === \"denik\" ? (\n <span className=\"text-sm\">{tab.icon}</span>\n ) : (\n <span className=\"block text-base mb-0.5\">{tab.icon}</span>\n )}\n {tab.label}\n </button>\n ))}\n </div>\n\n {!hiddenTabs.includes(\"blocks\") && <div\n ref={blocksRef}\n className={`flex-1 overflow-auto p-2 ${activePanel === \"blocks\" ? \"\" : \"hidden\"}`}\n />}\n <div\n ref={layersRef}\n className={`flex-1 overflow-auto ${activePanel === \"layers\" ? \"\" : \"hidden\"}`}\n />\n {!hiddenTabs.includes(\"styles\") && <div className={`flex-1 overflow-auto ${activePanel === \"styles\" ? \"\" : \"hidden\"}`}>\n {ready && <ImageSrcEditor editor={editorRef.current} />}\n {ready && <TailwindClassEditor\n editor={editorRef.current}\n themeVersion={themeVersion}\n themeColors={(() => {\n if (customColors && Object.keys(customColors).length) return customColors;\n const t = LANDING_THEMES.find((t) => t.id === theme);\n return t?.colors || {};\n })()}\n />}\n </div>}\n {!hiddenTabs.includes(\"themes\") && <div className={`flex-1 overflow-auto p-3 ${activePanel === \"themes\" ? \"\" : \"hidden\"}`}>\n <p className=\"text-xs text-gray-400 font-bold uppercase tracking-wider mb-3\">Temas</p>\n <div className=\"grid grid-cols-2 gap-2\">\n {LANDING_THEMES.map((t) => {\n const isActive = theme === t.id;\n const displayColors = isActive && customColors && Object.keys(customColors).length\n ? { ...t.colors, ...customColors }\n : t.colors;\n return (\n <button\n key={t.id}\n onClick={() => {\n onThemeChangeRef.current?.(t.id);\n setActiveBrandKitId(null);\n onBrandKitChangeRef.current?.(null);\n }}\n className={`flex flex-col items-center gap-1.5 p-2.5 rounded-xl border-2 transition-all ${\n isActive\n ? \"border-brand-500 bg-brand-500/10\"\n : \"border-gray-700 hover:border-gray-500\"\n }`}\n >\n <div className=\"flex gap-1\">\n <div className=\"w-5 h-5 rounded-full border border-gray-600\" style={{ background: displayColors.primary }} title=\"Primary\" />\n <div className=\"w-5 h-5 rounded-full border border-gray-600\" style={{ background: displayColors.surface }} title=\"Surface\" />\n <div className=\"w-5 h-5 rounded-full border border-gray-600\" style={{ background: displayColors.accent }} title=\"Accent\" />\n </div>\n <span className=\"text-[10px] font-bold text-gray-300\">{t.label}</span>\n </button>\n );\n })}\n </div>\n\n {(() => {\n const active = LANDING_THEMES.find((t) => t.id === theme);\n const baseColors: Record<string, string> = active?.colors ? { ...active.colors } : {};\n const currentColors: Record<string, string> = customColors && Object.keys(customColors).length\n ? { ...baseColors, ...customColors }\n : baseColors;\n if (!Object.keys(currentColors).length) return null;\n const COLOR_LABELS: Record<string, string> = {\n primary: \"Primary\", \"primary-light\": \"Primary Light\", \"primary-dark\": \"Primary Dark\",\n secondary: \"Secondary\", accent: \"Accent\", surface: \"Surface\",\n \"surface-alt\": \"Surface Alt\", \"on-surface\": \"On Surface\",\n \"on-surface-muted\": \"On Surface Muted\", \"on-primary\": \"On Primary\",\n \"on-secondary\": \"On Secondary\", \"on-accent\": \"On Accent\",\n };\n return (\n <div className=\"mt-3 space-y-1\">\n {Object.entries(currentColors).map(([key, hex]) => (\n <label\n key={key}\n className=\"flex items-center gap-2 w-full px-2 py-1 rounded-lg hover:bg-gray-800 transition-colors group text-left cursor-pointer\"\n >\n <input\n type=\"color\"\n value={hex}\n onChange={(e) => {\n const updated = { ...currentColors, [key]: e.target.value };\n onThemeChangeRef.current?.(themeRef.current, updated);\n }}\n className=\"w-4 h-4 rounded border border-gray-600 shrink-0 cursor-pointer p-0 bg-transparent [&::-webkit-color-swatch-wrapper]:p-0 [&::-webkit-color-swatch]:border-none [&::-webkit-color-swatch]:rounded\"\n />\n <span className=\"text-[10px] text-gray-400 flex-1 truncate\">{COLOR_LABELS[key] || key}</span>\n <code className=\"text-[10px] text-gray-500 group-hover:text-gray-300 font-mono\">{hex}</code>\n </label>\n ))}\n </div>\n );\n })()}\n\n {brandKits && brandKits.length > 0 && (\n <>\n <p className=\"text-xs text-gray-400 font-bold uppercase tracking-wider mt-5 mb-3\">Brand Kits</p>\n <div className=\"grid grid-cols-2 gap-2\">\n {brandKits.map((bk) => {\n const bkBase = flattenColors(bk.colors as Record<string, any>) || {};\n const displayColors = activeBrandKitId === bk.id && customColors && Object.keys(customColors).length\n ? { ...bkBase, ...customColors }\n : bkBase;\n return (\n <button\n key={bk.id}\n onClick={() => {\n onThemeChangeRef.current?.(\"custom\", bkBase, bk.id);\n setActiveBrandKitId(bk.id);\n onBrandKitChangeRef.current?.(bk);\n }}\n className={`flex flex-col items-center gap-1.5 p-2.5 rounded-xl border-2 transition-all ${\n activeBrandKitId === bk.id\n ? \"border-brand-500 bg-brand-500/10\"\n : \"border-gray-700 hover:border-gray-500\"\n }`}\n >\n <div className=\"flex gap-1\">\n {[\"primary\", \"surface\", \"accent\"].map((key) => (\n <div\n key={key}\n className=\"w-5 h-5 rounded-full border border-gray-600\"\n style={{ background: displayColors[key] || \"#888\" }}\n />\n ))}\n </div>\n <span className=\"text-[10px] font-bold text-gray-300 truncate max-w-full\">{bk.name}</span>\n </button>\n );\n })}\n </div>\n {activeBrandKitId && (() => {\n const bk = brandKits?.find((b) => b.id === activeBrandKitId);\n if (!bk) return null;\n const baseColors = flattenColors(bk.colors as Record<string, any>) || {};\n const colors = customColors && Object.keys(customColors).length\n ? { ...baseColors, ...customColors }\n : baseColors;\n return (\n <div className=\"mt-3 space-y-1\">\n {Object.entries(colors).map(([key, hex]) => (\n <label\n key={key}\n className=\"flex items-center gap-2 w-full px-2 py-1 rounded-lg hover:bg-gray-800 transition-colors group text-left cursor-pointer\"\n >\n <input\n type=\"color\"\n value={hex}\n onChange={(e) => {\n const updated = { ...colors, [key]: e.target.value };\n onThemeChangeRef.current?.(\"custom\", updated, activeBrandKitId || undefined);\n }}\n className=\"w-4 h-4 rounded border border-gray-600 shrink-0 cursor-pointer p-0 bg-transparent [&::-webkit-color-swatch-wrapper]:p-0 [&::-webkit-color-swatch]:border-none [&::-webkit-color-swatch]:rounded\"\n />\n <span className=\"text-[10px] text-gray-400 flex-1 truncate\">{key}</span>\n <code className=\"text-[10px] text-gray-500 group-hover:text-gray-300 font-mono\">{hex}</code>\n </label>\n ))}\n </div>\n );\n })()}\n </>\n )}\n </div>}\n </div>\n );\n\n const canvasClass = editorVariant === \"denik\"\n ? \"flex-1 h-full bg-white relative\"\n : \"flex-1 h-full bg-black\";\n const canvas = <div ref={editorContainerRef} className={canvasClass} />;\n\n return (\n <div className=\"flex h-full w-full relative\">\n {panelSide === \"right\" ? <>{canvas}{sidebar}</> : <>{sidebar}{canvas}</>}\n\n {/* Glass overlay while GrapesJS loads */}\n <div\n className={`absolute inset-0 z-50 pointer-events-none bg-gray-950/40 backdrop-blur-[2px] transition-all duration-500 ${\n ready ? \"opacity-0 invisible\" : \"opacity-100\"\n }`}\n />\n </div>\n );\n }\n);\n\nGrapesEditor.displayName = \"GrapesEditor\";\nexport default GrapesEditor;\n","/**\n * Predefined blocks for GrapesJS editor.\n * All section blocks use semantic colors (bg-primary, text-on-surface, etc.)\n */\nexport const LANDING_BLOCKS = [\n // ─── Basic Elements ───────────────────────────────────\n {\n id: \"text-block\",\n label: \"Text\",\n category: \"Basic\",\n content: `<p class=\"text-base text-on-surface\">Edit this text. Double click to start typing.</p>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M4 7V4h16v3\"/><path d=\"M9 20h6\"/><path d=\"M12 4v16\"/></svg>`,\n },\n {\n id: \"heading-block\",\n label: \"Heading\",\n category: \"Basic\",\n content: `<h2 class=\"text-4xl font-black text-on-surface\">Your Heading Here</h2>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M4 12h16\"/><path d=\"M4 4v16\"/><path d=\"M20 4v16\"/></svg>`,\n },\n {\n id: \"image-block\",\n label: \"Image\",\n category: \"Basic\",\n content: { type: \"image\" },\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"/><path d=\"m21 15-5-5L5 21\"/></svg>`,\n },\n {\n id: \"button-block\",\n label: \"Button\",\n category: \"Basic\",\n content: `<a href=\"#\" class=\"inline-block px-8 py-3 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Click Me</a>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"8\" width=\"18\" height=\"8\" rx=\"4\"/><path d=\"M8 12h8\"/></svg>`,\n },\n {\n id: \"link-block\",\n label: \"Link\",\n category: \"Basic\",\n content: `<a href=\"#\" class=\"text-primary font-bold underline hover:text-primary-dark transition\">Your Link</a>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/></svg>`,\n },\n {\n id: \"video-block\",\n label: \"Video\",\n category: \"Basic\",\n content: { type: \"video\" },\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polygon points=\"5 3 19 12 5 21 5 3\"/></svg>`,\n },\n {\n id: \"divider-block\",\n label: \"Divider\",\n category: \"Basic\",\n content: `<hr class=\"border-t-2 border-gray-200 my-8\" />`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M3 12h18\"/></svg>`,\n },\n {\n id: \"spacer-block\",\n label: \"Spacer\",\n category: \"Basic\",\n content: `<div class=\"h-16\"></div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 5v14\"/><path d=\"M5 5h14\"/><path d=\"M5 19h14\"/></svg>`,\n },\n // ─── Layout ───────────────────────────────────────────\n {\n id: \"container-block\",\n label: \"Container\",\n category: \"Layout\",\n content: `<div class=\"max-w-6xl mx-auto px-6 py-12\"></div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/></svg>`,\n },\n {\n id: \"two-columns\",\n label: \"2 Columns\",\n category: \"Layout\",\n content: `<div class=\"grid grid-cols-2 gap-8 px-6 py-12 max-w-6xl mx-auto\">\n <div class=\"bg-surface-alt rounded-xl p-8 min-h-[120px]\"></div>\n <div class=\"bg-surface-alt rounded-xl p-8 min-h-[120px]\"></div>\n</div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"2\" y=\"3\" width=\"9\" height=\"18\" rx=\"1\"/><rect x=\"13\" y=\"3\" width=\"9\" height=\"18\" rx=\"1\"/></svg>`,\n },\n {\n id: \"three-columns\",\n label: \"3 Columns\",\n category: \"Layout\",\n content: `<div class=\"grid grid-cols-3 gap-6 px-6 py-12 max-w-6xl mx-auto\">\n <div class=\"bg-surface-alt rounded-xl p-6 min-h-[120px]\"></div>\n <div class=\"bg-surface-alt rounded-xl p-6 min-h-[120px]\"></div>\n <div class=\"bg-surface-alt rounded-xl p-6 min-h-[120px]\"></div>\n</div>`,\n media: `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><rect x=\"1\" y=\"3\" width=\"6\" height=\"18\" rx=\"1\"/><rect x=\"9\" y=\"3\" width=\"6\" height=\"18\" rx=\"1\"/><rect x=\"17\" y=\"3\" width=\"6\" height=\"18\" rx=\"1\"/></svg>`,\n },\n // ─── Heroes ───────────────────────────────────────────\n {\n id: \"hero-centered\",\n label: \"Hero Centered\",\n category: \"Heroes\",\n content: `<section class=\"bg-primary py-24 px-6 text-center\">\n <div class=\"max-w-4xl mx-auto\">\n <h1 class=\"text-5xl md:text-7xl font-black text-on-primary mb-6\">Your Amazing Headline</h1>\n <p class=\"text-xl text-on-primary/80 mb-10 max-w-2xl mx-auto\">A compelling subtitle that explains your value proposition in one or two sentences.</p>\n <div class=\"flex gap-4 justify-center flex-wrap\">\n <a href=\"#\" class=\"px-8 py-4 bg-accent text-on-accent font-bold rounded-xl hover:opacity-90 transition\">Get Started</a>\n <a href=\"#\" class=\"px-8 py-4 border-2 border-on-primary text-on-primary font-bold rounded-xl hover:bg-on-primary/10 transition\">Learn More</a>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"6\" y=\"2\" width=\"12\" height=\"2\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"8\" y=\"5\" width=\"8\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"9\" y=\"8\" width=\"3\" height=\"1.5\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"13\" y=\"8\" width=\"3\" height=\"1.5\" rx=\".5\" fill=\"#d1d5db\"/></svg>`,\n },\n {\n id: \"hero-split\",\n label: \"Hero Split\",\n category: \"Heroes\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto grid md:grid-cols-2 gap-12 items-center\">\n <div>\n <h1 class=\"text-5xl font-black text-on-surface mb-6\">Build Something Amazing</h1>\n <p class=\"text-lg text-on-surface/70 mb-8\">Describe your product or service. Focus on the benefits and what makes you different.</p>\n <a href=\"#\" class=\"inline-block px-8 py-4 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Start Now</a>\n </div>\n <img src=\"https://placehold.co/600x400/e2e8f0/64748b?text=Your+Image\" alt=\"Hero image\" class=\"rounded-2xl w-full\" />\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"2\" width=\"10\" height=\"2\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"1\" y=\"5\" width=\"8\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"1\" y=\"8\" width=\"4\" height=\"1.5\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"13\" y=\"1\" width=\"10\" height=\"10\" rx=\"1\" fill=\"#e5e7eb\"/></svg>`,\n },\n {\n id: \"hero-image-bg\",\n label: \"Hero Image BG\",\n category: \"Heroes\",\n content: `<section class=\"relative bg-primary-dark py-32 px-6 text-center overflow-hidden\">\n <img src=\"https://placehold.co/1920x800/1f2937/374151?text=Background\" alt=\"\" class=\"absolute inset-0 w-full h-full object-cover opacity-40\" />\n <div class=\"relative max-w-4xl mx-auto\">\n <h1 class=\"text-5xl md:text-7xl font-black text-on-primary mb-6\">Bold Statement Here</h1>\n <p class=\"text-xl text-on-primary/80 mb-10 max-w-2xl mx-auto\">A powerful subtitle on top of a beautiful background image.</p>\n <a href=\"#\" class=\"inline-block px-10 py-4 bg-accent text-on-accent font-bold rounded-xl text-lg hover:opacity-90 transition\">Get Started</a>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#374151\"/><rect x=\"6\" y=\"2\" width=\"12\" height=\"2\" rx=\".5\" fill=\"#fff\"/><rect x=\"8\" y=\"5\" width=\"8\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"9\" y=\"8\" width=\"6\" height=\"1.5\" rx=\".5\" fill=\"#fff\"/></svg>`,\n },\n // ─── Features ─────────────────────────────────────────\n {\n id: \"features-grid\",\n label: \"Features Grid\",\n category: \"Features\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-4\">Features</h2>\n <p class=\"text-center text-on-surface/60 mb-12 max-w-2xl mx-auto\">Everything you need to succeed.</p>\n <div class=\"grid md:grid-cols-3 gap-8\">\n <div class=\"bg-primary/5 rounded-2xl p-8\">\n <div class=\"w-12 h-12 bg-primary rounded-xl flex items-center justify-center text-on-primary text-xl mb-4\">⚡</div>\n <h3 class=\"text-xl font-black text-on-surface mb-2\">Lightning Fast</h3>\n <p class=\"text-on-surface/60\">Built for speed from the ground up.</p>\n </div>\n <div class=\"bg-primary/5 rounded-2xl p-8\">\n <div class=\"w-12 h-12 bg-secondary rounded-xl flex items-center justify-center text-on-secondary text-xl mb-4\">🔒</div>\n <h3 class=\"text-xl font-black text-on-surface mb-2\">Secure</h3>\n <p class=\"text-on-surface/60\">Enterprise-grade security by default.</p>\n </div>\n <div class=\"bg-primary/5 rounded-2xl p-8\">\n <div class=\"w-12 h-12 bg-accent rounded-xl flex items-center justify-center text-on-accent text-xl mb-4\">🎨</div>\n <h3 class=\"text-xl font-black text-on-surface mb-2\">Beautiful</h3>\n <p class=\"text-on-surface/60\">Pixel-perfect designs that stand out.</p>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"9\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n {\n id: \"features-bento\",\n label: \"Bento Grid\",\n category: \"Features\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">Why Choose Us</h2>\n <div class=\"grid md:grid-cols-3 gap-4\">\n <div class=\"md:col-span-2 bg-primary rounded-2xl p-10 text-on-primary\">\n <h3 class=\"text-2xl font-black mb-3\">All-in-one Platform</h3>\n <p class=\"text-on-primary/80\">Everything you need under one roof. No more juggling between tools.</p>\n </div>\n <div class=\"bg-secondary rounded-2xl p-10 text-on-secondary\">\n <h3 class=\"text-2xl font-black mb-3\">Fast Setup</h3>\n <p class=\"text-on-secondary/80\">Get started in under 5 minutes.</p>\n </div>\n <div class=\"bg-accent rounded-2xl p-10 text-on-accent\">\n <h3 class=\"text-2xl font-black mb-3\">24/7 Support</h3>\n <p class=\"text-on-accent/80\">Always here when you need us.</p>\n </div>\n <div class=\"md:col-span-2 bg-on-surface/5 rounded-2xl p-10\">\n <h3 class=\"text-2xl font-black text-on-surface mb-3\">Analytics Dashboard</h3>\n <p class=\"text-on-surface/60\">Track everything that matters with beautiful real-time charts.</p>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"14\" height=\"4\" rx=\".5\" fill=\"#6366f1\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#10b981\"/><rect x=\"1\" y=\"7\" width=\"6\" height=\"4\" rx=\".5\" fill=\"#f59e0b\"/><rect x=\"9\" y=\"7\" width=\"14\" height=\"4\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n // ─── Testimonials ─────────────────────────────────────\n {\n id: \"testimonials-cards\",\n label: \"Testimonials\",\n category: \"Social Proof\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-6xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">What People Say</h2>\n <div class=\"grid md:grid-cols-3 gap-8\">\n <div class=\"bg-on-surface/5 rounded-2xl p-8\">\n <p class=\"text-on-surface/80 mb-6\">\"This product changed how we work. Absolutely incredible results in just weeks.\"</p>\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 bg-primary rounded-full flex items-center justify-center text-on-primary font-bold\">A</div>\n <div><p class=\"font-bold text-on-surface text-sm\">Alex Johnson</p><p class=\"text-xs text-on-surface/50\">CEO, TechCo</p></div>\n </div>\n </div>\n <div class=\"bg-on-surface/5 rounded-2xl p-8\">\n <p class=\"text-on-surface/80 mb-6\">\"The best tool I've used in my career. Support team is amazing.\"</p>\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 bg-secondary rounded-full flex items-center justify-center text-on-secondary font-bold\">M</div>\n <div><p class=\"font-bold text-on-surface text-sm\">Maria Garcia</p><p class=\"text-xs text-on-surface/50\">Designer, StudioX</p></div>\n </div>\n </div>\n <div class=\"bg-on-surface/5 rounded-2xl p-8\">\n <p class=\"text-on-surface/80 mb-6\">\"10x improvement in productivity. I recommend it to everyone.\"</p>\n <div class=\"flex items-center gap-3\">\n <div class=\"w-10 h-10 bg-accent rounded-full flex items-center justify-center text-on-accent font-bold\">S</div>\n <div><p class=\"font-bold text-on-surface text-sm\">Sam Lee</p><p class=\"text-xs text-on-surface/50\">CTO, BuildIt</p></div>\n </div>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"9\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n {\n id: \"logo-cloud\",\n label: \"Logo Cloud\",\n category: \"Social Proof\",\n content: `<section class=\"bg-surface py-16 px-6\">\n <div class=\"max-w-4xl mx-auto text-center\">\n <p class=\"text-sm font-bold text-on-surface/40 uppercase tracking-wider mb-8\">Trusted by industry leaders</p>\n <div class=\"flex flex-wrap justify-center items-center gap-12 opacity-50\">\n <span class=\"text-2xl font-black text-on-surface\">Brand</span>\n <span class=\"text-2xl font-black text-on-surface\">Company</span>\n <span class=\"text-2xl font-black text-on-surface\">Startup</span>\n <span class=\"text-2xl font-black text-on-surface\">Agency</span>\n <span class=\"text-2xl font-black text-on-surface\">Studio</span>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"2\" y=\"5\" width=\"4\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/><rect x=\"8\" y=\"5\" width=\"4\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/><rect x=\"14\" y=\"5\" width=\"4\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/><rect x=\"20\" y=\"5\" width=\"3\" height=\"2\" rx=\".5\" fill=\"#d1d5db\"/></svg>`,\n },\n // ─── Pricing ──────────────────────────────────────────\n {\n id: \"pricing-cards\",\n label: \"Pricing Cards\",\n category: \"Pricing\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-5xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-4\">Pricing</h2>\n <p class=\"text-center text-on-surface/60 mb-12\">Simple, transparent pricing.</p>\n <div class=\"grid md:grid-cols-3 gap-8\">\n <div class=\"border-2 border-on-surface/10 rounded-2xl p-8 bg-surface\">\n <h3 class=\"text-lg font-bold text-on-surface mb-2\">Basic</h3>\n <div class=\"text-4xl font-black text-on-surface mb-6\">$9<span class=\"text-lg font-normal text-on-surface/50\">/mo</span></div>\n <ul class=\"space-y-3 text-on-surface/70 mb-8\"><li>✓ 5 Projects</li><li>✓ Basic Support</li><li>✓ 1 GB Storage</li></ul>\n <a href=\"#\" class=\"block text-center px-6 py-3 border-2 border-primary text-primary font-bold rounded-xl hover:bg-primary/5 transition\">Choose Plan</a>\n </div>\n <div class=\"border-2 border-primary rounded-2xl p-8 bg-primary/5 relative\">\n <span class=\"absolute -top-3 left-1/2 -translate-x-1/2 bg-primary text-on-primary text-xs font-bold px-3 py-1 rounded-full\">Popular</span>\n <h3 class=\"text-lg font-bold text-on-surface mb-2\">Pro</h3>\n <div class=\"text-4xl font-black text-on-surface mb-6\">$29<span class=\"text-lg font-normal text-on-surface/50\">/mo</span></div>\n <ul class=\"space-y-3 text-on-surface/70 mb-8\"><li>✓ Unlimited Projects</li><li>✓ Priority Support</li><li>✓ 50 GB Storage</li></ul>\n <a href=\"#\" class=\"block text-center px-6 py-3 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Choose Plan</a>\n </div>\n <div class=\"border-2 border-on-surface/10 rounded-2xl p-8 bg-surface\">\n <h3 class=\"text-lg font-bold text-on-surface mb-2\">Enterprise</h3>\n <div class=\"text-4xl font-black text-on-surface mb-6\">$99<span class=\"text-lg font-normal text-on-surface/50\">/mo</span></div>\n <ul class=\"space-y-3 text-on-surface/70 mb-8\"><li>✓ Everything in Pro</li><li>✓ Dedicated Support</li><li>✓ Unlimited Storage</li></ul>\n <a href=\"#\" class=\"block text-center px-6 py-3 border-2 border-primary text-primary font-bold rounded-xl hover:bg-primary/5 transition\">Contact Sales</a>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"1\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"9\" y=\"0\" width=\"6\" height=\"11\" rx=\".5\" fill=\"#ddd6fe\"/><rect x=\"17\" y=\"1\" width=\"6\" height=\"10\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n // ─── FAQ ──────────────────────────────────────────────\n {\n id: \"faq-section\",\n label: \"FAQ\",\n category: \"Content\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-3xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">Frequently Asked Questions</h2>\n <div class=\"space-y-6\">\n <details class=\"bg-on-surface/5 rounded-xl p-6 group\" open>\n <summary class=\"font-bold text-on-surface cursor-pointer list-none flex justify-between items-center\">\n What is included in the free plan?\n <span class=\"text-on-surface/40 group-open:rotate-180 transition-transform\">▼</span>\n </summary>\n <p class=\"text-on-surface/60 mt-4\">The free plan includes up to 3 projects, basic analytics, and community support.</p>\n </details>\n <details class=\"bg-on-surface/5 rounded-xl p-6 group\">\n <summary class=\"font-bold text-on-surface cursor-pointer list-none flex justify-between items-center\">\n Can I upgrade at any time?\n <span class=\"text-on-surface/40 group-open:rotate-180 transition-transform\">▼</span>\n </summary>\n <p class=\"text-on-surface/60 mt-4\">Yes! You can upgrade or downgrade your plan at any time. Changes take effect immediately.</p>\n </details>\n <details class=\"bg-on-surface/5 rounded-xl p-6 group\">\n <summary class=\"font-bold text-on-surface cursor-pointer list-none flex justify-between items-center\">\n Do you offer refunds?\n <span class=\"text-on-surface/40 group-open:rotate-180 transition-transform\">▼</span>\n </summary>\n <p class=\"text-on-surface/60 mt-4\">We offer a 30-day money-back guarantee. No questions asked.</p>\n </details>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"3\" y=\"1\" width=\"18\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"3\" y=\"5\" width=\"18\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"3\" y=\"9\" width=\"18\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/></svg>`,\n },\n // ─── Stats ────────────────────────────────────────────\n {\n id: \"stats-section\",\n label: \"Stats\",\n category: \"Content\",\n content: `<section class=\"bg-primary py-16 px-6\">\n <div class=\"max-w-5xl mx-auto grid grid-cols-2 md:grid-cols-4 gap-8 text-center\">\n <div><div class=\"text-4xl font-black text-on-primary\">10K+</div><p class=\"text-on-primary/70 mt-1 text-sm\">Customers</p></div>\n <div><div class=\"text-4xl font-black text-on-primary\">99.9%</div><p class=\"text-on-primary/70 mt-1 text-sm\">Uptime</p></div>\n <div><div class=\"text-4xl font-black text-on-primary\">50M+</div><p class=\"text-on-primary/70 mt-1 text-sm\">Requests/day</p></div>\n <div><div class=\"text-4xl font-black text-on-primary\">150+</div><p class=\"text-on-primary/70 mt-1 text-sm\">Countries</p></div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#6366f1\"/><rect x=\"2\" y=\"3\" width=\"4\" height=\"3\" rx=\".5\" fill=\"#fff\"/><rect x=\"8\" y=\"3\" width=\"4\" height=\"3\" rx=\".5\" fill=\"#fff\"/><rect x=\"14\" y=\"3\" width=\"4\" height=\"3\" rx=\".5\" fill=\"#fff\"/><rect x=\"20\" y=\"3\" width=\"3\" height=\"3\" rx=\".5\" fill=\"#fff\"/></svg>`,\n },\n // ─── Team ─────────────────────────────────────────────\n {\n id: \"team-section\",\n label: \"Team\",\n category: \"Content\",\n content: `<section class=\"bg-surface py-20 px-6\">\n <div class=\"max-w-5xl mx-auto\">\n <h2 class=\"text-4xl font-black text-on-surface text-center mb-12\">Our Team</h2>\n <div class=\"grid md:grid-cols-4 gap-8 text-center\">\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">Jane Smith</h3>\n <p class=\"text-sm text-on-surface/50\">CEO</p>\n </div>\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">John Doe</h3>\n <p class=\"text-sm text-on-surface/50\">CTO</p>\n </div>\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">Lisa Park</h3>\n <p class=\"text-sm text-on-surface/50\">Designer</p>\n </div>\n <div>\n <img src=\"https://placehold.co/200x200/e2e8f0/64748b?text=Photo\" alt=\"Team member\" class=\"w-24 h-24 rounded-full mx-auto mb-4 object-cover\" />\n <h3 class=\"font-bold text-on-surface\">Mike Chen</h3>\n <p class=\"text-sm text-on-surface/50\">Engineer</p>\n </div>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><circle cx=\"4\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/><circle cx=\"10\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/><circle cx=\"16\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/><circle cx=\"22\" cy=\"5\" r=\"2\" fill=\"#d1d5db\"/></svg>`,\n },\n // ─── CTA ──────────────────────────────────────────────\n {\n id: \"cta-section\",\n label: \"Call to Action\",\n category: \"CTA\",\n content: `<section class=\"bg-primary py-20 px-6\">\n <div class=\"max-w-3xl mx-auto text-center\">\n <h2 class=\"text-4xl font-black text-on-primary mb-4\">Ready to get started?</h2>\n <p class=\"text-lg text-on-primary/80 mb-8\">Join thousands of happy customers and start building today.</p>\n <a href=\"#\" class=\"inline-block px-10 py-4 bg-accent text-on-accent font-bold rounded-xl text-lg hover:opacity-90 transition\">Start Free Trial</a>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#6366f1\"/><rect x=\"6\" y=\"3\" width=\"12\" height=\"2\" rx=\".5\" fill=\"#fff\"/><rect x=\"8\" y=\"7\" width=\"8\" height=\"2\" rx=\".5\" fill=\"#f59e0b\"/></svg>`,\n },\n {\n id: \"newsletter-section\",\n label: \"Newsletter\",\n category: \"CTA\",\n content: `<section class=\"bg-on-surface/5 py-20 px-6\">\n <div class=\"max-w-xl mx-auto text-center\">\n <h2 class=\"text-3xl font-black text-on-surface mb-4\">Stay Updated</h2>\n <p class=\"text-on-surface/60 mb-8\">Get the latest news and updates straight to your inbox.</p>\n <form class=\"flex gap-3 max-w-md mx-auto\">\n <input type=\"email\" placeholder=\"your@email.com\" class=\"flex-1 px-4 py-3 rounded-xl border-2 border-on-surface/20 bg-surface focus:border-primary focus:outline-none\" />\n <button class=\"px-6 py-3 bg-primary text-on-primary font-bold rounded-xl hover:opacity-90 transition\">Subscribe</button>\n </form>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#f3f4f6\"/><rect x=\"5\" y=\"6\" width=\"10\" height=\"2.5\" rx=\".5\" fill=\"#e5e7eb\"/><rect x=\"16\" y=\"6\" width=\"4\" height=\"2.5\" rx=\".5\" fill=\"#6366f1\"/></svg>`,\n },\n // ─── Footer ───────────────────────────────────────────\n {\n id: \"footer\",\n label: \"Footer\",\n category: \"Footer\",\n content: `<section class=\"bg-on-surface py-12 px-6\">\n <div class=\"max-w-6xl mx-auto flex flex-col md:flex-row justify-between items-center gap-6\">\n <div class=\"text-surface font-black text-xl\">YourBrand</div>\n <nav class=\"flex gap-6 text-surface/70 text-sm\">\n <a href=\"#\" class=\"hover:text-surface transition\">About</a>\n <a href=\"#\" class=\"hover:text-surface transition\">Features</a>\n <a href=\"#\" class=\"hover:text-surface transition\">Pricing</a>\n <a href=\"#\" class=\"hover:text-surface transition\">Contact</a>\n </nav>\n <p class=\"text-surface/50 text-xs\">© 2026 YourBrand. All rights reserved.</p>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#1f2937\"/><rect x=\"1\" y=\"5\" width=\"6\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"10\" y=\"5\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#6b7280\"/><rect x=\"16\" y=\"5\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#6b7280\"/></svg>`,\n },\n {\n id: \"footer-columns\",\n label: \"Footer Columns\",\n category: \"Footer\",\n content: `<section class=\"bg-on-surface py-16 px-6\">\n <div class=\"max-w-6xl mx-auto grid md:grid-cols-4 gap-8\">\n <div>\n <h4 class=\"text-surface font-black text-lg mb-4\">YourBrand</h4>\n <p class=\"text-surface/50 text-sm\">Building the future, one pixel at a time.</p>\n </div>\n <div>\n <h4 class=\"text-surface font-bold text-sm mb-4\">Product</h4>\n <ul class=\"space-y-2 text-surface/60 text-sm\"><li><a href=\"#\" class=\"hover:text-surface transition\">Features</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Pricing</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Changelog</a></li></ul>\n </div>\n <div>\n <h4 class=\"text-surface font-bold text-sm mb-4\">Company</h4>\n <ul class=\"space-y-2 text-surface/60 text-sm\"><li><a href=\"#\" class=\"hover:text-surface transition\">About</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Blog</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Careers</a></li></ul>\n </div>\n <div>\n <h4 class=\"text-surface font-bold text-sm mb-4\">Legal</h4>\n <ul class=\"space-y-2 text-surface/60 text-sm\"><li><a href=\"#\" class=\"hover:text-surface transition\">Privacy</a></li><li><a href=\"#\" class=\"hover:text-surface transition\">Terms</a></li></ul>\n </div>\n </div>\n</section>`,\n media: `<svg viewBox=\"0 0 24 12\" fill=\"none\"><rect width=\"24\" height=\"12\" rx=\"1\" fill=\"#1f2937\"/><rect x=\"1\" y=\"2\" width=\"5\" height=\"1\" rx=\".25\" fill=\"#fff\"/><rect x=\"8\" y=\"2\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"8\" y=\"4\" width=\"3\" height=\".5\" rx=\".25\" fill=\"#6b7280\"/><rect x=\"8\" y=\"5.5\" width=\"3\" height=\".5\" rx=\".25\" fill=\"#6b7280\"/><rect x=\"14\" y=\"2\" width=\"4\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/><rect x=\"20\" y=\"2\" width=\"3\" height=\"1\" rx=\".25\" fill=\"#9ca3af\"/></svg>`,\n },\n];\n","import { useEffect, useState, useRef, useCallback } from \"react\";\nimport { twMerge } from \"tailwind-merge\";\nimport type { Editor } from \"grapesjs\";\n\ninterface Props {\n editor: Editor | null;\n /** Bumped when theme/customColors change — forces color preview re-resolve */\n themeVersion?: number;\n /** Resolved theme colors keyed by semantic name (e.g. \"primary\" → \"#6366f1\") */\n themeColors?: Record<string, string>;\n}\n\ninterface ClassCategory {\n label: string;\n classes: string[];\n}\n\nconst CATEGORIES: { id: string; label: string; test: (c: string) => boolean }[] = [\n { id: \"layout\", label: \"Layout\", test: (c) => /^(flex|grid|block|inline|hidden|col-|row-|justify-|items-|self-|overflow-|order-|relative|absolute|fixed|sticky|inset-|top-|right-|bottom-|left-|z-|container)/.test(c) },\n { id: \"spacing\", label: \"Spacing\", test: (c) => /^(p-|px-|py-|pt-|pr-|pb-|pl-|m-|mx-|my-|mt-|mr-|mb-|ml-|gap-|space-)/.test(c) },\n { id: \"sizing\", label: \"Sizing\", test: (c) => /^(w-|h-|min-w-|max-w-|min-h-|max-h-|size-)/.test(c) },\n { id: \"typography\", label: \"Typography\", test: (c) => /^(text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|left|center|right|justify|wrap|nowrap|ellipsis|balance)|font-|leading-|tracking-|uppercase|lowercase|capitalize|italic|not-italic|truncate|line-clamp|whitespace-)/.test(c) },\n { id: \"colors\", label: \"Colors\", test: (c) => /^(bg-|text-(?!xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|7xl|8xl|9xl|left|center|right|justify|wrap|nowrap|ellipsis|balance)|from-|to-|via-|decoration-)/.test(c) },\n { id: \"borders\", label: \"Borders\", test: (c) => /^(border|rounded|ring-|divide-|outline-)/.test(c) },\n { id: \"effects\", label: \"Effects\", test: (c) => /^(shadow|opacity-|blur-|transition|duration-|ease-|animate-|transform|scale-|rotate-|translate-|hover:|focus:|active:|group-)/.test(c) },\n];\n\nfunction categorize(classes: string[]): ClassCategory[] {\n const buckets: Record<string, string[]> = {};\n const other: string[] = [];\n\n for (const cls of classes) {\n let matched = false;\n for (const cat of CATEGORIES) {\n // Strip responsive prefix for matching\n const bare = cls.replace(/^(sm:|md:|lg:|xl:|2xl:)/, \"\");\n if (cat.test(bare)) {\n (buckets[cat.id] ??= []).push(cls);\n matched = true;\n break;\n }\n }\n if (!matched) other.push(cls);\n }\n\n const result: ClassCategory[] = [];\n for (const cat of CATEGORIES) {\n if (buckets[cat.id]?.length) {\n result.push({ label: cat.label, classes: buckets[cat.id] });\n }\n }\n if (other.length) result.push({ label: \"Other\", classes: other });\n return result;\n}\n\n// Semantic theme color hints — grouped by property\nconst THEME_HINTS: { label: string; prefix: string; colors: { cls: string; name: string }[] }[] = [\n {\n label: \"Texto\", prefix: \"text-\",\n colors: [\n { cls: \"text-on-primary\", name: \"on-primary\" }, { cls: \"text-on-secondary\", name: \"on-secondary\" },\n { cls: \"text-on-accent\", name: \"on-accent\" }, { cls: \"text-on-surface\", name: \"on-surface\" },\n { cls: \"text-on-surface-muted\", name: \"on-surface-muted\" },\n ],\n },\n {\n label: \"Fondo\", prefix: \"bg-\",\n colors: [\n { cls: \"bg-primary\", name: \"primary\" }, { cls: \"bg-primary-light\", name: \"primary-light\" },\n { cls: \"bg-primary-dark\", name: \"primary-dark\" }, { cls: \"bg-secondary\", name: \"secondary\" },\n { cls: \"bg-accent\", name: \"accent\" }, { cls: \"bg-surface\", name: \"surface\" },\n { cls: \"bg-surface-alt\", name: \"surface-alt\" },\n ],\n },\n {\n label: \"Borde\", prefix: \"border-\",\n colors: [\n { cls: \"border-primary\", name: \"primary\" }, { cls: \"border-secondary\", name: \"secondary\" },\n { cls: \"border-accent\", name: \"accent\" }, { cls: \"border-surface-alt\", name: \"surface-alt\" },\n ],\n },\n];\n\n// Curated autocomplete list\nconst COMMON_CLASSES = [\n // Layout\n \"flex\", \"flex-col\", \"flex-row\", \"flex-wrap\", \"grid\", \"grid-cols-2\", \"grid-cols-3\", \"grid-cols-4\",\n \"block\", \"inline-block\", \"hidden\", \"relative\", \"absolute\", \"fixed\", \"sticky\",\n \"justify-start\", \"justify-center\", \"justify-end\", \"justify-between\", \"justify-around\",\n \"items-start\", \"items-center\", \"items-end\", \"items-stretch\",\n \"overflow-hidden\", \"overflow-auto\", \"z-10\", \"z-20\", \"z-50\",\n // Spacing\n \"p-0\", \"p-1\", \"p-2\", \"p-3\", \"p-4\", \"p-6\", \"p-8\", \"p-10\", \"p-12\", \"p-16\", \"p-20\",\n \"px-2\", \"px-4\", \"px-6\", \"px-8\", \"px-10\", \"px-12\", \"px-16\",\n \"py-2\", \"py-4\", \"py-6\", \"py-8\", \"py-10\", \"py-12\", \"py-16\", \"py-20\", \"py-24\",\n \"m-0\", \"m-auto\", \"mx-auto\", \"my-2\", \"my-4\", \"my-6\", \"my-8\",\n \"mt-2\", \"mt-4\", \"mt-6\", \"mt-8\", \"mb-2\", \"mb-4\", \"mb-6\", \"mb-8\",\n \"gap-1\", \"gap-2\", \"gap-3\", \"gap-4\", \"gap-6\", \"gap-8\", \"gap-10\", \"gap-12\",\n \"space-x-2\", \"space-x-4\", \"space-y-2\", \"space-y-4\", \"space-y-6\",\n // Sizing\n \"w-full\", \"w-auto\", \"w-1/2\", \"w-1/3\", \"w-2/3\", \"w-1/4\", \"w-3/4\", \"w-screen\",\n \"w-8\", \"w-10\", \"w-12\", \"w-16\", \"w-20\", \"w-24\", \"w-32\", \"w-48\", \"w-64\",\n \"h-full\", \"h-auto\", \"h-screen\", \"h-8\", \"h-10\", \"h-12\", \"h-16\", \"h-20\", \"h-24\", \"h-32\", \"h-48\", \"h-64\",\n \"max-w-sm\", \"max-w-md\", \"max-w-lg\", \"max-w-xl\", \"max-w-2xl\", \"max-w-4xl\", \"max-w-6xl\", \"max-w-7xl\", \"max-w-full\",\n \"min-h-screen\", \"min-h-0\",\n // Typography\n \"text-xs\", \"text-sm\", \"text-base\", \"text-lg\", \"text-xl\", \"text-2xl\", \"text-3xl\", \"text-4xl\", \"text-5xl\", \"text-6xl\",\n \"font-thin\", \"font-light\", \"font-normal\", \"font-medium\", \"font-semibold\", \"font-bold\", \"font-extrabold\", \"font-black\",\n \"text-left\", \"text-center\", \"text-right\", \"leading-tight\", \"leading-normal\", \"leading-relaxed\",\n \"tracking-tight\", \"tracking-normal\", \"tracking-wide\", \"uppercase\", \"lowercase\", \"capitalize\", \"italic\", \"truncate\",\n // Colors (semantic)\n \"bg-primary\", \"bg-primary-light\", \"bg-primary-dark\", \"bg-secondary\", \"bg-accent\", \"bg-surface\", \"bg-surface-alt\",\n \"text-on-primary\", \"text-on-secondary\", \"text-on-accent\", \"text-on-surface\", \"text-on-surface-muted\",\n // Colors (common)\n \"bg-white\", \"bg-black\", \"bg-transparent\", \"bg-gray-50\", \"bg-gray-100\", \"bg-gray-200\", \"bg-gray-800\", \"bg-gray-900\",\n \"text-white\", \"text-black\", \"text-gray-300\", \"text-gray-400\", \"text-gray-500\", \"text-gray-600\", \"text-gray-700\", \"text-gray-900\",\n // Borders\n \"border\", \"border-0\", \"border-2\", \"border-4\", \"border-t\", \"border-b\",\n \"border-gray-200\", \"border-gray-300\", \"border-gray-700\",\n \"rounded\", \"rounded-md\", \"rounded-lg\", \"rounded-xl\", \"rounded-2xl\", \"rounded-3xl\", \"rounded-full\", \"rounded-none\",\n \"ring-1\", \"ring-2\", \"ring-4\",\n // Effects\n \"shadow-sm\", \"shadow\", \"shadow-md\", \"shadow-lg\", \"shadow-xl\", \"shadow-2xl\", \"shadow-none\",\n \"opacity-0\", \"opacity-50\", \"opacity-75\", \"opacity-100\",\n \"transition\", \"transition-all\", \"transition-colors\", \"duration-150\", \"duration-200\", \"duration-300\",\n \"hover:opacity-80\", \"hover:scale-105\", \"hover:shadow-lg\",\n \"animate-pulse\", \"animate-bounce\",\n // Misc\n \"cursor-pointer\", \"select-none\", \"object-cover\", \"object-contain\", \"aspect-square\", \"aspect-video\",\n];\n\nexport default function TailwindClassEditor({ editor, themeVersion = 0, themeColors = {} }: Props) {\n const [classes, setClasses] = useState<string[]>([]);\n const [search, setSearch] = useState(\"\");\n const [showSuggestions, setShowSuggestions] = useState(false);\n const [highlightIdx, setHighlightIdx] = useState(-1);\n const [selectedComponent, setSelectedComponent] = useState<any>(null);\n const inputRef = useRef<HTMLInputElement>(null);\n const suggestionsRef = useRef<HTMLDivElement>(null);\n\n const readClasses = useCallback((component: any) => {\n if (!component) return [];\n const attrs = component.getAttributes?.() || {};\n const modelClass = attrs.class || \"\";\n if (modelClass) {\n return modelClass.split(/\\s+/).filter((c: string) => c && !c.startsWith(\"gjs-\"));\n }\n const el = component.getEl?.();\n if (!el) return [];\n const raw = typeof el.className === \"string\" ? el.className : el.className?.baseVal || \"\";\n return raw.split(/\\s+/).filter((c: string) => c && !c.startsWith(\"gjs-\"));\n }, []);\n\n const writeClasses = useCallback((component: any, newClasses: string[]) => {\n if (!component) return;\n const merged = twMerge(newClasses.join(\" \"));\n const newClassList = merged.split(/\\s+/).filter(Boolean);\n\n const el = component.getEl();\n if (el) {\n const raw = typeof el.className === \"string\" ? el.className : el.className?.baseVal || \"\";\n const gjsClasses = raw.split(/\\s+/).filter((c: string) => c.startsWith(\"gjs-\"));\n el.className = [...gjsClasses, ...newClassList].join(\" \");\n }\n\n const currentClasses = component.getClasses();\n currentClasses.forEach((cls: string) => {\n if (!cls.startsWith(\"gjs-\")) component.removeClass(cls);\n });\n newClassList.forEach((cls: string) => component.addClass(cls));\n\n editor?.trigger(\"sidebar:change\");\n\n setClasses(newClassList);\n }, [editor]);\n\n useEffect(() => {\n if (!editor) return;\n const onSelected = (component: any) => {\n setSelectedComponent(component);\n setClasses(readClasses(component));\n setSearch(\"\");\n };\n const onDeselected = () => {\n setSelectedComponent(null);\n setClasses([]);\n };\n const onUpdate = (component: any) => {\n if (component === selectedComponent || editor.getSelected() === component) {\n setClasses(readClasses(component));\n }\n };\n\n editor.on(\"component:selected\", onSelected);\n editor.on(\"component:deselected\", onDeselected);\n editor.on(\"component:update\", onUpdate);\n\n const current = editor.getSelected();\n if (current) onSelected(current);\n\n return () => {\n editor.off(\"component:selected\", onSelected);\n editor.off(\"component:deselected\", onDeselected);\n editor.off(\"component:update\", onUpdate);\n };\n }, [editor, readClasses, selectedComponent]);\n\n const removeClass = (cls: string) => {\n if (!selectedComponent) return;\n writeClasses(selectedComponent, classes.filter((c) => c !== cls));\n };\n\n const addClass = (cls: string) => {\n if (!selectedComponent || !cls.trim()) return;\n writeClasses(selectedComponent, [...classes, cls.trim()]);\n setSearch(\"\");\n setShowSuggestions(false);\n inputRef.current?.focus();\n };\n\n const filteredSuggestions = search.trim()\n ? COMMON_CLASSES.filter(\n (c) => c.includes(search.trim().toLowerCase()) && !classes.includes(c)\n ).slice(0, 20)\n : [];\n\n const categories = categorize(classes);\n\n const getColorPreview = (cls: string): string | null => {\n if (!editor || !selectedComponent) return null;\n const bare = cls.replace(/^(sm:|md:|lg:|xl:|2xl:)/, \"\");\n if (!/^(bg-|text-|from-|to-|via-|border-)/.test(bare)) return null;\n if (/^text-(xs|sm|base|lg|xl|2xl|3xl|4xl|5xl|6xl|left|center|right)/.test(bare)) return null;\n try {\n const doc = editor.Canvas.getDocument();\n const win = doc?.defaultView;\n if (!win) return null;\n const tmp = doc.createElement(\"div\");\n tmp.className = cls;\n tmp.style.position = \"absolute\";\n tmp.style.visibility = \"hidden\";\n doc.body.appendChild(tmp);\n const computed = win.getComputedStyle(tmp);\n const color = bare.startsWith(\"text-\") || bare.startsWith(\"decoration-\")\n ? computed.color\n : bare.startsWith(\"border-\")\n ? computed.borderColor\n : computed.backgroundColor;\n doc.body.removeChild(tmp);\n if (color && color !== \"rgba(0, 0, 0, 0)\" && color !== \"transparent\") return color;\n } catch { /* ignore */ }\n return null;\n };\n\n if (!selectedComponent) {\n return (\n <div className=\"p-4 text-center text-gray-500 text-xs\">\n <p className=\"mb-1 text-base\">◎</p>\n Selecciona un elemento para editar sus clases Tailwind\n </div>\n );\n }\n\n const tagName = selectedComponent.get?.(\"tagName\") || \"div\";\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"px-3 py-2 border-b border-gray-700 flex items-center gap-2\">\n <code className=\"text-[11px] bg-gray-800 text-brand-400 px-1.5 py-0.5 rounded font-mono\">\n &lt;{tagName}&gt;\n </code>\n <span className=\"text-[10px] text-gray-500\">{classes.length} clases</span>\n </div>\n\n <div className=\"px-3 py-2 border-b border-gray-700 relative\">\n <input\n ref={inputRef}\n type=\"text\"\n value={search}\n onChange={(e) => {\n setSearch(e.target.value);\n setShowSuggestions(true);\n setHighlightIdx(-1);\n }}\n onFocus={() => setShowSuggestions(true)}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\" && showSuggestions && filteredSuggestions.length > 0) {\n e.preventDefault();\n setHighlightIdx((i) => Math.min(i + 1, filteredSuggestions.length - 1));\n } else if (e.key === \"ArrowUp\" && showSuggestions && filteredSuggestions.length > 0) {\n e.preventDefault();\n setHighlightIdx((i) => Math.max(i - 1, 0));\n } else if (e.key === \"Enter\" && search.trim()) {\n e.preventDefault();\n if (showSuggestions && filteredSuggestions.length > 0) {\n addClass(filteredSuggestions[highlightIdx >= 0 ? highlightIdx : 0]);\n } else {\n addClass(search.trim());\n }\n } else if (e.key === \"Escape\") {\n setShowSuggestions(false);\n setSearch(\"\");\n setHighlightIdx(-1);\n }\n }}\n placeholder=\"Agregar clase...\"\n className=\"w-full bg-gray-800 border border-gray-600 rounded-lg px-3 py-1.5 text-xs text-gray-200 placeholder-gray-500 focus:border-brand-500 focus:outline-none\"\n />\n\n {showSuggestions && filteredSuggestions.length > 0 && (\n <div\n ref={suggestionsRef}\n className=\"absolute left-3 right-3 top-full mt-1 bg-gray-800 border border-gray-600 rounded-lg shadow-xl z-50 max-h-48 overflow-auto\"\n >\n {filteredSuggestions.map((s, i) => (\n <button\n key={s}\n ref={(el) => { if (i === highlightIdx && el) el.scrollIntoView({ block: \"nearest\" }); }}\n onMouseDown={(e) => {\n e.preventDefault();\n addClass(s);\n }}\n onMouseEnter={() => setHighlightIdx(i)}\n className={`w-full text-left px-3 py-1.5 text-xs transition-colors font-mono ${\n i === highlightIdx ? \"bg-brand-500/20 text-white\" : \"text-gray-300 hover:bg-gray-700 hover:text-white\"\n }`}\n >\n {s}\n </button>\n ))}\n </div>\n )}\n </div>\n\n <div className=\"flex-1 overflow-auto p-3 space-y-3\">\n {categories.length === 0 && (\n <p className=\"text-xs text-gray-500 text-center py-4\">Sin clases Tailwind</p>\n )}\n {categories.map((cat) => (\n <div key={cat.label}>\n <p className=\"text-[10px] text-gray-500 font-bold uppercase tracking-wider mb-1.5\">\n {cat.label}\n </p>\n <div className=\"flex flex-wrap gap-1\">\n {cat.classes.map((cls) => {\n const color = getColorPreview(cls);\n return (\n <span\n key={cls}\n className=\"inline-flex items-center gap-1 bg-gray-800 border border-gray-600 rounded-md px-2 py-0.5 text-[11px] font-mono text-gray-300 hover:border-gray-400 group\"\n >\n {color && (\n <span\n className=\"w-2.5 h-2.5 rounded-full border border-gray-500 shrink-0\"\n style={{ backgroundColor: color }}\n />\n )}\n {cls}\n <button\n onClick={() => removeClass(cls)}\n className=\"text-gray-600 hover:text-red-400 transition-colors ml-0.5 opacity-0 group-hover:opacity-100\"\n title=\"Eliminar\"\n >\n ×\n </button>\n </span>\n );\n })}\n </div>\n </div>\n ))}\n\n <div className=\"border-t border-gray-700 pt-3 mt-1 space-y-2.5\">\n <p className=\"text-[10px] text-gray-500 font-bold uppercase tracking-wider\">Colores del tema</p>\n {THEME_HINTS.map((group) => (\n <div key={group.label}>\n <p className=\"text-[10px] text-gray-600 mb-1\">{group.label}</p>\n <div className=\"flex flex-wrap gap-1\">\n {group.colors.map(({ cls, name }) => {\n const semanticName = cls.replace(/^(bg-|text-|border-)/, \"\");\n const color = themeColors[semanticName] || getColorPreview(cls);\n const isActive = classes.includes(cls);\n return (\n <button\n key={cls}\n onClick={() => isActive ? removeClass(cls) : addClass(cls)}\n className={`inline-flex items-center gap-1 rounded-md px-1.5 py-0.5 text-[10px] font-mono transition-all ${\n isActive\n ? \"bg-brand-500/20 border border-brand-500 text-brand-300\"\n : \"bg-gray-800/60 border border-gray-700 text-gray-500 hover:border-gray-500 hover:text-gray-300\"\n }`}\n title={cls}\n >\n <span\n className=\"w-2.5 h-2.5 rounded-full border border-gray-600 shrink-0\"\n style={{ backgroundColor: color || \"#666\" }}\n />\n {name}\n </button>\n );\n })}\n </div>\n </div>\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import { useEffect, useRef, useState, useCallback } from \"react\";\nimport type { Editor } from \"grapesjs\";\n\ninterface Props {\n editor: Editor | null;\n}\n\nfunction readSrc(component: any): string {\n if (!component) return \"\";\n const attrs = component.getAttributes?.() || {};\n return attrs.src || \"\";\n}\n\nfunction readAlt(component: any): string {\n if (!component) return \"\";\n const attrs = component.getAttributes?.() || {};\n return attrs.alt || \"\";\n}\n\nfunction isImageComponent(component: any): boolean {\n if (!component) return false;\n if (component.get?.(\"type\") === \"image\") return true;\n const el = component.getEl?.();\n return el?.tagName === \"IMG\";\n}\n\nfunction isValidHttpUrl(value: string): boolean {\n if (!value) return false;\n try {\n const u = new URL(value);\n return u.protocol === \"http:\" || u.protocol === \"https:\";\n } catch {\n return false;\n }\n}\n\nexport default function ImageSrcEditor({ editor }: Props) {\n const [selectedComponent, setSelectedComponent] = useState<any>(null);\n const [isImg, setIsImg] = useState(false);\n const [src, setSrc] = useState(\"\");\n const [alt, setAlt] = useState(\"\");\n const [previewError, setPreviewError] = useState(false);\n\n const apply = useCallback((next: { src?: string; alt?: string }) => {\n if (!selectedComponent) return;\n selectedComponent.addAttributes?.(next);\n if (next.src !== undefined) selectedComponent.set?.(\"src\", next.src);\n const el = selectedComponent.getEl?.();\n if (el) {\n if (next.src !== undefined) el.setAttribute(\"src\", next.src);\n if (next.alt !== undefined) el.setAttribute(\"alt\", next.alt);\n }\n editor?.trigger(\"sidebar:change\");\n }, [editor, selectedComponent]);\n\n const applySrc = useCallback(() => {\n if (!isValidHttpUrl(src)) return;\n apply({ src });\n }, [apply, src]);\n\n const applyAlt = useCallback(() => {\n apply({ alt });\n }, [apply, alt]);\n\n const prevCidRef = useRef<string | null>(null);\n\n useEffect(() => {\n if (!editor) return;\n\n const onSelected = (component: any) => {\n const cid: string | null = component?.cid ?? component?.getId?.() ?? null;\n const isSame = cid !== null && cid === prevCidRef.current;\n prevCidRef.current = cid;\n setSelectedComponent(component);\n const img = isImageComponent(component);\n setIsImg(img);\n if (isSame) return;\n if (img) {\n setSrc(readSrc(component));\n setAlt(readAlt(component));\n setPreviewError(false);\n } else {\n setSrc(\"\");\n setAlt(\"\");\n }\n };\n const onDeselected = () => {\n prevCidRef.current = null;\n setSelectedComponent(null);\n setIsImg(false);\n setSrc(\"\");\n setAlt(\"\");\n };\n\n editor.on(\"component:selected\", onSelected);\n editor.on(\"component:deselected\", onDeselected);\n\n const current = editor.getSelected();\n if (current) onSelected(current);\n\n return () => {\n editor.off(\"component:selected\", onSelected);\n editor.off(\"component:deselected\", onDeselected);\n };\n }, [editor]);\n\n if (!isImg) return null;\n\n const urlValid = isValidHttpUrl(src);\n\n return (\n <div className=\"p-3 border-b border-gray-800 bg-gray-900/50\">\n <p className=\"text-[10px] text-gray-400 font-bold uppercase tracking-wider mb-2\">Imagen</p>\n\n {src && !previewError && (\n <div className=\"mb-2 rounded-md overflow-hidden border border-gray-700 bg-gray-950\" style={{ aspectRatio: \"16 / 9\" }}>\n <img\n src={src}\n alt=\"\"\n className=\"w-full h-full object-cover\"\n onError={() => setPreviewError(true)}\n onLoad={() => setPreviewError(false)}\n />\n </div>\n )}\n\n <label className=\"block text-[10px] text-gray-500 uppercase tracking-wider mb-1\">URL</label>\n <div className=\"flex items-center gap-1 mb-2\">\n <input\n type=\"text\"\n value={src}\n onChange={(e) => { setSrc(e.target.value); setPreviewError(false); }}\n onKeyDown={(e) => { if (e.key === \"Enter\") applySrc(); }}\n placeholder=\"https://...\"\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1.5 outline-none border border-transparent focus:border-brand-500 min-w-0\"\n />\n <button\n onClick={applySrc}\n disabled={!urlValid}\n title=\"Aplicar URL\"\n className=\"w-7 h-7 flex items-center justify-center rounded bg-brand-500 hover:bg-brand-600 transition-colors shrink-0 disabled:opacity-40 disabled:cursor-not-allowed\"\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n </button>\n </div>\n {src && !urlValid && (\n <p className=\"text-[10px] text-amber-500 mb-2\">URL inválida — debe empezar con http:// o https://</p>\n )}\n {previewError && urlValid && (\n <p className=\"text-[10px] text-red-400 mb-2\">No se pudo cargar la imagen desde esa URL.</p>\n )}\n\n <label className=\"block text-[10px] text-gray-500 uppercase tracking-wider mb-1\">Alt</label>\n <div className=\"flex items-center gap-1\">\n <input\n type=\"text\"\n value={alt}\n onChange={(e) => setAlt(e.target.value)}\n onKeyDown={(e) => { if (e.key === \"Enter\") applyAlt(); }}\n placeholder=\"Descripción...\"\n className=\"flex-1 bg-gray-800 text-xs text-white rounded px-2 py-1.5 outline-none border border-transparent focus:border-brand-500 min-w-0\"\n />\n <button\n onClick={applyAlt}\n title=\"Aplicar alt\"\n className=\"w-7 h-7 flex items-center justify-center rounded bg-gray-700 hover:bg-gray-600 transition-colors shrink-0\"\n >\n <svg className=\"w-3.5 h-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><polyline points=\"20 6 9 17 4 12\" /></svg>\n </button>\n </div>\n </div>\n );\n}\n","/** GrapesJS theme CSS — injected at runtime to avoid CSS bundling. */\n\nexport type EditorVariant = \"classic\" | \"denik\";\n\n/** Classic dark theme — original EasyBits editor look (dark sidebar, black canvas, hierarchical block grid). */\nexport const GRAPES_DARK_CSS_CLASSIC = `\n/* Dark theme for GrapesJS editor — matches EasyBits dark sidebar */\n\n/* Main editor background */\n.gjs-one-bg { background-color: #111827 !important; }\n.gjs-two-color { color: #e5e7eb !important; }\n.gjs-three-bg { background-color: #1f2937 !important; }\n.gjs-four-color, .gjs-four-color-h:hover { color: #9ca3af !important; }\n\n/* Editor chrome */\n.gjs-editor { background-color: #000000 !important; }\n\n/* Block manager */\n.gjs-blocks-cs { background-color: #111827 !important; }\n.gjs-block { background-color: #1f2937 !important; color: #e5e7eb !important; border: 1px solid #374151 !important; border-radius: 8px !important; }\n.gjs-block:hover { border-color: #9870ED !important; }\n.gjs-block-label { color: #d1d5db !important; }\n.gjs-block svg { fill: #9ca3af !important; }\n\n/* Block categories */\n.gjs-block-categories { background-color: #111827 !important; }\n.gjs-block-category { background-color: #111827 !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-block-category .gjs-title { background-color: #111827 !important; color: #e5e7eb !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-block-category .gjs-title:hover { background-color: #1f2937 !important; }\n.gjs-block-category .gjs-caret-icon { color: #9ca3af !important; }\n\n/* Layer manager */\n.gjs-layers { background-color: #111827 !important; }\n.gjs-layer { background-color: #111827 !important; color: #e5e7eb !important; }\n.gjs-layer:hover { background-color: #1f2937 !important; }\n.gjs-layer-title { color: #e5e7eb !important; }\n.gjs-layer-title-inn { background-color: transparent !important; }\n.gjs-layer.gjs-selected .gjs-layer-title { background-color: rgba(152, 112, 237, 0.15) !important; }\n.gjs-layer-name { color: #e5e7eb !important; }\n.gjs-layer-vis { color: #9ca3af !important; }\n.gjs-layer-caret { color: #9ca3af !important; }\n\n/* Style manager */\n.gjs-sm-sectors { background-color: #111827 !important; }\n.gjs-sm-sector { background-color: #111827 !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-sm-sector .gjs-sm-sector-title { background-color: #111827 !important; color: #e5e7eb !important; border-bottom: 1px solid #1f2937 !important; }\n.gjs-sm-sector .gjs-sm-sector-title:hover { background-color: #1f2937 !important; }\n.gjs-sm-sector .gjs-sm-properties { background-color: #111827 !important; }\n.gjs-sm-label { color: #9ca3af !important; }\n.gjs-field { background-color: #1f2937 !important; border: 1px solid #374151 !important; color: #e5e7eb !important; }\n.gjs-field input, .gjs-field select, .gjs-field textarea { color: #e5e7eb !important; background-color: transparent !important; }\n.gjs-field .gjs-input-holder { color: #e5e7eb !important; }\n.gjs-field-arrows { color: #9ca3af !important; }\n.gjs-sm-composite { background-color: #111827 !important; }\n.gjs-sm-stack #gjs-sm-add { color: #9ca3af !important; }\n\n/* Trait manager */\n.gjs-trt-traits { background-color: #111827 !important; }\n.gjs-trt-trait { color: #e5e7eb !important; }\n\n/* Panels */\n.gjs-pn-panel { background-color: #111827 !important; }\n.gjs-pn-btn { color: #9ca3af !important; }\n.gjs-pn-btn:hover { color: #e5e7eb !important; }\n.gjs-pn-btn.gjs-pn-active { color: #9870ED !important; }\n\n/* Canvas — full width, no padding */\n.gjs-cv-canvas { background-color: #000000 !important; }\n.gjs-frame-wrapper { padding: 0 !important; }\n.gjs-frame { width: 100% !important; left: 0 !important; }\n\n/* Toolbar on selected component */\n.gjs-toolbar { background-color: #9870ED !important; }\n.gjs-toolbar-item { color: white !important; }\n\n/* Selection highlight */\n.gjs-selected { outline: 2px solid #9870ED !important; outline-offset: -2px; }\n.gjs-highlighter { outline: 2px solid #9870ED !important; }\n\n/* Scrollbars */\n.gjs-editor ::-webkit-scrollbar { width: 6px; }\n.gjs-editor ::-webkit-scrollbar-track { background: #111827; }\n.gjs-editor ::-webkit-scrollbar-thumb { background: #374151; border-radius: 3px; }\n.gjs-editor ::-webkit-scrollbar-thumb:hover { background: #4b5563; }\n\n/* Hide native GrapesJS panel buttons (preview eye, etc.) but keep panel system functional */\n.gjs-pn-btn {\n display: none !important;\n}\n/* The panels container that holds the buttons row */\n.gjs-pn-commands,\n.gjs-pn-options,\n.gjs-pn-views {\n height: 0 !important;\n overflow: hidden !important;\n padding: 0 !important;\n margin: 0 !important;\n border: none !important;\n}\n\n/* Rich text editor */\n.gjs-rte-toolbar { background-color: #1f2937 !important; border: 1px solid #374151 !important; }\n.gjs-rte-actionbar { background-color: #1f2937 !important; }\n.gjs-rte-action { color: #e5e7eb !important; }\n`;\n\n/**\n * Denik variant overrides — applied on top of CLASSIC.\n *\n * Differences vs classic:\n * - Editor chrome: white instead of black.\n * - Block manager: flat horizontal list (icon-box + label) instead of hierarchical grid.\n * Categories: \"Básicos\" first category always expanded (non-collapsible); other categories\n * collapsible with colored cube icons.\n * - Canvas: white frame floating with 32px margin inside a white canvas.\n */\nconst DENIK_OVERRIDES = `\n/* ═══ Denik variant overrides ═══ */\n\n/* Editor chrome */\n.gjs-editor { background-color: white !important; }\n\n/* Block manager — flat list */\n.gjs-blocks-cs { background: transparent !important; }\n.gjs-block-categories { background: transparent !important; padding: 0 !important; }\n\n/* All blocks: horizontal row — [icon-box] [label] */\n.gjs-blocks-c .gjs-block.gjs-block {\n background: transparent !important;\n color: #e5e7eb !important;\n border: none !important;\n border-radius: 6px !important;\n display: flex !important;\n flex-direction: row !important;\n align-items: center !important;\n justify-content: flex-start !important;\n text-align: left !important;\n gap: 10px !important;\n padding: 0 10px !important;\n margin: 0 !important;\n width: 100% !important;\n min-height: unset !important;\n height: 24px !important;\n box-shadow: none !important;\n cursor: grab !important;\n}\n.gjs-blocks-c .gjs-block.gjs-block:hover { background: rgba(255,255,255,0.06) !important; }\n\n/* Icon box: 24x24 rounded square #2D2D2D — target BOTH class variants */\n.gjs-block .gjs-block__media,\n.gjs-block .gjs-block-media {\n width: 24px !important;\n height: 24px !important;\n min-width: 24px !important;\n max-width: 24px !important;\n min-height: 24px !important;\n max-height: 24px !important;\n line-height: 0 !important;\n background: #2D2D2D !important;\n border-radius: 5px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n padding: 4px !important;\n flex-shrink: 0 !important;\n}\n.gjs-block .gjs-block__media svg,\n.gjs-block .gjs-block-media svg {\n width: 14px !important;\n height: 14px !important;\n display: block !important;\n}\n.gjs-block svg { fill: #9ca3af !important; stroke: #9ca3af !important; }\n\n/* Label: 14px, left-aligned */\n.gjs-blocks-c .gjs-block .gjs-block-label {\n color: #d1d5db !important;\n font-size: 14px !important;\n font-weight: 400 !important;\n text-align: left !important;\n padding: 0 !important;\n width: auto !important;\n flex: 1 !important;\n line-height: 24px !important;\n}\n\n/* Blocks container: vertical single-column list */\n.gjs-block-category:first-child .gjs-blocks-c { display: flex !important; gap: 12px !important; }\n.gjs-blocks-c {\n flex-direction: column !important;\n flex-wrap: nowrap !important;\n gap: 8px !important;\n padding: 4px 0 !important;\n width: 100% !important;\n}\n/* Respect GrapesJS collapse: when inline style has display:none, honor it */\n.gjs-blocks-c[style*=\"none\"] { display: none !important; }\n\n/* All categories: no border, transparent */\n.gjs-block-category {\n background: transparent !important;\n border: none !important;\n border-bottom: none !important;\n}\n\n/* ─── Básicos (first category): NOT collapsible, always open, flat ─── */\n.gjs-block-category:first-child .gjs-title {\n background: transparent !important;\n color: #9ca3af !important;\n font-size: 11px !important;\n font-weight: 600 !important;\n text-transform: uppercase !important;\n letter-spacing: 0.05em !important;\n padding: 14px 10px 6px !important;\n border: none !important;\n cursor: default !important;\n pointer-events: none !important;\n}\n.gjs-block-category:first-child .gjs-caret-icon { display: none !important; }\n/* Force always open even if GrapesJS collapsed it */\n.gjs-block-category:first-child .gjs-blocks-c { display: flex !important; }\n\n/* ─── Secciones (all other categories): collapsible ─── */\n.gjs-block-category:not(:first-child) .gjs-title {\n background: transparent !important;\n color: #e5e7eb !important;\n font-size: 14px !important;\n font-weight: 500 !important;\n padding: 8px 10px !important;\n border: none !important;\n display: flex !important;\n align-items: center !important;\n gap: 10px !important;\n cursor: pointer !important;\n}\n.gjs-block-category:not(:first-child) .gjs-title:hover { background: rgba(255,255,255,0.04) !important; }\n.gjs-block-category:not(:first-child) .gjs-caret-icon { color: #6b7280 !important; margin-left: auto !important; font-size: 12px !important; }\n\n/* \"Secciones\" label above the section categories */\n.gjs-block-category:nth-child(2)::before {\n content: 'Secciones';\n display: block;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: #9ca3af;\n padding: 18px 10px 6px;\n}\n\n/* Section category title icons: colored cubes (override the title text with an icon prefix) */\n.gjs-block-category:not(:first-child) .gjs-title::before {\n content: '';\n display: inline-block;\n width: 24px;\n height: 24px;\n min-width: 24px;\n border-radius: 5px;\n background: #ec4899;\n}\n/* Per-category colors for the title icon */\n.gjs-block-category:nth-child(2) .gjs-title::before { background: #f472b6; }\n.gjs-block-category:nth-child(3) .gjs-title::before { background: #fb923c; }\n.gjs-block-category:nth-child(4) .gjs-title::before { background: #f87171; }\n.gjs-block-category:nth-child(5) .gjs-title::before { background: #facc15; }\n.gjs-block-category:nth-child(6) .gjs-title::before { background: #4ade80; }\n.gjs-block-category:nth-child(7) .gjs-title::before { background: #60a5fa; }\n.gjs-block-category:nth-child(8) .gjs-title::before { background: #c084fc; }\n.gjs-block-category:nth-child(9) .gjs-title::before { background: #a8a29e; }\n\n/* Section title: [icon] [text] ... [arrow] */\n.gjs-block-category:not(:first-child) .gjs-title { justify-content: flex-start !important; }\n.gjs-block-category:not(:first-child) .gjs-caret-icon { order: 99 !important; margin-left: auto !important; }\n\n/* Canvas — white floating frame with 32px margin */\n.gjs-cv-canvas { background-color: white !important; width: 100% !important; height: 100% !important; top: 0 !important; left: 0 !important; }\n.gjs-frame-wrapper { background: white !important; top: 32px !important; left: 32px !important; right: 32px !important; bottom: 32px !important; width: auto !important; height: auto !important; padding: 0 !important; }\n.gjs-frame { left: 0 !important; }\n`;\n\nexport const GRAPES_DARK_CSS_DENIK = GRAPES_DARK_CSS_CLASSIC + DENIK_OVERRIDES;\n\nexport function getGrapesCss(variant: EditorVariant = \"classic\"): string {\n return variant === \"denik\" ? GRAPES_DARK_CSS_DENIK : GRAPES_DARK_CSS_CLASSIC;\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useEffect","useRef","useState","useCallback","jsx","jsxs","jsx","jsxs","useEffect","useRef","useState","vars","t"]}
package/dist/deploy.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  deployToEasyBits,
3
3
  deployToS3
4
- } from "./chunk-SJJZEW5W.js";
5
- import "./chunk-7MGKYJTI.js";
4
+ } from "./chunk-FOTINBTC.js";
5
+ import "./chunk-XDJMUIKY.js";
6
6
  import "./chunk-DCAQAHSU.js";
7
7
  export {
8
8
  deployToEasyBits,
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  FloatingToolbar,
14
14
  SectionList,
15
15
  ViewportToggle
16
- } from "./chunk-EP65R6DE.js";
16
+ } from "./chunk-CZSPAIBQ.js";
17
17
  import "./chunk-DUHALQL7.js";
18
18
  import {
19
19
  PROMPT_SUFFIX,
@@ -41,12 +41,12 @@ import {
41
41
  import {
42
42
  deployToEasyBits,
43
43
  deployToS3
44
- } from "./chunk-SJJZEW5W.js";
44
+ } from "./chunk-FOTINBTC.js";
45
45
  import {
46
46
  buildDeployHtml,
47
47
  buildPreviewHtml,
48
48
  getIframeScript
49
- } from "./chunk-7MGKYJTI.js";
49
+ } from "./chunk-XDJMUIKY.js";
50
50
  import {
51
51
  LANDING_THEMES,
52
52
  buildCustomTheme,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easybits.cloud/html-tailwind-generator",
3
- "version": "0.2.143",
3
+ "version": "0.2.144",
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/iframeScript.ts","../src/buildHtml.ts"],"sourcesContent":["/**\n * JavaScript injected into the landing v3 iframe.\n * Handles hover highlights, click selection, contentEditable text editing,\n * postMessage communication with the parent editor,\n * and incremental section injection from parent.\n */\nexport function getIframeScript(): string {\n return `\n(function() {\n let hoveredEl = null;\n let selectedEl = null;\n const SHADOW_HOVER = 'inset 0 0 0 2px #3B82F6';\n const SHADOW_SELECTED = 'inset 0 0 0 2px #8B5CF6';\n\n function getSectionId(el) {\n let node = el;\n while (node && node !== document.body) {\n if (node.dataset && node.dataset.sectionId) {\n return node.dataset.sectionId;\n }\n node = node.parentElement;\n }\n return null;\n }\n\n function getSectionElement(sectionId) {\n return document.querySelector('[data-section-id=\"' + sectionId + '\"]');\n }\n\n function getElementPath(el) {\n const parts = [];\n let node = el;\n while (node && node !== document.body) {\n let tag = node.tagName.toLowerCase();\n if (node.id) { tag += '#' + node.id; }\n const siblings = node.parentElement ? Array.from(node.parentElement.children).filter(function(c) { return c.tagName === node.tagName; }) : [];\n if (siblings.length > 1) { tag += ':nth(' + siblings.indexOf(node) + ')'; }\n parts.unshift(tag);\n node = node.parentElement;\n }\n return parts.join(' > ');\n }\n\n function getCleanSectionHtml(sectionEl) {\n var els = sectionEl.querySelectorAll('*');\n var saved = [];\n for (var i = 0; i < els.length; i++) {\n var s = els[i].style;\n saved.push({ boxShadow: s.boxShadow, ce: els[i].contentEditable });\n s.boxShadow = '';\n if (els[i].contentEditable === 'true') els[i].removeAttribute('contenteditable');\n }\n // Also clean the section root\n var rootShadow = sectionEl.style.boxShadow;\n sectionEl.style.boxShadow = '';\n var html = sectionEl.innerHTML;\n sectionEl.style.boxShadow = rootShadow;\n for (var i = 0; i < els.length; i++) {\n els[i].style.boxShadow = saved[i].boxShadow;\n if (saved[i].ce === 'true') els[i].contentEditable = 'true';\n }\n return html;\n }\n\n function isTextElement(el) {\n var textTags = ['H1','H2','H3','H4','H5','H6','P','DIV','SPAN','LI','A','BLOCKQUOTE','LABEL','TD','TH','FIGCAPTION','BUTTON'];\n return textTags.indexOf(el.tagName) !== -1;\n }\n\n function emitElementSelected(el) {\n var rect = el.getBoundingClientRect();\n var attrs = {};\n if (el.tagName === 'IMG') attrs = { src: el.getAttribute('src') || '', alt: el.getAttribute('alt') || '' };\n if (el.tagName === 'A') attrs = { href: el.getAttribute('href') || '', target: el.getAttribute('target') || '' };\n var ot = el.outerHTML.split('>')[0] + '>';\n if (ot.length > 200) ot = ot.substring(0, 200);\n window.parent.postMessage({\n type: 'element-selected',\n sectionId: getSectionId(el),\n tagName: el.tagName,\n rect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n text: (el.textContent || '').substring(0, 200),\n openTag: ot,\n elementPath: getElementPath(el),\n isSectionRoot: el.dataset && el.dataset.sectionId ? true : false,\n attrs: attrs,\n className: (typeof el.className === 'string' ? el.className : '') || '',\n }, '*');\n }\n\n // Hover\n document.addEventListener('mouseover', function(e) {\n var el = e.target;\n while (el && el !== document.body && (el instanceof SVGElement) && el.tagName !== 'svg') {\n el = el.parentElement;\n }\n if (el && el.tagName === 'svg' && el.parentElement) el = el.parentElement;\n if (el === document.body || el === document.documentElement) return;\n if (el === selectedEl) return;\n if (hoveredEl && hoveredEl !== selectedEl) {\n hoveredEl.style.boxShadow = '';\n }\n hoveredEl = el;\n if (el !== selectedEl) {\n el.style.boxShadow = SHADOW_HOVER;\n }\n });\n\n document.addEventListener('mouseout', function(e) {\n if (hoveredEl && hoveredEl !== selectedEl) {\n hoveredEl.style.boxShadow = '';\n }\n hoveredEl = null;\n });\n\n // Click — select element\n document.addEventListener('click', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var el = e.target;\n\n // Bubble up from SVG internals to the nearest HTML element\n while (el && el !== document.body && (el instanceof SVGElement) && el.tagName !== 'svg') {\n el = el.parentElement;\n }\n // If we landed on an <svg>, bubble up to its HTML parent\n if (el && el.tagName === 'svg' && el.parentElement) {\n el = el.parentElement;\n }\n\n // Deselect previous\n if (selectedEl) {\n selectedEl.style.boxShadow = '';\n }\n\n if (selectedEl === el) {\n selectedEl = null;\n window.parent.postMessage({ type: 'element-deselected' }, '*');\n return;\n }\n\n selectedEl = el;\n\n // Clear hover styles BEFORE capturing openTag (so it matches source HTML)\n el.style.boxShadow = '';\n var openTag = el.outerHTML.substring(0, el.outerHTML.indexOf('>') + 1).substring(0, 120);\n\n el.style.boxShadow = SHADOW_SELECTED;\n\n var rect = el.getBoundingClientRect();\n var attrs = {};\n if (el.tagName === 'IMG') {\n attrs = { src: el.getAttribute('src') || '', alt: el.getAttribute('alt') || '' };\n }\n if (el.tagName === 'A') {\n attrs = { href: el.getAttribute('href') || '', target: el.getAttribute('target') || '' };\n }\n\n window.parent.postMessage({\n type: 'element-selected',\n sectionId: getSectionId(el),\n tagName: el.tagName,\n rect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n text: (el.textContent || '').substring(0, 200),\n openTag: openTag,\n elementPath: getElementPath(el),\n isSectionRoot: el.dataset && el.dataset.sectionId ? true : false,\n attrs: attrs,\n className: el.className || '',\n }, '*');\n }, true);\n\n // Double-click — contentEditable for text\n document.addEventListener('dblclick', function(e) {\n e.preventDefault();\n e.stopPropagation();\n var el = e.target;\n if (!isTextElement(el)) return;\n\n el.contentEditable = 'true';\n el.focus();\n el.style.boxShadow = 'inset 0 0 0 2px #F59E0B';\n\n function onBlur() {\n el.contentEditable = 'false';\n el.style.boxShadow = '';\n el.removeEventListener('blur', onBlur);\n el.removeEventListener('keydown', onKeydown);\n\n var sid = getSectionId(el);\n var sectionEl = sid ? getSectionElement(sid) : null;\n window.parent.postMessage({\n type: 'text-edited',\n sectionId: sid,\n elementPath: getElementPath(el),\n newText: el.innerHTML,\n sectionHtml: sectionEl ? getCleanSectionHtml(sectionEl) : null,\n }, '*');\n\n selectedEl = null;\n }\n\n function onKeydown(ev) {\n if (ev.key === 'Escape') {\n el.blur();\n }\n }\n\n el.addEventListener('blur', onBlur);\n el.addEventListener('keydown', onKeydown);\n }, true);\n\n // Listen for messages FROM parent (incremental section injection)\n window.addEventListener('message', function(e) {\n var msg = e.data;\n if (!msg || !msg.action) return;\n\n if (msg.action === 'add-section') {\n var wrapper = document.createElement('div');\n wrapper.setAttribute('data-section-id', msg.id);\n wrapper.innerHTML = msg.html;\n wrapper.style.animation = 'fadeInUp 0.4s ease-out';\n document.body.appendChild(wrapper);\n if (msg.scroll) {\n wrapper.scrollIntoView({ behavior: 'smooth', block: 'end' });\n }\n }\n\n if (msg.action === 'update-section') {\n var el = getSectionElement(msg.id);\n if (el && typeof window.morphdom === 'function') {\n var tmp = document.createElement('div');\n tmp.innerHTML = msg.html;\n window.morphdom(el, tmp, {\n childrenOnly: true,\n onBeforeElUpdated: function(fromEl, toEl) {\n if (fromEl.isEqualNode(toEl)) return false;\n return true;\n }\n });\n } else if (el) {\n el.innerHTML = msg.html;\n }\n }\n\n if (msg.action === 'rename-section') {\n var el = getSectionElement(msg.oldId);\n if (el) {\n el.setAttribute('data-section-id', msg.newId);\n if (msg.html) {\n if (typeof window.morphdom === 'function') {\n var tmp = document.createElement('div');\n tmp.innerHTML = msg.html;\n window.morphdom(el, tmp, { childrenOnly: true, onBeforeElUpdated: function(f,t){ return !f.isEqualNode(t); } });\n } else {\n el.innerHTML = msg.html;\n }\n }\n }\n }\n\n if (msg.action === 'remove-section') {\n var el = getSectionElement(msg.id);\n if (el) { el.remove(); }\n }\n\n if (msg.action === 'reorder-sections') {\n // msg.order = [id1, id2, id3, ...]\n var order = msg.order;\n for (var i = 0; i < order.length; i++) {\n var el = getSectionElement(order[i]);\n if (el) { document.body.appendChild(el); }\n }\n }\n\n if (msg.action === 'update-attribute') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl) {\n var target = null;\n if (msg.elementPath) {\n // Find element by matching path\n var allEls = sectionEl.querySelectorAll(msg.tagName || '*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n }\n if (target) {\n if (msg.attr === 'style' && msg.value.indexOf(':') !== -1) {\n // Merge style property instead of replacing entire style\n var parts = msg.value.split(':');\n var prop = parts[0].trim();\n var val = parts.slice(1).join(':').trim();\n target.style.setProperty(prop, val);\n } else {\n target.setAttribute(msg.attr, msg.value);\n }\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n emitElementSelected(target);\n }\n }\n }\n\n if (msg.action === 'replace-class') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath) {\n var target = null;\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n if (target) {\n // Remove classes matching prefixes (supports responsive variants like md:p-4)\n var prefixes = msg.removePrefixes || [];\n var toRemove = [];\n for (var ci = 0; ci < target.classList.length; ci++) {\n var cls = target.classList[ci];\n var bare = cls.indexOf(':') !== -1 ? cls.substring(cls.lastIndexOf(':') + 1) : cls;\n for (var pi = 0; pi < prefixes.length; pi++) {\n if (bare === prefixes[pi] || bare.indexOf(prefixes[pi]) === 0) {\n toRemove.push(cls);\n break;\n }\n }\n }\n for (var ri = 0; ri < toRemove.length; ri++) {\n target.classList.remove(toRemove[ri]);\n }\n // Add new class\n if (msg.addClass && !target.classList.contains(msg.addClass)) {\n target.classList.add(msg.addClass);\n }\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n emitElementSelected(target);\n }\n }\n }\n\n if (msg.action === 'delete-element') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath) {\n var target = null;\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n if (target && target.parentNode) {\n target.parentNode.removeChild(target);\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n window.parent.postMessage({ type: 'element-deselected' }, '*');\n }\n }\n }\n\n if (msg.action === 'change-tag') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath && msg.newTag) {\n var target = null;\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n target = allEls[i];\n break;\n }\n }\n if (target && target.parentNode) {\n var newEl = document.createElement(msg.newTag);\n for (var a = 0; a < target.attributes.length; a++) {\n newEl.setAttribute(target.attributes[a].name, target.attributes[a].value);\n }\n while (target.firstChild) newEl.appendChild(target.firstChild);\n target.parentNode.replaceChild(newEl, target);\n window.parent.postMessage({\n type: 'section-html-updated',\n sectionId: msg.sectionId,\n sectionHtml: getCleanSectionHtml(sectionEl),\n }, '*');\n emitElementSelected(newEl);\n }\n }\n }\n\n if (msg.action === 'set-theme') {\n if (msg.theme && msg.theme !== 'default') {\n document.documentElement.setAttribute('data-theme', msg.theme);\n } else {\n document.documentElement.removeAttribute('data-theme');\n }\n }\n\n if (msg.action === 'set-custom-css') {\n var customStyle = document.getElementById('custom-theme-css');\n if (!customStyle) {\n customStyle = document.createElement('style');\n customStyle.id = 'custom-theme-css';\n document.head.appendChild(customStyle);\n }\n customStyle.textContent = msg.css || '';\n }\n\n if (msg.action === 'scroll-to-section') {\n var el = getSectionElement(msg.id);\n if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'start' }); }\n }\n\n if (msg.action === 'get-scroll') {\n window.parent.postMessage({ type: 'scroll-position', y: window.scrollY }, '*');\n }\n\n if (msg.action === 'restore-scroll') {\n window.scrollTo(0, msg.y);\n }\n\n if (msg.action === 'element-loading') {\n var sectionEl = getSectionElement(msg.sectionId);\n if (sectionEl && msg.elementPath) {\n var allEls = sectionEl.querySelectorAll('*');\n for (var i = 0; i < allEls.length; i++) {\n if (getElementPath(allEls[i]) === msg.elementPath) {\n var el = allEls[i];\n el.style.position = 'relative';\n el.style.overflow = 'hidden';\n var overlay = document.createElement('div');\n overlay.setAttribute('data-loading-overlay', 'true');\n overlay.style.cssText = 'position:absolute;inset:0;z-index:999;border-radius:inherit;background:linear-gradient(90deg,rgba(255,255,255,0) 0%,rgba(255,255,255,0.6) 50%,rgba(255,255,255,0) 100%);background-size:200% 100%;animation:shimmer 1.5s infinite;pointer-events:none;';\n el.appendChild(overlay);\n break;\n }\n }\n }\n }\n\n if (msg.action === 'element-loading-clear') {\n var overlays = document.querySelectorAll('[data-loading-overlay]');\n for (var i = 0; i < overlays.length; i++) {\n overlays[i].remove();\n }\n }\n\n if (msg.action === 'preview-version') {\n var el = getSectionElement(msg.sectionId);\n if (el) {\n // Store original html if not already stored\n if (!el.dataset.originalHtml) {\n el.dataset.originalHtml = el.innerHTML;\n }\n el.innerHTML = msg.html;\n el.style.outline = '2px dashed #8B5CF6';\n el.style.outlineOffset = '-2px';\n el.style.opacity = '0.85';\n }\n }\n\n if (msg.action === 'exit-preview') {\n var el = getSectionElement(msg.sectionId);\n if (el && el.dataset.originalHtml) {\n el.innerHTML = el.dataset.originalHtml;\n delete el.dataset.originalHtml;\n el.style.outline = '';\n el.style.outlineOffset = '';\n el.style.opacity = '';\n }\n }\n\n if (msg.action === 'full-rewrite') {\n // Fallback: rewrite everything\n document.body.innerHTML = msg.html;\n }\n });\n\n // Forward Cmd/Ctrl+Z undo/redo to parent (iframe captures keyboard focus)\n document.addEventListener('keydown', function(e) {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'z') {\n e.preventDefault();\n window.parent.postMessage({ type: e.shiftKey ? 'redo' : 'undo' }, '*');\n }\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'y') {\n e.preventDefault();\n window.parent.postMessage({ type: 'redo' }, '*');\n }\n });\n\n // Image loading placeholders\n function setupImagePlaceholder(img) {\n if (img.complete && img.naturalWidth > 0) return;\n img.style.background = 'linear-gradient(90deg, #e5e7eb 25%, #f3f4f6 50%, #e5e7eb 75%)';\n img.style.backgroundSize = '200% 100%';\n img.style.animation = 'shimmer 1.5s infinite';\n if (!img.style.minHeight && !img.getAttribute('height')) img.style.minHeight = '120px';\n function onDone() {\n img.style.background = '';\n img.style.backgroundSize = '';\n img.style.animation = '';\n if (img.style.minHeight === '120px') img.style.minHeight = '';\n img.removeEventListener('load', onDone);\n img.removeEventListener('error', onDone);\n }\n img.addEventListener('load', onDone);\n img.addEventListener('error', onDone);\n }\n // Observe new/changed images\n var imgObserver = new MutationObserver(function(mutations) {\n for (var m = 0; m < mutations.length; m++) {\n // New nodes\n for (var n = 0; n < mutations[m].addedNodes.length; n++) {\n var node = mutations[m].addedNodes[n];\n if (node.tagName === 'IMG') setupImagePlaceholder(node);\n if (node.querySelectorAll) {\n var imgs = node.querySelectorAll('img');\n for (var i = 0; i < imgs.length; i++) setupImagePlaceholder(imgs[i]);\n }\n }\n // src attribute changed\n if (mutations[m].type === 'attributes' && mutations[m].attributeName === 'src' && mutations[m].target.tagName === 'IMG') {\n setupImagePlaceholder(mutations[m].target);\n }\n }\n });\n imgObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });\n // Initial images\n var existingImgs = document.querySelectorAll('img');\n for (var ii = 0; ii < existingImgs.length; ii++) setupImagePlaceholder(existingImgs[ii]);\n\n // Inject animation keyframes\n var style = document.createElement('style');\n style.textContent = '@keyframes fadeInUp { from { opacity:0; transform:translateY(20px); } to { opacity:1; transform:translateY(0); } } @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } }';\n document.head.appendChild(style);\n\n // Notify parent we're ready\n window.parent.postMessage({ type: 'ready' }, '*');\n})();\n`;\n}\n","import type { Section3 } from \"./types\";\nimport { getIframeScript } from \"./iframeScript\";\nimport { buildThemeCss, buildSingleThemeCss, buildCustomTheme, type CustomColors } from \"./themes\";\n\n/**\n * Build the full HTML for the iframe preview (with editing script).\n */\nexport function buildPreviewHtml(sections: Section3[], theme?: string): string {\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n const body = sorted\n .map((s) => `<div data-section-id=\"${s.id}\">${s.html}</div>`)\n .join(\"\\n\");\n\n const dataTheme = theme && theme !== \"default\" ? ` data-theme=\"${theme}\"` : \"\";\n const { css, tailwindConfig } = buildThemeCss();\n\n return `<!DOCTYPE html>\n<html lang=\"es\"${dataTheme}>\n<head>\n<meta charset=\"UTF-8\"/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n<script src=\"https://cdn.tailwindcss.com\"></script>\n<script src=\"https://unpkg.com/morphdom@2.7.4/dist/morphdom-umd.min.js\"></script>\n<script>tailwind.config = ${tailwindConfig}</script>\n<style>\n${css}\n*{margin:0;padding:0;box-sizing:border-box}\nhtml{scroll-behavior:smooth}\nbody{font-family:system-ui,-apple-system,sans-serif;background-color:var(--color-surface);color:var(--color-on-surface)}\nimg{max-width:100%}\nsection{width:100%}\nsection>*{max-width:80rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem}\n[contenteditable=\"true\"]{cursor:text}\n</style>\n</head>\n<body class=\"bg-surface text-on-surface\">\n${body}\n<script>${getIframeScript()}</script>\n</body>\n</html>`;\n}\n\n/**\n * Build the deploy HTML (no editing script, clean output).\n */\n/**\n * Remove editor artifacts (outline, outlineOffset, contenteditable) from HTML before deploy.\n */\nfunction stripEditorArtifacts(html: string): string {\n return html\n .replace(/\\s*outline:\\s*[^;\"]+;?/gi, \"\")\n .replace(/\\s*outline-offset:\\s*[^;\"]+;?/gi, \"\")\n .replace(/\\s*style=\"\\s*\"/gi, \"\")\n .replace(/\\s+contenteditable=\"[^\"]*\"/gi, \"\")\n .replace(/\\s+data-section-id=\"[^\"]*\"/gi, \"\")\n}\n\nexport function buildDeployHtml(sections: Section3[], theme?: string, customColors?: CustomColors, showBranding = true): string {\n const sorted = [...sections].sort((a, b) => a.order - b.order);\n const body = sorted.map((s) => stripEditorArtifacts(s.html)).join(\"\\n\");\n\n const isCustom = theme === \"custom\" && customColors;\n const dataTheme = theme && theme !== \"default\" && !isCustom ? ` data-theme=\"${theme}\"` : \"\";\n\n // For custom theme, build CSS from the custom colors directly (no data-theme needed, inject as :root)\n const { css: baseCss, tailwindConfig } = isCustom\n ? (() => {\n const ct = buildCustomTheme(customColors);\n const vars = Object.entries(ct.colors).map(([k, v]) => ` --color-${k}: ${v};`).join(\"\\n\");\n return { css: `:root {\\n${vars}\\n}`, tailwindConfig: buildSingleThemeCss(\"default\").tailwindConfig };\n })()\n : buildSingleThemeCss(theme || \"default\");\n\n return `<!DOCTYPE html>\n<html lang=\"es\"${dataTheme}>\n<head>\n<meta charset=\"UTF-8\"/>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/>\n<title>Landing Page</title>\n<script src=\"https://cdn.tailwindcss.com\"></script>\n<script>tailwind.config = ${tailwindConfig}</script>\n<style>\n${baseCss}\n*{margin:0;padding:0;box-sizing:border-box}\nhtml{scroll-behavior:smooth}\nbody{font-family:system-ui,-apple-system,sans-serif;background-color:var(--color-surface);color:var(--color-on-surface)}\nsection{width:100%}\nsection>*{max-width:80rem;margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem}\n</style>\n</head>\n<body class=\"bg-surface text-on-surface\">\n${body}\n${showBranding ? `<div style=\"text-align:center;padding:16px 0 12px;font-size:12px\">\n <a href=\"https://www.easybits.cloud\" target=\"_blank\" rel=\"noopener\"\n style=\"color:#9ca3af;text-decoration:none\">\n Powered by easybits.cloud\n </a>\n</div>` : \"\"}\n</body>\n</html>`;\n}\n"],"mappings":";;;;;;;AAMO,SAAS,kBAA0B;AACxC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiiBT;;;ACjiBO,SAAS,iBAAiB,UAAsB,OAAwB;AAC7E,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC7D,QAAM,OAAO,OACV,IAAI,CAAC,MAAM,yBAAyB,EAAE,EAAE,KAAK,EAAE,IAAI,QAAQ,EAC3D,KAAK,IAAI;AAEZ,QAAM,YAAY,SAAS,UAAU,YAAY,gBAAgB,KAAK,MAAM;AAC5E,QAAM,EAAE,KAAK,eAAe,IAAI,cAAc;AAE9C,SAAO;AAAA,iBACQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAME,cAAc;AAAA;AAAA,EAExC,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWH,IAAI;AAAA,UACI,gBAAgB,CAAC;AAAA;AAAA;AAG3B;AAQA,SAAS,qBAAqB,MAAsB;AAClD,SAAO,KACJ,QAAQ,4BAA4B,EAAE,EACtC,QAAQ,mCAAmC,EAAE,EAC7C,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,gCAAgC,EAAE,EAC1C,QAAQ,gCAAgC,EAAE;AAC/C;AAEO,SAAS,gBAAgB,UAAsB,OAAgB,cAA6B,eAAe,MAAc;AAC9H,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC7D,QAAM,OAAO,OAAO,IAAI,CAAC,MAAM,qBAAqB,EAAE,IAAI,CAAC,EAAE,KAAK,IAAI;AAEtE,QAAM,WAAW,UAAU,YAAY;AACvC,QAAM,YAAY,SAAS,UAAU,aAAa,CAAC,WAAW,gBAAgB,KAAK,MAAM;AAGzF,QAAM,EAAE,KAAK,SAAS,eAAe,IAAI,YACpC,MAAM;AACL,UAAM,KAAK,iBAAiB,YAAY;AACxC,UAAM,OAAO,OAAO,QAAQ,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,IAAI;AACzF,WAAO,EAAE,KAAK;AAAA,EAAY,IAAI;AAAA,IAAO,gBAAgB,oBAAoB,SAAS,EAAE,eAAe;AAAA,EACrG,GAAG,IACH,oBAAoB,SAAS,SAAS;AAE1C,SAAO;AAAA,iBACQ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAME,cAAc;AAAA;AAAA,EAExC,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASP,IAAI;AAAA,EACJ,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,UAKP,EAAE;AAAA;AAAA;AAGZ;","names":[]}