@easybits.cloud/html-tailwind-generator 0.2.125 → 0.2.127

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.
Files changed (35) hide show
  1. package/dist/{ViewportToggle-DefLZWrz.d.ts → ViewportToggle-Dszv1gsL.d.ts} +3 -3
  2. package/dist/buildHtmlV4.d.ts +14 -0
  3. package/dist/buildHtmlV4.js +8 -0
  4. package/dist/buildHtmlV4.js.map +1 -0
  5. package/dist/chunk-7LKFTF32.js +54 -0
  6. package/dist/chunk-7LKFTF32.js.map +1 -0
  7. package/dist/{chunk-ZARS4VIK.js → chunk-CQXBVGVC.js} +4 -4
  8. package/dist/chunk-KXOAEC33.js +67 -0
  9. package/dist/chunk-KXOAEC33.js.map +1 -0
  10. package/dist/chunk-LI4UDDMT.js +117 -0
  11. package/dist/chunk-LI4UDDMT.js.map +1 -0
  12. package/dist/{chunk-T4F6F3HD.js → chunk-RJQKHWIH.js} +4 -4
  13. package/dist/{chunk-6LK7JW6Q.js → chunk-X5MEN76P.js} +52 -22
  14. package/dist/chunk-X5MEN76P.js.map +1 -0
  15. package/dist/components.d.ts +1 -1
  16. package/dist/components4.d.ts +121 -0
  17. package/dist/components4.js +1880 -0
  18. package/dist/components4.js.map +1 -0
  19. package/dist/directions.d.ts +8 -42
  20. package/dist/generate.js +2 -2
  21. package/dist/generateDocument.d.ts +40 -48
  22. package/dist/generateDocument.js +9 -3
  23. package/dist/grapesToSections.d.ts +12 -0
  24. package/dist/grapesToSections.js +7 -0
  25. package/dist/grapesToSections.js.map +1 -0
  26. package/dist/hooks/useThumbnailCapture.d.ts +12 -0
  27. package/dist/hooks/useThumbnailCapture.js +7 -0
  28. package/dist/hooks/useThumbnailCapture.js.map +1 -0
  29. package/dist/index.d.ts +4 -1
  30. package/dist/index.js +24 -12
  31. package/dist/refine.js +2 -2
  32. package/package.json +26 -2
  33. package/dist/chunk-6LK7JW6Q.js.map +0 -1
  34. /package/dist/{chunk-ZARS4VIK.js.map → chunk-CQXBVGVC.js.map} +0 -0
  35. /package/dist/{chunk-T4F6F3HD.js.map → chunk-RJQKHWIH.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components4/GrapesEditor.tsx","../src/components4/blocks.ts","../src/components4/TailwindClassEditor.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 { GRAPES_DARK_CSS } from \"./grapesDarkCss\";\n\n/** Inject GrapesJS dark theme CSS once at runtime */\nlet darkCssInjected = false;\nfunction injectDarkCss() {\n if (darkCssInjected || typeof document === \"undefined\") return;\n darkCssInjected = true;\n const style = document.createElement(\"style\");\n style.setAttribute(\"data-grapes-dark\", \"\");\n style.textContent = GRAPES_DARK_CSS;\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 */\n scrollToSection: (sectionId: string) => 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\nconst PANEL_TABS = [\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\nexport type PanelId = (typeof PANEL_TABS)[number][\"id\"];\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 }, ref) => {\n // Inject dark CSS on first render\n useEffect(() => { injectDarkCss(); }, []);\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 = PANEL_TABS.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 const contentComps = comps.filter((c: any) => (c.get(\"tagName\") || \"\").toLowerCase() !== \"style\");\n for (let i = 0; i < contentComps.length; i++) {\n if (contentComps[i].getAttributes()[\"data-section-id\"] === sectionId) {\n ed.select(contentComps[i]);\n const el = contentComps[i].getEl();\n if (el) {\n if (i === 0) {\n const doc = ed.Canvas.getDocument();\n doc?.documentElement?.scrollTo({ top: 0, behavior: \"smooth\" });\n } else {\n el.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n }\n }\n return;\n }\n }\n const doc = ed.Canvas.getDocument();\n if (doc) {\n const el = doc.querySelector(`[data-section-id=\"${sectionId}\"]`);\n if (el) { el.scrollIntoView({ behavior: \"smooth\", block: \"center\" }); return; }\n }\n console.warn(\"[scrollToSection] Section not found:\", sectionId, \"Available attrs:\", comps.map((c: any) => c.getAttributes()[\"data-section-id\"]));\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 ───\n editor.on(\"component:selected\", () => {\n 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\",\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 sidebar = (\n <div className={`w-80 shrink-0 flex flex-col bg-black ${sidebarBorder} border-gray-700 overflow-hidden`}>\n <div className=\"flex border-b border-gray-700\">\n {visibleTabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => setActivePanel(tab.id)}\n className={`flex-1 py-2.5 text-xs font-bold transition-colors ${\n activePanel === tab.id\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 title={tab.label}\n >\n <span className=\"block text-base mb-0.5\">{tab.icon}</span>\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 <div className={`flex-1 overflow-auto ${activePanel === \"styles\" ? \"\" : \"hidden\"}`}>\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 <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 canvas = <div ref={editorContainerRef} className=\"flex-1 h-full bg-black\" />;\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","/** GrapesJS dark theme CSS — injected at runtime to avoid CSS bundling */\nexport const GRAPES_DARK_CSS = `\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"],"mappings":"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","names":["useEffect","useRef","useState","jsx","jsxs","useEffect","useRef","useState","doc","vars","t"]}
@@ -12,50 +12,16 @@ declare const DesignDirectionSchema: z.ZodObject<{
12
12
  surface: z.ZodString;
13
13
  surfaceAlt: z.ZodString;
14
14
  text: z.ZodString;
15
- }, "strip", z.ZodTypeAny, {
16
- primary: string;
17
- accent: string;
18
- surface: string;
19
- text: string;
20
- surfaceAlt: string;
21
- }, {
22
- primary: string;
23
- accent: string;
24
- surface: string;
25
- text: string;
26
- surfaceAlt: string;
15
+ }, z.core.$strip>;
16
+ mood: z.ZodEnum<{
17
+ dark: "dark";
18
+ light: "light";
19
+ warm: "warm";
20
+ cool: "cool";
21
+ vibrant: "vibrant";
27
22
  }>;
28
- mood: z.ZodEnum<["dark", "light", "warm", "cool", "vibrant"]>;
29
23
  layoutHint: z.ZodString;
30
- }, "strip", z.ZodTypeAny, {
31
- colors: {
32
- primary: string;
33
- accent: string;
34
- surface: string;
35
- text: string;
36
- surfaceAlt: string;
37
- };
38
- mood: "dark" | "light" | "warm" | "cool" | "vibrant";
39
- name: string;
40
- tagline: string;
41
- headingFont: string;
42
- bodyFont: string;
43
- layoutHint: string;
44
- }, {
45
- colors: {
46
- primary: string;
47
- accent: string;
48
- surface: string;
49
- text: string;
50
- surfaceAlt: string;
51
- };
52
- mood: "dark" | "light" | "warm" | "cool" | "vibrant";
53
- name: string;
54
- tagline: string;
55
- headingFont: string;
56
- bodyFont: string;
57
- layoutHint: string;
58
- }>;
24
+ }, z.core.$strip>;
59
25
  type DesignDirection = z.infer<typeof DesignDirectionSchema>;
60
26
  interface DirectionsOptions {
61
27
  anthropicApiKey?: string;
package/dist/generate.js CHANGED
@@ -2,11 +2,11 @@ import {
2
2
  PROMPT_SUFFIX,
3
3
  SYSTEM_PROMPT,
4
4
  generateLanding
5
- } from "./chunk-ZARS4VIK.js";
6
- import "./chunk-VV5I53WR.js";
5
+ } from "./chunk-CQXBVGVC.js";
7
6
  import {
8
7
  extractJsonObjects
9
8
  } from "./chunk-YZHRLDQF.js";
9
+ import "./chunk-VV5I53WR.js";
10
10
  export {
11
11
  PROMPT_SUFFIX,
12
12
  SYSTEM_PROMPT,
@@ -3,8 +3,27 @@ import { z } from 'zod';
3
3
  import { S as Section3 } from './types-BIpbpCJr.js';
4
4
  import { DesignDirection } from './directions.js';
5
5
 
6
- declare const DOCUMENT_SYSTEM_PROMPT = "You are a professional document designer who creates stunning letter-sized (8.5\" \u00D7 11\") document pages using HTML + Tailwind CSS.\n\nRULES:\n- Each page is a <section> element sized for letter paper\n- Page structure: <section class=\"w-[8.5in] h-[11in] relative overflow-hidden flex flex-col\">\n- The section is EXACTLY 11in tall \u2014 content MUST fit, never exceed. Use flex flex-col so children can use flex-1.\n- The section itself has NO padding \u2014 backgrounds, gradients, and decorative elements go edge-to-edge\n- Use slot layout: shrink-0 for header/footer bands, flex-1 overflow-hidden for main content area\n- For text content, use an inner wrapper: <div class=\"flex-1 overflow-hidden px-[0.75in] py-[0.5in]\">...content...</div>\n- Footer elements (page numbers, decorative bars, contact info) MUST be direct children of <section> with shrink-0 and w-full \u2014 NEVER inside the padded content wrapper. This ensures footer backgrounds extend edge-to-edge\n- Cover pages and decorative sections can use full-bleed backgrounds (bg-primary, gradients, images that fill the entire page)\n- Content MUST NOT overflow page boundaries \u2014 be conservative with spacing\n- Use Tailwind CDN classes ONLY (no custom CSS, no @apply, no @import)\n- NO JavaScript, only HTML+Tailwind\n- All text content in Spanish unless the prompt specifies otherwise\n- Use real content from the source material, not Lorem ipsum\n- NOT responsive \u2014 fixed letter size, no breakpoints needed\n- Sections can have ANY background \u2014 full-bleed color, gradients, or white. Not limited to white paper.\n\nSTRICT PROHIBITIONS:\n1. **NO EMOJI** \u2014 Never use emoji characters (\uD83D\uDE80\u274C\u2705\uD83D\uDCCA etc.). Instead use inline SVG icons or colored divs. For bullet decorators use small colored circles (<span class=\"w-2 h-2 rounded-full bg-primary inline-block\"></span>) or simple SVG.\n2. **NO Chart.js / NO JavaScript** \u2014 Never reference Chart.js, canvas, or any JS library. For data visualization use pure CSS: progress bars (div with percentage width + bg-primary), horizontal bars, styled tables with colored cells. Never use <canvas> or <script>.\n3. **NO buttons or CTAs** \u2014 This is a print document, not a web page. No \"Contactar\", \"Ver m\u00E1s\", \"Comprar\" buttons. Use text with contact info instead.\n4. **CONTRAST IS MANDATORY** \u2014 Dark/colored backgrounds (bg-primary, bg-primary-dark, bg-secondary, dark gradients) MUST use text-white or text-on-primary. Light backgrounds (white, bg-surface, bg-surface-alt) MUST use text-gray-900 or text-on-surface. NEVER use dark text on dark backgrounds or light text on light backgrounds.\n5. **Max 2 font weights per page** \u2014 Pick 2 (e.g. font-semibold + font-normal, or font-bold + font-light). Don't mix 4-5 weights.\n6. **Generous whitespace** \u2014 Don't fill every centimeter. Leave breathing room. Use py-8, py-12, gap-6, gap-8 liberally. Less content per page = more professional.\n\nLAYOUT OVERFLOW PREVENTION \u2014 CRITICAL:\n- Max 2 columns side by side \u2014 each with w-1/2. NEVER use 3+ columns.\n- Decorative sidebars: max w-16 (4rem). NEVER use w-[2.5in] or wider sidebars \u2014 they steal too much space.\n- Stats/metric grids: max 3 items per row (grid-cols-3). Use gap-4 or gap-6.\n- Tables: max 4 columns, use text-xs or text-sm for cell text, px-3 py-2 cell padding.\n- Images: always w-full or max-w-[50%] \u2014 never fixed pixel widths.\n- Text: never use text-6xl or larger except for cover page title. Body text: text-sm or text-base.\n- NEVER use absolute positioning that could overflow \u2014 prefer flex/grid layouts.\n- Decorative shapes with absolute positioning MUST stay fully inside the page. Use overflow-hidden on parent AND keep coordinates positive (no negative right/left values).\n- Large decorative text (text-[200px], text-[10rem] etc.) MUST have opacity-5 or lower AND overflow-hidden on its container. These giant texts frequently overflow \u2014 be extra careful.\n- NEVER place elements beyond the right edge \u2014 all content and decorations must fit within 8.5in width.\n\nDESIGN \u2014 ADAPT to the document type. Read the prompt carefully and match the visual style:\n\nGENERAL PRINCIPLES (apply to ALL documents):\n- First page is ALWAYS a stunning cover/title page with impactful design\n- Typography: strong hierarchy with just 2 weights, clear headings vs body\n- Each page visually distinct \u2014 different layouts, accent placements\n- Use the full page creatively \u2014 backgrounds, sidebars, geometric shapes\n- Professional and polished, never generic or template-looking\n- Icons: use simple inline SVG (12-20px) for visual accents. Keep SVGs minimal (single path, no complex illustrations)\n\nADAPT YOUR STYLE to what the user is creating:\n- Reports/Data: structured grids, tables with alternating rows (bg-surface-alt), progress bars, stat cards, clean data hierarchy\n- Brochures/Marketing: bold hero images, large headlines, feature grids, testimonial-style quotes, visual storytelling\n- Catalogs/Products: product cards with images, specs grids, price highlights, category headers with full-bleed color\n- Invitations/Events: centered dramatic typography, decorative borders, elegant spacing, date/location prominently styled\n- Proposals/Pitches: problem\u2192solution flow, metric highlights, team/about sections, pricing tables\n- CVs/Resumes: clean sidebar layouts, skill bars, timeline for experience, contact info header\n- Creative/General: mix techniques \u2014 bento grids, full-bleed images, overlapping elements, bold color blocking\n\nVISUAL TECHNIQUES available to you:\n- Full-bleed colored pages (bg-primary, gradients)\n- Geometric accent shapes (CSS divs with clip-path or rotation)\n- Asymmetric layouts (grid with unequal columns)\n- Large stat numbers as visual anchors (text-5xl font-black)\n- Header/footer bands with contrasting color\n- Sidebar accents (thin, max w-16)\n- Image + text compositions\n- Bento-grid mixing content blocks of different sizes\n- Tables: alternating row colors, clean borders, generous cell padding (px-4 py-3)\n- For numerical data: CSS progress bars, styled tables with colored cells, large stat numbers \u2014 NEVER canvas/charts\n\nCSS PROGRESS BARS \u2014 use this pattern for data visualization:\n<div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-primary h-3 rounded-full\" style=\"width: 75%\"></div></div>\n\nCOLOR SYSTEM \u2014 use semantic classes:\n- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary\n- bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted\n- bg-secondary, text-secondary, bg-accent, text-accent\n- Cover pages should use bold full-bleed backgrounds (bg-primary, gradients from-primary to-primary-dark)\n- CONTRAST: bg-primary/bg-primary-dark/bg-secondary \u2192 text-white or text-on-primary. White/bg-surface \u2192 text-gray-900 or text-on-surface\n\nIMAGES \u2014 USE GENEROUSLY:\n- EVERY image MUST use: <img data-image-query=\"english search query\" alt=\"description\" class=\"w-full h-auto object-cover rounded-xl\"/>\n- NEVER include a src attribute \u2014 the system auto-replaces data-image-query with a real image\n- For avatar-like elements, use colored divs with initials instead of img tags\n- Include at LEAST 3-5 images across the document \u2014 hero images, section illustrations, backgrounds, product photos\n- Each data-image-query should be a UNIQUE, specific search query in English (e.g. \"modern office workspace aerial view\", \"team brainstorming whiteboard\", \"abstract blue technology network\")\n- Use images to break up text-heavy pages and add visual interest\n\nICONS \u2014 use data-icon-query for professional icons:\n- <span data-icon-query=\"icon-name\" class=\"inline-block w-5 h-5 text-primary\"></span>\n- Use common Lucide icon names in English: star, check, arrow-right, heart, zap, shield, users, mail, phone, calendar, clock, map-pin, briefcase, trending-up, award, target, layers, globe, etc.\n- Use in: feature lists, stat cards, CTAs, list items, contact info, section headers\n- Sizes: w-4 h-4 (small), w-5 h-5 (default), w-8 h-8 (large). Color inherits from text-* class.\n- NEVER draw SVG paths manually \u2014 ALWAYS use data-icon-query instead\n- The system auto-replaces data-icon-query with real SVG icons from Iconify\n\nCHARTS & DATA VISUALIZATION (SVG):\n- For charts, diagrams, and decorative data graphics, use:\n <div data-svg-chart=\"bar chart showing Q1 revenue: Jan $45K, Feb $52K, Mar $61K\" class=\"w-full\"></div>\n- The system generates professional SVG charts with a specialized tool \u2014 NEVER draw SVGs yourself\n- Use descriptive prompts with data points: type of chart + what it shows + actual values\n- Examples: \"donut chart: 40% Marketing, 30% Sales, 20% R&D, 10% Admin\", \"line chart showing growth: Q1 $100K, Q2 $150K, Q3 $220K, Q4 $310K\"\n- For simple metrics, still prefer CSS progress bars (they render faster)\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders\n\nEXAMPLE \u2014 Cover page (simple, no wide sidebars):\n<section class=\"w-[8.5in] h-[11in] relative overflow-hidden flex flex-col bg-white\">\n <div class=\"absolute left-0 top-0 w-2 h-full bg-primary\"></div>\n <div class=\"flex-1 overflow-hidden flex flex-col justify-center px-[1in]\">\n <div class=\"text-sm font-normal text-primary mb-4\">Marzo 2026 \u00B7 Versi\u00F3n 1.0</div>\n <h1 class=\"text-5xl font-bold text-gray-900 leading-tight\">Reporte<br/>Trimestral</h1>\n <div class=\"w-16 h-1 bg-primary mt-6 mb-4\"></div>\n <p class=\"text-lg font-normal text-gray-500\">Resultados y an\u00E1lisis del primer trimestre</p>\n </div>\n</section>\n\nEXAMPLE \u2014 Marketing/brochure page (bold, visual):\n<section class=\"w-[8.5in] h-[11in] relative overflow-hidden flex flex-col bg-primary\">\n <div class=\"flex flex-1 overflow-hidden\">\n <div class=\"w-1/2 flex flex-col justify-center px-[0.75in]\">\n <span class=\"text-sm font-normal text-on-primary opacity-70 uppercase tracking-widest mb-3\">Soluci\u00F3n Premium</span>\n <h2 class=\"text-4xl font-bold text-on-primary leading-tight mb-6\">Transforma tu negocio digital</h2>\n <p class=\"text-base font-normal text-on-primary opacity-80 mb-8\">Herramientas inteligentes que simplifican la gesti\u00F3n de tus activos digitales.</p>\n <div class=\"flex gap-6\">\n <div><div class=\"text-3xl font-bold text-accent\">98%</div><div class=\"text-xs text-on-primary opacity-70\">Satisfacci\u00F3n</div></div>\n <div><div class=\"text-3xl font-bold text-accent\">2.4K</div><div class=\"text-xs text-on-primary opacity-70\">Empresas</div></div>\n </div>\n </div>\n <div class=\"w-1/2 relative\">\n <img data-image-query=\"modern office team collaboration technology\" alt=\"Team working\" class=\"absolute inset-0 w-full h-full object-cover\" />\n </div>\n </div>\n</section>\n\nEXAMPLE \u2014 Catalog/product grid page:\n<section class=\"w-[8.5in] h-[11in] relative overflow-hidden flex flex-col bg-surface\">\n <div class=\"shrink-0 h-1 bg-primary w-full\"></div>\n <div class=\"flex-1 overflow-hidden px-[0.75in] py-[0.5in]\">\n <div class=\"flex justify-between items-baseline mb-6\">\n <h2 class=\"text-2xl font-bold text-on-surface\">Colecci\u00F3n Primavera</h2>\n <span class=\"text-xs font-normal text-on-surface-muted uppercase tracking-wider\">P\u00E1gina 3 de 8</span>\n </div>\n <div class=\"grid grid-cols-2 gap-6\">\n <div class=\"bg-surface-alt rounded-xl overflow-hidden\">\n <img data-image-query=\"minimalist product on white background\" alt=\"Product\" class=\"w-full h-48 object-cover\" />\n <div class=\"p-4\"><h3 class=\"font-bold text-on-surface text-sm\">Producto Alpha</h3><p class=\"text-xs text-on-surface-muted mt-1\">Dise\u00F1o ergon\u00F3mico premium</p><div class=\"text-lg font-bold text-primary mt-2\">$2,490</div></div>\n </div>\n <div class=\"bg-surface-alt rounded-xl overflow-hidden\">\n <img data-image-query=\"elegant product photography studio\" alt=\"Product\" class=\"w-full h-48 object-cover\" />\n <div class=\"p-4\"><h3 class=\"font-bold text-on-surface text-sm\">Producto Beta</h3><p class=\"text-xs text-on-surface-muted mt-1\">Tecnolog\u00EDa de vanguardia</p><div class=\"text-lg font-bold text-primary mt-2\">$3,190</div></div>\n </div>\n </div>\n </div>\n <!-- Footer: direct child of section, shrink-0, full width -->\n <div class=\"shrink-0 w-full bg-surface-alt px-[0.75in] py-3 flex justify-between items-center\">\n <span class=\"text-xs text-on-surface-muted\">Colecci\u00F3n Primavera 2026</span>\n <span class=\"text-xs text-on-surface-muted\">P\u00E1gina 3 de 8</span>\n </div>\n</section>\n\nEXAMPLE \u2014 Content page with table + progress bars:\n<section class=\"w-[8.5in] h-[11in] relative overflow-hidden flex flex-col bg-white\">\n <div class=\"shrink-0 h-1.5 bg-primary w-full\"></div>\n <div class=\"flex-1 overflow-hidden px-[0.75in] py-[0.5in]\">\n <h2 class=\"text-2xl font-bold text-gray-900 mb-1\">M\u00E9tricas de Rendimiento</h2>\n <p class=\"text-sm font-normal text-gray-500 mb-8\">Indicadores clave del periodo enero\u2014marzo</p>\n <table class=\"w-full text-sm mb-10\">\n <thead><tr class=\"bg-primary text-white\"><th class=\"px-4 py-3 text-left font-semibold\">Indicador</th><th class=\"px-4 py-3 text-left font-semibold\">Valor</th><th class=\"px-4 py-3 text-left font-semibold\">Meta</th></tr></thead>\n <tbody>\n <tr class=\"bg-surface-alt\"><td class=\"px-4 py-3 text-gray-900\">Ingresos</td><td class=\"px-4 py-3 text-gray-900\">$1.2M</td><td class=\"px-4 py-3 text-gray-900\">$1.5M</td></tr>\n <tr><td class=\"px-4 py-3 text-gray-900\">Clientes nuevos</td><td class=\"px-4 py-3 text-gray-900\">340</td><td class=\"px-4 py-3 text-gray-900\">300</td></tr>\n <tr class=\"bg-surface-alt\"><td class=\"px-4 py-3 text-gray-900\">Retenci\u00F3n</td><td class=\"px-4 py-3 text-gray-900\">92%</td><td class=\"px-4 py-3 text-gray-900\">90%</td></tr>\n </tbody>\n </table>\n <h3 class=\"text-lg font-bold text-gray-900 mb-4\">Progreso por \u00C1rea</h3>\n <div class=\"space-y-4\">\n <div><div class=\"flex justify-between text-sm mb-1\"><span class=\"text-gray-900 font-semibold\">Ventas</span><span class=\"text-gray-500\">80%</span></div><div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-primary h-3 rounded-full\" style=\"width: 80%\"></div></div></div>\n <div><div class=\"flex justify-between text-sm mb-1\"><span class=\"text-gray-900 font-semibold\">Marketing</span><span class=\"text-gray-500\">65%</span></div><div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-secondary h-3 rounded-full\" style=\"width: 65%\"></div></div></div>\n <div><div class=\"flex justify-between text-sm mb-1\"><span class=\"text-gray-900 font-semibold\">Producto</span><span class=\"text-gray-500\">95%</span></div><div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-accent h-3 rounded-full\" style=\"width: 95%\"></div></div></div>\n </div>\n </div>\n</section>";
7
- declare const DOCUMENT_PROMPT_SUFFIX = "\n\nOUTPUT FORMAT: NDJSON \u2014 one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Page Title\", \"html\": \"<section class='w-[8.5in] h-[11in] relative overflow-hidden flex flex-col'>...</section>\"}\n\nGenerate 3-8 pages depending on content length. First page = cover/title page.\nEach page must fit within letter size (8.5\" \u00D7 11\"). Be conservative with spacing.\nMake each page visually distinct \u2014 different layouts, different accent placements.\nIMPORTANT: Adapt your design style to match the type of document \u2014 not everything is a report. Brochures should feel bold and visual, catalogs should showcase products, invitations should feel elegant, etc.";
6
+ type PageFormat = "letter" | "web";
7
+ declare const PAGE_FORMAT_CONFIG: {
8
+ readonly letter: {
9
+ readonly container: "w-[8.5in] h-[11in]";
10
+ readonly bodyText: "text-sm or text-base (10-11px)";
11
+ readonly maxColumns: 2;
12
+ readonly heightMode: "fixed at 11in";
13
+ readonly description: "letter-sized (8.5\" × 11\") document pages";
14
+ };
15
+ readonly web: {
16
+ readonly container: "w-[1280px] min-h-[800px]";
17
+ readonly bodyText: "text-base or text-lg (16-18px)";
18
+ readonly maxColumns: 1;
19
+ readonly heightMode: "flexible, no max height";
20
+ readonly description: "web-optimized document sections";
21
+ };
22
+ };
23
+ declare function getDocumentSystemPrompt(format?: PageFormat): string;
24
+ declare const DOCUMENT_SYSTEM_PROMPT: string;
25
+ declare function getDocumentPromptSuffix(format?: PageFormat): string;
26
+ declare const DOCUMENT_PROMPT_SUFFIX: string;
8
27
  interface GenerateDocumentOptions {
9
28
  anthropicApiKey?: string;
10
29
  openaiApiKey?: string;
@@ -31,54 +50,26 @@ declare const DocumentOutlineSchema: z.ZodObject<{
31
50
  pages: z.ZodArray<z.ZodObject<{
32
51
  pageNumber: z.ZodNumber;
33
52
  label: z.ZodString;
34
- type: z.ZodEnum<["cover", "content", "data", "visual", "closing"]>;
53
+ type: z.ZodEnum<{
54
+ cover: "cover";
55
+ content: "content";
56
+ data: "data";
57
+ visual: "visual";
58
+ closing: "closing";
59
+ }>;
35
60
  layoutHint: z.ZodString;
36
61
  contentBrief: z.ZodString;
37
- keyElements: z.ZodArray<z.ZodString, "many">;
38
- backgroundStyle: z.ZodEnum<["white", "primary", "gradient", "surface-alt", "image"]>;
62
+ keyElements: z.ZodArray<z.ZodString>;
63
+ backgroundStyle: z.ZodEnum<{
64
+ primary: "primary";
65
+ "surface-alt": "surface-alt";
66
+ image: "image";
67
+ white: "white";
68
+ gradient: "gradient";
69
+ }>;
39
70
  continuesFrom: z.ZodOptional<z.ZodString>;
40
- }, "strip", z.ZodTypeAny, {
41
- type: "cover" | "content" | "data" | "visual" | "closing";
42
- layoutHint: string;
43
- pageNumber: number;
44
- label: string;
45
- contentBrief: string;
46
- keyElements: string[];
47
- backgroundStyle: "primary" | "surface-alt" | "image" | "white" | "gradient";
48
- continuesFrom?: string | undefined;
49
- }, {
50
- type: "cover" | "content" | "data" | "visual" | "closing";
51
- layoutHint: string;
52
- pageNumber: number;
53
- label: string;
54
- contentBrief: string;
55
- keyElements: string[];
56
- backgroundStyle: "primary" | "surface-alt" | "image" | "white" | "gradient";
57
- continuesFrom?: string | undefined;
58
- }>, "many">;
59
- }, "strip", z.ZodTypeAny, {
60
- pages: {
61
- type: "cover" | "content" | "data" | "visual" | "closing";
62
- layoutHint: string;
63
- pageNumber: number;
64
- label: string;
65
- contentBrief: string;
66
- keyElements: string[];
67
- backgroundStyle: "primary" | "surface-alt" | "image" | "white" | "gradient";
68
- continuesFrom?: string | undefined;
69
- }[];
70
- }, {
71
- pages: {
72
- type: "cover" | "content" | "data" | "visual" | "closing";
73
- layoutHint: string;
74
- pageNumber: number;
75
- label: string;
76
- contentBrief: string;
77
- keyElements: string[];
78
- backgroundStyle: "primary" | "surface-alt" | "image" | "white" | "gradient";
79
- continuesFrom?: string | undefined;
80
- }[];
81
- }>;
71
+ }, z.core.$strip>>;
72
+ }, z.core.$strip>;
82
73
  type DocumentOutline = z.infer<typeof DocumentOutlineSchema>;
83
74
  interface GenerateDocumentParallelOptions {
84
75
  anthropicApiKey?: string;
@@ -98,6 +89,7 @@ interface GenerateDocumentParallelOptions {
98
89
  persistImage?: (tempUrl: string, query: string) => Promise<string>;
99
90
  pageCount?: number;
100
91
  skipCover?: boolean;
92
+ pageFormat?: PageFormat;
101
93
  onOutline?: (outline: DocumentOutline) => void;
102
94
  onPageChunk?: (pageIndex: number, partialHtml: string) => void;
103
95
  onPageComplete?: (pageIndex: number, section: Section3) => void;
@@ -112,4 +104,4 @@ interface GenerateDocumentParallelOptions {
112
104
  }
113
105
  declare function generateDocumentParallel(options: GenerateDocumentParallelOptions): Promise<Section3[]>;
114
106
 
115
- export { DOCUMENT_PROMPT_SUFFIX, DOCUMENT_SYSTEM_PROMPT, type DocumentOutline, type GenerateDocumentOptions, type GenerateDocumentParallelOptions, generateDocument, generateDocumentParallel };
107
+ export { DOCUMENT_PROMPT_SUFFIX, DOCUMENT_SYSTEM_PROMPT, type DocumentOutline, type GenerateDocumentOptions, type GenerateDocumentParallelOptions, PAGE_FORMAT_CONFIG, type PageFormat, generateDocument, generateDocumentParallel, getDocumentPromptSuffix, getDocumentSystemPrompt };
@@ -1,14 +1,20 @@
1
1
  import {
2
2
  DOCUMENT_PROMPT_SUFFIX,
3
3
  DOCUMENT_SYSTEM_PROMPT,
4
+ PAGE_FORMAT_CONFIG,
4
5
  generateDocument,
5
- generateDocumentParallel
6
- } from "./chunk-6LK7JW6Q.js";
6
+ generateDocumentParallel,
7
+ getDocumentPromptSuffix,
8
+ getDocumentSystemPrompt
9
+ } from "./chunk-X5MEN76P.js";
7
10
  import "./chunk-YZHRLDQF.js";
8
11
  export {
9
12
  DOCUMENT_PROMPT_SUFFIX,
10
13
  DOCUMENT_SYSTEM_PROMPT,
14
+ PAGE_FORMAT_CONFIG,
11
15
  generateDocument,
12
- generateDocumentParallel
16
+ generateDocumentParallel,
17
+ getDocumentPromptSuffix,
18
+ getDocumentSystemPrompt
13
19
  };
14
20
  //# sourceMappingURL=generateDocument.js.map
@@ -0,0 +1,12 @@
1
+ import { S as Section3 } from './types-BIpbpCJr.js';
2
+
3
+ /**
4
+ * Extract Section3[] from GrapesJS editor HTML (which may include a <style> block).
5
+ * The <style> block with GrapesJS CSS is stored as a special first section.
6
+ * Each top-level <section> or element becomes one Section3 entry.
7
+ *
8
+ * NOTE: Browser-only — uses DOMParser.
9
+ */
10
+ declare function grapesToSections(html: string): Section3[];
11
+
12
+ export { grapesToSections };