best-email-builder 0.1.0 → 0.1.1

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/events.js","../src/core/mjmlAttributes.js","../src/core/EmailEditor.js","../src/adapters/grapesjs/engineConfig.js","../src/adapters/grapesjs/GrapesJsAdapter.js","../src/core/registry.js","../src/blocks/shared.js","../src/blocks/structure/index.js","../src/blocks/text/index.js","../src/blocks/image/index.js","../src/blocks/button/index.js","../src/blocks/divider/index.js","../src/blocks/spacer/index.js","../src/blocks/columns/index.js","../src/blocks/index.js","../src/features/autosave/index.js","../src/features/versions/VersionsMenu.jsx","../src/ui/primitives/button.jsx","../src/ui/primitives/cn.js","../src/ui/primitives/overlays.jsx","../src/ui/context.jsx","../src/ui/primitives/misc.jsx","../src/features/versions/index.js","../src/features/variables/VariablesMenu.jsx","../src/features/variables/VariableDialog.jsx","../src/ui/primitives/fields.jsx","../src/features/variables/VariablePicker.jsx","../src/features/variables/index.js","../src/features/preview/PreviewButton.jsx","../src/features/preview/index.js","../src/features/test-email/TestEmailButton.jsx","../src/features/test-email/index.js","../src/features/index.js","../src/ui/EmailBuilder.jsx","../src/features/templates/starter.js","../src/features/autosave/scheduler.js","../src/features/autosave/localDraft.js","../src/storage/client.js","../src/ui/EmailCanvas.jsx","../src/ui/BlockSidebar.jsx","../src/ui/ElementActions.jsx","../src/ui/PropertiesPanel.jsx","../src/ui/fields.jsx","../src/ui/primitives/color-picker.jsx","../src/features/variables/VariableInsertButton.jsx","../src/ui/Toolbar.jsx","../src/ui/useEmailEditorState.js","../src/ui/EmailBuilderBoundary.jsx","../src/index.js"],"sourcesContent":["// @ts-check\n/**\n * Minimal, dependency-free event emitter.\n *\n * A throwing listener does not prevent the next ones from running: the error\n * goes to `onError` (the console by default). A UI listening to the selection\n * must not break the history because one panel crashed.\n */\n\n/**\n * @typedef {(payload?: any) => void} Listener\n * @typedef {{\n * on: (event: string, listener: Listener) => () => void,\n * off: (event: string, listener: Listener) => void,\n * emit: (event: string, payload?: any) => void,\n * clear: () => void,\n * }} Emitter\n */\n\n/**\n * @param {{onError?: (error: unknown, event: string) => void}} [options]\n * @returns {Emitter}\n */\nexport function createEmitter({ onError } = {}) {\n /** @type {Map<string, Set<Listener>>} */\n const listeners = new Map();\n const report =\n onError ||\n ((error, event) => {\n console.warn(`[best-email-builder] listener for \"${event}\" failed`, error);\n });\n\n /** @param {string} event @param {Listener} listener */\n function off(event, listener) {\n listeners.get(event)?.delete(listener);\n }\n\n return {\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)?.add(listener);\n return () => off(event, listener);\n },\n off,\n emit(event, payload) {\n for (const listener of [...(listeners.get(event) || [])]) {\n try {\n listener(payload);\n } catch (error) {\n report(error, event);\n }\n }\n },\n clear() {\n listeners.clear();\n },\n };\n}\n","// @ts-check\n/**\n * MJML attributes — reading and writing properties panel values.\n *\n * This is knowledge of the LANGUAGE (MJML), not of the engine: it lives in\n * the core, and every adapter benefits from it.\n *\n * ── PADDING IS WRITTEN IN LONGHAND ─────────────────────────────────────────\n * An MJML element carries both `padding` and `padding-top/-right/-bottom/\n * -left`, and the longhand wins. The canvas, starting from the defaults\n * (`padding-top=\"10px\"`…), ignored a `padding=\"40px 60px\"` that the sent\n * email did apply: the screen lied. So `padding` is always written as four\n * attributes, and read back the same way.\n *\n * `inner-padding` (button) has no longhand in MJML: it stays as is.\n *\n * ── NO QUOTES IN A VALUE ───────────────────────────────────────────────────\n * The engine export writes attributes unescaped: a `\"` in a value would break\n * the MJML. Double quotes, angle brackets and line breaks are stripped on\n * write.\n */\n\n/** Spacing attributes that have a longhand form in MJML. */\nexport const LONGHAND_SPACING = new Set(['padding']);\n\nexport const SIDES = /** @type {const} */ (['top', 'right', 'bottom', 'left']);\n\n/**\n * \"10px 25px\" → ['10px', '25px', '10px', '25px'] (CSS 1-to-4 value rule).\n * @param {string|null|undefined} value\n * @returns {[string, string, string, string]}\n */\nexport function parseSpacing(value) {\n const parts = String(value || '')\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n const [a = '0px', b = a, c = a, d = b] = parts;\n return [a, b, c, d];\n}\n\n/**\n * Shortest form of a four-sided spacing.\n * @param {string[]} sides\n */\nexport function formatSpacing(sides) {\n const [t, r, b, l] = sides.map((s) => String(s || '0px'));\n if (t === b && r === l) return t === r ? t : `${t} ${r}`;\n if (r === l) return `${t} ${r} ${b}`;\n return `${t} ${r} ${b} ${l}`;\n}\n\n/** Attribute value safe for an unescaped export. @param {unknown} value */\nexport function cleanAttributeValue(value) {\n return String(value ?? '')\n .replace(/[\"<>\\r\\n]/g, '')\n .trim();\n}\n\n/**\n * Entered values → MJML attributes to set (`null` = attribute to remove).\n *\n * @param {Record<string, string|null|undefined>} values\n * @returns {Record<string, string|null>}\n */\nexport function toAttributes(values) {\n /** @type {Record<string, string|null>} */\n const out = {};\n for (const [key, raw] of Object.entries(values || {})) {\n const value = raw === null || raw === undefined ? '' : cleanAttributeValue(raw);\n if (LONGHAND_SPACING.has(key)) {\n const sides = value ? parseSpacing(value) : null;\n SIDES.forEach((side, i) => {\n out[`${key}-${side}`] = sides ? sides[i] : null;\n });\n out[key] = null;\n } else {\n out[key] = value || null;\n }\n }\n return out;\n}\n\n/**\n * Element attributes → a block's property values.\n *\n * @param {Record<string, unknown>} attributes\n * @param {{key: string}[]} properties\n * @returns {Record<string, string>}\n */\nexport function toValues(attributes, properties) {\n /** @type {Record<string, string>} */\n const values = {};\n for (const { key } of properties) {\n if (LONGHAND_SPACING.has(key)) {\n const base = parseSpacing(String(attributes[key] ?? ''));\n const sides = SIDES.map((side, i) => {\n const v = attributes[`${key}-${side}`];\n return v === undefined || v === null || v === '' ? base[i] : String(v);\n });\n const hasAny = attributes[key] || SIDES.some((side) => attributes[`${key}-${side}`]);\n values[key] = hasAny ? formatSpacing(sides) : '';\n } else {\n const v = attributes[key];\n values[key] = v === undefined || v === null ? '' : String(v);\n }\n }\n return values;\n}\n","// @ts-check\n/**\n * EmailEditor — THE email builder contract.\n *\n * ── THE ARCHITECTURE RULE ──────────────────────────────────────────────────\n *\n * React UI ─► EmailEditor ─► adapter ─► engine (GrapesJS) ─► MJML\n *\n * The UI (`ui/`), features (`features/`) and blocks (`blocks/`) talk ONLY to\n * this object. None of them imports GrapesJS: everything engine-related lives\n * in `adapters/grapesjs/`. Swapping the engine therefore means writing another\n * adapter that fulfils `EmailEditorAdapter`, rewriting nothing above it.\n *\n * ── WHAT THIS LAYER ADDS TO THE ADAPTER ────────────────────────────────────\n * - the lifecycle (idle → initializing → ready → idle), and a hard refusal\n * of any call made before `initialize` or after `destroy`;\n * - resolving blocks by id in the registry;\n * - the versioned document envelope (`core/document.js`);\n * - starting and stopping registered features.\n *\n * See `docs/ARCHITECTURE.md`.\n */\n\nimport { createEmitter } from './events.js';\nimport { EMAIL_DEVICES } from './constants.js';\nimport { createDocument, readDocument } from './document.js';\nimport { toAttributes, toValues } from './mjmlAttributes.js';\n\n/**\n * @typedef {import('./constants.js').EmailDevice} EmailDevice\n * @typedef {import('./document.js').EmailDocument} EmailDocument\n */\n\n/**\n * Editable block property, as shown in the right-hand panel. The key is an\n * MJML ATTRIBUTE (`color`, `padding`, `href`…) — the email's language, not\n * the engine's.\n *\n * @typedef {{\n * key: string,\n * label: string,\n * type: 'text'|'textarea'|'color'|'size'|'select'|'align'|'url'|'image'|'spacing',\n * group: string,\n * options?: {value: string, label: string}[],\n * placeholder?: string,\n * min?: number,\n * max?: number,\n * unit?: string,\n * }} BlockProperty\n */\n\n/**\n * Builder block.\n *\n * `content` : an element (text, image, button…) that lives INSIDE a column;\n * `layout` : an N-column section, living in the email body;\n * `structure` : body, section, column — selectable, not addable.\n *\n * `mjml` is the inserted fragment; `sectionMjml` the same wrapped in a\n * section, for when it must go outside any column; `tagName` identifies the\n * block of a selected element (`mj-text` → text).\n * `editableContent`: the content is editable (canvas for text, panel for a\n * button label).\n *\n * @typedef {{\n * id: string,\n * label: string,\n * description?: string,\n * icon: string,\n * kind: 'content'|'layout'|'structure',\n * tagName: string,\n * order?: number,\n * mjml?: string,\n * sectionMjml?: string,\n * properties: BlockProperty[],\n * editableContent?: boolean,\n * }} EmailBlock\n */\n\n/**\n * Selected element as described by the ENGINE: MJML tag and raw attributes,\n * nothing more.\n *\n * @typedef {{\n * id: string,\n * tagName: string,\n * attributes: Record<string, string>,\n * content: string|null,\n * canRemove: boolean,\n * canDuplicate: boolean,\n * canMoveUp: boolean,\n * canMoveDown: boolean,\n * }} EngineSelection\n */\n\n/**\n * Selected element, in the builder's vocabulary: its block and its property\n * values (padding recombined, see mjmlAttributes).\n *\n * @typedef {EngineSelection & {\n * blockId: string|null,\n * label: string,\n * values: Record<string, string>,\n * }} EmailSelection\n */\n\n/**\n * @typedef {{html: string, errors: {line?: number, message: string, tagName?: string}[]}} HtmlExport\n */\n\n/**\n * What an engine must provide. All element ids are opaque strings returned by\n * the adapter itself.\n *\n * Events emitted through `onEvent(type, payload)`:\n * `change` the document changed (typing, add, remove, undo…)\n * `load` a whole document was just loaded — NOT a modification: the\n * host screen decides whether it needs saving\n * `selection` the selection changed — payload: EngineSelection|null\n * `history` undo/redo state changed — payload: {canUndo, canRedo}\n * `device` the displayed device changed — payload: EmailDevice\n *\n * @typedef {{\n * name: string,\n * version: string,\n * initialize: (options: {\n * container: HTMLElement,\n * blocks: EmailBlock[],\n * document: EmailDocument|null,\n * onEvent: (type: string, payload?: any) => void,\n * }) => Promise<void>,\n * destroy: () => void,\n * addBlock: (block: EmailBlock, options?: {targetId?: string|null}) => string|null,\n * remove: (id: string) => boolean,\n * duplicate: (id: string) => string|null,\n * move: (id: string, direction: -1|1) => boolean,\n * select: (id: string|null) => void,\n * getSelection: () => EngineSelection|null,\n * describe: (id: string) => EngineSelection|null,\n * getRootId: () => string|null,\n * updateProperties: (id: string, attributes: Record<string, string|null>) => void,\n * setContent: (id: string, content: string) => void,\n * insertText: (text: string) => boolean,\n * insertLink: (href: string, label: string) => boolean,\n * undo: () => void,\n * redo: () => void,\n * canUndo: () => boolean,\n * canRedo: () => boolean,\n * clearHistory: () => void,\n * getProject: () => object,\n * loadProject: (project: object) => void,\n * loadMjml: (mjml: string) => void,\n * exportMjml: () => string,\n * exportHtml: () => HtmlExport,\n * setDevice: (device: EmailDevice) => void,\n * getDevice: () => EmailDevice,\n * startBlockDrag: (block: EmailBlock, event: Event) => void,\n * endBlockDrag: (cancel?: boolean) => void,\n * addShortcut: (id: string, keys: string, handler: () => void) => (() => void),\n * }} EmailEditorAdapter\n */\n\n/**\n * Pluggable feature. `setup` receives the ready editor and may return a\n * teardown function, called on `destroy`. `toolbar`: React component placed in\n * the toolbar (it receives the screen context); `options`: its settings, read\n * by the screen; `isAvailable(context)`: hides the toolbar entry when the\n * context cannot support it (e.g. a storage that cannot render).\n *\n * @typedef {{\n * id: string,\n * label?: string,\n * order?: number,\n * enabled?: boolean,\n * setup?: (editor: EmailEditor) => (void | (() => void)),\n * toolbar?: any,\n * isAvailable?: (context: any) => boolean,\n * options?: Record<string, any>,\n * }} EmailBuilderFeature\n */\n\n/**\n * @typedef {'idle'|'initializing'|'ready'} EmailEditorStatus\n */\n\n/**\n * @typedef {{\n * readonly status: EmailEditorStatus,\n * readonly adapterName: string,\n * initialize: (options: {container: HTMLElement, document?: EmailDocument|null}) => Promise<void>,\n * destroy: () => void,\n * listBlocks: () => EmailBlock[],\n * getBlock: (blockId: string) => EmailBlock|undefined,\n * addBlock: (blockId: string, options?: {targetId?: string|null}) => string|null,\n * remove: (id?: string|null) => boolean,\n * duplicate: (id?: string|null) => string|null,\n * move: (direction: -1|1, id?: string|null) => boolean,\n * select: (id: string|null) => void,\n * getSelection: () => EmailSelection|null,\n * getElement: (id: string) => EmailSelection|null,\n * getRootId: () => string|null,\n * updateProperties: (values: Record<string, string|null>, id?: string|null) => void,\n * setContent: (content: string, id?: string|null) => void,\n * insertText: (text: string) => boolean,\n * insertLink: (href: string, label: string) => boolean,\n * undo: () => void,\n * redo: () => void,\n * canUndo: () => boolean,\n * canRedo: () => boolean,\n * getDocument: () => EmailDocument,\n * loadDocument: (document: unknown) => void,\n * loadMjml: (mjml: string) => void,\n * exportMjml: () => string,\n * exportHtml: () => HtmlExport,\n * setDevice: (device: EmailDevice) => void,\n * getDevice: () => EmailDevice,\n * startBlockDrag: (blockId: string, event: Event) => void,\n * endBlockDrag: (cancel?: boolean) => void,\n * addShortcut: (id: string, keys: string, handler: () => void) => (() => void),\n * on: (event: string, listener: (payload?: any) => void) => () => void,\n * }} EmailEditor\n */\n\n/**\n * @param {{\n * adapter: EmailEditorAdapter,\n * blocks: import('./registry.js').Registry<EmailBlock>,\n * features?: import('./registry.js').Registry<EmailBuilderFeature> | null,\n * }} options\n * @returns {EmailEditor}\n */\nexport function createEmailEditor({ adapter, blocks, features = null }) {\n if (!adapter) throw new Error('EmailEditor: missing adapter');\n if (!blocks) throw new Error('EmailEditor: missing block registry');\n\n const emitter = createEmitter();\n /** @type {EmailEditorStatus} */\n let status = 'idle';\n /** Token of the pending initialization: a `destroy` invalidates it. */\n let generation = 0;\n /** @type {(() => void)[]} */\n let teardowns = [];\n\n function requireReady(action) {\n if (status !== 'ready') {\n throw new Error(`EmailEditor: \"${action}\" called before the editor was initialized`);\n }\n }\n\n /** @param {string|null|undefined} id */\n function targetOf(id, action) {\n const resolved = id ?? adapter.getSelection()?.id ?? null;\n if (!resolved) throw new Error(`EmailEditor: \"${action}\" with no selected element`);\n return resolved;\n }\n\n /** Block describing a tag: structure first (a section stays a section). */\n function blockForTag(tagName) {\n const all = blocks.list();\n return (\n all.find((b) => b.tagName === tagName && b.kind === 'structure') ||\n all.find((b) => b.tagName === tagName) ||\n null\n );\n }\n\n /** @param {EngineSelection|null} selection @returns {EmailSelection|null} */\n function toEmailSelection(selection) {\n if (!selection) return null;\n const block = blockForTag(selection.tagName);\n return {\n ...selection,\n blockId: block?.id || null,\n label: block?.label || selection.tagName,\n values: toValues(selection.attributes || {}, block?.properties || []),\n };\n }\n\n function startFeatures() {\n if (!features) return;\n for (const feature of features.list((f) => f.enabled !== false)) {\n try {\n const stop = feature.setup?.(editor);\n if (typeof stop === 'function') teardowns.push(stop);\n } catch (error) {\n // A broken feature must not prevent editing.\n console.warn(`[best-email-builder] feature \"${feature.id}\" failed`, error);\n }\n }\n }\n\n function stopFeatures() {\n for (const stop of teardowns.reverse()) {\n try {\n stop();\n } catch (error) {\n console.warn('[best-email-builder] feature teardown failed', error);\n }\n }\n teardowns = [];\n }\n\n /** @type {EmailEditor} */\n const editor = {\n get status() {\n return status;\n },\n get adapterName() {\n return adapter.name;\n },\n\n async initialize({ container, document = null }) {\n if (!container) throw new Error('EmailEditor: missing container');\n if (status !== 'idle') {\n throw new Error(`EmailEditor: initialization refused (status \"${status}\")`);\n }\n const ticket = ++generation;\n status = 'initializing';\n try {\n await adapter.initialize({\n container,\n blocks: blocks.list(),\n document: document ? readDocument(document) : null,\n onEvent: (type, payload) => {\n if (ticket !== generation) return;\n emitter.emit(type, type === 'selection' ? toEmailSelection(payload) : payload);\n },\n });\n } catch (error) {\n if (ticket === generation) status = 'idle';\n throw error;\n }\n // Destroyed while the engine was loading (React unmount, StrictMode):\n // the adapter is already released, nothing is declared ready.\n if (ticket !== generation) return;\n status = 'ready';\n startFeatures();\n emitter.emit('ready');\n },\n\n destroy() {\n generation += 1;\n stopFeatures();\n const etait = status;\n status = 'idle';\n adapter.destroy();\n if (etait === 'ready') emitter.emit('destroy');\n },\n\n listBlocks: () => blocks.list(),\n getBlock: (blockId) => blocks.get(blockId),\n\n addBlock(blockId, options = {}) {\n requireReady('addBlock');\n const block = blocks.get(blockId);\n if (!block || !block.mjml) throw new Error(`EmailEditor: unknown block \"${blockId}\"`);\n return adapter.addBlock(block, options);\n },\n\n remove(id = null) {\n requireReady('remove');\n return adapter.remove(targetOf(id, 'remove'));\n },\n\n duplicate(id = null) {\n requireReady('duplicate');\n return adapter.duplicate(targetOf(id, 'duplicate'));\n },\n\n move(direction, id = null) {\n requireReady('move');\n if (direction !== -1 && direction !== 1) throw new Error('EmailEditor: invalid move direction');\n return adapter.move(targetOf(id, 'move'), direction);\n },\n\n select(id) {\n requireReady('select');\n adapter.select(id);\n },\n\n getSelection() {\n return status === 'ready' ? toEmailSelection(adapter.getSelection()) : null;\n },\n\n getElement(id) {\n return status === 'ready' && id ? toEmailSelection(adapter.describe(id)) : null;\n },\n\n /** The email body: page background and width, edited without a selection. */\n getRootId: () => (status === 'ready' ? adapter.getRootId() : null),\n\n updateProperties(values, id = null) {\n requireReady('updateProperties');\n adapter.updateProperties(targetOf(id, 'updateProperties'), toAttributes(values));\n },\n\n setContent(content, id = null) {\n requireReady('setContent');\n adapter.setContent(targetOf(id, 'setContent'), content);\n },\n\n insertText(text) {\n requireReady('insertText');\n return adapter.insertText(String(text ?? ''));\n },\n\n /**\n * Link at the caret of the text being edited, at the end of the selected\n * text, or as the selected button's URL. False if nothing fits.\n */\n insertLink(href, label) {\n requireReady('insertLink');\n return adapter.insertLink(String(href || ''), String(label || href || ''));\n },\n\n undo() {\n requireReady('undo');\n adapter.undo();\n },\n redo() {\n requireReady('redo');\n adapter.redo();\n },\n canUndo: () => status === 'ready' && adapter.canUndo(),\n canRedo: () => status === 'ready' && adapter.canRedo(),\n\n getDocument() {\n requireReady('getDocument');\n return createDocument({\n engine: adapter.name,\n engineVersion: adapter.version,\n project: adapter.getProject(),\n });\n },\n\n loadDocument(raw) {\n requireReady('loadDocument');\n const document = readDocument(raw);\n if (document.engine !== adapter.name) {\n throw new Error(\n `EmailEditor: document written for engine \"${document.engine}\", ` +\n `editor runs on \"${adapter.name}\"`\n );\n }\n adapter.loadProject(document.project);\n // A reloaded document has no history: undo must not bring back the\n // state before the load.\n adapter.clearHistory();\n },\n\n loadMjml(mjml) {\n requireReady('loadMjml');\n adapter.loadMjml(String(mjml || ''));\n adapter.clearHistory();\n },\n\n exportMjml() {\n requireReady('exportMjml');\n return adapter.exportMjml();\n },\n\n exportHtml() {\n requireReady('exportHtml');\n return adapter.exportHtml();\n },\n\n setDevice(device) {\n requireReady('setDevice');\n if (!EMAIL_DEVICES.includes(device)) throw new Error(`EmailEditor: unknown device \"${device}\"`);\n adapter.setDevice(device);\n },\n\n getDevice: () => (status === 'ready' ? adapter.getDevice() : 'desktop'),\n\n startBlockDrag(blockId, event) {\n requireReady('startBlockDrag');\n const block = blocks.get(blockId);\n if (!block || !block.mjml) throw new Error(`EmailEditor: unknown block \"${blockId}\"`);\n adapter.startBlockDrag(block, event);\n },\n\n endBlockDrag(cancel = false) {\n if (status === 'ready') adapter.endBlockDrag(cancel);\n },\n\n /**\n * Keyboard shortcut that also works INSIDE the canvas (an iframe: page\n * listeners hear nothing there). `keys`: `mod+s` (Ctrl, or ⌘ on Mac),\n * several combinations separated by commas.\n */\n addShortcut(id, keys, handler) {\n requireReady('addShortcut');\n return adapter.addShortcut(id, keys, handler);\n },\n\n on: (event, listener) => emitter.on(event, listener),\n };\n\n return editor;\n}\n","// @ts-check\n/**\n * GrapesJS engine configuration — without any of its UI.\n *\n * The builder has ITS OWN React UI: GrapesJS only provides the canvas (the\n * iframe where you click and drag) and its data model. Hence:\n * - `customUI`, `panels.defaults: []` and `custom` managers: no panel, no\n * toolbar, no style or layer manager;\n * - `telemetry: false` and `cssIcons: ''`: no request to a third-party\n * service (GrapesJS stats, Font Awesome from a CDN);\n * - `storageManager: false`: saving is ours (`storage/`), never the\n * engine's `localStorage`;\n * - an HTML parser that rejects scripts and `on*` attributes: a reloaded\n * template must not be able to execute anything in the host page.\n */\n\n/** Canvas devices: ids = `EmailDevice`. */\nexport const DEVICES = [\n { id: 'desktop', name: 'desktop', width: '' },\n // `widthMedia`: MJML's mobile rule (480px) applies inside the frame.\n { id: 'mobile', name: 'mobile', width: '375px', widthMedia: '480px' },\n];\n\n/** Empty email: just the body, at the standard width. */\nexport const EMPTY_MJML =\n '<mjml><mj-body background-color=\"#eceff4\" width=\"600px\"></mj-body></mjml>';\n\n/**\n * Image WITHOUT A FILE, as shown in the canvas: a light grey 600 × 220 banner\n * with an icon. Replaces GrapesJS's default `src`, raw SVG markup whose quotes\n * and \";\" broke the attribute and the style string the MJML plugin reads back\n * (\"illegal transform attribute\"). This one is a `data:` URL with NO \";\" and\n * no double quote.\n *\n * It never leaves the adapter: `GrapesJsAdapter` turns it into \"no image\" in\n * the export, the project and the selection.\n */\nexport const IMAGE_PLACEHOLDER =\n \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 220'%3E\" +\n \"%3Crect width='600' height='220' fill='%23f3f5f9'/%3E\" +\n \"%3Cg transform='translate(276 86)' fill='none' stroke='%238b93a3' stroke-width='2' \" +\n \"stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='1' width='46' height='46' rx='5'/%3E\" +\n \"%3Ccircle cx='17' cy='17' r='5'/%3E%3Cpath d='m47 31-8-8a4 4 0 0 0-6 0L5 47'/%3E%3C/g%3E%3C/svg%3E\";\n\n/**\n * Stylesheet injected INTO the canvas iframe: editing cues only, never\n * exported into the email.\n */\nconst CANVAS_CSS = `\n body { background: #eceff4; }\n [data-gjs-highlightable] { outline-offset: -1px; }\n *::selection { background: rgba(53, 104, 168, .22); }\n`;\n\n/**\n * @param {{\n * container: HTMLElement,\n * mjmlPlugin: any,\n * locales?: {engine?: any, mjml?: any},\n * locale?: string,\n * }} options\n */\nexport function buildEngineConfig({ container, mjmlPlugin, locales = {}, locale = 'en' }) {\n return {\n container,\n height: '100%',\n width: 'auto',\n telemetry: false,\n customUI: true,\n cssIcons: '',\n noticeOnUnload: false,\n storageManager: /** @type {false} */ (false),\n fromElement: false,\n showDevices: false,\n showOffsets: false,\n multipleSelection: false,\n avoidInlineStyle: true,\n log: /** @type {('warning'|'error')[]} */ (['error']),\n canvasCss: CANVAS_CSS,\n i18n: {\n locale,\n localeFallback: locale,\n detectLocale: false,\n messages: locales.engine ? { [locale]: locales.engine } : {},\n },\n panels: { defaults: [] },\n blockManager: { custom: true },\n layerManager: { custom: true },\n traitManager: { custom: true },\n selectorManager: { custom: true, componentFirst: true },\n styleManager: { custom: true },\n assetManager: { custom: true, upload: false },\n deviceManager: { devices: DEVICES, default: 'desktop' },\n undoManager: { trackSelection: false, maximumStackLength: 300 },\n // Canvas shortcuts: the ones users expect (undo, redo — Ctrl+Y included —,\n // copy, paste, delete), without GrapesJS's single-letter navigation\n // (\"s\", \"w\", \"a\", \"d\") that moved the selection on any keypress outside a\n // field.\n keymaps: {\n defaults: {\n 'core:undo': { keys: '⌘+z, ctrl+z', handler: 'core:undo', opts: { prevent: true } },\n 'core:redo': { keys: '⌘+shift+z, ctrl+shift+z, ctrl+y', handler: 'core:redo', opts: { prevent: true } },\n 'core:copy': { keys: '⌘+c, ctrl+c', handler: 'core:copy' },\n 'core:paste': { keys: '⌘+v, ctrl+v', handler: 'core:paste' },\n 'core:component-delete': { keys: 'backspace, delete', handler: 'core:component-delete', opts: { prevent: true } },\n },\n },\n parser: {\n optionsHtml: {\n allowScripts: false,\n allowUnsafeAttr: false,\n allowUnsafeAttrValue: false,\n },\n },\n plugins: [\n (/** @type {any} */ editor) =>\n mjmlPlugin(editor, {\n // No blocks, devices or style settings from the plugin: blocks and\n // properties come from `blocks/`.\n blocks: [],\n resetBlocks: true,\n resetDevices: false,\n resetStyleManager: false,\n hideSelector: true,\n useCustomTheme: false,\n overwriteExport: false,\n imagePlaceholderSrc: IMAGE_PLACEHOLDER,\n i18n: locales.mjml ? { [locale]: locales.mjml } : {},\n }),\n // After the plugin: the empty image gets our banner, not the raw SVG.\n (/** @type {any} */ editor) =>\n editor.Components.addType('mj-image', { model: { defaults: { src: IMAGE_PLACEHOLDER } } }),\n ],\n };\n}\n","// @ts-check\n/**\n * GRAPESJS ADAPTER — the only file of the builder that talks to the engine.\n *\n * It fulfils the `EmailEditorAdapter` contract (core/EmailEditor.js) with\n * GrapesJS and its MJML plugin. Everything leaving this folder is expressed in\n * the email's vocabulary (blocks, MJML attributes, opaque ids), never in the\n * engine's: that is what makes the engine replaceable.\n *\n * ── LOADING ────────────────────────────────────────────────────────────────\n * GrapesJS and the MJML plugin (1.2 MB, `mjml-browser` included) touch\n * `window` as soon as they are evaluated: they are imported dynamically, on\n * the first `initialize`, never during server-side rendering.\n *\n * ── BLOCK PLACEMENT ────────────────────────────────────────────────────────\n * MJML enforces its hierarchy: body → section → column → content. A content\n * block added by click therefore goes:\n * - INTO the selected column;\n * - AFTER the selected element, in the same column;\n * - otherwise into a NEW one-column section, after the selected section or\n * at the end of the body.\n * A layout (N-column section) goes after the current section, or at the end.\n * On drag and drop, the MJML plugin's rules decide where the element can land.\n */\n\nimport { buildEngineConfig, EMPTY_MJML, IMAGE_PLACEHOLDER } from './engineConfig.js';\n\n/**\n * @typedef {import('../../core/EmailEditor.js').EmailEditorAdapter} EmailEditorAdapter\n * @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock\n * @typedef {import('../../core/EmailEditor.js').EngineSelection} EngineSelection\n * @typedef {import('../../core/constants.js').EmailDevice} EmailDevice\n */\n\nexport const ENGINE_NAME = 'grapesjs-mjml';\n/** Engine version, copied into every document (exact package.json version). */\nexport const ENGINE_VERSION = '0.22.16';\n\n/** Prefix of blocks registered with the engine — for drag and drop only. */\nconst BLOCK_PREFIX = 'eb-';\n\n/** Structural elements that cannot be removed, duplicated or moved. */\nconst LOCKED_TYPES = new Set(['mjml', 'mj-head', 'mj-body', 'wrapper']);\n\n/** Elements whose content is a plain label, edited in the panel. */\nconst LABEL_TYPES = new Set(['mj-button']);\n\n/** Elements whose content is edited in the canvas (rich text editor). */\nconst RICH_TYPES = new Set(['mj-text', 'mj-button']);\n\n/**\n * Engine labels visible in the canvas (element badge), per locale. Static\n * import paths so bundlers can see them; English needs none (engine default).\n *\n * @type {Record<string, () => Promise<any[]>>}\n */\nconst ENGINE_LOCALES = {\n fr: () => Promise.all([import('grapesjs/locale/fr.mjs'), import('grapesjs-mjml/locale/fr')]),\n};\n\n/**\n * Engine loading, injectable for tests. The canvas stylesheets (GrapesJS +\n * `engine-overrides.css`) ship in `best-email-builder/styles.css`.\n *\n * @param {string} locale\n */\nasync function defaultLoadEngine(locale) {\n const loadLocales = Object.prototype.hasOwnProperty.call(ENGINE_LOCALES, locale) ? ENGINE_LOCALES[locale] : null;\n const [grapesjs, mjml, localeModules] = await Promise.all([\n import('grapesjs'),\n import('grapesjs-mjml'),\n loadLocales ? loadLocales() : Promise.resolve(null),\n ]);\n /** @param {any} mod */\n const unwrap = (mod) => mod.default || mod;\n return {\n grapesjs: unwrap(grapesjs),\n mjmlPlugin: unwrap(mjml),\n locales: localeModules\n ? { engine: unwrap(localeModules[0]), mjml: unwrap(localeModules[1]) }\n : {},\n };\n}\n\n/**\n * Empty image: the canvas shows it as a banner (`IMAGE_PLACEHOLDER`, see\n * engineConfig) that never crosses the adapter boundary — it becomes \"no\n * image\" (`''`) in the MJML, the project and the selection. GrapesJS's\n * original SVG icon is handled the same way, in case an old project still\n * carries it.\n */\nconst ENGINE_SVG = /^\\s*<svg[\\s>]/i;\nconst PLACEHOLDER_SRC_ATTR = new RegExp(\n `\\\\ssrc=\"(?:${IMAGE_PLACEHOLDER.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}|\\\\s*<svg[\\\\s\\\\S]*?<\\\\/svg>\\\\s*)\"`,\n 'g'\n);\nconst PLACEHOLDER_SRC_STYLE = /src:\\s*<svg[\\s\\S]*?<\\/svg>;?/gi;\n\n/** @param {unknown} value */\nfunction isEnginePlaceholder(value) {\n return typeof value === 'string' && (value === IMAGE_PLACEHOLDER || ENGINE_SVG.test(value));\n}\n\n/**\n * Copy of the project without the engine's empty-image icon.\n * @param {any} node\n * @returns {any}\n */\nfunction withoutPlaceholders(node) {\n if (Array.isArray(node)) return node.map(withoutPlaceholders);\n if (!node || typeof node !== 'object') return node;\n /** @type {Record<string, any>} */\n const out = {};\n for (const [key, value] of Object.entries(node)) {\n if (key === 'src' && isEnginePlaceholder(value)) out[key] = '';\n else if (key === 'style' && typeof value === 'string') {\n out[key] = value.replace(PLACEHOLDER_SRC_STYLE, '').split(`src:${IMAGE_PLACEHOLDER};`).join('');\n } else out[key] = withoutPlaceholders(value);\n }\n return out;\n}\n\nfunction escapeHtml(text) {\n return String(text ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Inserts HTML at the CARET of the text being edited, or returns false.\n *\n * ⚠️ `view.rte` is the editing MODULE (no `insertHTML`); the instance holding\n * the selection is `view.activeRte`. The content is then synced back into the\n * model (`syncContent`): otherwise the export would only see it once the user\n * leaves the text.\n */\nfunction insertAtCaret(ed, html) {\n const view = ed.getEditing()?.view;\n const rte = view?.activeRte;\n if (!view || typeof rte?.insertHTML !== 'function') return false;\n rte.insertHTML(html);\n view.onInput?.();\n void view.syncContent?.();\n return true;\n}\n\n/**\n * @param {{\n * locale?: string,\n * loadEngine?: (locale: string) => Promise<{grapesjs: any, mjmlPlugin: any, locales?: {engine?: any, mjml?: any}}>,\n * }} [options]\n * @returns {EmailEditorAdapter & {readonly engine: any}}\n */\nexport function createGrapesJsAdapter({ locale = 'en', loadEngine = defaultLoadEngine } = {}) {\n /** @type {any} */\n let editor = null;\n /** @type {HTMLElement|null} */\n let host = null;\n /** @type {(type: string, payload?: any) => void} */\n let emit = () => {};\n /** Token: a `destroy` during engine loading invalidates the init. */\n let generation = 0;\n let selectionQueued = false;\n /**\n * Load in progress: GrapesJS reports changes through a DEFERRED `update`\n * (setTimeout 0). The one from a load would arrive late and look like user\n * input — the template would show as \"modified\" right after opening. It is\n * muted until the event-loop turn after the load.\n */\n let loading = false;\n\n function muteUntilFlushed() {\n loading = true;\n setTimeout(() => {\n loading = false;\n }, 0);\n }\n\n /* ── Model helpers ───────────────────────────────────────────────────── */\n\n function requireEditor() {\n if (!editor) throw new Error('GrapesJsAdapter: engine not initialized');\n return editor;\n }\n\n /** @param {string} id */\n function byId(id) {\n const all = requireEditor().Components.allById();\n return all[id] || null;\n }\n\n /** @param {any} component */\n function typeOf(component) {\n return component ? String(component.get('type') || '') : '';\n }\n\n function body() {\n const ed = requireEditor();\n return ed.getWrapper().findType('mj-body')[0] || null;\n }\n\n /**\n * First ancestor (or self) of one of the given types.\n * @param {any} component @param {string[]} types\n */\n function closest(component, types) {\n let current = component;\n while (current) {\n if (types.includes(typeOf(current))) return current;\n current = current.parent();\n }\n return null;\n }\n\n /**\n * An element's MJML attributes, as the export will see them: `src` read\n * from the model (see MJML plugin), engine icon cleared.\n * @param {any} component\n * @returns {Record<string, string>}\n */\n function attributesOf(component) {\n /** @type {Record<string, string>} */\n const out = {};\n for (const [key, value] of Object.entries(component.getAttributes() || {})) {\n if (key === 'style' || key === 'id' || value === undefined || value === null) continue;\n out[key] = String(value);\n }\n if (component.get('src') !== undefined) out.src = String(component.get('src') || '');\n if (isEnginePlaceholder(out.src)) out.src = '';\n return out;\n }\n\n /** @param {any} component @returns {EngineSelection|null} */\n function describe(component) {\n if (!component) return null;\n const type = typeOf(component);\n const parent = component.parent();\n const index = parent ? parent.components().indexOf(component) : -1;\n const siblings = parent ? parent.components().length : 0;\n const locked = LOCKED_TYPES.has(type);\n return {\n id: component.getId(),\n tagName: type,\n attributes: attributesOf(component),\n content: LABEL_TYPES.has(type) ? textOf(component) : null,\n canRemove: !locked && component.get('removable') !== false,\n canDuplicate: !locked && component.get('copyable') !== false,\n canMoveUp: !locked && index > 0,\n canMoveDown: !locked && index >= 0 && index < siblings - 1,\n };\n }\n\n /** Plain text of an element (button label). @param {any} component */\n function textOf(component) {\n const html = component.getInnerHTML ? component.getInnerHTML() : '';\n return String(html)\n .replace(/<br\\s*\\/?>/gi, ' ')\n .replace(/<[^>]*>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&amp;/g, '&')\n .trim();\n }\n\n function queueSelection() {\n if (selectionQueued) return;\n selectionQueued = true;\n queueMicrotask(() => {\n selectionQueued = false;\n if (editor) emit('selection', describe(editor.getSelected()));\n });\n }\n\n function emitHistory() {\n if (!editor) return;\n const um = editor.UndoManager;\n emit('history', { canUndo: um.hasUndo(), canRedo: um.hasRedo() });\n }\n\n /** @param {any} added */\n function firstOf(added) {\n return Array.isArray(added) ? added[0] : added;\n }\n\n /* ── Placement ───────────────────────────────────────────────────────── */\n\n /**\n * Where to put a block. Returns the target collection and index, or an\n * instruction to wrap the content in a new section.\n *\n * @param {EmailBlock} block @param {any} target\n */\n function placementFor(block, target) {\n const root = body();\n if (!root) throw new Error('GrapesJsAdapter: email body not found');\n\n const section = target ? closest(target, ['mj-section', 'mj-wrapper', 'mj-hero']) : null;\n const afterSection = () => {\n if (section && section.parent()) {\n const coll = section.parent().components();\n return { collection: coll, at: coll.indexOf(section) + 1, wrap: false };\n }\n return { collection: root.components(), at: root.components().length, wrap: false };\n };\n\n if (block.kind === 'layout') return afterSection();\n\n const type = typeOf(target);\n if (type === 'mj-column') {\n return { collection: target.components(), at: target.components().length, wrap: false };\n }\n const column = target ? closest(target, ['mj-column']) : null;\n if (column && target !== column) {\n // Walk up to the column's direct child: insert after it.\n let child = target;\n while (child.parent() && child.parent() !== column) child = child.parent();\n const coll = column.components();\n return { collection: coll, at: coll.indexOf(child) + 1, wrap: false };\n }\n return { ...afterSection(), wrap: true };\n }\n\n /* ── Contract ────────────────────────────────────────────────────────── */\n\n /** @type {EmailEditorAdapter & {readonly engine: any}} */\n const adapter = {\n name: ENGINE_NAME,\n version: ENGINE_VERSION,\n\n get engine() {\n return editor;\n },\n\n async initialize({ container, blocks: blockList, document, onEvent }) {\n if (editor) throw new Error('GrapesJsAdapter: already initialized');\n const ticket = ++generation;\n const { grapesjs, mjmlPlugin, locales } = await loadEngine(locale);\n if (ticket !== generation) return;\n\n emit = onEvent;\n host = createEngineHost(container);\n const instance = grapesjs.init(buildEngineConfig({ container: host, mjmlPlugin, locales, locale }));\n editor = instance;\n\n await new Promise((resolve) => instance.onReady(() => resolve(undefined)));\n if (ticket !== generation) return;\n\n // Blocks registered with the engine: only for its drag and drop\n // (`startBlockDrag`), never displayed by it.\n for (const block of blockList) {\n if (!block.mjml) continue;\n instance.Blocks.add(`${BLOCK_PREFIX}${block.id}`, {\n label: block.label,\n content: block.mjml,\n activate: true,\n select: true,\n });\n }\n\n muteUntilFlushed();\n if (document) instance.loadProjectData(document.project);\n else instance.setComponents(EMPTY_MJML);\n instance.UndoManager.clear();\n\n instance.on('update', () => {\n if (!loading) emit('change');\n emitHistory();\n });\n instance.on('undo', emitHistory);\n instance.on('redo', emitHistory);\n instance.on('component:toggled', queueSelection);\n instance.on('component:update', (/** @type {any} */ component) => {\n if (component && component === instance.getSelected()) queueSelection();\n });\n instance.on('change:device', () => emit('device', adapter.getDevice()));\n\n emitHistory();\n },\n\n destroy() {\n generation += 1;\n if (editor) {\n try {\n editor.destroy();\n } catch (error) {\n console.warn('[best-email-builder] engine destroy failed', error);\n }\n }\n editor = null;\n if (host?.parentNode) host.parentNode.removeChild(host);\n host = null;\n emit = () => {};\n },\n\n addBlock(block, { targetId = null } = {}) {\n const ed = requireEditor();\n if (!block.mjml) return null;\n const target = targetId ? byId(targetId) : ed.getSelected();\n const { collection, at, wrap } = placementFor(block, target);\n const source = wrap\n ? block.sectionMjml || `<mj-section><mj-column>${block.mjml}</mj-column></mj-section>`\n : block.mjml;\n const added = firstOf(collection.add(source, { at }));\n if (!added) return null;\n const focus = wrap ? added.findType(block.tagName)[0] || added : added;\n ed.select(focus);\n return focus.getId();\n },\n\n remove(id) {\n const component = byId(id);\n if (!component || LOCKED_TYPES.has(typeOf(component))) return false;\n if (component.get('removable') === false) return false;\n const ed = requireEditor();\n if (ed.getSelected() === component) ed.select(null);\n component.remove();\n return true;\n },\n\n duplicate(id) {\n const component = byId(id);\n if (!component || LOCKED_TYPES.has(typeOf(component)) || !component.parent()) return null;\n const collection = component.parent().components();\n const copy = firstOf(collection.add(component.clone(), { at: collection.indexOf(component) + 1 }));\n if (!copy) return null;\n requireEditor().select(copy);\n return copy.getId();\n },\n\n move(id, direction) {\n const component = byId(id);\n if (!component || LOCKED_TYPES.has(typeOf(component))) return false;\n const parent = component.parent();\n if (!parent) return false;\n const index = parent.components().indexOf(component);\n const to = index + direction;\n if (to < 0 || to >= parent.components().length) return false;\n // `at` is the position in the collection BEFORE the element is\n // removed: moving down must aim one step further.\n component.move(parent, { at: direction > 0 ? to + 1 : to });\n requireEditor().select(component);\n queueSelection();\n return true;\n },\n\n select(id) {\n const ed = requireEditor();\n ed.select(id ? byId(id) : null);\n },\n\n getSelection() {\n return editor ? describe(editor.getSelected()) : null;\n },\n\n describe(id) {\n return editor ? describe(byId(id)) : null;\n },\n\n getRootId() {\n return editor ? body()?.getId() || null : null;\n },\n\n updateProperties(id, attributes) {\n const component = byId(id);\n if (!component) return;\n /** @type {Record<string, string>} */\n const toSet = {};\n const toRemove = [];\n for (const [key, value] of Object.entries(attributes || {})) {\n // The image keeps its URL in the model (`src`), which the plugin\n // copies into the attributes: writing the attribute alone is undone.\n if (key === 'src' && component.get('src') !== undefined) {\n component.set('src', value || '');\n } else if (value === null || value === undefined || value === '') {\n toRemove.push(key);\n } else {\n toSet[key] = String(value);\n }\n }\n if (Object.keys(toSet).length) component.addAttributes(toSet);\n if (toRemove.length) {\n // The MJML plugin copies the style into the attributes: removing the\n // attribute alone would let it come back through the style.\n component.removeStyle?.(toRemove);\n component.removeAttributes(toRemove);\n }\n queueSelection();\n },\n\n setContent(id, content) {\n const component = byId(id);\n if (!component) return;\n if (LABEL_TYPES.has(typeOf(component))) {\n component.components(escapeHtml(content));\n } else if (RICH_TYPES.has(typeOf(component))) {\n component.components(String(content || ''));\n }\n queueSelection();\n },\n\n insertText(text) {\n const ed = requireEditor();\n if (insertAtCaret(ed, escapeHtml(text))) return true;\n const target = ed.getSelected();\n if (target && RICH_TYPES.has(typeOf(target))) {\n target.append({ type: 'textnode', content: ` ${text}` });\n queueSelection();\n return true;\n }\n return false;\n },\n\n insertLink(href, label) {\n const ed = requireEditor();\n const safeHref = escapeHtml(href).replace(/\"/g, '&quot;');\n const html = `<a href=\"${safeHref}\">${escapeHtml(label)}</a>`;\n if (insertAtCaret(ed, html)) return true;\n const target = ed.getSelected();\n if (target && typeOf(target) === 'mj-button') {\n target.addAttributes({ href });\n queueSelection();\n return true;\n }\n if (target && typeOf(target) === 'mj-text') {\n target.append(` ${html}`);\n queueSelection();\n return true;\n }\n return false;\n },\n\n undo() {\n requireEditor().UndoManager.undo();\n emitHistory();\n },\n redo() {\n requireEditor().UndoManager.redo();\n emitHistory();\n },\n canUndo: () => Boolean(editor?.UndoManager.hasUndo()),\n canRedo: () => Boolean(editor?.UndoManager.hasRedo()),\n clearHistory() {\n requireEditor().UndoManager.clear();\n emitHistory();\n },\n\n getProject() {\n return withoutPlaceholders(requireEditor().getProjectData());\n },\n\n loadProject(project) {\n const ed = requireEditor();\n ed.select(null);\n muteUntilFlushed();\n ed.loadProjectData(project);\n emit('load');\n queueSelection();\n },\n\n loadMjml(mjml) {\n const ed = requireEditor();\n ed.select(null);\n muteUntilFlushed();\n ed.setComponents(mjml || EMPTY_MJML);\n emit('load');\n queueSelection();\n },\n\n exportMjml() {\n return String(requireEditor().runCommand('mjml-code') || '')\n .replace(PLACEHOLDER_SRC_ATTR, '')\n .trim();\n },\n\n exportHtml() {\n const result = requireEditor().runCommand('mjml-code-to-html', { mjml: adapter.exportMjml() }) || {};\n return {\n html: String(result.html || ''),\n errors: (result.errors || []).map((/** @type {any} */ e) => ({\n line: e.line,\n message: String(e.formattedMessage || e.message || e),\n tagName: e.tagName,\n })),\n };\n },\n\n setDevice(device) {\n requireEditor().setDevice(device);\n },\n\n getDevice() {\n const name = editor?.getDevice?.();\n return name === 'mobile' ? 'mobile' : 'desktop';\n },\n\n startBlockDrag(block, event) {\n const ed = requireEditor();\n const engineBlock = ed.Blocks.get(`${BLOCK_PREFIX}${block.id}`);\n if (engineBlock) ed.Blocks.startDrag(engineBlock, event);\n },\n\n endBlockDrag(cancel = false) {\n editor?.Blocks.endDrag(cancel);\n },\n\n addShortcut(id, keys, handler) {\n const ed = requireEditor();\n const keymapId = `eb:${id}`;\n // `mod` = ⌘ on Mac, Ctrl elsewhere: both are registered.\n const engineKeys = keys\n .split(',')\n .map((k) => k.trim())\n .flatMap((k) => (k.startsWith('mod+') ? [`⌘+${k.slice(4)}`, `ctrl+${k.slice(4)}`] : [k]))\n .join(', ');\n ed.Keymaps.add(keymapId, engineKeys, () => handler(), { prevent: true });\n return () => {\n if (editor === ed) ed.Keymaps.remove(keymapId);\n };\n },\n };\n\n return adapter;\n}\n\n/**\n * GrapesJS empties and fills its container: it gets its own, a child of ours,\n * so React stays the sole owner of the node it rendered.\n *\n * @param {HTMLElement} container\n */\nfunction createEngineHost(container) {\n const el = container.ownerDocument.createElement('div');\n el.className = 'eb-engine-host';\n el.style.height = '100%';\n container.appendChild(el);\n return el;\n}\n","// @ts-check\n/**\n * Generic registry — used for blocks (`emailBlocks`) and features\n * (`emailBuilderFeatures`).\n *\n * Removing an entry from the registry is enough to remove it from the builder:\n * neither the core nor the adapter knows a block or feature by name. That is\n * what lets a piece be disabled without touching anything else.\n */\n\n/**\n * @template {{id: string, order?: number}} T\n * @typedef {{\n * kind: string,\n * register: (item: T) => () => void,\n * unregister: (id: string) => boolean,\n * get: (id: string) => T | undefined,\n * has: (id: string) => boolean,\n * list: (filter?: (item: T) => boolean) => T[],\n * ids: () => string[],\n * }} Registry\n */\n\nconst ID_SHAPE = /^[a-z][a-z0-9-]*$/;\n\n/**\n * @template {{id: string, order?: number}} T\n * @param {string} kind registry name, for error messages\n * @param {T[]} [initial]\n * @returns {Registry<T>}\n */\nexport function createRegistry(kind, initial = []) {\n /** @type {Map<string, T>} */\n const items = new Map();\n\n /** @param {string} id */\n function unregister(id) {\n return items.delete(id);\n }\n\n /** @param {T} item */\n function register(item) {\n if (!item || typeof item.id !== 'string' || !ID_SHAPE.test(item.id)) {\n throw new Error(`${kind}: invalid id (\"${item?.id}\")`);\n }\n if (items.has(item.id)) {\n throw new Error(`${kind}: \"${item.id}\" is already registered`);\n }\n items.set(item.id, item);\n return () => {\n unregister(item.id);\n };\n }\n\n initial.forEach(register);\n\n return {\n kind,\n register,\n unregister,\n get: (id) => items.get(id),\n has: (id) => items.has(id),\n // Stable sort: `order` first, then registration order.\n list: (filter) =>\n [...items.values()]\n .map((item, index) => ({ item, index }))\n .sort((a, b) => (a.item.order ?? 1000) - (b.item.order ?? 1000) || a.index - b.index)\n .map(({ item }) => item)\n .filter((item) => (filter ? filter(item) : true)),\n ids: () => [...items.keys()],\n };\n}\n","// @ts-check\n/**\n * Building blocks shared by all blocks: palette, fonts, recurring properties.\n *\n * -- DEFAULT PALETTE ---------------------------------------------------------\n * Plain hex values: email clients load no stylesheet and understand neither\n * `var()` nor modern color functions, so every value ends up inline in a\n * `style=\"\"` attribute.\n *\n * -- EVERY BLOCK SETS ITS OWN TEXT ATTRIBUTES --------------------------------\n * Font, size, line height and color are written on the element itself, never\n * left to MJML defaults (the \"Ubuntu\" font loaded from Google, line height 1):\n * the canvas and the sent email then render the same thing, and Outlook gets\n * explicit values.\n *\n * Fonts: only web-safe stacks, installed everywhere and understood by\n * Outlook - a web font only renders in a minority of email clients.\n */\n\n/** @typedef {import('../core/EmailEditor.js').BlockProperty} BlockProperty */\n\n/** The default palette. */\nexport const PALETTE = {\n ink: '#2b3038',\n inkSoft: '#41506b',\n navy: '#212e5a',\n brand: '#2977bc',\n border: '#dfe6f0',\n canvas: '#eceff4',\n surface: '#ffffff',\n white: '#ffffff',\n};\n\n/** Default link of a new button. */\nexport const DEFAULT_BUTTON_URL = 'https://example.com';\n\nexport const FONT_STACK = 'Arial, Helvetica, sans-serif';\n\n/** @type {{value: string, label: string}[]} */\nexport const FONT_OPTIONS = [\n { value: 'Arial, Helvetica, sans-serif', label: 'Arial' },\n { value: 'Verdana, Geneva, sans-serif', label: 'Verdana' },\n { value: 'Tahoma, Geneva, sans-serif', label: 'Tahoma' },\n { value: \"'Trebuchet MS', Helvetica, sans-serif\", label: 'Trebuchet' },\n { value: 'Georgia, Times, serif', label: 'Georgia' },\n { value: \"'Times New Roman', Times, serif\", label: 'Times' },\n { value: \"'Courier New', Courier, monospace\", label: 'Courier' },\n];\n\n/** @type {{value: string, label: string}[]} */\nexport const ALIGN_OPTIONS = [\n { value: 'left', label: 'Left' },\n { value: 'center', label: 'Center' },\n { value: 'right', label: 'Right' },\n];\n\n/** Properties panel groups, in display order. */\nexport const GROUPS = {\n content: 'Content',\n link: 'Link',\n typography: 'Typography',\n colors: 'Colors',\n layout: 'Layout',\n spacing: 'Spacing',\n};\n\n/** Recurring properties. */\nexport const prop = {\n /** @returns {BlockProperty} */\n fontFamily: () => ({ key: 'font-family', label: 'Font', type: 'select', group: GROUPS.typography, options: FONT_OPTIONS }),\n /** @returns {BlockProperty} */\n fontSize: (min = 10, max = 48) => ({ key: 'font-size', label: 'Size', type: 'size', group: GROUPS.typography, min, max, unit: 'px' }),\n /** @returns {BlockProperty} */\n lineHeight: () => ({ key: 'line-height', label: 'Line height', type: 'size', group: GROUPS.typography, min: 10, max: 80, unit: 'px' }),\n /** @returns {BlockProperty} */\n color: (label = 'Text') => ({ key: 'color', label, type: 'color', group: GROUPS.colors }),\n /** @returns {BlockProperty} */\n background: (key = 'background-color', label = 'Background') => ({ key, label, type: 'color', group: GROUPS.colors }),\n /** @returns {BlockProperty} */\n align: (options = ALIGN_OPTIONS) => ({ key: 'align', label: 'Alignment', type: 'align', group: GROUPS.layout, options }),\n /** @returns {BlockProperty} */\n padding: (key = 'padding', label = 'Padding') => ({ key, label, type: 'spacing', group: GROUPS.spacing }),\n /** @returns {BlockProperty} */\n href: (label = 'Link URL') => ({ key: 'href', label, type: 'url', group: GROUPS.link, placeholder: 'https://' }),\n /** @returns {BlockProperty} */\n radius: (max = 40) => ({ key: 'border-radius', label: 'Corner radius', type: 'size', group: GROUPS.layout, min: 0, max, unit: 'px' }),\n};\n\n/**\n * White one-column section: the wrapper of a content block dropped outside\n * any column (MJML does not accept text directly inside the body).\n *\n * Warning: padding in LONGHAND form, never `padding=\"...\"`. The canvas starts\n * from the longhand defaults (20 px for a section), which override the\n * shorthand, while the export omits them - the screen and the email would\n * diverge (see core/mjmlAttributes).\n *\n * @param {string} inner\n */\nexport function inWhiteSection(inner) {\n return (\n `<mj-section background-color=\"${PALETTE.surface}\" padding-top=\"0px\" padding-bottom=\"0px\">` +\n `<mj-column>${inner}</mj-column></mj-section>`\n );\n}\n","// @ts-check\n/**\n * STRUCTURE - body, section, column.\n *\n * These are not blocks you add (no `mjml`): they are the containers you\n * SELECT, whose background and padding are set in the right-hand panel. The\n * N-column layouts (`blocks/columns`) create sections; once added, this\n * definition describes them.\n */\n\nimport { GROUPS, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @type {EmailBlock} */\nexport const bodyBlock = {\n id: 'body',\n label: 'Email',\n icon: 'Mail',\n kind: 'structure',\n tagName: 'mj-body',\n order: 900,\n properties: [\n prop.background('background-color', 'Page background'),\n {\n key: 'width',\n label: 'Content width',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: '600px', label: '600 px (standard)' },\n { value: '640px', label: '640 px' },\n ],\n },\n ],\n};\n\n/** @type {EmailBlock} */\nexport const sectionBlock = {\n id: 'section',\n label: 'Section',\n icon: 'Rows3',\n kind: 'structure',\n tagName: 'mj-section',\n order: 901,\n properties: [\n prop.background('background-color', 'Background'),\n prop.padding('padding', 'Padding'),\n prop.radius(24),\n ],\n};\n\n/** @type {EmailBlock} */\nexport const columnBlock = {\n id: 'column',\n label: 'Column',\n icon: 'Columns2',\n kind: 'structure',\n tagName: 'mj-column',\n order: 902,\n properties: [\n prop.background('background-color', 'Background'),\n prop.padding('padding', 'Padding'),\n {\n key: 'vertical-align',\n label: 'Vertical alignment',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: 'top', label: 'Top' },\n { value: 'middle', label: 'Middle' },\n { value: 'bottom', label: 'Bottom' },\n ],\n },\n ],\n};\n","// @ts-check\n/**\n * TEXT - `mj-text`.\n *\n * Content is typed in the canvas (double-click: bold, italic, link); the panel\n * only controls the styling. Defaults are readable on mobile: 15 px on a 24 px\n * line height, ink #2b3038 (never pure black, which \"vibrates\" on phone\n * screens).\n */\n\nimport { FONT_STACK, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/**\n * A text with the block's settings. Also used by the column layouts, which\n * pre-fill each column.\n *\n * @param {string} content Already-safe HTML (fixed builder text)\n */\nexport function textMjml(content) {\n return (\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"15px\" line-height=\"24px\" color=\"${PALETTE.ink}\" ` +\n `align=\"left\">${content}</mj-text>`\n );\n}\n\nconst MJML = textMjml('Your text.');\n\n/** @type {EmailBlock} */\nexport const textBlock = {\n id: 'text',\n label: 'Text',\n description: 'Paragraph or heading',\n icon: 'Type',\n kind: 'content',\n tagName: 'mj-text',\n order: 10,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n editableContent: true,\n properties: [\n prop.fontFamily(),\n prop.fontSize(10, 48),\n prop.lineHeight(),\n prop.color('Text'),\n prop.background('container-background-color', 'Background'),\n { ...prop.align(), options: [...prop.align().options || [], { value: 'justify', label: 'Justify' }] },\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * IMAGE - `mj-image`.\n *\n * Added WITHOUT a file: the canvas shows a frame to fill, and the panel (file\n * upload or https URL) completes it. A sample image from a third-party service\n * would, one day, end up in a real send.\n *\n * Width is left to MJML (the full column, shrunk on mobile): a fixed width\n * larger than the column would overflow in Outlook.\n *\n * The alt text is not decorative: Outlook blocks images by default, and the\n * recipient reads the alt text in their place.\n */\n\nimport { GROUPS, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML = '<mj-image align=\"center\"></mj-image>';\n\n/** @type {EmailBlock} */\nexport const imageBlock = {\n id: 'image',\n label: 'Image',\n description: 'Photo, visual or logo',\n icon: 'Image',\n kind: 'content',\n tagName: 'mj-image',\n order: 20,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [\n { key: 'src', label: 'Image', type: 'image', group: GROUPS.content },\n {\n key: 'alt',\n label: 'Alt text',\n type: 'text',\n group: GROUPS.content,\n placeholder: 'Describes the image if it is blocked',\n },\n prop.href('Link on click'),\n { key: 'width', label: 'Width', type: 'size', group: GROUPS.layout, min: 20, max: 600, unit: 'px' },\n prop.align(),\n prop.radius(40),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * BUTTON - `mj-button`.\n *\n * MJML renders it as a table (not a styled `<a>`), which keeps it clickable\n * and at its size in Outlook. The default link is `DEFAULT_BUTTON_URL`.\n *\n * Defaults: navy background, bold white text, generous click area\n * (12 x 28 px) - a button that is too small is easy to miss with a finger.\n */\n\nimport { DEFAULT_BUTTON_URL, FONT_STACK, GROUPS, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML =\n `<mj-button href=\"${DEFAULT_BUTTON_URL}\" background-color=\"${PALETTE.navy}\" color=\"${PALETTE.white}\" ` +\n `font-family=\"${FONT_STACK}\" font-size=\"15px\" font-weight=\"bold\" border-radius=\"6px\" ` +\n 'inner-padding=\"12px 28px\" align=\"center\">Learn more</mj-button>';\n\n/** @type {EmailBlock} */\nexport const buttonBlock = {\n id: 'button',\n label: 'Button',\n description: 'Call to action',\n icon: 'RectangleHorizontal',\n kind: 'content',\n tagName: 'mj-button',\n order: 30,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n editableContent: true,\n properties: [\n prop.href('Link URL'),\n prop.background('background-color', 'Button background'),\n prop.color('Text'),\n prop.fontFamily(),\n prop.fontSize(11, 28),\n {\n key: 'font-weight',\n label: 'Weight',\n type: 'select',\n group: GROUPS.typography,\n options: [\n { value: 'bold', label: 'Bold' },\n { value: 'normal', label: 'Normal' },\n ],\n },\n prop.radius(30),\n {\n key: 'width',\n label: 'Width',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: '', label: 'Fit to text' },\n { value: '100%', label: 'Full width' },\n ],\n },\n prop.align(),\n prop.padding('inner-padding', 'Button padding'),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * DIVIDER - `mj-divider`.\n *\n * A thin rule in the default border color. MJML renders it as a `<p>` border\n * backed by a table for Outlook: it keeps its thickness everywhere, whereas an\n * `<hr>` varies from one email client to another.\n */\n\nimport { GROUPS, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML = `<mj-divider border-color=\"${PALETTE.border}\" border-width=\"1px\"></mj-divider>`;\n\n/** @type {EmailBlock} */\nexport const dividerBlock = {\n id: 'divider',\n label: 'Divider',\n description: 'Horizontal rule',\n icon: 'SeparatorHorizontal',\n kind: 'content',\n tagName: 'mj-divider',\n order: 40,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [\n prop.background('border-color', 'Line color'),\n { key: 'border-width', label: 'Thickness', type: 'size', group: GROUPS.layout, min: 1, max: 10, unit: 'px' },\n {\n key: 'border-style',\n label: 'Line style',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: 'solid', label: 'Solid' },\n { value: 'dashed', label: 'Dashed' },\n { value: 'dotted', label: 'Dotted' },\n ],\n },\n {\n key: 'width',\n label: 'Length',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: '100%', label: 'Full length' },\n { value: '75%', label: '75%' },\n { value: '50%', label: '50%' },\n { value: '25%', label: '25%' },\n ],\n },\n prop.align(),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * SPACER - `mj-spacer`.\n *\n * Fixed-height empty space. MJML renders it as a `<div>` with an explicit line\n * height (`mso-line-height-rule: exactly`): Outlook, which ignores margins,\n * honors it.\n */\n\nimport { GROUPS, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML = '<mj-spacer height=\"24px\"></mj-spacer>';\n\n/** @type {EmailBlock} */\nexport const spacerBlock = {\n id: 'spacer',\n label: 'Spacer',\n description: 'Vertical space',\n icon: 'MoveVertical',\n kind: 'content',\n tagName: 'mj-spacer',\n order: 50,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [\n { key: 'height', label: 'Height', type: 'size', group: GROUPS.layout, min: 4, max: 200, unit: 'px' },\n prop.background('container-background-color', 'Background'),\n ],\n};\n","// @ts-check\n/**\n * LAYOUTS - 1, 2 or 3 column sections (`mj-section` + `mj-column`).\n *\n * Each column is pre-filled with text: an empty column only offers a strip a\n * few pixels high to drop a block into. On mobile (under 480 px), MJML stacks\n * the columns on top of each other - nothing to configure.\n *\n * Once added, the section is described by the \"section\" structure\n * (`blocks/structure`): background, padding, corner radius.\n */\n\nimport { PALETTE } from '../shared.js';\nimport { textMjml } from '../text/index.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @param {number} count */\nfunction sectionWith(count) {\n const columns = Array.from({ length: count }, (_, i) =>\n `<mj-column>${textMjml(count === 1 ? 'Your text.' : `Column ${i + 1}`)}</mj-column>`\n ).join('');\n return `<mj-section background-color=\"${PALETTE.surface}\">${columns}</mj-section>`;\n}\n\n/**\n * @param {number} count\n * @param {string} icon\n * @returns {EmailBlock}\n */\nfunction layout(count, icon) {\n return {\n id: `columns-${count}`,\n label: count === 1 ? '1 column' : `${count} columns`,\n description: count === 1 ? 'Full-width section' : `${count}-column section`,\n icon,\n kind: 'layout',\n tagName: 'mj-section',\n order: 100 + count,\n mjml: sectionWith(count),\n properties: [],\n };\n}\n\nexport const oneColumnBlock = layout(1, 'Square');\nexport const twoColumnsBlock = layout(2, 'Columns2');\nexport const threeColumnsBlock = layout(3, 'Columns3');\n","// @ts-check\n/**\n * BLOCK REGISTRY - `emailBlocks`.\n *\n * Each block lives in its own folder and depends only on the core. Removing a\n * line below removes the block from the sidebar, the properties panel and\n * drag and drop, without changing anything else.\n */\n\nimport { createRegistry } from '../core/registry.js';\nimport { bodyBlock, columnBlock, sectionBlock } from './structure/index.js';\nimport { textBlock } from './text/index.js';\nimport { imageBlock } from './image/index.js';\nimport { buttonBlock } from './button/index.js';\nimport { dividerBlock } from './divider/index.js';\nimport { spacerBlock } from './spacer/index.js';\nimport { oneColumnBlock, threeColumnsBlock, twoColumnsBlock } from './columns/index.js';\n\n/** @typedef {import('../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @type {EmailBlock[]} */\nconst BLOCKS = [\n textBlock,\n imageBlock,\n buttonBlock,\n dividerBlock,\n spacerBlock,\n oneColumnBlock,\n twoColumnsBlock,\n threeColumnsBlock,\n bodyBlock,\n sectionBlock,\n columnBlock,\n];\n\nexport const emailBlocks = createRegistry('emailBlocks', BLOCKS);\n","// @ts-check\n/**\n * AUTOSAVE feature.\n *\n * template already saved → server save WITHOUT a new version, 20 s after\n * the last change (at most 2 min after the first one);\n * template never saved → local draft (`localDraft.js`), offered the next\n * time a new template is opened.\n *\n * The screen reads `options`; removing this entry from the registry turns both\n * off.\n */\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature & {options: {idleMs: number, maxWaitMs: number, draftDelayMs: number}}} */\nexport const autosaveFeature = {\n id: 'autosave',\n label: 'Autosave',\n order: 20,\n options: { idleMs: 20_000, maxWaitMs: 120_000, draftDelayMs: 1_500 },\n};\n","import { useState } from 'react';\nimport { History } from 'lucide-react';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/primitives/overlays.jsx';\nimport { Skeleton } from '../../ui/primitives/misc.jsx';\nimport { useUi } from '../../ui/context.jsx';\n\n/**\n * VERSIONS of a template — toolbar button.\n *\n * Every explicit \"Save\" creates a version (autosave never does). Restoring\n * RELOADS the version into the editor without writing anything: the next save\n * makes it current, by creating one more version. History is never rewritten.\n */\n\nfunction formatWhen(value, locale) {\n if (!value) return '';\n const d = new Date(value);\n return Number.isNaN(d.getTime())\n ? ''\n : d.toLocaleString(locale, { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });\n}\n\nexport default function VersionsMenu({ context }) {\n const { editor, storage, template, isDirty, markDirty, ready } = context;\n const { t, confirm, notify, locale } = useUi();\n const [open, setOpen] = useState(false);\n const [versions, setVersions] = useState(null);\n const [error, setError] = useState(null);\n const [restoring, setRestoring] = useState(null);\n\n const load = async () => {\n setVersions(null);\n setError(null);\n try {\n setVersions(await storage.listVersions(template.id));\n } catch (e) {\n setError(e.message);\n }\n };\n\n const restore = async (version) => {\n if (isDirty()) {\n const ok = await confirm({\n title: t('Restore version {n}?', { n: version.versionNumber }),\n description: t('Unsaved changes will be replaced.'),\n confirmLabel: t('Restore'),\n destructive: true,\n });\n if (!ok) return;\n }\n setRestoring(version.id);\n try {\n const full = await storage.getVersion(template.id, version.id);\n editor.loadDocument(full.document);\n markDirty();\n setOpen(false);\n notify('success', t('Version {n} restored — save to keep it.', { n: version.versionNumber }));\n } catch (e) {\n notify('error', e.message);\n } finally {\n setRestoring(null);\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (next) load();\n }}\n >\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready || !template.id}\n title={!template.id ? t('Save the template first') : undefined}\n >\n <History />\n {t('Versions')}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"eb:w-80 eb:p-0\">\n <div className=\"eb:border-b eb:border-border eb:px-3 eb:py-2.5 eb:text-[13px] eb:font-medium eb:text-foreground\">\n {t('Versions')}\n </div>\n <div className=\"eb:max-h-[320px] eb:overflow-y-auto eb:p-1\" aria-busy={versions === null && !error}>\n {error ? (\n <p role=\"alert\" className=\"eb:px-2 eb:py-1.5 eb:text-[12px] eb:text-destructive\">\n {error}\n </p>\n ) : versions === null ? (\n <div className=\"eb:space-y-1 eb:p-1\" aria-hidden=\"true\">\n <Skeleton className=\"eb:h-8 eb:w-40\" />\n <Skeleton className=\"eb:h-8 eb:w-32\" />\n <Skeleton className=\"eb:h-8 eb:w-36\" />\n </div>\n ) : versions.length === 0 ? (\n <p className=\"eb:px-2 eb:py-1.5 eb:text-[12px] eb:text-foreground-muted\">{t('No versions yet.')}</p>\n ) : (\n versions.map((version, index) => (\n <div\n key={version.id}\n className=\"eb:flex eb:items-center eb:gap-2 eb:rounded-lg2 eb:px-2 eb:py-1.5 eb:hover:bg-surface-100\"\n >\n <div className=\"eb:min-w-0 eb:flex-1\">\n <p className=\"eb:text-[13px] eb:text-foreground\">\n {t('Version {n}', { n: version.versionNumber })}\n {index === 0 && <span className=\"eb:ml-1.5 eb:text-[11px] eb:text-foreground-muted\">{t('current')}</span>}\n </p>\n <p className=\"eb:text-[11px] eb:tabular-nums eb:text-foreground-muted\">\n {formatWhen(version.createdAt, locale)}\n {version.createdBy ? ` · ${version.createdBy}` : ''}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n disabled={restoring !== null}\n onClick={() => restore(version)}\n aria-label={t('Restore version {n}', { n: version.versionNumber })}\n >\n {t('Restore')}\n </Button>\n </div>\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { Slot } from 'radix-ui';\nimport { cva } from 'class-variance-authority';\nimport { cn } from './cn.js';\n\nexport const buttonVariants = cva(\n \"eb:inline-flex eb:shrink-0 eb:items-center eb:justify-center eb:gap-2 eb:whitespace-nowrap eb:rounded-lg2 eb:text-sm eb:font-medium eb:transition-all eb:outline-none eb:disabled:pointer-events-none eb:disabled:opacity-50 eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: 'eb:bg-primary eb:text-primary-foreground eb:hover:bg-primary/90',\n destructive: 'eb:bg-destructive eb:text-white eb:hover:bg-destructive/90 eb:focus-visible:ring-destructive/20',\n outline: 'eb:border eb:border-border eb:bg-background eb:text-foreground eb:shadow-xs eb:hover:bg-accent eb:hover:text-accent-foreground',\n secondary: 'eb:bg-secondary eb:text-secondary-foreground eb:hover:bg-secondary/80',\n ghost: 'eb:text-foreground eb:hover:bg-accent eb:hover:text-accent-foreground',\n link: 'eb:text-primary eb:underline-offset-4 eb:hover:underline',\n },\n size: {\n default: 'eb:h-8 eb:gap-1.5 eb:px-3 eb:text-[13px] eb:has-[>svg]:px-2.5',\n xs: \"eb:h-6 eb:gap-1 eb:px-2 eb:text-xs eb:has-[>svg]:px-1.5 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'sm-compact': \"eb:h-7 eb:gap-1.5 eb:px-3 eb:text-xs eb:has-[>svg]:px-2.5 eb:[&_svg:not([class*='size-'])]:size-3\",\n sm: 'eb:h-8 eb:gap-1.5 eb:px-3 eb:text-[13px] eb:has-[>svg]:px-2.5',\n lg: 'eb:h-10 eb:px-6 eb:has-[>svg]:px-4',\n icon: 'eb:size-8',\n 'icon-xs': \"eb:size-6 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm-compact': \"eb:size-7 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm': 'eb:size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n }\n);\n\nexport function Button({ className, variant = 'default', size = 'default', asChild = false, type, ...props }) {\n const Comp = asChild ? Slot.Root : 'button';\n return (\n <Comp\n data-slot=\"button\"\n type={asChild ? type : type || 'button'}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n );\n}\n","import { clsx } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n// Every utility class of the package carries the `eb:` prefix (see src/styles.css),\n// so class merging has to know about it.\nconst twMerge = extendTailwindMerge({ prefix: 'eb' });\n\n/** Joins class names and resolves conflicting utilities (the last one wins). */\nexport function cn(...inputs) {\n return twMerge(clsx(inputs));\n}\n","import {\n AlertDialog as AlertDialogPrimitive,\n Dialog as DialogPrimitive,\n DropdownMenu as DropdownMenuPrimitive,\n Popover as PopoverPrimitive,\n Select as SelectPrimitive,\n} from 'radix-ui';\nimport { CheckIcon, ChevronDownIcon, XIcon } from 'lucide-react';\nimport { useT } from '../context.jsx';\nimport { cn } from './cn.js';\n\n/*\n * Overlays render in a portal, outside the builder's root element: each one\n * carries the `eb-scope` class so the package's base styles reach it.\n */\n\nconst FADE_ZOOM =\n 'eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=open]:zoom-in-95 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0 eb:data-[state=closed]:zoom-out-95';\n\n/* ── Dialog ───────────────────────────────────────────────────────────── */\n\nexport function Dialog(props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogContent({ className, children, showCloseButton = true, ...props }) {\n const t = useT();\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay className=\"eb-scope eb:fixed eb:inset-0 eb:z-50 eb:bg-black/50 eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0\" />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'eb-scope eb:fixed eb:top-[50%] eb:left-[50%] eb:z-50 eb:grid eb:w-full eb:max-w-[calc(100%-2rem)] eb:translate-x-[-50%] eb:translate-y-[-50%] eb:gap-4 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-6 eb:text-foreground eb:shadow-lg eb:duration-200 eb:outline-none eb:sm:max-w-lg',\n FADE_ZOOM,\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close className=\"eb:absolute eb:top-4 eb:right-4 eb:rounded-xs eb:opacity-70 eb:transition-opacity eb:hover:opacity-100 eb:focus:ring-2 eb:focus:ring-ring eb:focus:ring-offset-2 eb:focus:outline-hidden eb:disabled:pointer-events-none eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\">\n <XIcon />\n <span className=\"eb:sr-only\">{t('Close')}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n}\n\nexport function DialogHeader({ className, ...props }) {\n return <div className={cn('eb:flex eb:flex-col eb:gap-2 eb:text-left', className)} {...props} />;\n}\n\nexport function DialogFooter({ className, ...props }) {\n return <div className={cn('eb:flex eb:flex-col-reverse eb:gap-2 eb:sm:flex-row eb:sm:justify-end', className)} {...props} />;\n}\n\nexport function DialogTitle({ className, ...props }) {\n return <DialogPrimitive.Title className={cn('eb:text-lg eb:leading-none eb:font-semibold', className)} {...props} />;\n}\n\nexport function DialogDescription({ className, ...props }) {\n return <DialogPrimitive.Description className={cn('eb:text-sm eb:text-muted-foreground', className)} {...props} />;\n}\n\n/* ── Alert dialog (confirmations) ─────────────────────────────────────── */\n\nexport function AlertDialog(props) {\n return <AlertDialogPrimitive.Root {...props} />;\n}\n\nexport function AlertDialogContent({ className, ...props }) {\n return (\n <AlertDialogPrimitive.Portal>\n <AlertDialogPrimitive.Overlay className=\"eb-scope eb:fixed eb:inset-0 eb:z-50 eb:bg-black/50 eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0\" />\n <AlertDialogPrimitive.Content\n className={cn(\n 'eb-scope eb:fixed eb:top-[50%] eb:left-[50%] eb:z-50 eb:grid eb:w-full eb:max-w-[calc(100%-2rem)] eb:translate-x-[-50%] eb:translate-y-[-50%] eb:gap-4 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-6 eb:text-foreground eb:shadow-lg eb:duration-200 eb:sm:max-w-lg',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </AlertDialogPrimitive.Portal>\n );\n}\n\nexport const AlertDialogTitle = ({ className, ...props }) => (\n <AlertDialogPrimitive.Title className={cn('eb:text-lg eb:font-semibold', className)} {...props} />\n);\nexport const AlertDialogDescription = ({ className, ...props }) => (\n <AlertDialogPrimitive.Description className={cn('eb:text-sm eb:text-muted-foreground', className)} {...props} />\n);\nexport const AlertDialogAction = AlertDialogPrimitive.Action;\nexport const AlertDialogCancel = AlertDialogPrimitive.Cancel;\n\n/* ── Popover ──────────────────────────────────────────────────────────── */\n\nexport function Popover(props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverContent({ className, align = 'center', sideOffset = 4, ...props }) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:w-72 eb:origin-(--radix-popover-content-transform-origin) eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:p-4 eb:text-popover-foreground eb:shadow-md eb:outline-hidden',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/* ── Dropdown menu ────────────────────────────────────────────────────── */\n\nexport function DropdownMenu(props) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nexport function DropdownMenuTrigger(props) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nexport function DropdownMenuContent({ className, sideOffset = 4, ...props }) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:max-h-(--radix-dropdown-menu-content-available-height) eb:min-w-[8rem] eb:origin-(--radix-dropdown-menu-content-transform-origin) eb:overflow-x-hidden eb:overflow-y-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:p-1 eb:text-popover-foreground eb:shadow-md',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport function DropdownMenuGroup(props) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nexport function DropdownMenuItem({ className, ...props }) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n className={cn(\n \"eb:relative eb:flex eb:cursor-default eb:items-center eb:gap-2 eb:rounded-sm eb:px-2 eb:py-1.5 eb:text-[13px] eb:outline-hidden eb:select-none eb:focus:bg-accent eb:focus:text-accent-foreground eb:data-[disabled]:pointer-events-none eb:data-[disabled]:opacity-50 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport function DropdownMenuLabel({ className, ...props }) {\n return <DropdownMenuPrimitive.Label className={cn('eb:px-2 eb:py-1.5 eb:text-[13px] eb:font-medium', className)} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ className, ...props }) {\n return <DropdownMenuPrimitive.Separator className={cn('eb:-mx-1 eb:my-1 eb:h-px eb:bg-border', className)} {...props} />;\n}\n\n/* ── Select ───────────────────────────────────────────────────────────── */\n\nexport function Select(props) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nexport function SelectValue(props) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nexport function SelectTrigger({ className, children, ...props }) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n className={cn(\n \"eb:flex eb:h-8 eb:w-full eb:items-center eb:justify-between eb:gap-2 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-1 eb:text-[13px] eb:whitespace-nowrap eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:disabled:cursor-not-allowed eb:disabled:opacity-50 eb:data-[placeholder]:text-foreground-muted eb:*:data-[slot=select-value]:line-clamp-1 eb:*:data-[slot=select-value]:flex eb:*:data-[slot=select-value]:items-center eb:*:data-[slot=select-value]:gap-2 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"eb:size-4 eb:opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nexport function SelectContent({ className, children, position = 'popper', ...props }) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n position={position}\n className={cn(\n 'eb-scope eb:relative eb:z-50 eb:max-h-(--radix-select-content-available-height) eb:min-w-[8rem] eb:origin-(--radix-select-content-transform-origin) eb:overflow-x-hidden eb:overflow-y-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:text-popover-foreground eb:shadow-md',\n FADE_ZOOM,\n position === 'popper' && 'eb:data-[side=bottom]:translate-y-1 eb:data-[side=top]:-translate-y-1',\n className\n )}\n {...props}\n >\n <SelectPrimitive.Viewport\n className={cn(\n 'eb:p-1',\n position === 'popper' &&\n 'eb:h-[var(--radix-select-trigger-height)] eb:w-full eb:min-w-[var(--radix-select-trigger-width)] eb:scroll-my-1'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nexport function SelectItem({ className, children, ...props }) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n 'eb:relative eb:flex eb:w-full eb:cursor-default eb:items-center eb:gap-2 eb:rounded-sm eb:py-1.5 eb:pr-8 eb:pl-2 eb:text-[13px] eb:outline-hidden eb:select-none eb:focus:bg-accent eb:focus:text-accent-foreground eb:data-[disabled]:pointer-events-none eb:data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"eb:absolute eb:right-2 eb:flex eb:size-3.5 eb:items-center eb:justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"eb:size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { AlertCircle, CheckCircle2, Info, TriangleAlert, X } from 'lucide-react';\nimport { identity, translatorFor } from '../i18n/index.js';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogTitle,\n} from './primitives/overlays.jsx';\nimport { buttonVariants } from './primitives/button.jsx';\nimport { TooltipProvider } from './primitives/misc.jsx';\nimport { cn } from './primitives/cn.js';\n\n/**\n * Interface services shared by every component of the builder:\n *\n * t translation (see src/i18n) ;\n * locale BCP 47 tag used for dates and times ;\n * notify short messages (`success`, `info`, `warning`, `error`) — shown by\n * the builder itself, or handed to the host's own toaster through\n * the `onNotify` prop ;\n * confirm asynchronous confirmation dialog → Promise<boolean>.\n */\n\n/**\n * @typedef {'success'|'info'|'warning'|'error'} NotifyLevel\n * @typedef {{title?: string, description?: string, confirmLabel?: string,\n * cancelLabel?: string, destructive?: boolean}} ConfirmOptions\n */\n\nconst NoticeContext = createContext({ notices: [], dismiss: () => {} });\n\nconst UiContext = createContext({\n t: identity,\n locale: 'en',\n /** @type {(level: NotifyLevel, message: string) => void} */\n notify: () => {},\n /** @type {(options: ConfirmOptions) => Promise<boolean>} */\n confirm: async () => false,\n});\n\nexport const useUi = () => useContext(UiContext);\nexport const useT = () => useContext(UiContext).t;\n\nconst NOTICE_ICON = { success: CheckCircle2, info: Info, warning: TriangleAlert, error: AlertCircle };\nconst NOTICE_TTL = { success: 3500, info: 4000, warning: 6000, error: 7000 };\n\n/** Where the builder's own notices appear (bottom-right of its root element). */\nexport function NoticeArea() {\n const t = useT();\n const { notices, dismiss: onDismiss } = useContext(NoticeContext);\n return (\n <div className=\"eb:pointer-events-none eb:absolute eb:right-3 eb:bottom-3 eb:z-40 eb:flex eb:w-80 eb:max-w-[calc(100%-1.5rem)] eb:flex-col eb:gap-2\">\n {notices.map((notice) => {\n const Icon = NOTICE_ICON[notice.level] || Info;\n return (\n <div\n key={notice.id}\n role={notice.level === 'error' ? 'alert' : 'status'}\n data-level={notice.level}\n className=\"eb:pointer-events-auto eb:flex eb:items-start eb:gap-2 eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:px-3 eb:py-2.5 eb:text-[13px] eb:text-popover-foreground eb:shadow-lg\"\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\n 'eb:mt-0.5 eb:size-4 eb:shrink-0',\n notice.level === 'error' && 'eb:text-destructive',\n notice.level === 'warning' && 'eb:text-warning',\n notice.level === 'success' && 'eb:text-success',\n notice.level === 'info' && 'eb:text-foreground-muted'\n )}\n />\n <p className=\"eb:min-w-0 eb:flex-1\">{notice.message}</p>\n <button\n type=\"button\"\n aria-label={t('Dismiss')}\n className=\"eb:shrink-0 eb:rounded-sm eb:text-foreground-muted eb:hover:text-foreground\"\n onClick={() => onDismiss(notice.id)}\n >\n <X className=\"eb:size-3.5\" />\n </button>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * @param {{\n * locale?: string,\n * messages?: Record<string, string>,\n * onNotify?: (level: NotifyLevel, message: string) => void,\n * children: import('react').ReactNode,\n * }} props\n */\nexport function UiProvider({ locale = 'en', messages, onNotify, children }) {\n const t = useMemo(() => translatorFor(locale, messages), [locale, messages]);\n\n /* ── Notices ── */\n const [notices, setNotices] = useState([]);\n const timers = useRef(new Map());\n const dismiss = useCallback((id) => {\n clearTimeout(timers.current.get(id));\n timers.current.delete(id);\n setNotices((list) => list.filter((n) => n.id !== id));\n }, []);\n const hostNotify = useRef(onNotify);\n hostNotify.current = onNotify;\n const nextId = useRef(0);\n const notify = useCallback(\n (level, message) => {\n if (hostNotify.current) {\n hostNotify.current(level, message);\n return;\n }\n const id = (nextId.current += 1);\n setNotices((list) => [...list.slice(-3), { id, level, message }]);\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), NOTICE_TTL[level] || 4000)\n );\n },\n [dismiss]\n );\n useEffect(() => {\n const pending = timers.current;\n return () => pending.forEach((timer) => clearTimeout(timer));\n }, []);\n\n /* ── Confirmation ── */\n const [request, setRequest] = useState(null);\n const confirm = useCallback(\n (options = {}) =>\n new Promise((resolve) => {\n setRequest((current) => {\n current?.resolve(false);\n return { options, resolve };\n });\n }),\n []\n );\n const settle = (result) => {\n request?.resolve(result);\n setRequest(null);\n };\n\n const value = useMemo(() => ({ t, locale, notify, confirm }), [t, locale, notify, confirm]);\n const noticeValue = useMemo(() => ({ notices, dismiss }), [notices, dismiss]);\n const options = request?.options || {};\n\n return (\n <UiContext.Provider value={value}>\n <TooltipProvider delayDuration={300}>\n <NoticeContext.Provider value={noticeValue}>{children}</NoticeContext.Provider>\n <AlertDialog open={Boolean(request)} onOpenChange={(open) => !open && settle(false)}>\n <AlertDialogContent>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span\n className={cn(\n 'eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2',\n options.destructive ? 'eb:bg-destructive/10 eb:text-destructive' : 'eb:bg-primary/10 eb:text-primary'\n )}\n >\n <AlertCircle className=\"eb:size-5\" />\n </span>\n <AlertDialogTitle className=\"eb:text-base\">{options.title || t('Confirm')}</AlertDialogTitle>\n </div>\n {options.description && (\n <AlertDialogDescription className=\"eb:text-[13px] eb:leading-relaxed\">{options.description}</AlertDialogDescription>\n )}\n <div className=\"eb:flex eb:flex-col-reverse eb:gap-2 eb:sm:flex-row eb:sm:justify-end\">\n <AlertDialogCancel className={buttonVariants({ variant: 'outline' })} onClick={() => settle(false)}>\n {options.cancelLabel || t('Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n className={buttonVariants({ variant: options.destructive ? 'destructive' : 'default' })}\n onClick={() => settle(true)}\n >\n {options.confirmLabel || t('Confirm')}\n </AlertDialogAction>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n </TooltipProvider>\n </UiContext.Provider>\n );\n}\n","import { Separator as SeparatorPrimitive, Tabs as TabsPrimitive, Tooltip as TooltipPrimitive } from 'radix-ui';\nimport { cn } from './cn.js';\n\nexport function Separator({ className, orientation = 'horizontal', decorative = true, ...props }) {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'eb:shrink-0 eb:bg-border eb:data-[orientation=horizontal]:h-px eb:data-[orientation=horizontal]:w-full eb:data-[orientation=vertical]:h-full eb:data-[orientation=vertical]:w-px',\n className\n )}\n {...props}\n />\n );\n}\n\nexport function Skeleton({ className, as: Comp = 'div', ...props }) {\n return <Comp data-slot=\"skeleton\" className={cn('eb:animate-pulse eb:rounded-lg2 eb:bg-accent', className)} {...props} />;\n}\n\n/** Small uppercase heading of a panel section. */\nexport function SectionLabel({ className, ...props }) {\n return (\n <span\n data-slot=\"section-label\"\n className={cn('eb:font-mono eb:text-[10px] eb:uppercase eb:tracking-[0.14em] eb:text-foreground-muted', className)}\n {...props}\n />\n );\n}\n\n/** One line of text, cut with an ellipsis when it overflows (full text on hover). */\nexport function TruncatedText({ children, className, as: Comp = 'span', ...props }) {\n return (\n <Comp\n className={cn('eb:block eb:truncate', className)}\n title={typeof children === 'string' ? children : undefined}\n {...props}\n >\n {children}\n </Comp>\n );\n}\n\n/* ── Tabs ─────────────────────────────────────────────────────────────── */\n\nexport function Tabs({ className, ...props }) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('eb:flex eb:flex-col eb:gap-2', className)} {...props} />;\n}\n\nexport function TabsList({ className, ...props }) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'eb:inline-flex eb:h-8 eb:w-fit eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-muted eb:p-[3px] eb:text-muted-foreground',\n className\n )}\n {...props}\n />\n );\n}\n\nexport function TabsTrigger({ className, ...props }) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"eb:inline-flex eb:h-[calc(100%-1px)] eb:flex-1 eb:items-center eb:justify-center eb:gap-1.5 eb:rounded-lg2 eb:border eb:border-transparent eb:px-2 eb:py-1 eb:text-[13px] eb:font-medium eb:whitespace-nowrap eb:text-foreground/60 eb:transition-all eb:hover:text-foreground eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:focus-visible:outline-1 eb:disabled:pointer-events-none eb:disabled:opacity-50 eb:data-[state=active]:bg-background eb:data-[state=active]:text-foreground eb:data-[state=active]:shadow-sm eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\n/* ── Tooltip ──────────────────────────────────────────────────────────── */\n\nexport function TooltipProvider({ delayDuration = 0, ...props }) {\n return <TooltipPrimitive.Provider delayDuration={delayDuration} {...props} />;\n}\n\nexport function Tooltip(props) {\n return <TooltipPrimitive.Root {...props} />;\n}\n\nexport function TooltipTrigger(props) {\n return <TooltipPrimitive.Trigger {...props} />;\n}\n\nexport function TooltipContent({ className, sideOffset = 4, children, ...props }) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:w-fit eb:origin-(--radix-tooltip-content-transform-origin) eb:animate-in eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:px-3 eb:py-1.5 eb:text-xs eb:text-balance eb:text-popover-foreground eb:shadow-md eb:fade-in-0 eb:zoom-in-95 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0 eb:data-[state=closed]:zoom-out-95',\n className\n )}\n {...props}\n >\n {children}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\n/** Wraps a control with a tooltip; without a label, renders the control alone. */\nexport function TooltipWrap({ label, side = 'top', children, asChild = true, delayDuration }) {\n if (!label) return children;\n return (\n <Tooltip delayDuration={delayDuration}>\n <TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>\n <TooltipContent side={side} className=\"eb:px-2 eb:py-1 eb:text-[11px]\">\n {label}\n </TooltipContent>\n </Tooltip>\n );\n}\n","// @ts-check\n/**\n * VERSIONS feature: toolbar button (`VersionsMenu`).\n */\n\nimport VersionsMenu from './VersionsMenu.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const versionsFeature = {\n id: 'versions',\n label: 'Versions',\n order: 30,\n toolbar: VersionsMenu,\n};\n","import { useState } from 'react';\nimport { Braces } from 'lucide-react';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/primitives/overlays.jsx';\nimport { tokenOf } from './catalog.js';\nimport VariableDialog from './VariableDialog.jsx';\nimport VariablePicker from './VariablePicker.jsx';\n\n/**\n * VARIABLES — toolbar menu.\n *\n * Inserts the variable's TAG where the user is typing (caret of the text being\n * edited), otherwise at the end of the selected text or button. The\n * unsubscribe link is inserted as a link (or becomes the button's URL). The\n * editor replaces nothing: rendering does, per recipient.\n *\n * When the storage supports it, users create, edit and delete their own\n * variables from here; they are shared by every template.\n *\n * The menu never takes the caret away from the text being edited: it does not\n * give focus back on close, and its mousedown does not reach the document —\n * any mousedown there ends the text editing.\n */\nexport default function VariablesMenu({ context }) {\n const { editor, ready, variables, storage, canManageVariables, reloadVariables } = context;\n const { t, notify } = useUi();\n const [open, setOpen] = useState(false);\n const [dialog, setDialog] = useState(null); // { variable } | { label }\n\n const insert = (variable) => {\n setOpen(false);\n const done =\n variable.kind === 'link'\n ? editor.insertLink(tokenOf(variable), t('Unsubscribe'))\n : editor.insertText(tokenOf(variable));\n if (!done) notify('info', t('Select a text or a button first.'));\n return done;\n };\n\n const manage = canManageVariables\n ? {\n onCreate: (label) => {\n setOpen(false);\n setDialog({ variable: null, label });\n },\n onEdit: (variable) => {\n setOpen(false);\n setDialog({ variable, label: '' });\n },\n }\n : {};\n\n return (\n <>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready}\n // No mousedown: the text being edited keeps its caret (the click still opens the menu).\n onPointerDown={(e) => e.pointerType === 'mouse' && e.preventDefault()}\n >\n <Braces />\n {t('Variables')}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n className=\"eb:w-80 eb:p-0\"\n onCloseAutoFocus={(e) => e.preventDefault()}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <VariablePicker variables={variables} onPick={insert} {...manage} />\n </PopoverContent>\n </Popover>\n {canManageVariables && (\n <VariableDialog\n open={Boolean(dialog)}\n onOpenChange={(next) => !next && setDialog(null)}\n variable={dialog?.variable || null}\n initialLabel={dialog?.label || ''}\n variables={variables}\n storage={storage}\n onSaved={async (variable, created) => {\n await reloadVariables();\n if (created) {\n // A text was being edited: the new variable goes at its caret.\n if (editor.insertText(tokenOf(variable))) {\n notify('success', t('Variable “{name}” created and inserted.', { name: variable.label }));\n } else {\n notify('success', t('Variable “{name}” created.', { name: variable.label }));\n }\n } else {\n notify('success', t('Variable “{name}” saved.', { name: variable.label }));\n }\n }}\n onDeleted={async () => {\n await reloadVariables();\n notify('success', t('Variable deleted.'));\n }}\n />\n )}\n </>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { Braces, Loader2, Trash2 } from 'lucide-react';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Input, Label } from '../../ui/primitives/fields.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/primitives/overlays.jsx';\nimport { CUSTOM_GROUP, VARIABLE_LIMITS, keyFromLabel, validateCustomVariable } from './catalog.js';\n\n/**\n * Create or edit a CUSTOM variable.\n *\n * Name what the menu shows (\"Order number\");\n * Tag proposed from the name, editable until the variable\n * exists — then frozen: templates contain it;\n * Group free text, existing groups suggested;\n * Sample value used by the preview and test sends;\n * Value if empty what a recipient without a value sees.\n *\n * @param {{\n * open: boolean,\n * onOpenChange: (open: boolean) => void,\n * variable?: import('./catalog.js').EmailVariable|null, // null: creation\n * initialLabel?: string,\n * variables: import('./catalog.js').EmailVariable[],\n * storage: import('../../storage/client.js').TemplateStorage,\n * onSaved: (variable: import('./catalog.js').EmailVariable, created: boolean) => void,\n * onDeleted?: (key: string) => void,\n * }} props\n */\nexport default function VariableDialog({ open, onOpenChange, variable = null, initialLabel = '', variables, storage, onSaved, onDeleted }) {\n const { t, notify, confirm } = useUi();\n const editing = Boolean(variable);\n const [form, setForm] = useState({ label: '', key: '', group: '', sample: '', fallback: '' });\n const [keyTouched, setKeyTouched] = useState(false);\n const [errors, setErrors] = useState({});\n const [busy, setBusy] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n setForm(\n variable\n ? {\n label: variable.label,\n key: variable.key,\n group: variable.group || '',\n sample: variable.sample || '',\n fallback: variable.fallback || '',\n }\n : { label: initialLabel, key: initialLabel ? keyFromLabel(initialLabel) : '', group: '', sample: '', fallback: '' }\n );\n setKeyTouched(false);\n setErrors({});\n }, [open, variable, initialLabel]);\n\n const groups = useMemo(\n () => [...new Set([CUSTOM_GROUP, ...variables.filter((v) => v.custom).map((v) => v.group)])].filter(Boolean),\n [variables]\n );\n\n const set = (field) => (e) => {\n const value = e.target.value;\n setForm((f) => {\n const next = { ...f, [field]: value };\n // The tag follows the name until the user types one.\n if (field === 'label' && !editing && !keyTouched) next.key = value.trim() ? keyFromLabel(value) : '';\n return next;\n });\n if (field === 'key') setKeyTouched(true);\n setErrors((errs) => ({ ...errs, [field]: undefined }));\n };\n\n const submit = async (e) => {\n e.preventDefault();\n const existing = variables.filter((v) => !editing || v.key !== variable.key);\n const check = validateCustomVariable(form, { existing, editing: editing ? variable.key : null, t });\n if (check.errors) {\n setErrors(check.errors);\n return;\n }\n setBusy(true);\n try {\n const saved = await storage.saveVariable(check.variable, { create: !editing });\n onSaved(saved, !editing);\n onOpenChange(false);\n } catch (error) {\n notify('error', error.message);\n } finally {\n setBusy(false);\n }\n };\n\n const remove = async () => {\n const ok = await confirm({\n title: t('Delete the variable “{name}”?', { name: variable.label }),\n description: t('Templates that use it will show its “value if empty”.'),\n confirmLabel: t('Delete'),\n destructive: true,\n });\n if (!ok) return;\n setBusy(true);\n try {\n await storage.deleteVariable(variable.key);\n onDeleted?.(variable.key);\n onOpenChange(false);\n } catch (error) {\n notify('error', error.message);\n } finally {\n setBusy(false);\n }\n };\n\n const field = (name, label, props = {}, hint = null) => (\n <div className=\"eb:space-y-1.5\">\n <Label htmlFor={`eb-var-${name}`}>{label}</Label>\n <Input\n id={`eb-var-${name}`}\n value={form[name]}\n onChange={set(name)}\n aria-invalid={errors[name] ? true : undefined}\n aria-describedby={errors[name] || hint ? `eb-var-${name}-hint` : undefined}\n {...props}\n />\n {(errors[name] || hint) && (\n <p id={`eb-var-${name}-hint`} className={errors[name] ? 'eb:text-[12px] eb:text-destructive' : 'eb:text-[11px] eb:text-foreground-muted'}>\n {errors[name] || hint}\n </p>\n )}\n </div>\n );\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className=\"eb:sm:max-w-[440px]\"\n // A text being edited in the canvas keeps its caret: a mousedown that\n // reaches the document would end the editing.\n onMouseDown={(e) => e.stopPropagation()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Braces className=\"eb:size-5\" />\n </span>\n <div>\n <DialogTitle className=\"eb:text-base eb:font-normal\">{editing ? t('Edit variable') : t('New variable')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">{t('Available in every template.')}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <form onSubmit={submit} className=\"eb:space-y-3\" noValidate>\n {field('label', t('Name'), { autoFocus: true, maxLength: VARIABLE_LIMITS.label, placeholder: t('Order number') })}\n {field(\n 'key',\n t('Tag'),\n { disabled: editing, maxLength: VARIABLE_LIMITS.key, className: 'eb:font-mono eb:text-[12px]' },\n form.key ? `{{${form.key}}}` : null\n )}\n <div className=\"eb:space-y-1.5\">\n <Label htmlFor=\"eb-var-group\">{t('Group')}</Label>\n <Input\n id=\"eb-var-group\"\n list=\"eb-var-groups\"\n value={form.group}\n onChange={set('group')}\n maxLength={VARIABLE_LIMITS.group}\n placeholder={t(CUSTOM_GROUP)}\n />\n <datalist id=\"eb-var-groups\">\n {groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n </div>\n <div className=\"eb:grid eb:grid-cols-2 eb:gap-3\">\n {field('sample', t('Sample value'), { maxLength: VARIABLE_LIMITS.sample, placeholder: 'CMD-1042' }, t('Preview and tests'))}\n {field('fallback', t('Value if empty'), { maxLength: VARIABLE_LIMITS.fallback }, t('When a recipient has none'))}\n </div>\n <div className=\"eb:flex eb:items-center eb:gap-2 eb:pt-1\">\n {editing && (\n <Button variant=\"ghost\" className=\"eb:text-destructive eb:hover:text-destructive\" onClick={remove} disabled={busy}>\n <Trash2 />\n {t('Delete')}\n </Button>\n )}\n <div className=\"eb:ml-auto eb:flex eb:gap-2\">\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={busy}>\n {t('Cancel')}\n </Button>\n <Button type=\"submit\" disabled={busy}>\n {busy && <Loader2 className=\"eb:animate-spin\" />}\n {editing ? t('Save') : t('Create')}\n </Button>\n </div>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n","import { forwardRef } from 'react';\nimport { Label as LabelPrimitive } from 'radix-ui';\nimport { cn } from './cn.js';\n\n// forwardRef: React 18 does not pass `ref` as a prop.\nexport const Input = forwardRef(function Input({ className, type, ...props }, ref) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n 'eb:h-8 eb:w-full eb:min-w-0 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-1 eb:text-[13px] eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:placeholder:text-foreground-muted eb:selection:bg-primary eb:selection:text-primary-foreground eb:disabled:pointer-events-none eb:disabled:cursor-not-allowed eb:disabled:opacity-50',\n 'eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n 'eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20',\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Textarea = forwardRef(function Textarea({ className, ...props }, ref) {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(\n 'eb:flex eb:field-sizing-content eb:min-h-16 eb:w-full eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-2 eb:text-[13px] eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:placeholder:text-foreground-muted eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20 eb:disabled:cursor-not-allowed eb:disabled:opacity-50',\n className\n )}\n {...props}\n />\n );\n});\n\nexport function Label({ className, ...props }) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n 'eb:flex eb:items-center eb:gap-2 eb:text-[13px] eb:leading-none eb:font-medium eb:text-foreground eb:select-none eb:peer-disabled:cursor-not-allowed eb:peer-disabled:opacity-50',\n className\n )}\n {...props}\n />\n );\n}\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { Pencil, Plus, Search } from 'lucide-react';\nimport { useT } from '../../ui/context.jsx';\nimport { cn } from '../../ui/primitives/cn.js';\nimport { tokenOf } from './catalog.js';\n\n/**\n * List of variables with a search field — shared by the toolbar menu and the\n * buttons next to the subject and preview text fields.\n *\n * Keyboard: type to filter, ↑/↓ to move, Enter to insert. A search with no\n * result offers to create the variable under that name.\n *\n * @param {{\n * variables: import('./catalog.js').EmailVariable[],\n * onPick: (variable: import('./catalog.js').EmailVariable) => void,\n * onCreate?: ((label: string) => void) | null,\n * onEdit?: ((variable: import('./catalog.js').EmailVariable) => void) | null,\n * filter?: (variable: import('./catalog.js').EmailVariable) => boolean,\n * }} props\n */\nexport default function VariablePicker({ variables, onPick, onCreate = null, onEdit = null, filter }) {\n const t = useT();\n const [query, setQuery] = useState('');\n const [active, setActive] = useState(0);\n const listRef = useRef(null);\n\n const matches = useMemo(() => {\n const q = query.trim().toLowerCase();\n return variables\n .filter((v) => (filter ? filter(v) : true))\n .filter(\n (v) =>\n !q ||\n t(v.label).toLowerCase().includes(q) ||\n v.key.toLowerCase().includes(q) ||\n t(v.group).toLowerCase().includes(q)\n );\n }, [variables, query, filter, t]);\n const groups = useMemo(() => [...new Set(matches.map((v) => v.group))], [matches]);\n // Display order (grouped) = keyboard order.\n const ordered = useMemo(() => groups.flatMap((g) => matches.filter((v) => v.group === g)), [groups, matches]);\n\n useEffect(() => setActive(0), [query]);\n useEffect(() => {\n listRef.current?.querySelector('[data-active=\"true\"]')?.scrollIntoView({ block: 'nearest' });\n }, [active]);\n\n const onKeyDown = (e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActive((i) => Math.min(i + 1, ordered.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActive((i) => Math.max(i - 1, 0));\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (ordered[active]) onPick(ordered[active]);\n else if (onCreate && query.trim()) onCreate(query.trim());\n }\n };\n\n return (\n <div className=\"eb:flex eb:max-h-[min(440px,70vh)] eb:flex-col\" data-testid=\"variable-picker\">\n <div className=\"eb:relative eb:border-b eb:border-border eb:p-2\">\n <Search className=\"eb:pointer-events-none eb:absolute eb:top-1/2 eb:left-4 eb:size-3.5 eb:-translate-y-1/2 eb:text-foreground-muted\" />\n <input\n autoFocus\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={onKeyDown}\n placeholder={t('Search variables…')}\n aria-label={t('Search variables…')}\n className=\"eb:h-8 eb:w-full eb:rounded-md eb:bg-surface-75 eb:pr-2 eb:pl-7 eb:text-[13px] eb:text-foreground eb:outline-none eb:placeholder:text-foreground-muted eb:focus-visible:ring-2 eb:focus-visible:ring-ring/40\"\n />\n </div>\n <div ref={listRef} role=\"listbox\" aria-label={t('Variables')} className=\"eb:min-h-0 eb:flex-1 eb:overflow-y-auto eb:p-1\">\n {ordered.length === 0 && (\n <div className=\"eb:px-2 eb:py-3 eb:text-center eb:text-[12px] eb:text-foreground-muted\">\n <p>{t('No variable found.')}</p>\n {onCreate && query.trim() && (\n <button\n type=\"button\"\n onClick={() => onCreate(query.trim())}\n className=\"eb:mt-2 eb:inline-flex eb:items-center eb:gap-1 eb:rounded-md eb:px-2 eb:py-1 eb:text-[12px] eb:font-medium eb:text-primary eb:hover:bg-accent\"\n >\n <Plus className=\"eb:size-3.5\" />\n {t('Create “{name}”', { name: query.trim() })}\n </button>\n )}\n </div>\n )}\n {groups.map((group) => (\n <div key={group} role=\"group\" aria-label={t(group)}>\n <p className=\"eb:px-2 eb:pt-2 eb:pb-1 eb:text-[11px] eb:text-foreground-muted\">{t(group)}</p>\n {ordered\n .filter((v) => v.group === group)\n .map((variable) => {\n const index = ordered.indexOf(variable);\n return (\n <div\n key={variable.key}\n data-active={index === active}\n className={cn(\n 'eb:group/var eb:flex eb:items-center eb:gap-1 eb:rounded-md',\n index === active ? 'eb:bg-accent eb:text-accent-foreground' : 'eb:hover:bg-accent/60'\n )}\n onMouseEnter={() => setActive(index)}\n >\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={index === active}\n data-variable={variable.key}\n onClick={() => onPick(variable)}\n className=\"eb:flex eb:min-w-0 eb:flex-1 eb:items-center eb:gap-2 eb:px-2 eb:py-1.5 eb:text-left eb:text-[13px]\"\n title={variable.description || undefined}\n >\n <span className=\"eb:min-w-0 eb:flex-1 eb:truncate\">{variable.custom ? variable.label : t(variable.label)}</span>\n <code className=\"eb:shrink-0 eb:font-mono eb:text-[10.5px] eb:text-foreground-muted\">{tokenOf(variable)}</code>\n </button>\n {onEdit && variable.custom && (\n <button\n type=\"button\"\n aria-label={t('Edit “{name}”', { name: variable.label })}\n title={t('Edit')}\n onClick={() => onEdit(variable)}\n className=\"eb:mr-1 eb:flex eb:size-6 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-md eb:text-foreground-muted eb:opacity-0 eb:group-hover/var:opacity-100 eb:hover:bg-background eb:hover:text-foreground eb:focus-visible:opacity-100\"\n >\n <Pencil className=\"eb:size-3\" />\n </button>\n )}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n {onCreate && (\n <div className=\"eb:border-t eb:border-border eb:p-1\">\n <button\n type=\"button\"\n onClick={() => onCreate(query.trim())}\n className=\"eb:flex eb:w-full eb:items-center eb:gap-2 eb:rounded-md eb:px-2 eb:py-1.5 eb:text-left eb:text-[13px] eb:font-medium eb:text-primary eb:hover:bg-accent\"\n >\n <Plus className=\"eb:size-4\" />\n {t('New variable')}\n </button>\n </div>\n )}\n </div>\n );\n}\n","// @ts-check\n/**\n * VARIABLES feature: insertion menu (`VariablesMenu`), creation and editing of\n * custom variables (`VariableDialog`). The catalog (`catalog.js`) and the\n * replacement (`service.js`) are shared with the server.\n */\n\nimport VariablesMenu from './VariablesMenu.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const variablesFeature = {\n id: 'variables',\n label: 'Variables',\n order: 10,\n toolbar: VariablesMenu,\n};\n","import { useMemo, useState } from 'react';\nimport { AlertTriangle, CheckCircle2, Eye, Info, Loader2, Monitor, RefreshCw, Smartphone } from 'lucide-react';\nimport { EMAIL_MOBILE_WIDTH } from '../../core/constants.js';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/primitives/overlays.jsx';\nimport { SectionLabel } from '../../ui/primitives/misc.jsx';\nimport { cn } from '../../ui/primitives/cn.js';\n\n/**\n * PREVIEW of the FINAL email — rendered by the server, as it will be stored.\n *\n * The canvas already compiles in the browser; the preview goes through the\n * server compilation (the only one that counts), with sample values for the\n * variables, and lists the quality checks (unsubscribe link, alt texts, links,\n * Gmail clipping size) and the MJML warnings.\n *\n * The HTML is shown in an iframe with an EMPTY sandbox: no script, form,\n * navigation, nor same origin. An email is a complete HTML document: injected\n * into the page it would inherit the application's styles and lie.\n */\n\nconst LEVEL_ICON = { warning: AlertTriangle, info: Info };\n\nexport function QualityList({ quality = [], warnings = [] }) {\n const { t } = useUi();\n if (!quality.length && !warnings.length) {\n return (\n <p className=\"eb:flex eb:items-center eb:gap-1.5 eb:text-[12px] eb:text-foreground-lighter\">\n <CheckCircle2 className=\"eb:size-3.5 eb:text-success\" aria-hidden=\"true\" />\n {t('Nothing to fix.')}\n </p>\n );\n }\n return (\n <ul className=\"eb:space-y-1.5\" aria-label={t('Points to check')}>\n {quality.map((issue) => {\n const Icon = LEVEL_ICON[issue.level] || Info;\n return (\n <li key={issue.code} className=\"eb:flex eb:items-start eb:gap-1.5 eb:text-[12px] eb:text-foreground\">\n <Icon\n className={cn(\n 'eb:mt-0.5 eb:size-3.5 eb:shrink-0',\n issue.level === 'warning' ? 'eb:text-warning' : 'eb:text-foreground-muted'\n )}\n aria-hidden=\"true\"\n />\n {issue.message}\n </li>\n );\n })}\n {warnings.slice(0, 5).map((w, i) => (\n <li key={`mjml-${i}`} className=\"eb:flex eb:items-start eb:gap-1.5 eb:text-[12px] eb:text-foreground-lighter\">\n <Info className=\"eb:mt-0.5 eb:size-3.5 eb:shrink-0 eb:text-foreground-muted\" aria-hidden=\"true\" />\n MJML: {w.message}\n </li>\n ))}\n </ul>\n );\n}\n\n/** Sandboxed preview frame, desktop or mobile width. */\nexport function EmailPreview({ html, loading = false, error = null, device = 'desktop', onDeviceChange, onRefresh, hint = true }) {\n const { t } = useUi();\n const isMobile = device === 'mobile';\n // `srcDoc`, not a blob URL: nothing to revoke when the HTML changes.\n const srcDoc = useMemo(() => html || '', [html]);\n\n return (\n <div className=\"eb:flex eb:h-full eb:min-h-0 eb:flex-col\">\n <div className=\"eb:mb-2 eb:flex eb:shrink-0 eb:items-center eb:justify-between eb:gap-2\">\n <div className=\"eb:inline-flex eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:p-0.5\">\n <Button\n variant={isMobile ? 'ghost' : 'secondary'}\n size=\"sm-compact\"\n onClick={() => onDeviceChange?.('desktop')}\n aria-pressed={!isMobile}\n >\n <Monitor />\n {t('Desktop')}\n </Button>\n <Button\n variant={isMobile ? 'secondary' : 'ghost'}\n size=\"sm-compact\"\n onClick={() => onDeviceChange?.('mobile')}\n aria-pressed={isMobile}\n >\n <Smartphone />\n {t('Mobile')}\n </Button>\n </div>\n {onRefresh && (\n <Button variant=\"outline\" size=\"sm-compact\" onClick={onRefresh} disabled={loading}>\n {loading ? <Loader2 className=\"eb:animate-spin\" /> : <RefreshCw />}\n {t('Refresh')}\n </Button>\n )}\n </div>\n\n <div className=\"eb:min-h-0 eb:flex-1 eb:overflow-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-surface-75 eb:p-3\">\n {error ? (\n <div className=\"eb:flex eb:h-full eb:items-center eb:justify-center eb:p-6 eb:text-center eb:text-[13px] eb:text-destructive\">{error}</div>\n ) : !srcDoc ? (\n <div className=\"eb:flex eb:h-full eb:items-center eb:justify-center eb:p-6 eb:text-center eb:text-[13px] eb:text-foreground-lighter\">\n {loading ? t('Rendering…') : t('Nothing to show yet.')}\n </div>\n ) : (\n <div\n className={cn('eb:mx-auto eb:bg-white', isMobile && 'eb:shadow-sm')}\n style={isMobile ? { width: EMAIL_MOBILE_WIDTH } : undefined}\n >\n <iframe\n sandbox=\"\"\n srcDoc={srcDoc}\n title={t('Email preview')}\n className=\"eb:block eb:w-full eb:border-0 eb:bg-white\"\n style={{ height: isMobile ? 760 : 900 }}\n />\n </div>\n )}\n </div>\n\n {hint && (\n <p className=\"eb:mt-2 eb:shrink-0 eb:text-[11px] eb:leading-relaxed eb:text-foreground-lighter\">\n {t('Indicative preview — check it with “Send test”.')}\n </p>\n )}\n </div>\n );\n}\n\nexport default function PreviewButton({ context }) {\n const { editor, ready, meta, storage } = context;\n const { t } = useUi();\n const [open, setOpen] = useState(false);\n const [device, setDevice] = useState('desktop');\n const [state, setState] = useState({ loading: false, html: '', subject: null, preheader: null, warnings: [], quality: [], error: null });\n\n const refresh = async () => {\n setState((s) => ({ ...s, loading: true, error: null }));\n try {\n const data = await storage.render({ mjml: editor.exportMjml(), subject: meta.subject, preheader: meta.preheader });\n setState({\n loading: false,\n html: data.html,\n // Subject and preview text with their variables filled, when the backend returns them.\n subject: data.subject ?? null,\n preheader: data.preheader ?? null,\n warnings: data.warnings || [],\n quality: data.quality || [],\n error: null,\n });\n } catch (error) {\n setState({ loading: false, html: '', subject: null, preheader: null, warnings: [], quality: [], error: error.message });\n }\n };\n\n return (\n <>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready}\n onClick={() => {\n setOpen(true);\n refresh();\n }}\n >\n <Eye />\n {t('Preview')}\n </Button>\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent className=\"eb:flex eb:h-[85vh] eb:max-h-[85vh] eb:flex-col eb:gap-4 eb:sm:max-w-[67.2rem]\">\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Eye className=\"eb:size-5\" />\n </span>\n <div>\n <DialogTitle className=\"eb:text-base eb:font-normal\">{t('Email preview')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">{t('Final rendering, variables filled with samples.')}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <div className=\"eb:grid eb:min-h-0 eb:flex-1 eb:grid-cols-1 eb:gap-4 eb:md:grid-cols-[minmax(0,1fr)_260px]\">\n <EmailPreview\n html={state.html}\n loading={state.loading}\n error={state.error}\n device={device}\n onDeviceChange={setDevice}\n onRefresh={refresh}\n // The reminder points to \"Send test\": only when it exists.\n hint={typeof storage.sendTest === 'function'}\n />\n <aside className=\"eb:min-h-0 eb:space-y-5 eb:overflow-y-auto\" aria-busy={state.loading}>\n <section className=\"eb:space-y-2\">\n <SectionLabel>{t('Inbox')}</SectionLabel>\n <div className=\"eb:rounded-lg2 eb:border eb:border-border eb:bg-surface-75 eb:px-3 eb:py-2.5\">\n <p className=\"eb:text-[13px] eb:font-medium eb:text-foreground\">{(state.subject ?? meta.subject) || t('No subject')}</p>\n <p className=\"eb:text-[12px] eb:text-foreground-muted\">{(state.preheader ?? meta.preheader) || t('No preview text')}</p>\n </div>\n </section>\n <section className=\"eb:space-y-2\">\n <SectionLabel>{t('To check')}</SectionLabel>\n {!state.loading && !state.error && <QualityList quality={state.quality} warnings={state.warnings} />}\n </section>\n </aside>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","// @ts-check\n/**\n * PREVIEW feature: server rendering of the final email, desktop and mobile,\n * with the quality checks (`PreviewButton`). Shown when the storage can render.\n */\n\nimport PreviewButton from './PreviewButton.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const previewFeature = {\n id: 'preview',\n label: 'Preview',\n order: 40,\n toolbar: PreviewButton,\n isAvailable: (context) => typeof context.storage?.render === 'function',\n};\n","import { useState } from 'react';\nimport { CheckCircle2, Loader2, Send, XCircle } from 'lucide-react';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Label, Textarea } from '../../ui/primitives/fields.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/primitives/overlays.jsx';\n\n/**\n * TEST SEND — the only real layout check: a browser preview says nothing about\n * what Outlook will do. Sends the MJML on screen, saved or not.\n *\n * The addresses are remembered in the browser for the next test.\n */\n\nconst KEY = 'best-email-builder:test-addresses';\n\nfunction readAddresses(fallback) {\n try {\n return window.localStorage.getItem(KEY) ?? fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction rememberAddresses(value) {\n try {\n window.localStorage.setItem(KEY, value);\n } catch {\n /* private browsing: nothing to remember */\n }\n}\n\nexport default function TestEmailButton({ context }) {\n const { editor, ready, meta, storage, testRecipients = [] } = context;\n const { t, notify } = useUi();\n const [open, setOpen] = useState(false);\n const [addresses, setAddresses] = useState('');\n const [sending, setSending] = useState(false);\n const [report, setReport] = useState(null);\n\n const emails = addresses\n .split(/[,;\\s]+/)\n .map((a) => a.trim())\n .filter(Boolean);\n\n const send = async () => {\n if (!emails.length) return;\n rememberAddresses(addresses);\n setSending(true);\n setReport(null);\n try {\n const result = await storage.sendTest({\n mjml: editor.exportMjml(),\n subject: meta.subject,\n preheader: meta.preheader,\n emails,\n });\n setReport(result);\n if (result.failed > 0) notify('warning', t('{sent} sent, {failed} failed.', { sent: result.sent, failed: result.failed }));\n else notify('success', t('{sent} test(s) sent — check your inbox.', { sent: result.sent }));\n } catch (error) {\n notify('error', error.message);\n } finally {\n setSending(false);\n }\n };\n\n return (\n <>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready}\n onClick={() => {\n setAddresses(readAddresses(testRecipients.join(', ')));\n setReport(null);\n setOpen(true);\n }}\n >\n <Send />\n {t('Test')}\n </Button>\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent className=\"eb:sm:max-w-[460px]\">\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Send className=\"eb:size-5\" />\n </span>\n <div>\n <DialogTitle className=\"eb:text-base eb:font-normal\">{t('Send a test')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">{t('The email on screen, to reviewers’ addresses.')}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <div className=\"eb:space-y-2\">\n <Label htmlFor=\"eb-test-addresses\">{t('Addresses')}</Label>\n <Textarea\n id=\"eb-test-addresses\"\n value={addresses}\n onChange={(e) => setAddresses(e.target.value)}\n placeholder=\"jane@example.com, john@example.com\"\n rows={3}\n />\n </div>\n {report && (\n <ul className=\"eb:space-y-1\" aria-label={t('Results')}>\n {report.results.map((r) => (\n <li key={r.email} className=\"eb:flex eb:items-start eb:gap-1.5 eb:text-[12px] eb:text-foreground\">\n {r.ok ? (\n <CheckCircle2 className=\"eb:mt-0.5 eb:size-3.5 eb:shrink-0 eb:text-success\" aria-hidden=\"true\" />\n ) : (\n <XCircle className=\"eb:mt-0.5 eb:size-3.5 eb:shrink-0 eb:text-destructive\" aria-hidden=\"true\" />\n )}\n <span className=\"eb:min-w-0 eb:break-all\">\n {r.email}\n {r.error ? ` — ${r.error}` : ''}\n </span>\n </li>\n ))}\n {report.invalid.map((email) => (\n <li key={`invalid-${email}`} className=\"eb:text-[12px] eb:text-foreground-muted\">\n {t('Ignored (invalid): {email}', { email })}\n </li>\n ))}\n </ul>\n )}\n <div className=\"eb:flex eb:justify-end eb:gap-2\">\n <Button variant=\"outline\" onClick={() => setOpen(false)}>\n {t('Close')}\n </Button>\n <Button onClick={send} disabled={sending || !emails.length}>\n {sending ? <Loader2 className=\"eb:animate-spin\" /> : <Send />}\n {t('Send')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","// @ts-check\n/**\n * TEST SEND feature (`TestEmailButton`) — rendering and sending by the server\n * (`sendTestEmail`). Shown when the storage can send tests.\n */\n\nimport TestEmailButton from './TestEmailButton.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const testEmailFeature = {\n id: 'test-email',\n label: 'Send a test',\n order: 50,\n toolbar: TestEmailButton,\n isAvailable: (context) => typeof context.storage?.sendTest === 'function',\n};\n","// @ts-check\n/**\n * FEATURES REGISTRY — `emailBuilderFeatures`.\n *\n * A feature (versions, preview, variables, test send…) is a self-contained\n * module. The interface asks this registry what to show; disabling an entry\n * (`enabled: false`) or removing it from here is enough to make it disappear.\n * A toolbar feature may also declare `isAvailable(context)`: the preview, for\n * instance, only appears when the storage can render.\n */\n\nimport { createRegistry } from '../core/registry.js';\nimport { autosaveFeature } from './autosave/index.js';\nimport { versionsFeature } from './versions/index.js';\nimport { variablesFeature } from './variables/index.js';\nimport { previewFeature } from './preview/index.js';\nimport { testEmailFeature } from './test-email/index.js';\n\n/** @typedef {import('../core/EmailEditor.js').EmailBuilderFeature} EmailBuilderFeature */\n\n/** @type {EmailBuilderFeature[]} */\nconst FEATURES = [variablesFeature, autosaveFeature, versionsFeature, previewFeature, testEmailFeature];\n\nexport const emailBuilderFeatures = createRegistry('emailBuilderFeatures', FEATURES);\n\n/** Is a feature enabled? @param {string} id */\nexport function isFeatureEnabled(id) {\n const feature = emailBuilderFeatures.get(id);\n return Boolean(feature && feature.enabled !== false);\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AlertTriangle, Loader2, Save } from 'lucide-react';\nimport { createDefaultEmailEditor } from '../index.js';\nimport { emailBuilderFeatures, isFeatureEnabled } from '../features/index.js';\nimport { DEFAULT_VARIABLES, defineVariables, mergeVariables } from '../features/variables/catalog.js';\nimport { createStarterMjml } from '../features/templates/starter.js';\nimport { createAutosaveScheduler } from '../features/autosave/scheduler.js';\nimport { clearLocalDraft, readLocalDraft, saveLocalDraft } from '../features/autosave/localDraft.js';\nimport { createHttpStorage } from '../storage/client.js';\nimport { NoticeArea, UiProvider, useUi } from './context.jsx';\nimport { Button } from './primitives/button.jsx';\nimport { cn } from './primitives/cn.js';\nimport EmailCanvas from './EmailCanvas.jsx';\nimport BlockSidebar from './BlockSidebar.jsx';\nimport ElementActions from './ElementActions.jsx';\nimport PropertiesPanel from './PropertiesPanel.jsx';\nimport Toolbar from './Toolbar.jsx';\nimport { useEmailEditorState } from './useEmailEditorState.js';\n\n/**\n * THE EMAIL BUILDER — the screen.\n *\n * ┌───────────────────────────────────────────────────────────────┐\n * │ Back · name ↶ ↷ Desktop|Mobile … Save │\n * ├────────────┬───────────────────────────────┬──────────────────┤\n * │ Blocks │ canvas │ Properties │\n * └────────────┴───────────────────────────────┴──────────────────┘\n *\n * Only talks to `EmailEditor` (core/EmailEditor.js) and to the storage\n * (storage/client.js). The engine is loaded when the canvas mounts.\n *\n * ── SAVE ────────────────────────────────────────────────────────────────────\n * \"Save\" (or Ctrl+S, inside the canvas too) sends the PROJECT and its MJML;\n * the server validates, compiles and creates a version. A template changed\n * elsewhere in the meantime is not overwritten: saving a copy is offered.\n *\n * ── INITIAL CONTENT (`initialMjml`, `initialMeta`) ──────────────────────────\n * A new template can start from given MJML instead of the starter template —\n * e.g. a template imported from another format. It counts as modified until\n * the first save.\n *\n * ── AUTOSAVE (feature `autosave`) ───────────────────────────────────────────\n * Template already saved: server save without a version. New template: local\n * draft, offered again at the next opening.\n */\n\nconst EMPTY_META = { name: '', subject: '', preheader: '', description: '' };\n\nfunction metaOf(template) {\n return {\n name: template?.name || '',\n subject: template?.subject || '',\n preheader: template?.preheader || '',\n description: template?.description || '',\n };\n}\n\nconst sameMeta = (a, b) => Object.keys(EMPTY_META).every((k) => (a[k] || '') === (b[k] || ''));\n\nfunction Builder({\n editor: injected,\n storage: injectedStorage,\n templateId: initialTemplateId,\n variables: variablesProp,\n sender,\n starterMjml,\n testRecipients,\n initialMjml,\n initialMeta,\n onClose,\n onSaved,\n onDirtyChange,\n dirtyCheckRef,\n className,\n}) {\n const { t, locale, notify, confirm } = useUi();\n const editor = useMemo(() => injected || createDefaultEmailEditor({ locale }), [injected, locale]);\n const storage = useMemo(() => injectedStorage || createHttpStorage(), [injectedStorage]);\n const systemVariables = useMemo(() => defineVariables(variablesProp || DEFAULT_VARIABLES), [variablesProp]);\n const [customVariables, setCustomVariables] = useState([]);\n const variables = useMemo(() => mergeVariables(systemVariables, customVariables), [systemVariables, customVariables]);\n const canManageVariables = typeof storage.saveVariable === 'function' && typeof storage.listVariables === 'function';\n const reloadVariables = useCallback(async () => {\n if (typeof storage.listVariables !== 'function') return;\n try {\n setCustomVariables(await storage.listVariables());\n } catch (error) {\n notify('error', error.message);\n }\n }, [storage, notify]);\n useEffect(() => {\n reloadVariables();\n }, [reloadVariables]);\n const starter = useMemo(() => starterMjml || createStarterMjml({ sender, t }), [starterMjml, sender, t]);\n const services = useMemo(() => ({ uploadImage: (file) => storage.uploadImage(file) }), [storage]);\n const state = useEmailEditorState(editor);\n const autosaveOn = isFeatureEnabled('autosave');\n const autosaveOptions = emailBuilderFeatures.get('autosave')?.options || {};\n\n const [template, setTemplate] = useState({ id: initialTemplateId, revision: null, savedAt: null, auto: false });\n /** loading → (error) → ready ; `document`: project to mount (null = starter template). */\n const [boot, setBoot] = useState({ status: 'loading', document: null, draft: false, message: null });\n const [meta, setMeta] = useState(EMPTY_META);\n const [savedMeta, setSavedMeta] = useState(EMPTY_META);\n const [saving, setSaving] = useState(null);\n const [showErrors, setShowErrors] = useState(false);\n const [autosaveBlocked, setAutosaveBlocked] = useState(null);\n const [engineError, setEngineError] = useState(null);\n const [attempt, setAttempt] = useState(0);\n\n const ready = state.status === 'ready';\n const metaDirty = !sameMeta(meta, savedMeta);\n const dirty = state.dirty || metaDirty;\n\n const timeOf = useCallback(\n (date) => (date ? new Date(date).toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' }) : ''),\n [locale]\n );\n\n /* ── Start: saved template, local draft, or starter template ── */\n const booted = useRef(false);\n useEffect(() => {\n if (booted.current) return;\n booted.current = true;\n (async () => {\n if (initialTemplateId) {\n try {\n const loaded = await storage.load(initialTemplateId);\n setMeta(metaOf(loaded));\n setSavedMeta(metaOf(loaded));\n setTemplate({ id: loaded.id, revision: loaded.revision, savedAt: null, auto: false });\n setBoot({ status: 'ready', document: loaded.document, draft: false, message: null });\n } catch (error) {\n setBoot({ status: 'error', document: null, draft: false, message: error.message });\n }\n return;\n }\n if (initialMjml) {\n setMeta({ ...EMPTY_META, ...initialMeta });\n setBoot({ status: 'ready', document: null, draft: true, message: null });\n return;\n }\n const draft = autosaveOn ? readLocalDraft() : null;\n if (draft) {\n const when = new Date(draft.savedAt).toLocaleString(locale, {\n day: '2-digit',\n month: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n const restore = await confirm({\n title: t('Resume the draft?'),\n description: t('Unsaved template from {when}.', { when }),\n confirmLabel: t('Resume'),\n cancelLabel: t('Start over'),\n });\n if (restore) {\n setMeta({ ...EMPTY_META, ...draft.meta });\n setBoot({ status: 'ready', document: draft.document, draft: true, message: null });\n return;\n }\n clearLocalDraft();\n }\n setBoot({ status: 'ready', document: null, draft: false, message: null });\n })();\n // Initial content is read once, at start-up, like `templateId`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialTemplateId, storage, autosaveOn, confirm, t, locale]);\n\n const onReady = useCallback(() => {\n if (!boot.document) editor.loadMjml(initialMjml || starter);\n }, [editor, boot.document, starter, initialMjml]);\n\n // A resumed draft was never saved: it is \"modified\".\n const { markDirty, markClean, checkDirty } = state;\n useEffect(() => {\n if (ready && boot.draft) markDirty();\n }, [ready, boot.draft, markDirty]);\n\n /* ── Modified? (the host screen and \"Back\" need the immediate answer) ── */\n const isDirty = useCallback(\n () => (editor.status === 'ready' && checkDirty()) || metaDirty,\n [editor, checkDirty, metaDirty]\n );\n const reportDirty = useRef(onDirtyChange);\n reportDirty.current = onDirtyChange;\n useEffect(() => {\n reportDirty.current?.(dirty);\n }, [dirty]);\n useEffect(() => {\n if (!dirtyCheckRef) return undefined;\n dirtyCheckRef.current = isDirty;\n return () => {\n dirtyCheckRef.current = null;\n };\n }, [dirtyCheckRef, isDirty]);\n\n // Closing the tab with work in progress: the browser asks.\n useEffect(() => {\n if (!dirty) return undefined;\n const warn = (e) => {\n e.preventDefault();\n e.returnValue = '';\n };\n window.addEventListener('beforeunload', warn);\n return () => window.removeEventListener('beforeunload', warn);\n }, [dirty]);\n\n /* ── Save ────────────────────────────────────────────────────────────── */\n const savingRef = useRef(false);\n const latest = useRef({});\n latest.current = { template, meta, onSaved };\n\n const save = useCallback(\n async ({ auto = false } = {}) => {\n if (savingRef.current || editor.status !== 'ready') return false;\n const { template: current, meta: currentMeta } = latest.current;\n if (!currentMeta.name.trim()) {\n if (!auto) {\n setShowErrors(true);\n editor.select(null);\n notify('error', t('Give the template a name before saving it.'));\n }\n return false;\n }\n const document = editor.getDocument();\n const mjml = editor.exportMjml();\n const payload = { ...currentMeta, document, mjml };\n savingRef.current = true;\n setSaving(auto ? 'auto' : 'manual');\n try {\n const result = current.id\n ? await storage.save(current.id, { ...payload, revision: current.revision, createVersion: !auto })\n : await storage.create(payload);\n setTemplate({ id: result.template.id, revision: result.template.revision, savedAt: new Date(), auto });\n setSavedMeta(currentMeta);\n setShowErrors(false);\n setAutosaveBlocked(null);\n markClean(mjml);\n if (!current.id) clearLocalDraft();\n latest.current.onSaved?.(result.template);\n const warnings = result.warnings || [];\n if (warnings.length) {\n notify(\n 'warning',\n t('Saved, with {count} MJML warning(s): {message}', { count: warnings.length, message: warnings[0].message })\n );\n } else if (!auto) {\n notify(\n 'success',\n result.version ? t('Saved — version {n}.', { n: result.version.versionNumber }) : t('Template saved.')\n );\n }\n return true;\n } catch (error) {\n if (error.status === 409 && current.id) {\n if (auto) {\n setAutosaveBlocked(error.message);\n return false;\n }\n const copy = await confirm({\n title: t('Template changed in the meantime'),\n description: t('{message} Your version can be saved as a copy.', { message: error.message }),\n confirmLabel: t('Save a copy'),\n });\n if (!copy) return false;\n try {\n const result = await storage.create({\n ...payload,\n name: t('{name} (copy)', { name: currentMeta.name }).slice(0, 200),\n });\n const copyMeta = { ...currentMeta, name: result.template.name };\n setMeta(copyMeta);\n setSavedMeta(copyMeta);\n setTemplate({ id: result.template.id, revision: result.template.revision, savedAt: new Date(), auto: false });\n setAutosaveBlocked(null);\n markClean(mjml);\n latest.current.onSaved?.(result.template);\n notify('success', t('Copy saved: “{name}”.', { name: result.template.name }));\n return true;\n } catch (copyError) {\n notify('error', copyError.message);\n return false;\n }\n }\n if (auto) setAutosaveBlocked(error.message);\n else notify('error', error.message);\n return false;\n } finally {\n savingRef.current = false;\n setSaving(null);\n }\n },\n [editor, storage, markClean, notify, confirm, t]\n );\n\n // Ctrl+S: in the page (fields included) and in the canvas (iframe).\n useEffect(() => {\n const onKey = (e) => {\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey && e.key.toLowerCase() === 's') {\n e.preventDefault();\n save();\n }\n };\n window.addEventListener('keydown', onKey, true);\n return () => window.removeEventListener('keydown', onKey, true);\n }, [save]);\n useEffect(() => {\n if (!ready) return undefined;\n return editor.addShortcut('save', 'mod+s', () => save());\n }, [ready, editor, save]);\n\n /* ── Autosave ────────────────────────────────────────────────────────── */\n const scheduler = useMemo(\n () =>\n createAutosaveScheduler({\n run: () => save({ auto: true }),\n idleMs: autosaveOptions.idleMs,\n maxWaitMs: autosaveOptions.maxWaitMs,\n }),\n [save, autosaveOptions.idleMs, autosaveOptions.maxWaitMs]\n );\n useEffect(() => () => scheduler.dispose(), [scheduler]);\n useEffect(() => {\n if (!autosaveOn || !ready || !template.id || autosaveBlocked) return;\n if (dirty) scheduler.notify();\n else scheduler.reset();\n }, [autosaveOn, ready, template.id, autosaveBlocked, dirty, state.changes, meta, scheduler]);\n\n // Never saved template: local draft.\n useEffect(() => {\n if (!autosaveOn || !ready || template.id || !dirty) return undefined;\n const timer = setTimeout(() => {\n if (editor.status === 'ready') saveLocalDraft({ document: editor.getDocument(), meta });\n }, autosaveOptions.draftDelayMs ?? 1500);\n return () => clearTimeout(timer);\n }, [autosaveOn, ready, template.id, dirty, state.changes, meta, editor, autosaveOptions.draftDelayMs]);\n\n /* ── Back ────────────────────────────────────────────────────────────── */\n const back = async () => {\n if (isDirty()) {\n const ok = await confirm({\n title: t('Leave the builder?'),\n description: template.id\n ? t('Unsaved changes will be lost.')\n : t('The draft will be offered again next time.'),\n confirmLabel: t('Leave'),\n destructive: true,\n });\n if (!ok) return;\n }\n onClose?.();\n };\n\n /* ── Render ──────────────────────────────────────────────────────────── */\n const status = !ready\n ? t('Loading…')\n : saving === 'manual'\n ? t('Saving…')\n : saving === 'auto'\n ? t('Autosaving…')\n : autosaveBlocked\n ? t('Autosave paused')\n : dirty\n ? t('Unsaved changes')\n : template.savedAt\n ? template.auto\n ? t('Autosaved at {time}', { time: timeOf(template.savedAt) })\n : t('Saved at {time}', { time: timeOf(template.savedAt) })\n : template.id\n ? t('Saved')\n : t('No changes');\n\n const featureContext = {\n editor,\n storage,\n template,\n meta,\n ready,\n isDirty,\n markDirty,\n save,\n variables,\n systemVariables,\n canManageVariables,\n reloadVariables,\n testRecipients,\n };\n const toolbarFeatures = emailBuilderFeatures.list(\n (f) => f.enabled !== false && Boolean(f.toolbar) && (f.isAvailable ? f.isAvailable(featureContext) : true)\n );\n\n return (\n <div\n className={cn('eb-root eb:relative eb:flex eb:h-full eb:min-h-0 eb:flex-col eb:bg-background eb:text-foreground', className)}\n data-testid=\"email-builder\"\n data-status={state.status}\n data-template-id={template.id || ''}\n >\n <Toolbar\n title={meta.name}\n status={status}\n ready={ready}\n canUndo={state.canUndo}\n canRedo={state.canRedo}\n onUndo={() => editor.undo()}\n onRedo={() => editor.redo()}\n device={state.device}\n onDeviceChange={(device) => editor.setDevice(device)}\n onBack={onClose ? back : undefined}\n actions={\n <>\n {toolbarFeatures.map((feature) => {\n const Action = feature.toolbar;\n return <Action key={feature.id} context={featureContext} />;\n })}\n <Button size=\"sm-compact\" onClick={() => save()} disabled={!ready || saving !== null}>\n {saving === 'manual' ? <Loader2 className=\"eb:animate-spin\" /> : <Save />}\n {t('Save')}\n </Button>\n </>\n }\n />\n <div className=\"eb:grid eb:min-h-0 eb:flex-1 eb:grid-cols-[224px_minmax(0,1fr)_296px] eb:grid-rows-1\">\n <BlockSidebar editor={editor} disabled={!ready} />\n <div className=\"eb:relative eb:min-w-0 eb:bg-surface-75\" aria-busy={!ready}>\n {boot.status === 'error' || engineError ? (\n <div role=\"alert\" className=\"eb:flex eb:h-full eb:flex-col eb:items-center eb:justify-center eb:gap-2 eb:p-6 eb:text-center\">\n <AlertTriangle className=\"eb:size-6 eb:text-destructive\" aria-hidden=\"true\" />\n <p className=\"eb:text-[13px] eb:text-foreground\">\n {boot.status === 'error' ? t('The template could not be loaded.') : t('The builder could not start.')}\n </p>\n <p className=\"eb:max-w-sm eb:text-[12px] eb:text-foreground-muted\">{boot.message || engineError}</p>\n {engineError && (\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n onClick={() => {\n setEngineError(null);\n setAttempt((n) => n + 1);\n }}\n >\n {t('Retry')}\n </Button>\n )}\n </div>\n ) : (\n <>\n {boot.status === 'ready' && (\n <EmailCanvas\n key={attempt}\n editor={editor}\n document={boot.document}\n onReady={onReady}\n onError={(error) => setEngineError(error.message)}\n />\n )}\n {!ready && (\n <div className=\"eb:absolute eb:inset-0 eb:flex eb:items-center eb:justify-center eb:bg-surface-75\" role=\"status\" aria-live=\"polite\">\n <Loader2 className=\"eb:size-6 eb:animate-spin eb:text-foreground-muted\" aria-hidden=\"true\" />\n <span className=\"eb:sr-only\">{t('Loading the builder')}</span>\n </div>\n )}\n </>\n )}\n </div>\n <PropertiesPanel\n editor={editor}\n selection={ready ? state.selection : null}\n meta={meta}\n onMetaChange={setMeta}\n changes={state.changes}\n showErrors={showErrors}\n actions={<ElementActions editor={editor} selection={state.selection} />}\n services={services}\n variables={variables}\n />\n </div>\n <NoticeArea />\n </div>\n );\n}\n\n/**\n * @param {{\n * storage?: import('../storage/client.js').TemplateStorage,\n * templateId?: string|number|null,\n * editor?: import('../core/EmailEditor.js').EmailEditor,\n * locale?: string,\n * messages?: Record<string, string>,\n * onNotify?: (level: 'success'|'info'|'warning'|'error', message: string) => void,\n * variables?: import('../features/variables/catalog.js').EmailVariable[],\n * sender?: import('../features/templates/starter.js').StarterSender,\n * starterMjml?: string,\n * testRecipients?: string[],\n * initialMjml?: string,\n * initialMeta?: {name?: string, subject?: string, preheader?: string, description?: string},\n * onClose?: () => void,\n * onSaved?: (template: object) => void,\n * onDirtyChange?: (dirty: boolean) => void,\n * dirtyCheckRef?: {current: null | (() => boolean)},\n * className?: string,\n * }} props\n */\nexport default function EmailBuilder({ locale = 'en', messages, onNotify, ...props }) {\n return (\n <UiProvider locale={locale} messages={messages} onNotify={onNotify}>\n <Builder {...props} templateId={props.templateId ?? null} />\n </UiProvider>\n );\n}\n","// @ts-check\n/**\n * Starter template of a new email.\n *\n * A complete email rather than a blank page: header (logo or sender name),\n * headline, text, button, and a FOOTER with the sender's postal address and the\n * unsubscribe link — the two mentions a bulk email must carry (CAN-SPAM, GDPR)\n * and that get forgotten when starting from nothing.\n *\n * Written with the same settings as the blocks (`blocks/`), with longhand\n * paddings (see core/mjmlAttributes): what the canvas shows is what gets sent.\n */\n\nimport { identity } from '../../i18n/index.js';\nimport { DEFAULT_BUTTON_URL, FONT_STACK, PALETTE } from '../../blocks/shared.js';\n\n/**\n * @typedef {{\n * name?: string,\n * address?: string,\n * logoUrl?: string,\n * logoWidth?: number,\n * }} StarterSender\n */\n\nfunction escapeXml(text) {\n return String(text ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nconst SIDE = 'padding-left=\"32px\" padding-right=\"32px\"';\nconst TEXT = `font-family=\"${FONT_STACK}\" color=\"${PALETTE.ink}\"`;\n\n/**\n * @param {{\n * sender?: StarterSender,\n * buttonUrl?: string,\n * t?: import('../../i18n/index.js').Translate,\n * }} [options]\n */\nexport function createStarterMjml({ sender = {}, buttonUrl = DEFAULT_BUTTON_URL, t = identity } = {}) {\n const name = escapeXml(sender.name || t('Your company'));\n const footer = [name, sender.address ? escapeXml(sender.address) : ''].filter(Boolean).join(' · ');\n const header = sender.logoUrl\n ? `<mj-image src=\"${escapeXml(sender.logoUrl)}\" alt=\"${name}\" width=\"${Number(sender.logoWidth) || 140}px\" align=\"left\" ${SIDE}></mj-image>`\n : `<mj-text ${TEXT} font-size=\"18px\" line-height=\"24px\" font-weight=\"bold\" ${SIDE}>${name}</mj-text>`;\n\n return [\n '<mjml>',\n `<mj-body background-color=\"${PALETTE.canvas}\" width=\"600px\">`,\n // Header: logo or sender name.\n `<mj-section background-color=\"${PALETTE.surface}\" padding-top=\"28px\" padding-bottom=\"8px\">`,\n '<mj-column>',\n header,\n '</mj-column>',\n '</mj-section>',\n // Body: headline, text, button.\n `<mj-section background-color=\"${PALETTE.surface}\" padding-top=\"8px\" padding-bottom=\"28px\">`,\n '<mj-column>',\n `<mj-text ${TEXT} font-size=\"24px\" line-height=\"32px\" font-weight=\"bold\" ${SIDE}>${escapeXml(t('Your headline'))}</mj-text>`,\n `<mj-text ${TEXT} font-size=\"15px\" line-height=\"24px\" ${SIDE}>` +\n `${escapeXml(t('Hello {name},', { name: '{{contact.firstname}}' }))}<br /><br />${escapeXml(t('Your text.'))}</mj-text>`,\n `<mj-button href=\"${escapeXml(buttonUrl)}\" background-color=\"${PALETTE.navy}\" color=\"${PALETTE.white}\" ` +\n `font-family=\"${FONT_STACK}\" font-size=\"15px\" font-weight=\"bold\" border-radius=\"6px\" ` +\n `inner-padding=\"12px 28px\" align=\"left\" ${SIDE}>${escapeXml(t('Learn more'))}</mj-button>`,\n '</mj-column>',\n '</mj-section>',\n // Footer: sender and unsubscribe link.\n '<mj-section padding-top=\"20px\" padding-bottom=\"28px\">',\n '<mj-column>',\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"12px\" line-height=\"18px\" color=\"#6d7484\" align=\"center\" ${SIDE}>` +\n `${footer}<br />` +\n `<a href=\"{{ unsubscribe }}\" style=\"color:#6d7484;text-decoration:underline;\">${escapeXml(t('Unsubscribe'))}</a>` +\n '</mj-text>',\n '</mj-column>',\n '</mj-section>',\n '</mj-body>',\n '</mjml>',\n ].join('');\n}\n\n/** The starter template with default (English) texts. */\nexport const STARTER_MJML = createStarterMjml();\n","// @ts-check\n/**\n * AUTOSAVE scheduler — no React, no global timer.\n *\n * Two delays, because one is not enough:\n * - `idleMs` after the LAST change (do not save in the middle of a\n * sentence);\n * - `maxWaitMs` since the FIRST unsaved change: someone editing without a\n * pause for ten minutes must still get their work saved.\n *\n * `notify()` on every change, `reset()` after any save (automatic or not),\n * `dispose()` on unmount. Timers are injectable for tests.\n */\n\n/**\n * @param {{\n * run: () => (void | Promise<unknown>),\n * idleMs?: number,\n * maxWaitMs?: number,\n * now?: () => number,\n * setTimer?: (fn: () => void, ms: number) => any,\n * clearTimer?: (handle: any) => void,\n * }} options\n */\nexport function createAutosaveScheduler({\n run,\n idleMs = 20_000,\n maxWaitMs = 120_000,\n now = () => Date.now(),\n setTimer = (fn, ms) => setTimeout(fn, ms),\n clearTimer = (handle) => clearTimeout(handle),\n}) {\n /** @type {number|null} */\n let firstChangeAt = null;\n let handle = null;\n let disposed = false;\n\n function clear() {\n if (handle !== null) clearTimer(handle);\n handle = null;\n }\n\n function fire() {\n handle = null;\n firstChangeAt = null;\n if (!disposed) run();\n }\n\n return {\n notify() {\n if (disposed) return;\n const at = now();\n if (firstChangeAt === null) firstChangeAt = at;\n const remainingMax = Math.max(0, firstChangeAt + maxWaitMs - at);\n clear();\n handle = setTimer(fire, Math.min(idleMs, remainingMax));\n },\n reset() {\n clear();\n firstChangeAt = null;\n },\n get pending() {\n return handle !== null;\n },\n dispose() {\n disposed = true;\n clear();\n },\n };\n}\n","// @ts-check\n/**\n * LOCAL DRAFT of a template that has never been saved.\n *\n * A new template does not exist on the server yet: server-side autosave cannot\n * help it, and creating an \"untitled\" record on every open would clutter the\n * template library. Its work is therefore kept in the browser (document +\n * metadata such as label, subject, preview text), and offered the next time a\n * new template is opened, as long as it was never saved.\n *\n * Cleared on the first successful save. Ignored after seven days, or when it\n * cannot be read (written by another version of the builder).\n */\n\nimport { readDocument } from '../../core/document.js';\n\nconst KEY = 'best-email-builder:new-template-draft';\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** @param {Storage|null|undefined} store */\nfunction usable(store) {\n return store && typeof store.getItem === 'function' ? store : null;\n}\n\nfunction defaultStore() {\n try {\n return typeof window !== 'undefined' ? window.localStorage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * @param {{document: object, meta: object}} draft\n * @param {Storage|null} [store]\n */\nexport function saveLocalDraft({ document, meta }, store = defaultStore()) {\n const target = usable(store);\n if (!target) return false;\n try {\n target.setItem(KEY, JSON.stringify({ savedAt: Date.now(), document, meta }));\n return true;\n } catch {\n // Quota exceeded, private browsing: a lost draft is not an error.\n return false;\n }\n}\n\n/**\n * @param {Storage|null} [store]\n * @returns {{savedAt: number, document: import('../../core/document.js').EmailDocument, meta: Record<string, string>}|null}\n */\nexport function readLocalDraft(store = defaultStore(), { now = Date.now() } = {}) {\n const target = usable(store);\n if (!target) return null;\n try {\n const raw = target.getItem(KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed || now - Number(parsed.savedAt) > MAX_AGE_MS) {\n target.removeItem(KEY);\n return null;\n }\n return { savedAt: Number(parsed.savedAt), document: readDocument(parsed.document), meta: parsed.meta || {} };\n } catch {\n target.removeItem(KEY);\n return null;\n }\n}\n\n/** @param {Storage|null} [store] */\nexport function clearLocalDraft(store = defaultStore()) {\n try {\n usable(store)?.removeItem(KEY);\n } catch {\n /* nothing to clear */\n }\n}\n","// @ts-check\n/**\n * STORAGE on the browser side — the interface only knows this contract.\n *\n * load(id) → template (document, mjml, revision…)\n * create(payload) → { template, warnings }\n * duplicate(id) → { template, warnings }\n * save(id, payload) → { template, warnings, version }\n * listVersions(id) → versions, newest first\n * getVersion(id, versionId) → version, project included\n * uploadImage(file) → { path }: RELATIVE path of the uploaded image\n * render(input) → { html, warnings, quality } (optional: preview)\n * sendTest(input) → { sent, failed, invalid, results } (optional: test send)\n * listVariables() → custom variables (optional: user-defined\n * saveVariable(variable) → saved variable variables, shared by\n * deleteVariable(key) → void every template)\n *\n * Two implementations: HTTP (talks to `createEmailBuilderHandler` from\n * `best-email-builder/server`, or to any backend with the same routes) and memory\n * (stories, tests, demos). The interface cannot tell them apart.\n *\n * The document ALWAYS travels serialized then re-read (`readDocument`): a\n * project that would not survive JSON shows up in the memory implementation\n * already, not in production.\n */\n\nimport { readDocument } from '../core/document.js';\nimport { DEFAULT_ASSETS_PATH } from '../renderer/links.js';\nimport { IMAGE_TYPES, imageUploadError } from '../validation/images.js';\nimport { DEFAULT_VARIABLES, validateCustomVariable } from '../features/variables/catalog.js';\n\n/**\n * @typedef {import('../core/document.js').EmailDocument} EmailDocument\n * @typedef {import('../features/variables/catalog.js').EmailVariable} EmailVariable\n *\n * @typedef {{\n * id: number|string,\n * name: string,\n * description?: string|null,\n * subject?: string|null,\n * preheader?: string|null,\n * revision?: string|null,\n * document?: EmailDocument,\n * mjml?: string,\n * html?: string,\n * createdAt?: string,\n * updatedAt?: string|null,\n * }} StoredTemplate\n *\n * @typedef {{\n * name?: string,\n * description?: string|null,\n * subject?: string|null,\n * preheader?: string|null,\n * document: EmailDocument,\n * mjml: string,\n * revision?: string|null,\n * createVersion?: boolean,\n * }} SavePayload\n *\n * @typedef {{\n * id: number|string,\n * versionNumber: number,\n * name?: string,\n * subject?: string|null,\n * createdBy?: string|null,\n * createdAt?: string,\n * }} TemplateVersion\n *\n * @typedef {{mjml: string, subject?: string|null, preheader?: string|null}} RenderInput\n * @typedef {{html: string, warnings: {message: string}[], quality: {code: string, level: string, message: string}[]}} RenderResult\n * @typedef {{email: string, ok: boolean, error: string|null}} TestResult\n * @typedef {{sent: number, failed: number, invalid: string[], results: TestResult[]}} SendTestResult\n *\n * @typedef {{\n * load: (id: number|string) => Promise<StoredTemplate>,\n * create: (payload: SavePayload & {name: string}) => Promise<{template: StoredTemplate, warnings: object[]}>,\n * duplicate: (id: number|string) => Promise<{template: StoredTemplate, warnings: object[]}>,\n * save: (id: number|string, payload: SavePayload) => Promise<{template: StoredTemplate, warnings: object[], version: {id: number|string, versionNumber: number}|null}>,\n * listVersions: (id: number|string) => Promise<TemplateVersion[]>,\n * getVersion: (id: number|string, versionId: number|string) => Promise<TemplateVersion & {document: EmailDocument, mjml: string}>,\n * uploadImage: (file: Blob & {name?: string}) => Promise<{path: string}>,\n * render?: (input: RenderInput) => Promise<RenderResult>,\n * sendTest?: (input: RenderInput & {emails: string[]}) => Promise<SendTestResult>,\n * listVariables?: () => Promise<EmailVariable[]>,\n * saveVariable?: (variable: Partial<EmailVariable>, options?: {create?: boolean}) => Promise<EmailVariable>,\n * deleteVariable?: (key: string) => Promise<void>,\n * }} TemplateStorage\n */\n\nexport class StorageError extends Error {\n /** @param {string} message @param {number} status @param {string} [code] */\n constructor(message, status, code) {\n super(message);\n this.name = 'StorageError';\n this.status = status;\n this.code = code;\n }\n}\n\n/** @param {{type?: string, size?: number}} file */\nfunction assertUploadable(file) {\n const error = imageUploadError(file);\n if (error) throw new StorageError(error, 415, 'UNSUPPORTED_IMAGE');\n}\n\n/** Re-reads the document of a received template (JSON → validated envelope). */\nfunction withDocument(template) {\n if (!template || !template.document) return template;\n return { ...template, document: readDocument(template.document) };\n}\n\n/**\n * Client for the routes of `createEmailBuilderHandler` (`best-email-builder/server`).\n *\n * @param {{\n * baseUrl?: string,\n * headers?: Record<string, string> | (() => Record<string, string>),\n * fetch?: typeof fetch,\n * }} [options]\n * @returns {TemplateStorage}\n */\nexport function createHttpStorage({ baseUrl = '/api/email-builder', headers = {}, fetch: fetchImpl } = {}) {\n const root = baseUrl.replace(/\\/+$/, '');\n const doFetch = fetchImpl || ((input, init) => fetch(input, init));\n const extraHeaders = () => (typeof headers === 'function' ? headers() : headers);\n\n /** @param {Response} res */\n async function unwrap(res) {\n const json = await res.json().catch(() => ({}));\n if (!res.ok || json.error) {\n throw new StorageError(json.error || `Request failed (HTTP ${res.status})`, res.status, json.code);\n }\n return json.data;\n }\n\n /** @param {string} path @param {RequestInit} [init] */\n async function call(path, init) {\n const res = await doFetch(`${root}${path}`, {\n ...init,\n headers: { 'Content-Type': 'application/json', ...extraHeaders(), ...(init?.headers || {}) },\n });\n return unwrap(res);\n }\n\n /** @param {SavePayload} payload */\n function body(payload) {\n return JSON.stringify({ ...payload, document: readDocument(payload.document) });\n }\n\n return {\n load: async (id) => withDocument(await call(`/templates/${encodeURIComponent(id)}`)),\n create: async (payload) => call('/templates', { method: 'POST', body: body(payload) }),\n duplicate: async (id) => call('/templates', { method: 'POST', body: JSON.stringify({ duplicateOf: id }) }),\n save: async (id, payload) => call(`/templates/${encodeURIComponent(id)}`, { method: 'PUT', body: body(payload) }),\n listVersions: async (id) => call(`/templates/${encodeURIComponent(id)}/versions`),\n getVersion: async (id, versionId) =>\n withDocument(await call(`/templates/${encodeURIComponent(id)}/versions/${encodeURIComponent(versionId)}`)),\n render: async (input) => call('/render', { method: 'POST', body: JSON.stringify(input) }),\n sendTest: async (input) => call('/test', { method: 'POST', body: JSON.stringify(input) }),\n listVariables: async () => call('/variables'),\n saveVariable: async (variable, { create = false } = {}) =>\n create\n ? call('/variables', { method: 'POST', body: JSON.stringify(variable) })\n : call(`/variables/${encodeURIComponent(String(variable.key))}`, { method: 'PUT', body: JSON.stringify(variable) }),\n deleteVariable: async (key) => {\n await call(`/variables/${encodeURIComponent(key)}`, { method: 'DELETE' });\n },\n async uploadImage(file) {\n assertUploadable(file);\n const form = new FormData();\n form.append('file', file, file.name || 'image');\n // No Content-Type: the browser sets the multipart boundary itself.\n const res = await doFetch(`${root}/assets`, { method: 'POST', body: form, headers: extraHeaders() });\n const data = await unwrap(res);\n return { path: data.path };\n },\n };\n}\n\n/**\n * In-memory storage, same contract. Documents are kept SERIALIZED.\n * `render` and `sendTest` cannot run in a browser (MJML compiles on the\n * server): pass implementations to enable the preview and test buttons.\n *\n * @param {{\n * render?: TemplateStorage['render'],\n * sendTest?: TemplateStorage['sendTest'],\n * assetsPath?: string,\n * systemVariables?: EmailVariable[],\n * }} [options] `systemVariables`: keys a custom variable may not take\n * @returns {TemplateStorage & {dump: () => object}}\n */\nexport function createMemoryStorage({ render, sendTest, assetsPath = DEFAULT_ASSETS_PATH, systemVariables = DEFAULT_VARIABLES } = {}) {\n /** @type {Map<string, any>} */\n const rows = new Map();\n /** @type {Map<string, any[]>} */\n const versions = new Map();\n /** @type {Map<string, Blob>} */\n const images = new Map();\n /** @type {Map<string, EmailVariable>} */\n const customVariables = new Map();\n let nextId = 1;\n let tick = Date.parse('2026-01-01T00:00:00.000Z');\n const now = () => new Date((tick += 1000)).toISOString();\n\n /** @param {any} row */\n function toTemplate(row) {\n return {\n id: row.id,\n name: row.name,\n description: row.description,\n subject: row.subject,\n preheader: row.preheader,\n revision: row.revision,\n document: readDocument(row.documentJson),\n mjml: row.mjml,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n /** @param {any} row */\n function snapshot(row) {\n const list = versions.get(String(row.id)) || [];\n const entry = {\n id: list.length + 1,\n versionNumber: list.length + 1,\n name: row.name,\n subject: row.subject,\n createdBy: null,\n createdAt: row.revision,\n documentJson: row.documentJson,\n mjml: row.mjml,\n };\n versions.set(String(row.id), [...list, entry]);\n return { id: entry.id, versionNumber: entry.versionNumber };\n }\n\n /** @param {number|string} id */\n function rowOf(id) {\n const row = rows.get(String(id));\n if (!row) throw new StorageError('Template not found', 404, 'NOT_FOUND');\n return row;\n }\n\n /** @type {TemplateStorage & {dump: () => object}} */\n const storage = {\n async load(id) {\n return toTemplate(rowOf(id));\n },\n async create(payload) {\n if (!payload.name?.trim()) throw new StorageError('Name required', 400, 'NAME_REQUIRED');\n const at = now();\n const row = {\n id: nextId++,\n name: payload.name.trim(),\n description: payload.description ?? null,\n subject: payload.subject ?? null,\n preheader: payload.preheader ?? null,\n documentJson: JSON.stringify(readDocument(payload.document)),\n mjml: payload.mjml,\n createdAt: at,\n updatedAt: null,\n revision: at,\n };\n rows.set(String(row.id), row);\n snapshot(row);\n return { template: toTemplate(row), warnings: [] };\n },\n async duplicate(id) {\n const source = rowOf(id);\n return storage.create({\n name: `${source.name} (copy)`,\n description: source.description,\n subject: source.subject,\n preheader: source.preheader,\n document: readDocument(source.documentJson),\n mjml: source.mjml,\n });\n },\n async save(id, payload) {\n const row = rowOf(id);\n if (payload.revision && payload.revision !== row.revision) {\n throw new StorageError('Template changed in the meantime — reload it before saving', 409, 'CONFLICT');\n }\n const at = now();\n Object.assign(row, {\n ...(payload.name !== undefined ? { name: payload.name } : {}),\n ...(payload.description !== undefined ? { description: payload.description } : {}),\n ...(payload.subject !== undefined ? { subject: payload.subject } : {}),\n ...(payload.preheader !== undefined ? { preheader: payload.preheader } : {}),\n documentJson: JSON.stringify(readDocument(payload.document)),\n mjml: payload.mjml,\n updatedAt: at,\n revision: at,\n });\n const version = payload.createVersion ? snapshot(row) : null;\n const { document: _omit, ...template } = toTemplate(row);\n return { template, warnings: [], version };\n },\n async listVersions(id) {\n rowOf(id);\n return [...(versions.get(String(id)) || [])].reverse().map(({ documentJson: _d, mjml: _m, ...v }) => v);\n },\n async getVersion(id, versionId) {\n const entry = (versions.get(String(id)) || []).find((v) => String(v.id) === String(versionId));\n if (!entry) throw new StorageError('Version not found', 404, 'NOT_FOUND');\n const { documentJson, ...version } = entry;\n return { ...version, document: readDocument(documentJson) };\n },\n async uploadImage(file) {\n assertUploadable(file);\n // Same key as the server: 32 hex characters of the hash + extension.\n const digest = await crypto.subtle.digest('SHA-256', await file.arrayBuffer());\n const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n const path = `${assetsPath}${hex.slice(0, 32)}.${IMAGE_TYPES[file.type]}`;\n images.set(path, file);\n return { path };\n },\n async listVariables() {\n return [...customVariables.values()].map((v) => ({ ...v }));\n },\n async saveVariable(input, { create = false } = {}) {\n const existing = [...systemVariables, ...customVariables.values()];\n if (!create && !customVariables.has(String(input?.key))) {\n throw new StorageError('Variable not found', 404, 'NOT_FOUND');\n }\n const base = create ? {} : customVariables.get(String(input.key));\n const { variable, errors } = validateCustomVariable({ ...base, ...input }, { existing, editing: create ? null : input.key });\n if (errors) throw new StorageError(Object.values(errors)[0], 400, 'INVALID_VARIABLE');\n customVariables.set(variable.key, variable);\n return { ...variable };\n },\n async deleteVariable(key) {\n if (!customVariables.delete(String(key))) throw new StorageError('Variable not found', 404, 'NOT_FOUND');\n },\n ...(render ? { render } : {}),\n ...(sendTest ? { sendTest } : {}),\n dump: () => ({\n rows: [...rows.values()],\n versions: Object.fromEntries(versions),\n images: [...images.keys()],\n variables: [...customVariables.values()],\n }),\n };\n return storage;\n}\n","import { useEffect, useRef } from 'react';\nimport { cn } from './primitives/cn.js';\n\n/**\n * Canvas area: the node where the editor mounts its engine.\n *\n * Only knows `EmailEditor`: `initialize` on mount, `destroy` on unmount.\n * React strict mode's double mount is absorbed by the editor (an\n * initialization made stale by a `destroy` never reports ready).\n *\n * `document` is only read on mount: reloading a document goes through\n * `editor.loadDocument`, not through a new render.\n */\nexport default function EmailCanvas({ editor, document = null, onReady, onError, className }) {\n const ref = useRef(null);\n const documentRef = useRef(document);\n const callbacks = useRef({ onReady, onError });\n callbacks.current = { onReady, onError };\n\n useEffect(() => {\n if (!editor || !ref.current) return undefined;\n let alive = true;\n editor\n .initialize({ container: ref.current, document: documentRef.current })\n .then(() => {\n if (alive && editor.status === 'ready') callbacks.current.onReady?.(editor);\n })\n .catch((error) => {\n if (alive) callbacks.current.onError?.(error);\n });\n return () => {\n alive = false;\n editor.destroy();\n };\n }, [editor]);\n\n return <div ref={ref} className={cn('eb-canvas eb:h-full eb:w-full', className)} data-testid=\"eb-canvas\" />;\n}\n","import { SectionLabel } from './primitives/misc.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport {\n Columns2,\n Columns3,\n Image as ImageIcon,\n MoveVertical,\n RectangleHorizontal,\n SeparatorHorizontal,\n Square,\n Type,\n} from 'lucide-react';\nimport { cn } from './primitives/cn.js';\nimport { useT } from './context.jsx';\n\n/**\n * Block sidebar, left of the canvas.\n *\n * Two gestures for the same block:\n * - CLICK: the editor inserts it at the logical place (inside the selected\n * column, after the selected element, otherwise at the end of the email);\n * - DRAG onto the canvas: the engine follows the pointer and rejects the\n * drop targets MJML does not allow.\n *\n * Blocks come from the registry (`editor.listBlocks()`): a block removed from\n * the registry disappears from here without touching this file. Only the icon\n * table is local (names come from the registry, components from here).\n */\n\nconst ICONS = {\n Type,\n Image: ImageIcon,\n RectangleHorizontal,\n SeparatorHorizontal,\n MoveVertical,\n Square,\n Columns2,\n Columns3,\n};\n\nconst GROUPS = [\n { kind: 'content', title: 'Content' },\n { kind: 'layout', title: 'Layout' },\n];\n\nfunction BlockTile({ block, disabled, onAdd, onDragStart, onDragEnd }) {\n const t = useT();\n const Icon = ICONS[block.icon] || Square;\n return (\n <TooltipWrap label={block.description ? t(block.description) : block.description}>\n <button\n type=\"button\"\n draggable={!disabled}\n disabled={disabled}\n onClick={() => onAdd(block.id)}\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'copy';\n e.dataTransfer.setData('text/plain', block.id);\n onDragStart(block.id, e.nativeEvent);\n }}\n onDragEnd={(e) => onDragEnd(e.dataTransfer?.dropEffect === 'none')}\n data-block-id={block.id}\n className={cn(\n 'eb:flex eb:h-20 eb:cursor-grab eb:select-none eb:flex-col eb:items-center eb:justify-center eb:gap-1.5 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:px-2 eb:text-center eb:transition-colors eb:active:cursor-grabbing',\n 'eb:hover:border-primary/50 eb:hover:bg-primary/5 eb:focus-visible:outline-none eb:focus-visible:ring-2 eb:focus-visible:ring-ring/50',\n disabled && 'eb:cursor-not-allowed eb:opacity-50'\n )}\n >\n <Icon className=\"eb:h-5 eb:w-5 eb:text-foreground-lighter\" aria-hidden=\"true\" />\n <span className=\"eb:text-[12px] eb:text-foreground\">{t(block.label)}</span>\n </button>\n </TooltipWrap>\n );\n}\n\nexport default function BlockSidebar({ editor, disabled = false }) {\n const t = useT();\n const blocks = editor.listBlocks();\n\n return (\n <aside aria-label={t('Blocks')} className=\"eb:min-h-0 eb:space-y-5 eb:overflow-y-auto eb:border-r eb:border-border eb:p-3\">\n {GROUPS.map((group) => {\n const items = blocks.filter((b) => b.kind === group.kind && b.mjml);\n if (!items.length) return null;\n return (\n <section key={group.kind} className=\"eb:space-y-2\">\n <SectionLabel>{t(group.title)}</SectionLabel>\n <div className=\"eb:grid eb:grid-cols-2 eb:gap-2\">\n {items.map((block) => (\n <BlockTile\n key={block.id}\n block={block}\n disabled={disabled}\n onAdd={(id) => editor.addBlock(id)}\n onDragStart={(id, event) => editor.startBlockDrag(id, event)}\n onDragEnd={(cancel) => editor.endBlockDrag(cancel)}\n />\n ))}\n </div>\n </section>\n );\n })}\n </aside>\n );\n}\n","import { Button } from './primitives/button.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Copy, Trash2 } from 'lucide-react';\nimport { useT } from './context.jsx';\n\n/**\n * Actions on the selected element: move, duplicate, delete.\n *\n * Same gestures as the canvas toolbar (above the element) and the keyboard\n * (Del), but readable and keyboard-accessible from the panel. No confirmation\n * before deleting: \"Undo\" (Ctrl+Z) reverts it.\n *\n * A column moves left or right, everything else up or down.\n */\nexport default function ElementActions({ editor, selection }) {\n const t = useT();\n if (!selection || (!selection.canRemove && !selection.canDuplicate)) return null;\n const horizontal = selection.tagName === 'mj-column';\n const [Prev, Next] = horizontal ? [ArrowLeft, ArrowRight] : [ArrowUp, ArrowDown];\n const [prevLabel, nextLabel] = horizontal\n ? [t('Move left'), t('Move right')]\n : [t('Move up'), t('Move down')];\n\n return (\n <div className=\"eb:flex eb:items-center eb:gap-0.5 eb:border-b eb:border-border eb:px-3 eb:py-1.5\" role=\"toolbar\" aria-label={t('Element actions')}>\n <TooltipWrap label={prevLabel}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={prevLabel}\n disabled={!selection.canMoveUp}\n onClick={() => editor.move(-1, selection.id)}\n >\n <Prev />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={nextLabel}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={nextLabel}\n disabled={!selection.canMoveDown}\n onClick={() => editor.move(1, selection.id)}\n >\n <Next />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={t('Duplicate')}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={t('Duplicate')}\n disabled={!selection.canDuplicate}\n onClick={() => editor.duplicate(selection.id)}\n >\n <Copy />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={t('Delete (Del)')}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={t('Delete')}\n disabled={!selection.canRemove}\n onClick={() => editor.remove(selection.id)}\n className=\"eb:ml-auto eb:text-foreground-muted eb:hover:bg-destructive/10 eb:hover:text-destructive\"\n >\n <Trash2 />\n </Button>\n </TooltipWrap>\n </div>\n );\n}\n","import { useMemo, useRef } from 'react';\nimport { Button } from './primitives/button.jsx';\nimport { Input } from './primitives/fields.jsx';\nimport { Label } from './primitives/fields.jsx';\nimport { Textarea } from './primitives/fields.jsx';\nimport { SectionLabel } from './primitives/misc.jsx';\nimport { TruncatedText as FadedText } from './primitives/misc.jsx';\nimport { X } from 'lucide-react';\nimport { GROUPS } from '../blocks/shared.js';\nimport { PropertyField } from './fields.jsx';\nimport { useT } from './context.jsx';\nimport VariableInsertButton from '../features/variables/VariableInsertButton.jsx';\n\n/**\n * Properties panel, right of the canvas.\n *\n * an element is selected -> its properties, by group (those of its block in\n * the registry); a button also gets its label here;\n * nothing is selected -> the TEMPLATE (name, subject, preview text) and\n * the page (background, width), i.e. the email body.\n *\n * `actions`: the element action bar (move, duplicate, delete), provided by\n * the host screen.\n */\n\nconst GROUP_ORDER = Object.values(GROUPS);\n\n/** A block's properties, grouped in panel order. */\nfunction grouped(properties) {\n const map = new Map();\n for (const property of properties) {\n if (!map.has(property.group)) map.set(property.group, []);\n map.get(property.group).push(property);\n }\n return [...map.entries()].sort(\n ([a], [b]) =>\n (GROUP_ORDER.indexOf(a) + 1 || 99) - (GROUP_ORDER.indexOf(b) + 1 || 99)\n );\n}\n\nfunction PropertyGroups({ editor, element, block, idPrefix, services = null }) {\n const t = useT();\n return grouped(block?.properties || []).map(([group, properties]) => (\n <section key={group} className=\"eb:space-y-3\">\n <SectionLabel>{t(group)}</SectionLabel>\n {properties.map((property) => (\n <PropertyField\n key={`${element.id}:${property.key}`}\n idPrefix={idPrefix}\n property={property}\n value={element.values[property.key]}\n services={services}\n onCommit={(value) => editor.updateProperties({ [property.key]: value }, element.id)}\n />\n ))}\n </section>\n ));\n}\n\nconst LABEL_PROPERTY = { key: 'content', label: 'Label', type: 'text', group: GROUPS.content };\n\nfunction PanelHeader({ title, onClose }) {\n const t = useT();\n return (\n <header className=\"eb:sticky eb:top-0 eb:z-10 eb:flex eb:h-11 eb:shrink-0 eb:items-center eb:gap-2 eb:border-b eb:border-border eb:bg-background eb:px-4\">\n <h3 className=\"eb:min-w-0 eb:flex-1 eb:text-[13px] eb:font-medium eb:text-foreground\">\n <FadedText>{title}</FadedText>\n </h3>\n {onClose && (\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onClose} aria-label={t('Deselect')}>\n <X />\n </Button>\n )}\n </header>\n );\n}\n\n/** Nothing selected: the template and the page. */\nfunction TemplateSettings({ editor, meta, onMetaChange, changes, showErrors, variables = null }) {\n const t = useT();\n const subjectRef = useRef(null);\n const preheaderRef = useRef(null);\n const rootId = editor.getRootId();\n // `changes`: the page is re-read after every change (background, width).\n const root = useMemo(() => (rootId ? editor.getElement(rootId) : null), [editor, rootId, changes]); // eslint-disable-line react-hooks/exhaustive-deps\n const bodyBlock = root?.blockId ? editor.getBlock(root.blockId) : null;\n const field = (key) => (e) => onMetaChange({ ...meta, [key]: e.target.value });\n\n return (\n <>\n <PanelHeader title={t('Email')} />\n <div className=\"eb:space-y-5 eb:p-4\">\n <section className=\"eb:space-y-3\">\n <SectionLabel>{t('Template')}</SectionLabel>\n <div className=\"eb:space-y-1.5\">\n <Label htmlFor=\"eb-meta-name\" className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {t('Name')} <span className=\"eb:text-destructive\">*</span>\n </Label>\n <Input\n id=\"eb-meta-name\"\n maxLength={200}\n value={meta.name}\n onChange={field('name')}\n aria-invalid={(showErrors && !meta.name.trim()) || undefined}\n />\n {showErrors && !meta.name.trim() && (\n <p className=\"eb:text-[12px] eb:text-destructive\">{t('Name is required')}</p>\n )}\n </div>\n <div className=\"eb:space-y-1.5\">\n <div className=\"eb:flex eb:h-6 eb:items-center eb:justify-between\">\n <Label htmlFor=\"eb-meta-subject\" className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {t('Subject')}\n </Label>\n {variables && (\n <VariableInsertButton\n variables={variables}\n inputRef={subjectRef}\n value={meta.subject}\n onChange={(subject) => onMetaChange({ ...meta, subject })}\n label={t('Insert a variable in the subject')}\n />\n )}\n </div>\n <Input ref={subjectRef} id=\"eb-meta-subject\" maxLength={250} value={meta.subject} onChange={field('subject')} />\n </div>\n <div className=\"eb:space-y-1.5\">\n <div className=\"eb:flex eb:h-6 eb:items-center eb:justify-between\">\n <Label htmlFor=\"eb-meta-preheader\" className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {t('Preview text')}\n </Label>\n {variables && (\n <VariableInsertButton\n variables={variables}\n inputRef={preheaderRef}\n value={meta.preheader}\n onChange={(preheader) => onMetaChange({ ...meta, preheader })}\n label={t('Insert a variable in the preview text')}\n />\n )}\n </div>\n <Textarea\n ref={preheaderRef}\n id=\"eb-meta-preheader\"\n rows={2}\n maxLength={250}\n value={meta.preheader}\n onChange={field('preheader')}\n placeholder={t('Shown after the subject in the inbox')}\n />\n </div>\n </section>\n {root && bodyBlock && <PropertyGroups editor={editor} element={root} block={bodyBlock} idPrefix=\"eb-page\" />}\n </div>\n </>\n );\n}\n\nexport default function PropertiesPanel({\n editor,\n selection,\n meta,\n onMetaChange,\n changes,\n actions = null,\n showErrors = false,\n services = null,\n variables = null,\n}) {\n const t = useT();\n const block = selection?.blockId ? editor.getBlock(selection.blockId) : null;\n\n return (\n <aside aria-label={t('Properties')} className=\"eb:min-h-0 eb:overflow-y-auto eb:border-l eb:border-border\" data-testid=\"eb-properties\">\n {!selection ? (\n <TemplateSettings\n editor={editor}\n meta={meta}\n onMetaChange={onMetaChange}\n changes={changes}\n showErrors={showErrors}\n variables={variables}\n />\n ) : (\n <>\n <PanelHeader title={t(selection.label)} onClose={() => editor.select(null)} />\n {actions}\n <div className=\"eb:space-y-5 eb:p-4\">\n {selection.tagName === 'mj-button' && (\n <section className=\"eb:space-y-3\">\n <SectionLabel>{t(GROUPS.content)}</SectionLabel>\n <PropertyField\n key={`${selection.id}:content`}\n idPrefix=\"eb-prop\"\n property={LABEL_PROPERTY}\n value={selection.content || ''}\n onCommit={(value) => editor.setContent(value || '', selection.id)}\n />\n </section>\n )}\n {selection.tagName === 'mj-text' && (\n <p className=\"eb:text-[12px] eb:text-foreground-muted\">{t('Double-click the text to edit it.')}</p>\n )}\n <PropertyGroups editor={editor} element={selection} block={block} idPrefix=\"eb-prop\" services={services} />\n </div>\n </>\n )}\n </aside>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { Input } from './primitives/fields.jsx';\nimport { Textarea } from './primitives/fields.jsx';\nimport { Label } from './primitives/fields.jsx';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from './primitives/overlays.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport { ColorPicker } from './primitives/color-picker.jsx';\nimport { Button } from './primitives/button.jsx';\nimport { AlignCenter, AlignJustify, AlignLeft, AlignRight, Loader2, Upload } from 'lucide-react';\nimport { cn } from './primitives/cn.js';\nimport { isSafeUrl } from '../validation/urls.js';\nimport { imageUploadError } from '../validation/images.js';\nimport { parseSpacing, formatSpacing } from '../core/mjmlAttributes.js';\nimport { useT } from './context.jsx';\n\n/**\n * Properties panel fields - one per `BlockProperty` type.\n *\n * -- ONE EDIT = ONE UNDO STEP -----------------------------------------------\n * Each field keeps a local draft and only hands it to the editor once the\n * edit is FINISHED: on blur or Enter for text, after a 250 ms pause for a\n * color being dragged. Typing \"Hello\" must not leave five steps in the\n * history, nor recompile the canvas on every keystroke. Escape restores the\n * original value.\n *\n * -- WHAT CANNOT BE SENT IS REJECTED HERE -----------------------------------\n * An address the server would refuse (`javascript:`, non-https image) is\n * flagged under the field and not passed on; a color with transparency loses\n * its alpha channel, which no version of Outlook reads.\n *\n * -- IMAGES -----------------------------------------------------------------\n * An image is UPLOADED (application storage, `uploadImage`) or given as an\n * https address. Never `data:`: it would bloat the email.\n */\n\nconst COLOR_DEBOUNCE_MS = 250;\n\n/** `#RGB` or `#RRGGBB`; a `#RRGGBBAA` is reduced to `#RRGGBB`. */\nexport function emailColor(value) {\n const v = String(value || '').trim();\n if (/^#[0-9a-f]{3}$/i.test(v) || /^#[0-9a-f]{6}$/i.test(v)) return v.toLowerCase();\n if (/^#[0-9a-f]{8}$/i.test(v)) return v.slice(0, 7).toLowerCase();\n return null;\n}\n\n/**\n * A field's draft, realigned with the editor value when it changes from\n * elsewhere (undo, redo) - except while typing, which must not be\n * overwritten under the user's fingers.\n */\nfunction useDraft(value, toDraft) {\n const [draft, setDraft] = useState(() => toDraft(value));\n const ref = useRef(null);\n const convert = useRef(toDraft);\n convert.current = toDraft;\n useEffect(() => {\n const el = ref.current;\n const focused = el && el.ownerDocument?.activeElement && el.contains(el.ownerDocument.activeElement);\n if (!focused) setDraft(convert.current(value));\n }, [value]);\n return [draft, setDraft, ref];\n}\n\nconst asText = (v) => v || '';\n\nfunction FieldLabel({ id, children }) {\n return (\n <Label htmlFor={id} className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {children}\n </Label>\n );\n}\n\nfunction FieldError({ children }) {\n return children ? <p className=\"eb:text-[12px] eb:text-destructive\">{children}</p> : null;\n}\n\n/** Text, address, long text: draft committed on blur or Enter. */\nfunction TextField({ id, property, value, onCommit, addon = null, error = null }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asText);\n const isUrl = property.type === 'url' || property.type === 'image';\n const kind = property.type === 'image' ? 'image' : 'link';\n const invalid = isUrl && draft.trim() !== '' && !isSafeUrl(draft, kind);\n\n const commit = () => {\n const next = draft.trim();\n if (invalid || next === (value || '')) return;\n onCommit(next || null);\n };\n const keyDown = (e) => {\n if (e.key === 'Escape') {\n setDraft(value || '');\n e.currentTarget.blur();\n } else if (e.key === 'Enter' && property.type !== 'textarea') {\n e.preventDefault();\n commit();\n }\n };\n\n const shared = {\n id,\n value: draft,\n placeholder: property.placeholder ? t(property.placeholder) : property.placeholder,\n onChange: (e) => setDraft(e.target.value),\n onBlur: commit,\n onKeyDown: keyDown,\n 'aria-invalid': invalid || undefined,\n };\n return (\n <div ref={ref} className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n {property.type === 'textarea' ? (\n <Textarea rows={3} {...shared} />\n ) : addon ? (\n <div className=\"eb:flex eb:gap-2\">\n <Input {...shared} className=\"eb:min-w-0 eb:flex-1\" />\n {addon}\n </div>\n ) : (\n <Input {...shared} />\n )}\n <FieldError>{invalid ? (kind === 'image' ? t('An https:// address is required') : t('Address not allowed')) : error}</FieldError>\n </div>\n );\n}\n\n/** Image: https address, or a file uploaded to the application storage. */\nfunction ImageField({ id, property, value, onCommit, services }) {\n const t = useT();\n const inputRef = useRef(/** @type {HTMLInputElement|null} */ (null));\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(/** @type {string|null} */ (null));\n const upload = services?.uploadImage;\n\n const pick = async (event) => {\n const file = event.target.files?.[0];\n event.target.value = '';\n if (!file || !upload) return;\n const refused = imageUploadError(file, { t });\n setError(refused);\n if (refused) return;\n setBusy(true);\n try {\n const { path } = await upload(file);\n onCommit(path);\n } catch (err) {\n setError(err?.message || t('Upload failed'));\n } finally {\n setBusy(false);\n }\n };\n\n const addon = upload ? (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/gif\"\n className=\"eb:sr-only\"\n tabIndex={-1}\n aria-hidden=\"true\"\n data-testid={`${id}-file`}\n onChange={pick}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n onClick={() => inputRef.current?.click()}\n >\n {busy ? <Loader2 className=\"eb:animate-spin\" /> : <Upload />}\n {t('Upload')}\n </Button>\n </>\n ) : null;\n\n return <TextField id={id} property={property} value={value} onCommit={onCommit} addon={addon} error={error} />;\n}\n\n/** Number in pixels, clamped. Empty = MJML default value. */\nconst asNumber = (v) => {\n const n = Number.parseFloat(String(v || ''));\n return Number.isFinite(n) ? String(n) : '';\n};\n\nfunction SizeField({ id, property, value, onCommit }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asNumber);\n\n const commit = (raw = draft) => {\n if (String(raw).trim() === '') {\n if (value) onCommit(null);\n return;\n }\n let n = Number.parseFloat(String(raw));\n if (!Number.isFinite(n)) return;\n if (property.min !== undefined) n = Math.max(property.min, n);\n if (property.max !== undefined) n = Math.min(property.max, n);\n setDraft(String(n));\n const next = `${n}${property.unit || 'px'}`;\n if (next !== value) onCommit(next);\n };\n\n return (\n <div ref={ref} className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <div className=\"eb:relative\">\n <Input\n id={id}\n type=\"number\"\n inputMode=\"numeric\"\n min={property.min}\n max={property.max}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={() => commit()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commit();\n if (e.key === 'Escape') setDraft(asNumber(value));\n }}\n className=\"eb:pr-9 eb:tabular-nums\"\n />\n <span className=\"eb:pointer-events-none eb:absolute eb:right-3 eb:top-1/2 eb:-translate-y-1/2 eb:text-[12px] eb:text-foreground-muted\">\n {property.unit || 'px'}\n </span>\n </div>\n </div>\n );\n}\n\n/** Color: swatch + hex code, committed after a short pause. */\nfunction ColorField({ id, property, value, onCommit }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asText);\n const timer = useRef(null);\n const latest = useRef({ value, onCommit });\n latest.current = { value, onCommit };\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n const change = (next) => {\n setDraft(next);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n const color = emailColor(next);\n if (!String(next || '').trim()) {\n if (latest.current.value) latest.current.onCommit(null);\n } else if (color && color !== latest.current.value) {\n latest.current.onCommit(color);\n }\n }, COLOR_DEBOUNCE_MS);\n };\n\n return (\n <div ref={ref} className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <ColorPicker id={id} value={draft} onChange={change} />\n </div>\n );\n}\n\n/** Radix does not accept an empty option (\"default value\"): use a sentinel. */\nconst DEFAULT_OPTION = '__default__';\n\nfunction SelectField({ id, property, value, onCommit }) {\n const t = useT();\n const current = value || DEFAULT_OPTION;\n return (\n <div className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <Select\n value={current}\n onValueChange={(next) => {\n const v = next === DEFAULT_OPTION ? '' : next;\n if (v !== (value || '')) onCommit(v || null);\n }}\n >\n <SelectTrigger id={id} className=\"eb:w-full\">\n <SelectValue placeholder={t('Default')} />\n </SelectTrigger>\n <SelectContent>\n {!(property.options || []).some((o) => !o.value) && (\n <SelectItem value={DEFAULT_OPTION}>{t('Default')}</SelectItem>\n )}\n {(property.options || []).map((o) => (\n <SelectItem key={o.value || DEFAULT_OPTION} value={o.value || DEFAULT_OPTION}>\n {t(o.label)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n}\n\nconst ALIGN_ICONS = { left: AlignLeft, center: AlignCenter, right: AlignRight, justify: AlignJustify };\n\n/** Alignment: toggle group (solid `bg-primary` on the active one). */\nfunction AlignField({ id, property, value, onCommit }) {\n const t = useT();\n return (\n <div className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <div\n id={id}\n role=\"radiogroup\"\n aria-label={t(property.label)}\n className=\"eb:flex eb:w-fit eb:items-center eb:gap-0.5 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:p-0.5\"\n >\n {(property.options || []).map((option) => {\n const Icon = ALIGN_ICONS[option.value] || AlignLeft;\n const active = value === option.value;\n return (\n <TooltipWrap key={option.value} label={t(option.label)}>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-label={t(option.label)}\n onClick={() => !active && onCommit(option.value)}\n className={cn(\n 'eb:inline-flex eb:h-7 eb:w-7 eb:items-center eb:justify-center eb:rounded-lg2 eb:transition-colors',\n active\n ? 'eb:bg-primary eb:text-primary-foreground'\n : 'eb:text-foreground-lighter eb:hover:bg-surface-200 eb:hover:text-foreground'\n )}\n >\n <Icon className=\"eb:h-3.5 eb:w-3.5\" />\n </button>\n </TooltipWrap>\n );\n })}\n </div>\n </div>\n );\n}\n\nconst SIDE_LABELS = [\n ['top', 'Top'],\n ['right', 'Right'],\n ['bottom', 'Bottom'],\n ['left', 'Left'],\n];\n\n/** Spacing: four sides in pixels, rewritten in their shortest form. */\nconst asSides = (v) => parseSpacing(v || '').map((s) => String(Number.parseFloat(s) || 0));\n\nfunction SpacingField({ id, property, value, onCommit }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asSides);\n\n const commit = (sides = draft) => {\n const next = formatSpacing(sides.map((s) => `${Math.max(0, Math.min(200, Number.parseFloat(s) || 0))}px`));\n if (next !== (value || '')) onCommit(next);\n };\n\n return (\n <fieldset ref={ref} className=\"eb:space-y-1.5\">\n <legend className=\"eb:mb-1.5 eb:text-[12px] eb:text-foreground-lighter\">{t(property.label)}</legend>\n <div className=\"eb:grid eb:grid-cols-4 eb:gap-1.5\">\n {SIDE_LABELS.map(([side, label], i) => (\n <div key={side} className=\"eb:space-y-1\">\n <Input\n id={`${id}-${side}`}\n type=\"number\"\n min={0}\n max={200}\n aria-label={t('{label} — {side}', { label: t(property.label), side: t(label) })}\n title={t(label)}\n value={draft[i]}\n onChange={(e) => setDraft((d) => d.map((v, j) => (j === i ? e.target.value : v)))}\n onBlur={() => commit()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commit();\n }}\n className=\"eb:px-2 eb:text-center eb:tabular-nums\"\n />\n <span className=\"eb:block eb:text-center eb:text-[10.5px] eb:text-foreground-muted\">{t(label)}</span>\n </div>\n ))}\n </div>\n </fieldset>\n );\n}\n\nconst FIELDS = {\n text: TextField,\n textarea: TextField,\n url: TextField,\n image: ImageField,\n size: SizeField,\n color: ColorField,\n select: SelectField,\n align: AlignField,\n spacing: SpacingField,\n};\n\n/**\n * Field of a property. The caller's `key` (element + property) remounts it on\n * every selection change: a draft never carries over from one element to another.\n */\nexport function PropertyField({ property, value, onCommit, idPrefix = 'eb', services = null }) {\n const Field = FIELDS[property.type] || TextField;\n const id = `${idPrefix}-${property.key}`;\n return <Field id={id} property={property} value={value} onCommit={onCommit} services={services} />;\n}\n","import { useState } from 'react';\nimport { HexAlphaColorPicker } from 'react-colorful';\nimport { Check } from 'lucide-react';\nimport { useT } from '../context.jsx';\nimport { Input } from './fields.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from './overlays.jsx';\nimport { cn } from './cn.js';\n\nconst PRESET_COLORS = [\n '#8B5CF6', '#A78BFA', '#6366F1', '#3B82F6', '#06B6D4', '#17A2B8',\n '#10B981', '#22C55E', '#28A745', '#84CC16', '#EAB308', '#FFC107',\n '#F59E0B', '#F97316', '#EF4444', '#DC3545', '#EC4899', '#6B7280',\n];\n\n// Shown by the picker while the typed value is not a colour yet (\"#8B\", empty).\nconst FALLBACK_COLOR = '#8B5CF6';\n\nconst isValidHex = (v) => /^#([0-9A-Fa-f]{8}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{3})$/.test(v || '');\n\nfunction normalizeHex(v) {\n if (!v) return '';\n let s = v.trim();\n if (s && !s.startsWith('#')) s = `#${s}`;\n return s.toUpperCase();\n}\n\n/**\n * Colour field: a swatch opening a full-spectrum picker (with alpha), a hex\n * input and presets. `value` is `#RRGGBB` or `#RRGGBBAA`; `onChange(hex)`.\n */\nexport function ColorPicker({ value, onChange, id, className }) {\n const t = useT();\n const [open, setOpen] = useState(false);\n const valid = isValidHex(value);\n const normalized = valid ? normalizeHex(value) : '';\n const emit = (hex) => onChange(normalizeHex(hex));\n\n return (\n <div className={cn('eb:flex eb:gap-2', className)}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={t('Pick a colour')}\n title={t('Pick a colour')}\n className=\"eb-checker eb:relative eb:h-8 eb:w-[44px] eb:shrink-0 eb:overflow-hidden eb:rounded-lg2 eb:shadow-sm eb:ring-1 eb:ring-black/10 eb:ring-inset eb:transition-transform eb:hover:scale-[1.04]\"\n >\n <span className=\"eb:absolute eb:inset-0\" style={{ backgroundColor: valid ? value : 'transparent' }} aria-hidden />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"eb:w-64 eb:space-y-3 eb:p-3\">\n <div className=\"eb-picker\">\n <HexAlphaColorPicker color={valid ? value : FALLBACK_COLOR} onChange={emit} />\n </div>\n <div className=\"eb:flex eb:items-center eb:gap-2\">\n <span\n className=\"eb-checker eb:relative eb:size-8 eb:shrink-0 eb:overflow-hidden eb:rounded-lg2 eb:ring-1 eb:ring-black/10 eb:ring-inset\"\n aria-hidden\n >\n <span className=\"eb:absolute eb:inset-0\" style={{ backgroundColor: valid ? value : 'transparent' }} />\n </span>\n <Input\n value={value || ''}\n onChange={(e) => emit(e.target.value)}\n placeholder=\"#RRGGBB\"\n maxLength={9}\n aria-label={t('Hex code')}\n className=\"eb:h-8 eb:flex-1 eb:font-mono eb:text-[12px] eb:uppercase\"\n />\n </div>\n <div className=\"eb:grid eb:grid-cols-6 eb:gap-1.5 eb:border-t eb:border-border eb:pt-2.5\">\n {PRESET_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => onChange(c)}\n title={c}\n aria-label={c}\n className=\"eb:relative eb:size-6 eb:rounded-lg2 eb:ring-1 eb:ring-black/10 eb:ring-inset eb:transition-transform eb:hover:scale-110\"\n style={{ backgroundColor: c }}\n >\n {normalized === c && (\n <Check className=\"eb:absolute eb:inset-0 eb:m-auto eb:size-3.5 eb:text-white eb:drop-shadow-[0_1px_1px_rgba(0,0,0,0.6)]\" />\n )}\n </button>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n <Input\n id={id}\n value={value || ''}\n onChange={(e) => onChange(e.target.value)}\n maxLength={9}\n placeholder=\"#RRGGBB\"\n className=\"eb:h-8 eb:flex-1 eb:font-mono eb:text-[13px]\"\n />\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Braces } from 'lucide-react';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/primitives/overlays.jsx';\nimport { tokenOf } from './catalog.js';\nimport VariablePicker from './VariablePicker.jsx';\n\n/**\n * `{ }` button next to a plain-text field (subject, preview text): inserts a\n * variable at the field's caret, or at its end.\n *\n * @param {{\n * variables: import('./catalog.js').EmailVariable[],\n * inputRef: {current: HTMLInputElement|HTMLTextAreaElement|null},\n * value: string,\n * onChange: (value: string) => void,\n * label: string,\n * }} props\n */\nexport default function VariableInsertButton({ variables, inputRef, value, onChange, label }) {\n const [open, setOpen] = useState(false);\n\n const insert = (variable) => {\n const input = inputRef.current;\n const text = String(value || '');\n const token = tokenOf(variable);\n const start = input?.selectionStart ?? text.length;\n const end = input?.selectionEnd ?? text.length;\n const next = `${text.slice(0, start)}${token}${text.slice(end)}`;\n onChange(next);\n setOpen(false);\n // Caret right after the inserted tag.\n requestAnimationFrame(() => {\n if (!input) return;\n input.focus();\n input.setSelectionRange(start + token.length, start + token.length);\n });\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"icon-xs\" aria-label={label} title={label}>\n <Braces />\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"eb:w-72 eb:p-0\" onCloseAutoFocus={(e) => e.preventDefault()}>\n {/* Links have no meaning in a subject line. */}\n <VariablePicker variables={variables} onPick={insert} filter={(v) => v.kind !== 'link'} />\n </PopoverContent>\n </Popover>\n );\n}\n","import { Button } from './primitives/button.jsx';\nimport { Separator } from './primitives/misc.jsx';\nimport { Tabs, TabsList, TabsTrigger } from './primitives/misc.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport { TruncatedText as FadedText } from './primitives/misc.jsx';\nimport { ArrowLeft, Monitor, Redo2, Smartphone, Undo2 } from 'lucide-react';\nimport { useT } from './context.jsx';\n\n/**\n * Builder toolbar.\n *\n * left: back, template name and its status;\n * center: undo / redo, device (desktop, mobile);\n * right: actions provided by the host screen (`actions`: variables,\n * preview, test, save - each one comes from its feature).\n */\nexport default function Toolbar({\n title,\n status,\n ready,\n canUndo,\n canRedo,\n onUndo,\n onRedo,\n device,\n onDeviceChange,\n onBack,\n actions = null,\n}) {\n const t = useT();\n return (\n <div className=\"eb:flex eb:h-12 eb:shrink-0 eb:items-center eb:gap-3 eb:border-b eb:border-border eb:px-3\">\n <Button variant=\"ghost\" size=\"sm-compact\" onClick={onBack}>\n <ArrowLeft />\n {t('Back')}\n </Button>\n <Separator orientation=\"vertical\" className=\"eb:h-5\" />\n <div className=\"eb:min-w-0 eb:max-w-[320px] eb:flex-1\">\n <p className=\"eb:text-[13px] eb:font-medium eb:text-foreground\">\n <FadedText>{title || t('New template')}</FadedText>\n </p>\n <p className=\"eb:text-[11px] eb:text-foreground-muted\" role=\"status\" aria-live=\"polite\">\n {status}\n </p>\n </div>\n\n <div className=\"eb:flex eb:items-center eb:gap-2\">\n <div className=\"eb:flex eb:items-center eb:gap-0.5\">\n <TooltipWrap label={t('Undo (Ctrl+Z)')}>\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onUndo} disabled={!ready || !canUndo} aria-label={t('Undo')}>\n <Undo2 />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={t('Redo (Ctrl+Y)')}>\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onRedo} disabled={!ready || !canRedo} aria-label={t('Redo')}>\n <Redo2 />\n </Button>\n </TooltipWrap>\n </div>\n <Tabs value={device} onValueChange={onDeviceChange}>\n <TabsList aria-label={t('Device')}>\n <TabsTrigger value=\"desktop\" disabled={!ready}>\n <Monitor />\n {t('Desktop')}\n </TabsTrigger>\n <TabsTrigger value=\"mobile\" disabled={!ready}>\n <Smartphone />\n {t('Mobile')}\n </TabsTrigger>\n </TabsList>\n </Tabs>\n </div>\n\n <div className=\"eb:ml-auto eb:flex eb:items-center eb:gap-2\">{actions}</div>\n </div>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * React state of an `EmailEditor`: status, selection, undo/redo, device, and\n * \"modified since the last clean point\".\n *\n * The UI reads the editor ONLY through this hook (and its methods): no\n * component subscribes to the engine.\n *\n * -- \"MODIFIED\" IS MEASURED, NOT COUNTED ------------------------------------\n * Counting `change` events does not work: the engine also emits them outside\n * any edit (deferred canvas render after a load), and undoing back to the\n * saved state would leave a counter at 2. So the exported MJML is compared to\n * the one of the last clean point (load, or `markClean()` after a save). MJML\n * omits default values: engine noise does not show up in it.\n *\n * `dirty` (display) lags by 150 ms; `checkDirty()` measures RIGHT NOW - it is\n * the one to query before leaving, since a click on \"Back\" can follow an edit\n * by a few milliseconds.\n *\n * `markDirty()` forces the state until the next clean point (restored\n * version: identical to nothing saved, but still to be saved).\n * `changes` counts modifications: it is used to re-read what depends on them.\n */\n\nconst DIRTY_CHECK_MS = 150;\n\nexport function useEmailEditorState(editor) {\n const [state, setState] = useState(() => ({\n status: editor?.status || 'idle',\n selection: null,\n canUndo: false,\n canRedo: false,\n device: 'desktop',\n changes: 0,\n dirty: false,\n }));\n const clean = useRef(null);\n const forced = useRef(false);\n const timer = useRef(null);\n\n const snapshot = useCallback(() => {\n try {\n return editor.status === 'ready' ? editor.exportMjml() : null;\n } catch {\n return null;\n }\n }, [editor]);\n\n /** Clean point: the given MJML (the one just saved) or the current one. */\n const markClean = useCallback((saved = null) => {\n clean.current = saved ?? snapshot();\n forced.current = false;\n const current = snapshot();\n // Edited WHILE saving: still needs saving.\n setState((s) => ({ ...s, dirty: current !== null && current !== clean.current }));\n }, [snapshot]);\n\n const checkDirty = useCallback(() => {\n if (forced.current) return true;\n const current = snapshot();\n return current !== null && current !== clean.current;\n }, [snapshot]);\n\n const markDirty = useCallback(() => {\n forced.current = true;\n setState((s) => ({ ...s, dirty: true }));\n }, []);\n\n useEffect(() => {\n if (!editor) return undefined;\n const patch = (values) => setState((s) => ({ ...s, ...values }));\n const measure = () => {\n clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n const current = snapshot();\n patch({ dirty: forced.current || (current !== null && current !== clean.current) });\n }, DIRTY_CHECK_MS);\n };\n const offs = [\n editor.on('ready', () => {\n clean.current = snapshot();\n forced.current = false;\n patch({\n status: 'ready',\n device: editor.getDevice(),\n canUndo: editor.canUndo(),\n canRedo: editor.canRedo(),\n selection: editor.getSelection(),\n dirty: false,\n });\n }),\n editor.on('destroy', () => patch({ status: 'idle', selection: null, canUndo: false, canRedo: false })),\n editor.on('selection', (selection) => patch({ selection })),\n editor.on('history', ({ canUndo, canRedo }) => patch({ canUndo, canRedo })),\n editor.on('device', (device) => patch({ device })),\n editor.on('change', () => {\n setState((s) => ({ ...s, changes: s.changes + 1 }));\n measure();\n }),\n editor.on('load', () => {\n clearTimeout(timer.current);\n clean.current = snapshot();\n forced.current = false;\n setState((s) => ({ ...s, changes: s.changes + 1, dirty: false }));\n }),\n ];\n return () => {\n clearTimeout(timer.current);\n offs.forEach((off) => off());\n };\n }, [editor, snapshot]);\n\n return { ...state, markClean, markDirty, checkDirty };\n}\n","import { Component } from 'react';\nimport { AlertTriangle, ArrowLeft, RefreshCw } from 'lucide-react';\nimport { Button } from './primitives/button.jsx';\n\n/**\n * Guard around the builder: a LOADING failure must not take the page down.\n *\n * Applications usually load the builder lazily (engine + MJML are heavy). Its\n * chunk may not arrive: slow server, or a new version deployed while the page\n * was open (the old chunk no longer exists). Without this guard the error\n * reaches the framework — a blank \"Application error\" page.\n *\n * Retry: missing chunk → reload the page (the loader caches the failure);\n * any other failure → mount the builder again.\n *\n * <EmailBuilderBoundary onClose={…} t={…}>\n * <LazyEmailBuilder … />\n * </EmailBuilderBoundary>\n *\n * `t`: translator for its three strings (class component: no hooks).\n */\n\nconst isChunkError = (error) =>\n error?.name === 'ChunkLoadError' || /Loading (CSS )?chunk .* failed/i.test(String(error?.message || ''));\n\nconst english = (text) => text;\n\nexport default class EmailBuilderBoundary extends Component {\n constructor(props) {\n super(props);\n this.state = { error: null, attempt: 0 };\n }\n\n static getDerivedStateFromError(error) {\n return { error };\n }\n\n componentDidCatch(error) {\n console.warn('[best-email-builder] the builder could not load', error);\n }\n\n retry = () => {\n if (isChunkError(this.state.error)) {\n window.location.reload();\n return;\n }\n this.setState((s) => ({ error: null, attempt: s.attempt + 1 }));\n };\n\n render() {\n const { error, attempt } = this.state;\n const t = this.props.t || english;\n if (!error) {\n return (\n <div key={attempt} style={{ height: '100%' }}>\n {this.props.children}\n </div>\n );\n }\n return (\n <div\n role=\"alert\"\n className=\"eb-root eb:flex eb:h-full eb:flex-col eb:items-center eb:justify-center eb:gap-3 eb:p-6 eb:text-center\"\n >\n <AlertTriangle className=\"eb:size-6 eb:text-destructive\" aria-hidden=\"true\" />\n <p className=\"eb:text-[13px] eb:text-foreground\">{t('The builder could not load.')}</p>\n <div className=\"eb:flex eb:gap-2\">\n {this.props.onClose && (\n <Button variant=\"outline\" size=\"sm\" onClick={this.props.onClose}>\n <ArrowLeft />\n {t('Back')}\n </Button>\n )}\n <Button size=\"sm\" onClick={this.retry}>\n <RefreshCw />\n {t('Retry')}\n </Button>\n </div>\n </div>\n );\n }\n}\n","// @ts-check\n/**\n * BEST EMAIL BUILDER — entry point.\n *\n * src/\n * core/ EmailEditor contract, versioned document, registries\n * adapters/ the engine (GrapesJS + MJML) — the only place that knows it\n * blocks/ one folder per block + the `emailBlocks` registry\n * features/ one folder per feature + `emailBuilderFeatures`\n * ui/ the React UI, which only talks to EmailEditor\n * storage/ reading/writing templates (client and server)\n * renderer/ MJML → final HTML (server compilation, variables, links)\n * validation/ what a template is allowed to contain\n *\n * See `docs/ARCHITECTURE.md`.\n */\n\nimport { createEmailEditor } from './core/EmailEditor.js';\nimport { createGrapesJsAdapter } from './adapters/grapesjs/GrapesJsAdapter.js';\nimport { emailBlocks } from './blocks/index.js';\nimport { emailBuilderFeatures } from './features/index.js';\n\nexport { createEmailEditor } from './core/EmailEditor.js';\nexport { emailBlocks } from './blocks/index.js';\nexport { emailBuilderFeatures, isFeatureEnabled } from './features/index.js';\n\n/**\n * An editor wired to the default engine and the built-in registries.\n *\n * @param {{locale?: string}} [options] `locale`: engine UI locale (`'en'` by default)\n */\nexport function createDefaultEmailEditor(options = {}) {\n const { locale } = options;\n return createEmailEditor({\n adapter: createGrapesJsAdapter({ locale }),\n blocks: emailBlocks,\n features: emailBuilderFeatures,\n });\n}\n\n/* ── React interface ─────────────────────────────────────────────────────── */\nexport { default as EmailBuilder } from './ui/EmailBuilder.jsx';\nexport { default as EmailBuilderBoundary } from './ui/EmailBuilderBoundary.jsx';\nexport { default as EmailCanvas } from './ui/EmailCanvas.jsx';\nexport { UiProvider, useUi, useT } from './ui/context.jsx';\n\n/* ── Storage (browser) ───────────────────────────────────────────────────── */\nexport { createHttpStorage, createMemoryStorage, StorageError } from './storage/client.js';\n\n/* ── Engine, document, registries ────────────────────────────────────────── */\nexport { createGrapesJsAdapter } from './adapters/grapesjs/GrapesJsAdapter.js';\nexport { createRegistry } from './core/registry.js';\nexport { readDocument, createDocument, serializeDocument, EmailDocumentError } from './core/document.js';\nexport { EMAIL_BUILDER_VERSION, EMAIL_DOCUMENT_SCHEMA_VERSION, EMAIL_DEVICES } from './core/constants.js';\n\n/* ── Variables, templates, rendering helpers shared with the server ──────── */\nexport {\n DEFAULT_VARIABLES,\n CUSTOM_GROUP,\n defineVariables,\n mergeVariables,\n keyFromLabel,\n validateCustomVariable,\n tokenOf,\n} from './features/variables/catalog.js';\nexport { applyVariables, applyVariablesToText, usedVariables, unknownVariables } from './features/variables/service.js';\nexport { createStarterMjml, STARTER_MJML } from './features/templates/starter.js';\nexport { isAssetPath, absoluteAssetUrls, DEFAULT_ASSETS_PATH } from './renderer/links.js';\n\n/* ── Translations ────────────────────────────────────────────────────────── */\nexport { createTranslator, translatorFor, LOCALES } from './i18n/index.js';\n"],"mappings":"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","names":["MJML","MJML","MJML","MJML","useState","jsx","jsx","jsxs","options","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useState","Braces","useEffect","useMemo","useState","jsx","Input","Textarea","jsx","jsxs","useState","useEffect","useMemo","field","useEffect","useMemo","useRef","useState","jsx","jsxs","useState","useRef","useMemo","useEffect","jsx","jsxs","useState","Braces","useMemo","useState","CheckCircle2","Info","Loader2","Fragment","jsx","jsxs","Info","CheckCircle2","useMemo","Loader2","useState","useState","CheckCircle2","Loader2","Fragment","jsx","jsxs","useState","CheckCircle2","Loader2","useCallback","useEffect","useMemo","useRef","useState","AlertTriangle","Loader2","KEY","useEffect","useRef","jsx","useRef","useEffect","jsx","jsxs","GROUPS","Trash2","jsx","jsxs","Trash2","useMemo","useRef","X","useEffect","useRef","useState","useState","jsx","jsxs","useState","Loader2","Fragment","jsx","jsxs","useState","useRef","useEffect","Loader2","useState","Braces","jsx","jsxs","useState","Braces","Fragment","jsx","jsxs","X","useRef","useMemo","bodyBlock","ArrowLeft","Monitor","Smartphone","jsx","jsxs","ArrowLeft","Monitor","Smartphone","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","useMemo","useState","useCallback","useEffect","useRef","Loader2","AlertTriangle","AlertTriangle","ArrowLeft","RefreshCw","jsx","jsxs","AlertTriangle","ArrowLeft","RefreshCw"]}
1
+ {"version":3,"sources":["../src/core/events.js","../src/core/mjmlAttributes.js","../src/core/EmailEditor.js","../src/adapters/grapesjs/engineConfig.js","../src/adapters/grapesjs/unwrapModule.js","../src/adapters/grapesjs/GrapesJsAdapter.js","../src/core/registry.js","../src/blocks/shared.js","../src/blocks/structure/index.js","../src/blocks/text/index.js","../src/blocks/image/index.js","../src/blocks/button/index.js","../src/blocks/divider/index.js","../src/blocks/spacer/index.js","../src/blocks/columns/index.js","../src/blocks/index.js","../src/features/autosave/index.js","../src/features/versions/VersionsMenu.jsx","../src/ui/primitives/button.jsx","../src/ui/primitives/cn.js","../src/ui/primitives/overlays.jsx","../src/ui/context.jsx","../src/ui/primitives/misc.jsx","../src/features/versions/index.js","../src/features/variables/VariablesMenu.jsx","../src/features/variables/VariableDialog.jsx","../src/ui/primitives/fields.jsx","../src/features/variables/VariablePicker.jsx","../src/features/variables/index.js","../src/features/preview/PreviewButton.jsx","../src/features/preview/index.js","../src/features/test-email/TestEmailButton.jsx","../src/features/test-email/index.js","../src/features/index.js","../src/ui/EmailBuilder.jsx","../src/features/templates/starter.js","../src/features/autosave/scheduler.js","../src/features/autosave/localDraft.js","../src/storage/client.js","../src/ui/EmailCanvas.jsx","../src/ui/BlockSidebar.jsx","../src/ui/ElementActions.jsx","../src/ui/PropertiesPanel.jsx","../src/ui/fields.jsx","../src/ui/primitives/color-picker.jsx","../src/features/variables/VariableInsertButton.jsx","../src/ui/Toolbar.jsx","../src/ui/useEmailEditorState.js","../src/ui/EmailBuilderBoundary.jsx","../src/index.js"],"sourcesContent":["// @ts-check\n/**\n * Minimal, dependency-free event emitter.\n *\n * A throwing listener does not prevent the next ones from running: the error\n * goes to `onError` (the console by default). A UI listening to the selection\n * must not break the history because one panel crashed.\n */\n\n/**\n * @typedef {(payload?: any) => void} Listener\n * @typedef {{\n * on: (event: string, listener: Listener) => () => void,\n * off: (event: string, listener: Listener) => void,\n * emit: (event: string, payload?: any) => void,\n * clear: () => void,\n * }} Emitter\n */\n\n/**\n * @param {{onError?: (error: unknown, event: string) => void}} [options]\n * @returns {Emitter}\n */\nexport function createEmitter({ onError } = {}) {\n /** @type {Map<string, Set<Listener>>} */\n const listeners = new Map();\n const report =\n onError ||\n ((error, event) => {\n console.warn(`[best-email-builder] listener for \"${event}\" failed`, error);\n });\n\n /** @param {string} event @param {Listener} listener */\n function off(event, listener) {\n listeners.get(event)?.delete(listener);\n }\n\n return {\n on(event, listener) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)?.add(listener);\n return () => off(event, listener);\n },\n off,\n emit(event, payload) {\n for (const listener of [...(listeners.get(event) || [])]) {\n try {\n listener(payload);\n } catch (error) {\n report(error, event);\n }\n }\n },\n clear() {\n listeners.clear();\n },\n };\n}\n","// @ts-check\n/**\n * MJML attributes — reading and writing properties panel values.\n *\n * This is knowledge of the LANGUAGE (MJML), not of the engine: it lives in\n * the core, and every adapter benefits from it.\n *\n * ── PADDING IS WRITTEN IN LONGHAND ─────────────────────────────────────────\n * An MJML element carries both `padding` and `padding-top/-right/-bottom/\n * -left`, and the longhand wins. The canvas, starting from the defaults\n * (`padding-top=\"10px\"`…), ignored a `padding=\"40px 60px\"` that the sent\n * email did apply: the screen lied. So `padding` is always written as four\n * attributes, and read back the same way.\n *\n * `inner-padding` (button) has no longhand in MJML: it stays as is.\n *\n * ── NO QUOTES IN A VALUE ───────────────────────────────────────────────────\n * The engine export writes attributes unescaped: a `\"` in a value would break\n * the MJML. Double quotes, angle brackets and line breaks are stripped on\n * write.\n */\n\n/** Spacing attributes that have a longhand form in MJML. */\nexport const LONGHAND_SPACING = new Set(['padding']);\n\nexport const SIDES = /** @type {const} */ (['top', 'right', 'bottom', 'left']);\n\n/**\n * \"10px 25px\" → ['10px', '25px', '10px', '25px'] (CSS 1-to-4 value rule).\n * @param {string|null|undefined} value\n * @returns {[string, string, string, string]}\n */\nexport function parseSpacing(value) {\n const parts = String(value || '')\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n const [a = '0px', b = a, c = a, d = b] = parts;\n return [a, b, c, d];\n}\n\n/**\n * Shortest form of a four-sided spacing.\n * @param {string[]} sides\n */\nexport function formatSpacing(sides) {\n const [t, r, b, l] = sides.map((s) => String(s || '0px'));\n if (t === b && r === l) return t === r ? t : `${t} ${r}`;\n if (r === l) return `${t} ${r} ${b}`;\n return `${t} ${r} ${b} ${l}`;\n}\n\n/** Attribute value safe for an unescaped export. @param {unknown} value */\nexport function cleanAttributeValue(value) {\n return String(value ?? '')\n .replace(/[\"<>\\r\\n]/g, '')\n .trim();\n}\n\n/**\n * Entered values → MJML attributes to set (`null` = attribute to remove).\n *\n * @param {Record<string, string|null|undefined>} values\n * @returns {Record<string, string|null>}\n */\nexport function toAttributes(values) {\n /** @type {Record<string, string|null>} */\n const out = {};\n for (const [key, raw] of Object.entries(values || {})) {\n const value = raw === null || raw === undefined ? '' : cleanAttributeValue(raw);\n if (LONGHAND_SPACING.has(key)) {\n const sides = value ? parseSpacing(value) : null;\n SIDES.forEach((side, i) => {\n out[`${key}-${side}`] = sides ? sides[i] : null;\n });\n out[key] = null;\n } else {\n out[key] = value || null;\n }\n }\n return out;\n}\n\n/**\n * Element attributes → a block's property values.\n *\n * @param {Record<string, unknown>} attributes\n * @param {{key: string}[]} properties\n * @returns {Record<string, string>}\n */\nexport function toValues(attributes, properties) {\n /** @type {Record<string, string>} */\n const values = {};\n for (const { key } of properties) {\n if (LONGHAND_SPACING.has(key)) {\n const base = parseSpacing(String(attributes[key] ?? ''));\n const sides = SIDES.map((side, i) => {\n const v = attributes[`${key}-${side}`];\n return v === undefined || v === null || v === '' ? base[i] : String(v);\n });\n const hasAny = attributes[key] || SIDES.some((side) => attributes[`${key}-${side}`]);\n values[key] = hasAny ? formatSpacing(sides) : '';\n } else {\n const v = attributes[key];\n values[key] = v === undefined || v === null ? '' : String(v);\n }\n }\n return values;\n}\n","// @ts-check\n/**\n * EmailEditor — THE email builder contract.\n *\n * ── THE ARCHITECTURE RULE ──────────────────────────────────────────────────\n *\n * React UI ─► EmailEditor ─► adapter ─► engine (GrapesJS) ─► MJML\n *\n * The UI (`ui/`), features (`features/`) and blocks (`blocks/`) talk ONLY to\n * this object. None of them imports GrapesJS: everything engine-related lives\n * in `adapters/grapesjs/`. Swapping the engine therefore means writing another\n * adapter that fulfils `EmailEditorAdapter`, rewriting nothing above it.\n *\n * ── WHAT THIS LAYER ADDS TO THE ADAPTER ────────────────────────────────────\n * - the lifecycle (idle → initializing → ready → idle), and a hard refusal\n * of any call made before `initialize` or after `destroy`;\n * - resolving blocks by id in the registry;\n * - the versioned document envelope (`core/document.js`);\n * - starting and stopping registered features.\n *\n * See `docs/ARCHITECTURE.md`.\n */\n\nimport { createEmitter } from './events.js';\nimport { EMAIL_DEVICES } from './constants.js';\nimport { createDocument, readDocument } from './document.js';\nimport { toAttributes, toValues } from './mjmlAttributes.js';\n\n/**\n * @typedef {import('./constants.js').EmailDevice} EmailDevice\n * @typedef {import('./document.js').EmailDocument} EmailDocument\n */\n\n/**\n * Editable block property, as shown in the right-hand panel. The key is an\n * MJML ATTRIBUTE (`color`, `padding`, `href`…) — the email's language, not\n * the engine's.\n *\n * @typedef {{\n * key: string,\n * label: string,\n * type: 'text'|'textarea'|'color'|'size'|'select'|'align'|'url'|'image'|'spacing',\n * group: string,\n * options?: {value: string, label: string}[],\n * placeholder?: string,\n * min?: number,\n * max?: number,\n * unit?: string,\n * }} BlockProperty\n */\n\n/**\n * Builder block.\n *\n * `content` : an element (text, image, button…) that lives INSIDE a column;\n * `layout` : an N-column section, living in the email body;\n * `structure` : body, section, column — selectable, not addable.\n *\n * `mjml` is the inserted fragment; `sectionMjml` the same wrapped in a\n * section, for when it must go outside any column; `tagName` identifies the\n * block of a selected element (`mj-text` → text).\n * `editableContent`: the content is editable (canvas for text, panel for a\n * button label).\n *\n * @typedef {{\n * id: string,\n * label: string,\n * description?: string,\n * icon: string,\n * kind: 'content'|'layout'|'structure',\n * tagName: string,\n * order?: number,\n * mjml?: string,\n * sectionMjml?: string,\n * properties: BlockProperty[],\n * editableContent?: boolean,\n * }} EmailBlock\n */\n\n/**\n * Selected element as described by the ENGINE: MJML tag and raw attributes,\n * nothing more.\n *\n * @typedef {{\n * id: string,\n * tagName: string,\n * attributes: Record<string, string>,\n * content: string|null,\n * canRemove: boolean,\n * canDuplicate: boolean,\n * canMoveUp: boolean,\n * canMoveDown: boolean,\n * }} EngineSelection\n */\n\n/**\n * Selected element, in the builder's vocabulary: its block and its property\n * values (padding recombined, see mjmlAttributes).\n *\n * @typedef {EngineSelection & {\n * blockId: string|null,\n * label: string,\n * values: Record<string, string>,\n * }} EmailSelection\n */\n\n/**\n * @typedef {{html: string, errors: {line?: number, message: string, tagName?: string}[]}} HtmlExport\n */\n\n/**\n * What an engine must provide. All element ids are opaque strings returned by\n * the adapter itself.\n *\n * Events emitted through `onEvent(type, payload)`:\n * `change` the document changed (typing, add, remove, undo…)\n * `load` a whole document was just loaded — NOT a modification: the\n * host screen decides whether it needs saving\n * `selection` the selection changed — payload: EngineSelection|null\n * `history` undo/redo state changed — payload: {canUndo, canRedo}\n * `device` the displayed device changed — payload: EmailDevice\n *\n * @typedef {{\n * name: string,\n * version: string,\n * initialize: (options: {\n * container: HTMLElement,\n * blocks: EmailBlock[],\n * document: EmailDocument|null,\n * onEvent: (type: string, payload?: any) => void,\n * }) => Promise<void>,\n * destroy: () => void,\n * addBlock: (block: EmailBlock, options?: {targetId?: string|null}) => string|null,\n * remove: (id: string) => boolean,\n * duplicate: (id: string) => string|null,\n * move: (id: string, direction: -1|1) => boolean,\n * select: (id: string|null) => void,\n * getSelection: () => EngineSelection|null,\n * describe: (id: string) => EngineSelection|null,\n * getRootId: () => string|null,\n * updateProperties: (id: string, attributes: Record<string, string|null>) => void,\n * setContent: (id: string, content: string) => void,\n * insertText: (text: string) => boolean,\n * insertLink: (href: string, label: string) => boolean,\n * undo: () => void,\n * redo: () => void,\n * canUndo: () => boolean,\n * canRedo: () => boolean,\n * clearHistory: () => void,\n * getProject: () => object,\n * loadProject: (project: object) => void,\n * loadMjml: (mjml: string) => void,\n * exportMjml: () => string,\n * exportHtml: () => HtmlExport,\n * setDevice: (device: EmailDevice) => void,\n * getDevice: () => EmailDevice,\n * startBlockDrag: (block: EmailBlock, event: Event) => void,\n * endBlockDrag: (cancel?: boolean) => void,\n * addShortcut: (id: string, keys: string, handler: () => void) => (() => void),\n * }} EmailEditorAdapter\n */\n\n/**\n * Pluggable feature. `setup` receives the ready editor and may return a\n * teardown function, called on `destroy`. `toolbar`: React component placed in\n * the toolbar (it receives the screen context); `options`: its settings, read\n * by the screen; `isAvailable(context)`: hides the toolbar entry when the\n * context cannot support it (e.g. a storage that cannot render).\n *\n * @typedef {{\n * id: string,\n * label?: string,\n * order?: number,\n * enabled?: boolean,\n * setup?: (editor: EmailEditor) => (void | (() => void)),\n * toolbar?: any,\n * isAvailable?: (context: any) => boolean,\n * options?: Record<string, any>,\n * }} EmailBuilderFeature\n */\n\n/**\n * @typedef {'idle'|'initializing'|'ready'} EmailEditorStatus\n */\n\n/**\n * @typedef {{\n * readonly status: EmailEditorStatus,\n * readonly adapterName: string,\n * initialize: (options: {container: HTMLElement, document?: EmailDocument|null}) => Promise<void>,\n * destroy: () => void,\n * listBlocks: () => EmailBlock[],\n * getBlock: (blockId: string) => EmailBlock|undefined,\n * addBlock: (blockId: string, options?: {targetId?: string|null}) => string|null,\n * remove: (id?: string|null) => boolean,\n * duplicate: (id?: string|null) => string|null,\n * move: (direction: -1|1, id?: string|null) => boolean,\n * select: (id: string|null) => void,\n * getSelection: () => EmailSelection|null,\n * getElement: (id: string) => EmailSelection|null,\n * getRootId: () => string|null,\n * updateProperties: (values: Record<string, string|null>, id?: string|null) => void,\n * setContent: (content: string, id?: string|null) => void,\n * insertText: (text: string) => boolean,\n * insertLink: (href: string, label: string) => boolean,\n * undo: () => void,\n * redo: () => void,\n * canUndo: () => boolean,\n * canRedo: () => boolean,\n * getDocument: () => EmailDocument,\n * loadDocument: (document: unknown) => void,\n * loadMjml: (mjml: string) => void,\n * exportMjml: () => string,\n * exportHtml: () => HtmlExport,\n * setDevice: (device: EmailDevice) => void,\n * getDevice: () => EmailDevice,\n * startBlockDrag: (blockId: string, event: Event) => void,\n * endBlockDrag: (cancel?: boolean) => void,\n * addShortcut: (id: string, keys: string, handler: () => void) => (() => void),\n * on: (event: string, listener: (payload?: any) => void) => () => void,\n * }} EmailEditor\n */\n\n/**\n * @param {{\n * adapter: EmailEditorAdapter,\n * blocks: import('./registry.js').Registry<EmailBlock>,\n * features?: import('./registry.js').Registry<EmailBuilderFeature> | null,\n * }} options\n * @returns {EmailEditor}\n */\nexport function createEmailEditor({ adapter, blocks, features = null }) {\n if (!adapter) throw new Error('EmailEditor: missing adapter');\n if (!blocks) throw new Error('EmailEditor: missing block registry');\n\n const emitter = createEmitter();\n /** @type {EmailEditorStatus} */\n let status = 'idle';\n /** Token of the pending initialization: a `destroy` invalidates it. */\n let generation = 0;\n /** @type {(() => void)[]} */\n let teardowns = [];\n\n function requireReady(action) {\n if (status !== 'ready') {\n throw new Error(`EmailEditor: \"${action}\" called before the editor was initialized`);\n }\n }\n\n /** @param {string|null|undefined} id */\n function targetOf(id, action) {\n const resolved = id ?? adapter.getSelection()?.id ?? null;\n if (!resolved) throw new Error(`EmailEditor: \"${action}\" with no selected element`);\n return resolved;\n }\n\n /** Block describing a tag: structure first (a section stays a section). */\n function blockForTag(tagName) {\n const all = blocks.list();\n return (\n all.find((b) => b.tagName === tagName && b.kind === 'structure') ||\n all.find((b) => b.tagName === tagName) ||\n null\n );\n }\n\n /** @param {EngineSelection|null} selection @returns {EmailSelection|null} */\n function toEmailSelection(selection) {\n if (!selection) return null;\n const block = blockForTag(selection.tagName);\n return {\n ...selection,\n blockId: block?.id || null,\n label: block?.label || selection.tagName,\n values: toValues(selection.attributes || {}, block?.properties || []),\n };\n }\n\n function startFeatures() {\n if (!features) return;\n for (const feature of features.list((f) => f.enabled !== false)) {\n try {\n const stop = feature.setup?.(editor);\n if (typeof stop === 'function') teardowns.push(stop);\n } catch (error) {\n // A broken feature must not prevent editing.\n console.warn(`[best-email-builder] feature \"${feature.id}\" failed`, error);\n }\n }\n }\n\n function stopFeatures() {\n for (const stop of teardowns.reverse()) {\n try {\n stop();\n } catch (error) {\n console.warn('[best-email-builder] feature teardown failed', error);\n }\n }\n teardowns = [];\n }\n\n /** @type {EmailEditor} */\n const editor = {\n get status() {\n return status;\n },\n get adapterName() {\n return adapter.name;\n },\n\n async initialize({ container, document = null }) {\n if (!container) throw new Error('EmailEditor: missing container');\n if (status !== 'idle') {\n throw new Error(`EmailEditor: initialization refused (status \"${status}\")`);\n }\n const ticket = ++generation;\n status = 'initializing';\n try {\n await adapter.initialize({\n container,\n blocks: blocks.list(),\n document: document ? readDocument(document) : null,\n onEvent: (type, payload) => {\n if (ticket !== generation) return;\n emitter.emit(type, type === 'selection' ? toEmailSelection(payload) : payload);\n },\n });\n } catch (error) {\n if (ticket === generation) status = 'idle';\n throw error;\n }\n // Destroyed while the engine was loading (React unmount, StrictMode):\n // the adapter is already released, nothing is declared ready.\n if (ticket !== generation) return;\n status = 'ready';\n startFeatures();\n emitter.emit('ready');\n },\n\n destroy() {\n generation += 1;\n stopFeatures();\n const etait = status;\n status = 'idle';\n adapter.destroy();\n if (etait === 'ready') emitter.emit('destroy');\n },\n\n listBlocks: () => blocks.list(),\n getBlock: (blockId) => blocks.get(blockId),\n\n addBlock(blockId, options = {}) {\n requireReady('addBlock');\n const block = blocks.get(blockId);\n if (!block || !block.mjml) throw new Error(`EmailEditor: unknown block \"${blockId}\"`);\n return adapter.addBlock(block, options);\n },\n\n remove(id = null) {\n requireReady('remove');\n return adapter.remove(targetOf(id, 'remove'));\n },\n\n duplicate(id = null) {\n requireReady('duplicate');\n return adapter.duplicate(targetOf(id, 'duplicate'));\n },\n\n move(direction, id = null) {\n requireReady('move');\n if (direction !== -1 && direction !== 1) throw new Error('EmailEditor: invalid move direction');\n return adapter.move(targetOf(id, 'move'), direction);\n },\n\n select(id) {\n requireReady('select');\n adapter.select(id);\n },\n\n getSelection() {\n return status === 'ready' ? toEmailSelection(adapter.getSelection()) : null;\n },\n\n getElement(id) {\n return status === 'ready' && id ? toEmailSelection(adapter.describe(id)) : null;\n },\n\n /** The email body: page background and width, edited without a selection. */\n getRootId: () => (status === 'ready' ? adapter.getRootId() : null),\n\n updateProperties(values, id = null) {\n requireReady('updateProperties');\n adapter.updateProperties(targetOf(id, 'updateProperties'), toAttributes(values));\n },\n\n setContent(content, id = null) {\n requireReady('setContent');\n adapter.setContent(targetOf(id, 'setContent'), content);\n },\n\n insertText(text) {\n requireReady('insertText');\n return adapter.insertText(String(text ?? ''));\n },\n\n /**\n * Link at the caret of the text being edited, at the end of the selected\n * text, or as the selected button's URL. False if nothing fits.\n */\n insertLink(href, label) {\n requireReady('insertLink');\n return adapter.insertLink(String(href || ''), String(label || href || ''));\n },\n\n undo() {\n requireReady('undo');\n adapter.undo();\n },\n redo() {\n requireReady('redo');\n adapter.redo();\n },\n canUndo: () => status === 'ready' && adapter.canUndo(),\n canRedo: () => status === 'ready' && adapter.canRedo(),\n\n getDocument() {\n requireReady('getDocument');\n return createDocument({\n engine: adapter.name,\n engineVersion: adapter.version,\n project: adapter.getProject(),\n });\n },\n\n loadDocument(raw) {\n requireReady('loadDocument');\n const document = readDocument(raw);\n if (document.engine !== adapter.name) {\n throw new Error(\n `EmailEditor: document written for engine \"${document.engine}\", ` +\n `editor runs on \"${adapter.name}\"`\n );\n }\n adapter.loadProject(document.project);\n // A reloaded document has no history: undo must not bring back the\n // state before the load.\n adapter.clearHistory();\n },\n\n loadMjml(mjml) {\n requireReady('loadMjml');\n adapter.loadMjml(String(mjml || ''));\n adapter.clearHistory();\n },\n\n exportMjml() {\n requireReady('exportMjml');\n return adapter.exportMjml();\n },\n\n exportHtml() {\n requireReady('exportHtml');\n return adapter.exportHtml();\n },\n\n setDevice(device) {\n requireReady('setDevice');\n if (!EMAIL_DEVICES.includes(device)) throw new Error(`EmailEditor: unknown device \"${device}\"`);\n adapter.setDevice(device);\n },\n\n getDevice: () => (status === 'ready' ? adapter.getDevice() : 'desktop'),\n\n startBlockDrag(blockId, event) {\n requireReady('startBlockDrag');\n const block = blocks.get(blockId);\n if (!block || !block.mjml) throw new Error(`EmailEditor: unknown block \"${blockId}\"`);\n adapter.startBlockDrag(block, event);\n },\n\n endBlockDrag(cancel = false) {\n if (status === 'ready') adapter.endBlockDrag(cancel);\n },\n\n /**\n * Keyboard shortcut that also works INSIDE the canvas (an iframe: page\n * listeners hear nothing there). `keys`: `mod+s` (Ctrl, or ⌘ on Mac),\n * several combinations separated by commas.\n */\n addShortcut(id, keys, handler) {\n requireReady('addShortcut');\n return adapter.addShortcut(id, keys, handler);\n },\n\n on: (event, listener) => emitter.on(event, listener),\n };\n\n return editor;\n}\n","// @ts-check\n/**\n * GrapesJS engine configuration — without any of its UI.\n *\n * The builder has ITS OWN React UI: GrapesJS only provides the canvas (the\n * iframe where you click and drag) and its data model. Hence:\n * - `customUI`, `panels.defaults: []` and `custom` managers: no panel, no\n * toolbar, no style or layer manager;\n * - `telemetry: false` and `cssIcons: ''`: no request to a third-party\n * service (GrapesJS stats, Font Awesome from a CDN);\n * - `storageManager: false`: saving is ours (`storage/`), never the\n * engine's `localStorage`;\n * - an HTML parser that rejects scripts and `on*` attributes: a reloaded\n * template must not be able to execute anything in the host page.\n */\n\n/** Canvas devices: ids = `EmailDevice`. */\nexport const DEVICES = [\n { id: 'desktop', name: 'desktop', width: '' },\n // `widthMedia`: MJML's mobile rule (480px) applies inside the frame.\n { id: 'mobile', name: 'mobile', width: '375px', widthMedia: '480px' },\n];\n\n/** Empty email: just the body, at the standard width. */\nexport const EMPTY_MJML =\n '<mjml><mj-body background-color=\"#eceff4\" width=\"600px\"></mj-body></mjml>';\n\n/**\n * Image WITHOUT A FILE, as shown in the canvas: a light grey 600 × 220 banner\n * with an icon. Replaces GrapesJS's default `src`, raw SVG markup whose quotes\n * and \";\" broke the attribute and the style string the MJML plugin reads back\n * (\"illegal transform attribute\"). This one is a `data:` URL with NO \";\" and\n * no double quote.\n *\n * It never leaves the adapter: `GrapesJsAdapter` turns it into \"no image\" in\n * the export, the project and the selection.\n */\nexport const IMAGE_PLACEHOLDER =\n \"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 220'%3E\" +\n \"%3Crect width='600' height='220' fill='%23f3f5f9'/%3E\" +\n \"%3Cg transform='translate(276 86)' fill='none' stroke='%238b93a3' stroke-width='2' \" +\n \"stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='1' y='1' width='46' height='46' rx='5'/%3E\" +\n \"%3Ccircle cx='17' cy='17' r='5'/%3E%3Cpath d='m47 31-8-8a4 4 0 0 0-6 0L5 47'/%3E%3C/g%3E%3C/svg%3E\";\n\n/**\n * Stylesheet injected INTO the canvas iframe: editing cues only, never\n * exported into the email.\n */\nconst CANVAS_CSS = `\n body { background: #eceff4; }\n [data-gjs-highlightable] { outline-offset: -1px; }\n *::selection { background: rgba(53, 104, 168, .22); }\n`;\n\n/**\n * @param {{\n * container: HTMLElement,\n * mjmlPlugin: any,\n * locales?: {engine?: any, mjml?: any},\n * locale?: string,\n * }} options\n */\nexport function buildEngineConfig({ container, mjmlPlugin, locales = {}, locale = 'en' }) {\n return {\n container,\n height: '100%',\n width: 'auto',\n telemetry: false,\n customUI: true,\n cssIcons: '',\n noticeOnUnload: false,\n storageManager: /** @type {false} */ (false),\n fromElement: false,\n showDevices: false,\n showOffsets: false,\n multipleSelection: false,\n avoidInlineStyle: true,\n log: /** @type {('warning'|'error')[]} */ (['error']),\n canvasCss: CANVAS_CSS,\n i18n: {\n locale,\n localeFallback: locale,\n detectLocale: false,\n messages: locales.engine ? { [locale]: locales.engine } : {},\n },\n panels: { defaults: [] },\n blockManager: { custom: true },\n layerManager: { custom: true },\n traitManager: { custom: true },\n selectorManager: { custom: true, componentFirst: true },\n styleManager: { custom: true },\n assetManager: { custom: true, upload: false },\n deviceManager: { devices: DEVICES, default: 'desktop' },\n undoManager: { trackSelection: false, maximumStackLength: 300 },\n // Canvas shortcuts: the ones users expect (undo, redo — Ctrl+Y included —,\n // copy, paste, delete), without GrapesJS's single-letter navigation\n // (\"s\", \"w\", \"a\", \"d\") that moved the selection on any keypress outside a\n // field.\n keymaps: {\n defaults: {\n 'core:undo': { keys: '⌘+z, ctrl+z', handler: 'core:undo', opts: { prevent: true } },\n 'core:redo': { keys: '⌘+shift+z, ctrl+shift+z, ctrl+y', handler: 'core:redo', opts: { prevent: true } },\n 'core:copy': { keys: '⌘+c, ctrl+c', handler: 'core:copy' },\n 'core:paste': { keys: '⌘+v, ctrl+v', handler: 'core:paste' },\n 'core:component-delete': { keys: 'backspace, delete', handler: 'core:component-delete', opts: { prevent: true } },\n },\n },\n parser: {\n optionsHtml: {\n allowScripts: false,\n allowUnsafeAttr: false,\n allowUnsafeAttrValue: false,\n },\n },\n plugins: [\n (/** @type {any} */ editor) =>\n mjmlPlugin(editor, {\n // No blocks, devices or style settings from the plugin: blocks and\n // properties come from `blocks/`.\n blocks: [],\n resetBlocks: true,\n resetDevices: false,\n resetStyleManager: false,\n hideSelector: true,\n useCustomTheme: false,\n overwriteExport: false,\n imagePlaceholderSrc: IMAGE_PLACEHOLDER,\n i18n: locales.mjml ? { [locale]: locales.mjml } : {},\n }),\n // After the plugin: the empty image gets our banner, not the raw SVG.\n (/** @type {any} */ editor) =>\n editor.Components.addType('mj-image', { model: { defaults: { src: IMAGE_PLACEHOLDER } } }),\n ],\n };\n}\n","// @ts-check\n/**\n * A dynamically imported module → the value it exports by default.\n *\n * `grapesjs-mjml` and its locales are CommonJS/UMD modules flagged\n * `__esModule`. How `import()` hands them over depends on the bundler:\n *\n * Vite, esbuild { default: value }\n * webpack (Next.js), from an { default: { __esModule: true, default: value } }\n * ES module package\n *\n * so a single `.default` returned an object instead of the plugin under\n * Next.js (\"mjmlPlugin is not a function\"). Every interop layer is peeled —\n * a module namespace or an `__esModule` object — never the value itself.\n *\n * @param {any} mod\n * @returns {any}\n */\nexport function unwrapModule(mod) {\n let value = mod;\n for (let depth = 0; depth < 3 && isInteropLayer(value); depth += 1) value = value.default;\n return value;\n}\n\n/** @param {any} value */\nfunction isInteropLayer(value) {\n if (value === null || typeof value !== 'object' || !('default' in value)) return false;\n return value.__esModule === true || Object.prototype.toString.call(value) === '[object Module]';\n}\n","// @ts-check\n/**\n * GRAPESJS ADAPTER — the only file of the builder that talks to the engine.\n *\n * It fulfils the `EmailEditorAdapter` contract (core/EmailEditor.js) with\n * GrapesJS and its MJML plugin. Everything leaving this folder is expressed in\n * the email's vocabulary (blocks, MJML attributes, opaque ids), never in the\n * engine's: that is what makes the engine replaceable.\n *\n * ── LOADING ────────────────────────────────────────────────────────────────\n * GrapesJS and the MJML plugin (1.2 MB, `mjml-browser` included) touch\n * `window` as soon as they are evaluated: they are imported dynamically, on\n * the first `initialize`, never during server-side rendering.\n *\n * ── BLOCK PLACEMENT ────────────────────────────────────────────────────────\n * MJML enforces its hierarchy: body → section → column → content. A content\n * block added by click therefore goes:\n * - INTO the selected column;\n * - AFTER the selected element, in the same column;\n * - otherwise into a NEW one-column section, after the selected section or\n * at the end of the body.\n * A layout (N-column section) goes after the current section, or at the end.\n * On drag and drop, the MJML plugin's rules decide where the element can land.\n */\n\nimport { buildEngineConfig, EMPTY_MJML, IMAGE_PLACEHOLDER } from './engineConfig.js';\nimport { unwrapModule } from './unwrapModule.js';\n\n/**\n * @typedef {import('../../core/EmailEditor.js').EmailEditorAdapter} EmailEditorAdapter\n * @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock\n * @typedef {import('../../core/EmailEditor.js').EngineSelection} EngineSelection\n * @typedef {import('../../core/constants.js').EmailDevice} EmailDevice\n */\n\nexport const ENGINE_NAME = 'grapesjs-mjml';\n/** Engine version, copied into every document (exact package.json version). */\nexport const ENGINE_VERSION = '0.22.16';\n\n/** Prefix of blocks registered with the engine — for drag and drop only. */\nconst BLOCK_PREFIX = 'eb-';\n\n/** Structural elements that cannot be removed, duplicated or moved. */\nconst LOCKED_TYPES = new Set(['mjml', 'mj-head', 'mj-body', 'wrapper']);\n\n/** Elements whose content is a plain label, edited in the panel. */\nconst LABEL_TYPES = new Set(['mj-button']);\n\n/** Elements whose content is edited in the canvas (rich text editor). */\nconst RICH_TYPES = new Set(['mj-text', 'mj-button']);\n\n/**\n * Engine labels visible in the canvas (element badge), per locale. Static\n * import paths so bundlers can see them; English needs none (engine default).\n *\n * @type {Record<string, () => Promise<any[]>>}\n */\nconst ENGINE_LOCALES = {\n fr: () => Promise.all([import('grapesjs/locale/fr.mjs'), import('grapesjs-mjml/locale/fr')]),\n};\n\n/**\n * Engine loading, injectable for tests. The canvas stylesheets (GrapesJS +\n * `engine-overrides.css`) ship in `best-email-builder/styles.css`.\n *\n * @param {string} locale\n */\nasync function defaultLoadEngine(locale) {\n const loadLocales = Object.prototype.hasOwnProperty.call(ENGINE_LOCALES, locale) ? ENGINE_LOCALES[locale] : null;\n const [grapesjs, mjml, localeModules] = await Promise.all([\n import('grapesjs'),\n import('grapesjs-mjml'),\n loadLocales ? loadLocales() : Promise.resolve(null),\n ]);\n return {\n grapesjs: unwrapModule(grapesjs),\n mjmlPlugin: unwrapModule(mjml),\n locales: localeModules\n ? { engine: unwrapModule(localeModules[0]), mjml: unwrapModule(localeModules[1]) }\n : {},\n };\n}\n\n/**\n * Empty image: the canvas shows it as a banner (`IMAGE_PLACEHOLDER`, see\n * engineConfig) that never crosses the adapter boundary — it becomes \"no\n * image\" (`''`) in the MJML, the project and the selection. GrapesJS's\n * original SVG icon is handled the same way, in case an old project still\n * carries it.\n */\nconst ENGINE_SVG = /^\\s*<svg[\\s>]/i;\nconst PLACEHOLDER_SRC_ATTR = new RegExp(\n `\\\\ssrc=\"(?:${IMAGE_PLACEHOLDER.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')}|\\\\s*<svg[\\\\s\\\\S]*?<\\\\/svg>\\\\s*)\"`,\n 'g'\n);\nconst PLACEHOLDER_SRC_STYLE = /src:\\s*<svg[\\s\\S]*?<\\/svg>;?/gi;\n\n/** @param {unknown} value */\nfunction isEnginePlaceholder(value) {\n return typeof value === 'string' && (value === IMAGE_PLACEHOLDER || ENGINE_SVG.test(value));\n}\n\n/**\n * Copy of the project without the engine's empty-image icon.\n * @param {any} node\n * @returns {any}\n */\nfunction withoutPlaceholders(node) {\n if (Array.isArray(node)) return node.map(withoutPlaceholders);\n if (!node || typeof node !== 'object') return node;\n /** @type {Record<string, any>} */\n const out = {};\n for (const [key, value] of Object.entries(node)) {\n if (key === 'src' && isEnginePlaceholder(value)) out[key] = '';\n else if (key === 'style' && typeof value === 'string') {\n out[key] = value.replace(PLACEHOLDER_SRC_STYLE, '').split(`src:${IMAGE_PLACEHOLDER};`).join('');\n } else out[key] = withoutPlaceholders(value);\n }\n return out;\n}\n\nfunction escapeHtml(text) {\n return String(text ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n}\n\n/**\n * Inserts HTML at the CARET of the text being edited, or returns false.\n *\n * ⚠️ `view.rte` is the editing MODULE (no `insertHTML`); the instance holding\n * the selection is `view.activeRte`. The content is then synced back into the\n * model (`syncContent`): otherwise the export would only see it once the user\n * leaves the text.\n */\nfunction insertAtCaret(ed, html) {\n const view = ed.getEditing()?.view;\n const rte = view?.activeRte;\n if (!view || typeof rte?.insertHTML !== 'function') return false;\n rte.insertHTML(html);\n view.onInput?.();\n void view.syncContent?.();\n return true;\n}\n\n/**\n * @param {{\n * locale?: string,\n * loadEngine?: (locale: string) => Promise<{grapesjs: any, mjmlPlugin: any, locales?: {engine?: any, mjml?: any}}>,\n * }} [options]\n * @returns {EmailEditorAdapter & {readonly engine: any}}\n */\nexport function createGrapesJsAdapter({ locale = 'en', loadEngine = defaultLoadEngine } = {}) {\n /** @type {any} */\n let editor = null;\n /** @type {HTMLElement|null} */\n let host = null;\n /** @type {(type: string, payload?: any) => void} */\n let emit = () => {};\n /** Token: a `destroy` during engine loading invalidates the init. */\n let generation = 0;\n let selectionQueued = false;\n /**\n * Load in progress: GrapesJS reports changes through a DEFERRED `update`\n * (setTimeout 0). The one from a load would arrive late and look like user\n * input — the template would show as \"modified\" right after opening. It is\n * muted until the event-loop turn after the load.\n */\n let loading = false;\n\n function muteUntilFlushed() {\n loading = true;\n setTimeout(() => {\n loading = false;\n }, 0);\n }\n\n /* ── Model helpers ───────────────────────────────────────────────────── */\n\n function requireEditor() {\n if (!editor) throw new Error('GrapesJsAdapter: engine not initialized');\n return editor;\n }\n\n /** @param {string} id */\n function byId(id) {\n const all = requireEditor().Components.allById();\n return all[id] || null;\n }\n\n /** @param {any} component */\n function typeOf(component) {\n return component ? String(component.get('type') || '') : '';\n }\n\n function body() {\n const ed = requireEditor();\n return ed.getWrapper().findType('mj-body')[0] || null;\n }\n\n /**\n * First ancestor (or self) of one of the given types.\n * @param {any} component @param {string[]} types\n */\n function closest(component, types) {\n let current = component;\n while (current) {\n if (types.includes(typeOf(current))) return current;\n current = current.parent();\n }\n return null;\n }\n\n /**\n * An element's MJML attributes, as the export will see them: `src` read\n * from the model (see MJML plugin), engine icon cleared.\n * @param {any} component\n * @returns {Record<string, string>}\n */\n function attributesOf(component) {\n /** @type {Record<string, string>} */\n const out = {};\n for (const [key, value] of Object.entries(component.getAttributes() || {})) {\n if (key === 'style' || key === 'id' || value === undefined || value === null) continue;\n out[key] = String(value);\n }\n if (component.get('src') !== undefined) out.src = String(component.get('src') || '');\n if (isEnginePlaceholder(out.src)) out.src = '';\n return out;\n }\n\n /** @param {any} component @returns {EngineSelection|null} */\n function describe(component) {\n if (!component) return null;\n const type = typeOf(component);\n const parent = component.parent();\n const index = parent ? parent.components().indexOf(component) : -1;\n const siblings = parent ? parent.components().length : 0;\n const locked = LOCKED_TYPES.has(type);\n return {\n id: component.getId(),\n tagName: type,\n attributes: attributesOf(component),\n content: LABEL_TYPES.has(type) ? textOf(component) : null,\n canRemove: !locked && component.get('removable') !== false,\n canDuplicate: !locked && component.get('copyable') !== false,\n canMoveUp: !locked && index > 0,\n canMoveDown: !locked && index >= 0 && index < siblings - 1,\n };\n }\n\n /** Plain text of an element (button label). @param {any} component */\n function textOf(component) {\n const html = component.getInnerHTML ? component.getInnerHTML() : '';\n return String(html)\n .replace(/<br\\s*\\/?>/gi, ' ')\n .replace(/<[^>]*>/g, '')\n .replace(/&nbsp;/g, ' ')\n .replace(/&lt;/g, '<')\n .replace(/&gt;/g, '>')\n .replace(/&amp;/g, '&')\n .trim();\n }\n\n function queueSelection() {\n if (selectionQueued) return;\n selectionQueued = true;\n queueMicrotask(() => {\n selectionQueued = false;\n if (editor) emit('selection', describe(editor.getSelected()));\n });\n }\n\n function emitHistory() {\n if (!editor) return;\n const um = editor.UndoManager;\n emit('history', { canUndo: um.hasUndo(), canRedo: um.hasRedo() });\n }\n\n /** @param {any} added */\n function firstOf(added) {\n return Array.isArray(added) ? added[0] : added;\n }\n\n /* ── Placement ───────────────────────────────────────────────────────── */\n\n /**\n * Where to put a block. Returns the target collection and index, or an\n * instruction to wrap the content in a new section.\n *\n * @param {EmailBlock} block @param {any} target\n */\n function placementFor(block, target) {\n const root = body();\n if (!root) throw new Error('GrapesJsAdapter: email body not found');\n\n const section = target ? closest(target, ['mj-section', 'mj-wrapper', 'mj-hero']) : null;\n const afterSection = () => {\n if (section && section.parent()) {\n const coll = section.parent().components();\n return { collection: coll, at: coll.indexOf(section) + 1, wrap: false };\n }\n return { collection: root.components(), at: root.components().length, wrap: false };\n };\n\n if (block.kind === 'layout') return afterSection();\n\n const type = typeOf(target);\n if (type === 'mj-column') {\n return { collection: target.components(), at: target.components().length, wrap: false };\n }\n const column = target ? closest(target, ['mj-column']) : null;\n if (column && target !== column) {\n // Walk up to the column's direct child: insert after it.\n let child = target;\n while (child.parent() && child.parent() !== column) child = child.parent();\n const coll = column.components();\n return { collection: coll, at: coll.indexOf(child) + 1, wrap: false };\n }\n return { ...afterSection(), wrap: true };\n }\n\n /* ── Contract ────────────────────────────────────────────────────────── */\n\n /** @type {EmailEditorAdapter & {readonly engine: any}} */\n const adapter = {\n name: ENGINE_NAME,\n version: ENGINE_VERSION,\n\n get engine() {\n return editor;\n },\n\n async initialize({ container, blocks: blockList, document, onEvent }) {\n if (editor) throw new Error('GrapesJsAdapter: already initialized');\n const ticket = ++generation;\n const { grapesjs, mjmlPlugin, locales } = await loadEngine(locale);\n if (ticket !== generation) return;\n\n emit = onEvent;\n host = createEngineHost(container);\n const instance = grapesjs.init(buildEngineConfig({ container: host, mjmlPlugin, locales, locale }));\n editor = instance;\n\n await new Promise((resolve) => instance.onReady(() => resolve(undefined)));\n if (ticket !== generation) return;\n\n // Blocks registered with the engine: only for its drag and drop\n // (`startBlockDrag`), never displayed by it.\n for (const block of blockList) {\n if (!block.mjml) continue;\n instance.Blocks.add(`${BLOCK_PREFIX}${block.id}`, {\n label: block.label,\n content: block.mjml,\n activate: true,\n select: true,\n });\n }\n\n muteUntilFlushed();\n if (document) instance.loadProjectData(document.project);\n else instance.setComponents(EMPTY_MJML);\n instance.UndoManager.clear();\n\n instance.on('update', () => {\n if (!loading) emit('change');\n emitHistory();\n });\n instance.on('undo', emitHistory);\n instance.on('redo', emitHistory);\n instance.on('component:toggled', queueSelection);\n instance.on('component:update', (/** @type {any} */ component) => {\n if (component && component === instance.getSelected()) queueSelection();\n });\n instance.on('change:device', () => emit('device', adapter.getDevice()));\n\n emitHistory();\n },\n\n destroy() {\n generation += 1;\n if (editor) {\n try {\n editor.destroy();\n } catch (error) {\n console.warn('[best-email-builder] engine destroy failed', error);\n }\n }\n editor = null;\n if (host?.parentNode) host.parentNode.removeChild(host);\n host = null;\n emit = () => {};\n },\n\n addBlock(block, { targetId = null } = {}) {\n const ed = requireEditor();\n if (!block.mjml) return null;\n const target = targetId ? byId(targetId) : ed.getSelected();\n const { collection, at, wrap } = placementFor(block, target);\n const source = wrap\n ? block.sectionMjml || `<mj-section><mj-column>${block.mjml}</mj-column></mj-section>`\n : block.mjml;\n const added = firstOf(collection.add(source, { at }));\n if (!added) return null;\n const focus = wrap ? added.findType(block.tagName)[0] || added : added;\n ed.select(focus);\n return focus.getId();\n },\n\n remove(id) {\n const component = byId(id);\n if (!component || LOCKED_TYPES.has(typeOf(component))) return false;\n if (component.get('removable') === false) return false;\n const ed = requireEditor();\n if (ed.getSelected() === component) ed.select(null);\n component.remove();\n return true;\n },\n\n duplicate(id) {\n const component = byId(id);\n if (!component || LOCKED_TYPES.has(typeOf(component)) || !component.parent()) return null;\n const collection = component.parent().components();\n const copy = firstOf(collection.add(component.clone(), { at: collection.indexOf(component) + 1 }));\n if (!copy) return null;\n requireEditor().select(copy);\n return copy.getId();\n },\n\n move(id, direction) {\n const component = byId(id);\n if (!component || LOCKED_TYPES.has(typeOf(component))) return false;\n const parent = component.parent();\n if (!parent) return false;\n const index = parent.components().indexOf(component);\n const to = index + direction;\n if (to < 0 || to >= parent.components().length) return false;\n // `at` is the position in the collection BEFORE the element is\n // removed: moving down must aim one step further.\n component.move(parent, { at: direction > 0 ? to + 1 : to });\n requireEditor().select(component);\n queueSelection();\n return true;\n },\n\n select(id) {\n const ed = requireEditor();\n ed.select(id ? byId(id) : null);\n },\n\n getSelection() {\n return editor ? describe(editor.getSelected()) : null;\n },\n\n describe(id) {\n return editor ? describe(byId(id)) : null;\n },\n\n getRootId() {\n return editor ? body()?.getId() || null : null;\n },\n\n updateProperties(id, attributes) {\n const component = byId(id);\n if (!component) return;\n /** @type {Record<string, string>} */\n const toSet = {};\n const toRemove = [];\n for (const [key, value] of Object.entries(attributes || {})) {\n // The image keeps its URL in the model (`src`), which the plugin\n // copies into the attributes: writing the attribute alone is undone.\n if (key === 'src' && component.get('src') !== undefined) {\n component.set('src', value || '');\n } else if (value === null || value === undefined || value === '') {\n toRemove.push(key);\n } else {\n toSet[key] = String(value);\n }\n }\n if (Object.keys(toSet).length) component.addAttributes(toSet);\n if (toRemove.length) {\n // The MJML plugin copies the style into the attributes: removing the\n // attribute alone would let it come back through the style.\n component.removeStyle?.(toRemove);\n component.removeAttributes(toRemove);\n }\n queueSelection();\n },\n\n setContent(id, content) {\n const component = byId(id);\n if (!component) return;\n if (LABEL_TYPES.has(typeOf(component))) {\n component.components(escapeHtml(content));\n } else if (RICH_TYPES.has(typeOf(component))) {\n component.components(String(content || ''));\n }\n queueSelection();\n },\n\n insertText(text) {\n const ed = requireEditor();\n if (insertAtCaret(ed, escapeHtml(text))) return true;\n const target = ed.getSelected();\n if (target && RICH_TYPES.has(typeOf(target))) {\n target.append({ type: 'textnode', content: ` ${text}` });\n queueSelection();\n return true;\n }\n return false;\n },\n\n insertLink(href, label) {\n const ed = requireEditor();\n const safeHref = escapeHtml(href).replace(/\"/g, '&quot;');\n const html = `<a href=\"${safeHref}\">${escapeHtml(label)}</a>`;\n if (insertAtCaret(ed, html)) return true;\n const target = ed.getSelected();\n if (target && typeOf(target) === 'mj-button') {\n target.addAttributes({ href });\n queueSelection();\n return true;\n }\n if (target && typeOf(target) === 'mj-text') {\n target.append(` ${html}`);\n queueSelection();\n return true;\n }\n return false;\n },\n\n undo() {\n requireEditor().UndoManager.undo();\n emitHistory();\n },\n redo() {\n requireEditor().UndoManager.redo();\n emitHistory();\n },\n canUndo: () => Boolean(editor?.UndoManager.hasUndo()),\n canRedo: () => Boolean(editor?.UndoManager.hasRedo()),\n clearHistory() {\n requireEditor().UndoManager.clear();\n emitHistory();\n },\n\n getProject() {\n return withoutPlaceholders(requireEditor().getProjectData());\n },\n\n loadProject(project) {\n const ed = requireEditor();\n ed.select(null);\n muteUntilFlushed();\n ed.loadProjectData(project);\n emit('load');\n queueSelection();\n },\n\n loadMjml(mjml) {\n const ed = requireEditor();\n ed.select(null);\n muteUntilFlushed();\n ed.setComponents(mjml || EMPTY_MJML);\n emit('load');\n queueSelection();\n },\n\n exportMjml() {\n return String(requireEditor().runCommand('mjml-code') || '')\n .replace(PLACEHOLDER_SRC_ATTR, '')\n .trim();\n },\n\n exportHtml() {\n const result = requireEditor().runCommand('mjml-code-to-html', { mjml: adapter.exportMjml() }) || {};\n return {\n html: String(result.html || ''),\n errors: (result.errors || []).map((/** @type {any} */ e) => ({\n line: e.line,\n message: String(e.formattedMessage || e.message || e),\n tagName: e.tagName,\n })),\n };\n },\n\n setDevice(device) {\n requireEditor().setDevice(device);\n },\n\n getDevice() {\n const name = editor?.getDevice?.();\n return name === 'mobile' ? 'mobile' : 'desktop';\n },\n\n startBlockDrag(block, event) {\n const ed = requireEditor();\n const engineBlock = ed.Blocks.get(`${BLOCK_PREFIX}${block.id}`);\n if (engineBlock) ed.Blocks.startDrag(engineBlock, event);\n },\n\n endBlockDrag(cancel = false) {\n editor?.Blocks.endDrag(cancel);\n },\n\n addShortcut(id, keys, handler) {\n const ed = requireEditor();\n const keymapId = `eb:${id}`;\n // `mod` = ⌘ on Mac, Ctrl elsewhere: both are registered.\n const engineKeys = keys\n .split(',')\n .map((k) => k.trim())\n .flatMap((k) => (k.startsWith('mod+') ? [`⌘+${k.slice(4)}`, `ctrl+${k.slice(4)}`] : [k]))\n .join(', ');\n ed.Keymaps.add(keymapId, engineKeys, () => handler(), { prevent: true });\n return () => {\n if (editor === ed) ed.Keymaps.remove(keymapId);\n };\n },\n };\n\n return adapter;\n}\n\n/**\n * GrapesJS empties and fills its container: it gets its own, a child of ours,\n * so React stays the sole owner of the node it rendered.\n *\n * @param {HTMLElement} container\n */\nfunction createEngineHost(container) {\n const el = container.ownerDocument.createElement('div');\n el.className = 'eb-engine-host';\n el.style.height = '100%';\n container.appendChild(el);\n return el;\n}\n","// @ts-check\n/**\n * Generic registry — used for blocks (`emailBlocks`) and features\n * (`emailBuilderFeatures`).\n *\n * Removing an entry from the registry is enough to remove it from the builder:\n * neither the core nor the adapter knows a block or feature by name. That is\n * what lets a piece be disabled without touching anything else.\n */\n\n/**\n * @template {{id: string, order?: number}} T\n * @typedef {{\n * kind: string,\n * register: (item: T) => () => void,\n * unregister: (id: string) => boolean,\n * get: (id: string) => T | undefined,\n * has: (id: string) => boolean,\n * list: (filter?: (item: T) => boolean) => T[],\n * ids: () => string[],\n * }} Registry\n */\n\nconst ID_SHAPE = /^[a-z][a-z0-9-]*$/;\n\n/**\n * @template {{id: string, order?: number}} T\n * @param {string} kind registry name, for error messages\n * @param {T[]} [initial]\n * @returns {Registry<T>}\n */\nexport function createRegistry(kind, initial = []) {\n /** @type {Map<string, T>} */\n const items = new Map();\n\n /** @param {string} id */\n function unregister(id) {\n return items.delete(id);\n }\n\n /** @param {T} item */\n function register(item) {\n if (!item || typeof item.id !== 'string' || !ID_SHAPE.test(item.id)) {\n throw new Error(`${kind}: invalid id (\"${item?.id}\")`);\n }\n if (items.has(item.id)) {\n throw new Error(`${kind}: \"${item.id}\" is already registered`);\n }\n items.set(item.id, item);\n return () => {\n unregister(item.id);\n };\n }\n\n initial.forEach(register);\n\n return {\n kind,\n register,\n unregister,\n get: (id) => items.get(id),\n has: (id) => items.has(id),\n // Stable sort: `order` first, then registration order.\n list: (filter) =>\n [...items.values()]\n .map((item, index) => ({ item, index }))\n .sort((a, b) => (a.item.order ?? 1000) - (b.item.order ?? 1000) || a.index - b.index)\n .map(({ item }) => item)\n .filter((item) => (filter ? filter(item) : true)),\n ids: () => [...items.keys()],\n };\n}\n","// @ts-check\n/**\n * Building blocks shared by all blocks: palette, fonts, recurring properties.\n *\n * -- DEFAULT PALETTE ---------------------------------------------------------\n * Plain hex values: email clients load no stylesheet and understand neither\n * `var()` nor modern color functions, so every value ends up inline in a\n * `style=\"\"` attribute.\n *\n * -- EVERY BLOCK SETS ITS OWN TEXT ATTRIBUTES --------------------------------\n * Font, size, line height and color are written on the element itself, never\n * left to MJML defaults (the \"Ubuntu\" font loaded from Google, line height 1):\n * the canvas and the sent email then render the same thing, and Outlook gets\n * explicit values.\n *\n * Fonts: only web-safe stacks, installed everywhere and understood by\n * Outlook - a web font only renders in a minority of email clients.\n */\n\n/** @typedef {import('../core/EmailEditor.js').BlockProperty} BlockProperty */\n\n/** The default palette. */\nexport const PALETTE = {\n ink: '#2b3038',\n inkSoft: '#41506b',\n navy: '#212e5a',\n brand: '#2977bc',\n border: '#dfe6f0',\n canvas: '#eceff4',\n surface: '#ffffff',\n white: '#ffffff',\n};\n\n/** Default link of a new button. */\nexport const DEFAULT_BUTTON_URL = 'https://example.com';\n\nexport const FONT_STACK = 'Arial, Helvetica, sans-serif';\n\n/** @type {{value: string, label: string}[]} */\nexport const FONT_OPTIONS = [\n { value: 'Arial, Helvetica, sans-serif', label: 'Arial' },\n { value: 'Verdana, Geneva, sans-serif', label: 'Verdana' },\n { value: 'Tahoma, Geneva, sans-serif', label: 'Tahoma' },\n { value: \"'Trebuchet MS', Helvetica, sans-serif\", label: 'Trebuchet' },\n { value: 'Georgia, Times, serif', label: 'Georgia' },\n { value: \"'Times New Roman', Times, serif\", label: 'Times' },\n { value: \"'Courier New', Courier, monospace\", label: 'Courier' },\n];\n\n/** @type {{value: string, label: string}[]} */\nexport const ALIGN_OPTIONS = [\n { value: 'left', label: 'Left' },\n { value: 'center', label: 'Center' },\n { value: 'right', label: 'Right' },\n];\n\n/** Properties panel groups, in display order. */\nexport const GROUPS = {\n content: 'Content',\n link: 'Link',\n typography: 'Typography',\n colors: 'Colors',\n layout: 'Layout',\n spacing: 'Spacing',\n};\n\n/** Recurring properties. */\nexport const prop = {\n /** @returns {BlockProperty} */\n fontFamily: () => ({ key: 'font-family', label: 'Font', type: 'select', group: GROUPS.typography, options: FONT_OPTIONS }),\n /** @returns {BlockProperty} */\n fontSize: (min = 10, max = 48) => ({ key: 'font-size', label: 'Size', type: 'size', group: GROUPS.typography, min, max, unit: 'px' }),\n /** @returns {BlockProperty} */\n lineHeight: () => ({ key: 'line-height', label: 'Line height', type: 'size', group: GROUPS.typography, min: 10, max: 80, unit: 'px' }),\n /** @returns {BlockProperty} */\n color: (label = 'Text') => ({ key: 'color', label, type: 'color', group: GROUPS.colors }),\n /** @returns {BlockProperty} */\n background: (key = 'background-color', label = 'Background') => ({ key, label, type: 'color', group: GROUPS.colors }),\n /** @returns {BlockProperty} */\n align: (options = ALIGN_OPTIONS) => ({ key: 'align', label: 'Alignment', type: 'align', group: GROUPS.layout, options }),\n /** @returns {BlockProperty} */\n padding: (key = 'padding', label = 'Padding') => ({ key, label, type: 'spacing', group: GROUPS.spacing }),\n /** @returns {BlockProperty} */\n href: (label = 'Link URL') => ({ key: 'href', label, type: 'url', group: GROUPS.link, placeholder: 'https://' }),\n /** @returns {BlockProperty} */\n radius: (max = 40) => ({ key: 'border-radius', label: 'Corner radius', type: 'size', group: GROUPS.layout, min: 0, max, unit: 'px' }),\n};\n\n/**\n * White one-column section: the wrapper of a content block dropped outside\n * any column (MJML does not accept text directly inside the body).\n *\n * Warning: padding in LONGHAND form, never `padding=\"...\"`. The canvas starts\n * from the longhand defaults (20 px for a section), which override the\n * shorthand, while the export omits them - the screen and the email would\n * diverge (see core/mjmlAttributes).\n *\n * @param {string} inner\n */\nexport function inWhiteSection(inner) {\n return (\n `<mj-section background-color=\"${PALETTE.surface}\" padding-top=\"0px\" padding-bottom=\"0px\">` +\n `<mj-column>${inner}</mj-column></mj-section>`\n );\n}\n","// @ts-check\n/**\n * STRUCTURE - body, section, column.\n *\n * These are not blocks you add (no `mjml`): they are the containers you\n * SELECT, whose background and padding are set in the right-hand panel. The\n * N-column layouts (`blocks/columns`) create sections; once added, this\n * definition describes them.\n */\n\nimport { GROUPS, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @type {EmailBlock} */\nexport const bodyBlock = {\n id: 'body',\n label: 'Email',\n icon: 'Mail',\n kind: 'structure',\n tagName: 'mj-body',\n order: 900,\n properties: [\n prop.background('background-color', 'Page background'),\n {\n key: 'width',\n label: 'Content width',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: '600px', label: '600 px (standard)' },\n { value: '640px', label: '640 px' },\n ],\n },\n ],\n};\n\n/** @type {EmailBlock} */\nexport const sectionBlock = {\n id: 'section',\n label: 'Section',\n icon: 'Rows3',\n kind: 'structure',\n tagName: 'mj-section',\n order: 901,\n properties: [\n prop.background('background-color', 'Background'),\n prop.padding('padding', 'Padding'),\n prop.radius(24),\n ],\n};\n\n/** @type {EmailBlock} */\nexport const columnBlock = {\n id: 'column',\n label: 'Column',\n icon: 'Columns2',\n kind: 'structure',\n tagName: 'mj-column',\n order: 902,\n properties: [\n prop.background('background-color', 'Background'),\n prop.padding('padding', 'Padding'),\n {\n key: 'vertical-align',\n label: 'Vertical alignment',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: 'top', label: 'Top' },\n { value: 'middle', label: 'Middle' },\n { value: 'bottom', label: 'Bottom' },\n ],\n },\n ],\n};\n","// @ts-check\n/**\n * TEXT - `mj-text`.\n *\n * Content is typed in the canvas (double-click: bold, italic, link); the panel\n * only controls the styling. Defaults are readable on mobile: 15 px on a 24 px\n * line height, ink #2b3038 (never pure black, which \"vibrates\" on phone\n * screens).\n */\n\nimport { FONT_STACK, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/**\n * A text with the block's settings. Also used by the column layouts, which\n * pre-fill each column.\n *\n * @param {string} content Already-safe HTML (fixed builder text)\n */\nexport function textMjml(content) {\n return (\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"15px\" line-height=\"24px\" color=\"${PALETTE.ink}\" ` +\n `align=\"left\">${content}</mj-text>`\n );\n}\n\nconst MJML = textMjml('Your text.');\n\n/** @type {EmailBlock} */\nexport const textBlock = {\n id: 'text',\n label: 'Text',\n description: 'Paragraph or heading',\n icon: 'Type',\n kind: 'content',\n tagName: 'mj-text',\n order: 10,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n editableContent: true,\n properties: [\n prop.fontFamily(),\n prop.fontSize(10, 48),\n prop.lineHeight(),\n prop.color('Text'),\n prop.background('container-background-color', 'Background'),\n { ...prop.align(), options: [...prop.align().options || [], { value: 'justify', label: 'Justify' }] },\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * IMAGE - `mj-image`.\n *\n * Added WITHOUT a file: the canvas shows a frame to fill, and the panel (file\n * upload or https URL) completes it. A sample image from a third-party service\n * would, one day, end up in a real send.\n *\n * Width is left to MJML (the full column, shrunk on mobile): a fixed width\n * larger than the column would overflow in Outlook.\n *\n * The alt text is not decorative: Outlook blocks images by default, and the\n * recipient reads the alt text in their place.\n */\n\nimport { GROUPS, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML = '<mj-image align=\"center\"></mj-image>';\n\n/** @type {EmailBlock} */\nexport const imageBlock = {\n id: 'image',\n label: 'Image',\n description: 'Photo, visual or logo',\n icon: 'Image',\n kind: 'content',\n tagName: 'mj-image',\n order: 20,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [\n { key: 'src', label: 'Image', type: 'image', group: GROUPS.content },\n {\n key: 'alt',\n label: 'Alt text',\n type: 'text',\n group: GROUPS.content,\n placeholder: 'Describes the image if it is blocked',\n },\n prop.href('Link on click'),\n { key: 'width', label: 'Width', type: 'size', group: GROUPS.layout, min: 20, max: 600, unit: 'px' },\n prop.align(),\n prop.radius(40),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * BUTTON - `mj-button`.\n *\n * MJML renders it as a table (not a styled `<a>`), which keeps it clickable\n * and at its size in Outlook. The default link is `DEFAULT_BUTTON_URL`.\n *\n * Defaults: navy background, bold white text, generous click area\n * (12 x 28 px) - a button that is too small is easy to miss with a finger.\n */\n\nimport { DEFAULT_BUTTON_URL, FONT_STACK, GROUPS, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML =\n `<mj-button href=\"${DEFAULT_BUTTON_URL}\" background-color=\"${PALETTE.navy}\" color=\"${PALETTE.white}\" ` +\n `font-family=\"${FONT_STACK}\" font-size=\"15px\" font-weight=\"bold\" border-radius=\"6px\" ` +\n 'inner-padding=\"12px 28px\" align=\"center\">Learn more</mj-button>';\n\n/** @type {EmailBlock} */\nexport const buttonBlock = {\n id: 'button',\n label: 'Button',\n description: 'Call to action',\n icon: 'RectangleHorizontal',\n kind: 'content',\n tagName: 'mj-button',\n order: 30,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n editableContent: true,\n properties: [\n prop.href('Link URL'),\n prop.background('background-color', 'Button background'),\n prop.color('Text'),\n prop.fontFamily(),\n prop.fontSize(11, 28),\n {\n key: 'font-weight',\n label: 'Weight',\n type: 'select',\n group: GROUPS.typography,\n options: [\n { value: 'bold', label: 'Bold' },\n { value: 'normal', label: 'Normal' },\n ],\n },\n prop.radius(30),\n {\n key: 'width',\n label: 'Width',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: '', label: 'Fit to text' },\n { value: '100%', label: 'Full width' },\n ],\n },\n prop.align(),\n prop.padding('inner-padding', 'Button padding'),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * DIVIDER - `mj-divider`.\n *\n * A thin rule in the default border color. MJML renders it as a `<p>` border\n * backed by a table for Outlook: it keeps its thickness everywhere, whereas an\n * `<hr>` varies from one email client to another.\n */\n\nimport { GROUPS, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML = `<mj-divider border-color=\"${PALETTE.border}\" border-width=\"1px\"></mj-divider>`;\n\n/** @type {EmailBlock} */\nexport const dividerBlock = {\n id: 'divider',\n label: 'Divider',\n description: 'Horizontal rule',\n icon: 'SeparatorHorizontal',\n kind: 'content',\n tagName: 'mj-divider',\n order: 40,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [\n prop.background('border-color', 'Line color'),\n { key: 'border-width', label: 'Thickness', type: 'size', group: GROUPS.layout, min: 1, max: 10, unit: 'px' },\n {\n key: 'border-style',\n label: 'Line style',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: 'solid', label: 'Solid' },\n { value: 'dashed', label: 'Dashed' },\n { value: 'dotted', label: 'Dotted' },\n ],\n },\n {\n key: 'width',\n label: 'Length',\n type: 'select',\n group: GROUPS.layout,\n options: [\n { value: '100%', label: 'Full length' },\n { value: '75%', label: '75%' },\n { value: '50%', label: '50%' },\n { value: '25%', label: '25%' },\n ],\n },\n prop.align(),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * SPACER - `mj-spacer`.\n *\n * Fixed-height empty space. MJML renders it as a `<div>` with an explicit line\n * height (`mso-line-height-rule: exactly`): Outlook, which ignores margins,\n * honors it.\n */\n\nimport { GROUPS, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML = '<mj-spacer height=\"24px\"></mj-spacer>';\n\n/** @type {EmailBlock} */\nexport const spacerBlock = {\n id: 'spacer',\n label: 'Spacer',\n description: 'Vertical space',\n icon: 'MoveVertical',\n kind: 'content',\n tagName: 'mj-spacer',\n order: 50,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [\n { key: 'height', label: 'Height', type: 'size', group: GROUPS.layout, min: 4, max: 200, unit: 'px' },\n prop.background('container-background-color', 'Background'),\n ],\n};\n","// @ts-check\n/**\n * LAYOUTS - 1, 2 or 3 column sections (`mj-section` + `mj-column`).\n *\n * Each column is pre-filled with text: an empty column only offers a strip a\n * few pixels high to drop a block into. On mobile (under 480 px), MJML stacks\n * the columns on top of each other - nothing to configure.\n *\n * Once added, the section is described by the \"section\" structure\n * (`blocks/structure`): background, padding, corner radius.\n */\n\nimport { PALETTE } from '../shared.js';\nimport { textMjml } from '../text/index.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @param {number} count */\nfunction sectionWith(count) {\n const columns = Array.from({ length: count }, (_, i) =>\n `<mj-column>${textMjml(count === 1 ? 'Your text.' : `Column ${i + 1}`)}</mj-column>`\n ).join('');\n return `<mj-section background-color=\"${PALETTE.surface}\">${columns}</mj-section>`;\n}\n\n/**\n * @param {number} count\n * @param {string} icon\n * @returns {EmailBlock}\n */\nfunction layout(count, icon) {\n return {\n id: `columns-${count}`,\n label: count === 1 ? '1 column' : `${count} columns`,\n description: count === 1 ? 'Full-width section' : `${count}-column section`,\n icon,\n kind: 'layout',\n tagName: 'mj-section',\n order: 100 + count,\n mjml: sectionWith(count),\n properties: [],\n };\n}\n\nexport const oneColumnBlock = layout(1, 'Square');\nexport const twoColumnsBlock = layout(2, 'Columns2');\nexport const threeColumnsBlock = layout(3, 'Columns3');\n","// @ts-check\n/**\n * BLOCK REGISTRY - `emailBlocks`.\n *\n * Each block lives in its own folder and depends only on the core. Removing a\n * line below removes the block from the sidebar, the properties panel and\n * drag and drop, without changing anything else.\n */\n\nimport { createRegistry } from '../core/registry.js';\nimport { bodyBlock, columnBlock, sectionBlock } from './structure/index.js';\nimport { textBlock } from './text/index.js';\nimport { imageBlock } from './image/index.js';\nimport { buttonBlock } from './button/index.js';\nimport { dividerBlock } from './divider/index.js';\nimport { spacerBlock } from './spacer/index.js';\nimport { oneColumnBlock, threeColumnsBlock, twoColumnsBlock } from './columns/index.js';\n\n/** @typedef {import('../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @type {EmailBlock[]} */\nconst BLOCKS = [\n textBlock,\n imageBlock,\n buttonBlock,\n dividerBlock,\n spacerBlock,\n oneColumnBlock,\n twoColumnsBlock,\n threeColumnsBlock,\n bodyBlock,\n sectionBlock,\n columnBlock,\n];\n\nexport const emailBlocks = createRegistry('emailBlocks', BLOCKS);\n","// @ts-check\n/**\n * AUTOSAVE feature.\n *\n * template already saved → server save WITHOUT a new version, 20 s after\n * the last change (at most 2 min after the first one);\n * template never saved → local draft (`localDraft.js`), offered the next\n * time a new template is opened.\n *\n * The screen reads `options`; removing this entry from the registry turns both\n * off.\n */\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature & {options: {idleMs: number, maxWaitMs: number, draftDelayMs: number}}} */\nexport const autosaveFeature = {\n id: 'autosave',\n label: 'Autosave',\n order: 20,\n options: { idleMs: 20_000, maxWaitMs: 120_000, draftDelayMs: 1_500 },\n};\n","import { useState } from 'react';\nimport { History } from 'lucide-react';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/primitives/overlays.jsx';\nimport { Skeleton } from '../../ui/primitives/misc.jsx';\nimport { useUi } from '../../ui/context.jsx';\n\n/**\n * VERSIONS of a template — toolbar button.\n *\n * Every explicit \"Save\" creates a version (autosave never does). Restoring\n * RELOADS the version into the editor without writing anything: the next save\n * makes it current, by creating one more version. History is never rewritten.\n */\n\nfunction formatWhen(value, locale) {\n if (!value) return '';\n const d = new Date(value);\n return Number.isNaN(d.getTime())\n ? ''\n : d.toLocaleString(locale, { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });\n}\n\nexport default function VersionsMenu({ context }) {\n const { editor, storage, template, isDirty, markDirty, ready } = context;\n const { t, confirm, notify, locale } = useUi();\n const [open, setOpen] = useState(false);\n const [versions, setVersions] = useState(null);\n const [error, setError] = useState(null);\n const [restoring, setRestoring] = useState(null);\n\n const load = async () => {\n setVersions(null);\n setError(null);\n try {\n setVersions(await storage.listVersions(template.id));\n } catch (e) {\n setError(e.message);\n }\n };\n\n const restore = async (version) => {\n if (isDirty()) {\n const ok = await confirm({\n title: t('Restore version {n}?', { n: version.versionNumber }),\n description: t('Unsaved changes will be replaced.'),\n confirmLabel: t('Restore'),\n destructive: true,\n });\n if (!ok) return;\n }\n setRestoring(version.id);\n try {\n const full = await storage.getVersion(template.id, version.id);\n editor.loadDocument(full.document);\n markDirty();\n setOpen(false);\n notify('success', t('Version {n} restored — save to keep it.', { n: version.versionNumber }));\n } catch (e) {\n notify('error', e.message);\n } finally {\n setRestoring(null);\n }\n };\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (next) load();\n }}\n >\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready || !template.id}\n title={!template.id ? t('Save the template first') : undefined}\n >\n <History />\n {t('Versions')}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"eb:w-80 eb:p-0\">\n <div className=\"eb:border-b eb:border-border eb:px-3 eb:py-2.5 eb:text-[13px] eb:font-medium eb:text-foreground\">\n {t('Versions')}\n </div>\n <div className=\"eb:max-h-[320px] eb:overflow-y-auto eb:p-1\" aria-busy={versions === null && !error}>\n {error ? (\n <p role=\"alert\" className=\"eb:px-2 eb:py-1.5 eb:text-[12px] eb:text-destructive\">\n {error}\n </p>\n ) : versions === null ? (\n <div className=\"eb:space-y-1 eb:p-1\" aria-hidden=\"true\">\n <Skeleton className=\"eb:h-8 eb:w-40\" />\n <Skeleton className=\"eb:h-8 eb:w-32\" />\n <Skeleton className=\"eb:h-8 eb:w-36\" />\n </div>\n ) : versions.length === 0 ? (\n <p className=\"eb:px-2 eb:py-1.5 eb:text-[12px] eb:text-foreground-muted\">{t('No versions yet.')}</p>\n ) : (\n versions.map((version, index) => (\n <div\n key={version.id}\n className=\"eb:flex eb:items-center eb:gap-2 eb:rounded-lg2 eb:px-2 eb:py-1.5 eb:hover:bg-surface-100\"\n >\n <div className=\"eb:min-w-0 eb:flex-1\">\n <p className=\"eb:text-[13px] eb:text-foreground\">\n {t('Version {n}', { n: version.versionNumber })}\n {index === 0 && <span className=\"eb:ml-1.5 eb:text-[11px] eb:text-foreground-muted\">{t('current')}</span>}\n </p>\n <p className=\"eb:text-[11px] eb:tabular-nums eb:text-foreground-muted\">\n {formatWhen(version.createdAt, locale)}\n {version.createdBy ? ` · ${version.createdBy}` : ''}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n disabled={restoring !== null}\n onClick={() => restore(version)}\n aria-label={t('Restore version {n}', { n: version.versionNumber })}\n >\n {t('Restore')}\n </Button>\n </div>\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n","import { Slot } from 'radix-ui';\nimport { cva } from 'class-variance-authority';\nimport { cn } from './cn.js';\n\nexport const buttonVariants = cva(\n \"eb:inline-flex eb:shrink-0 eb:items-center eb:justify-center eb:gap-2 eb:whitespace-nowrap eb:rounded-lg2 eb:text-sm eb:font-medium eb:transition-all eb:outline-none eb:disabled:pointer-events-none eb:disabled:opacity-50 eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: 'eb:bg-primary eb:text-primary-foreground eb:hover:bg-primary/90',\n destructive: 'eb:bg-destructive eb:text-white eb:hover:bg-destructive/90 eb:focus-visible:ring-destructive/20',\n outline: 'eb:border eb:border-border eb:bg-background eb:text-foreground eb:shadow-xs eb:hover:bg-accent eb:hover:text-accent-foreground',\n secondary: 'eb:bg-secondary eb:text-secondary-foreground eb:hover:bg-secondary/80',\n ghost: 'eb:text-foreground eb:hover:bg-accent eb:hover:text-accent-foreground',\n link: 'eb:text-primary eb:underline-offset-4 eb:hover:underline',\n },\n size: {\n default: 'eb:h-8 eb:gap-1.5 eb:px-3 eb:text-[13px] eb:has-[>svg]:px-2.5',\n xs: \"eb:h-6 eb:gap-1 eb:px-2 eb:text-xs eb:has-[>svg]:px-1.5 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'sm-compact': \"eb:h-7 eb:gap-1.5 eb:px-3 eb:text-xs eb:has-[>svg]:px-2.5 eb:[&_svg:not([class*='size-'])]:size-3\",\n sm: 'eb:h-8 eb:gap-1.5 eb:px-3 eb:text-[13px] eb:has-[>svg]:px-2.5',\n lg: 'eb:h-10 eb:px-6 eb:has-[>svg]:px-4',\n icon: 'eb:size-8',\n 'icon-xs': \"eb:size-6 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm-compact': \"eb:size-7 eb:[&_svg:not([class*='size-'])]:size-3\",\n 'icon-sm': 'eb:size-8',\n },\n },\n defaultVariants: { variant: 'default', size: 'default' },\n }\n);\n\nexport function Button({ className, variant = 'default', size = 'default', asChild = false, type, ...props }) {\n const Comp = asChild ? Slot.Root : 'button';\n return (\n <Comp\n data-slot=\"button\"\n type={asChild ? type : type || 'button'}\n className={cn(buttonVariants({ variant, size }), className)}\n {...props}\n />\n );\n}\n","import { clsx } from 'clsx';\nimport { extendTailwindMerge } from 'tailwind-merge';\n\n// Every utility class of the package carries the `eb:` prefix (see src/styles.css),\n// so class merging has to know about it.\nconst twMerge = extendTailwindMerge({ prefix: 'eb' });\n\n/** Joins class names and resolves conflicting utilities (the last one wins). */\nexport function cn(...inputs) {\n return twMerge(clsx(inputs));\n}\n","import {\n AlertDialog as AlertDialogPrimitive,\n Dialog as DialogPrimitive,\n DropdownMenu as DropdownMenuPrimitive,\n Popover as PopoverPrimitive,\n Select as SelectPrimitive,\n} from 'radix-ui';\nimport { CheckIcon, ChevronDownIcon, XIcon } from 'lucide-react';\nimport { useT } from '../context.jsx';\nimport { cn } from './cn.js';\n\n/*\n * Overlays render in a portal, outside the builder's root element: each one\n * carries the `eb-scope` class so the package's base styles reach it.\n */\n\nconst FADE_ZOOM =\n 'eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=open]:zoom-in-95 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0 eb:data-[state=closed]:zoom-out-95';\n\n/* ── Dialog ───────────────────────────────────────────────────────────── */\n\nexport function Dialog(props) {\n return <DialogPrimitive.Root data-slot=\"dialog\" {...props} />;\n}\n\nexport function DialogContent({ className, children, showCloseButton = true, ...props }) {\n const t = useT();\n return (\n <DialogPrimitive.Portal>\n <DialogPrimitive.Overlay className=\"eb-scope eb:fixed eb:inset-0 eb:z-50 eb:bg-black/50 eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0\" />\n <DialogPrimitive.Content\n data-slot=\"dialog-content\"\n className={cn(\n 'eb-scope eb:fixed eb:top-[50%] eb:left-[50%] eb:z-50 eb:grid eb:w-full eb:max-w-[calc(100%-2rem)] eb:translate-x-[-50%] eb:translate-y-[-50%] eb:gap-4 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-6 eb:text-foreground eb:shadow-lg eb:duration-200 eb:outline-none eb:sm:max-w-lg',\n FADE_ZOOM,\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <DialogPrimitive.Close className=\"eb:absolute eb:top-4 eb:right-4 eb:rounded-xs eb:opacity-70 eb:transition-opacity eb:hover:opacity-100 eb:focus:ring-2 eb:focus:ring-ring eb:focus:ring-offset-2 eb:focus:outline-hidden eb:disabled:pointer-events-none eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\">\n <XIcon />\n <span className=\"eb:sr-only\">{t('Close')}</span>\n </DialogPrimitive.Close>\n )}\n </DialogPrimitive.Content>\n </DialogPrimitive.Portal>\n );\n}\n\nexport function DialogHeader({ className, ...props }) {\n return <div className={cn('eb:flex eb:flex-col eb:gap-2 eb:text-left', className)} {...props} />;\n}\n\nexport function DialogFooter({ className, ...props }) {\n return <div className={cn('eb:flex eb:flex-col-reverse eb:gap-2 eb:sm:flex-row eb:sm:justify-end', className)} {...props} />;\n}\n\nexport function DialogTitle({ className, ...props }) {\n return <DialogPrimitive.Title className={cn('eb:text-lg eb:leading-none eb:font-semibold', className)} {...props} />;\n}\n\nexport function DialogDescription({ className, ...props }) {\n return <DialogPrimitive.Description className={cn('eb:text-sm eb:text-muted-foreground', className)} {...props} />;\n}\n\n/* ── Alert dialog (confirmations) ─────────────────────────────────────── */\n\nexport function AlertDialog(props) {\n return <AlertDialogPrimitive.Root {...props} />;\n}\n\nexport function AlertDialogContent({ className, ...props }) {\n return (\n <AlertDialogPrimitive.Portal>\n <AlertDialogPrimitive.Overlay className=\"eb-scope eb:fixed eb:inset-0 eb:z-50 eb:bg-black/50 eb:data-[state=open]:animate-in eb:data-[state=open]:fade-in-0 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0\" />\n <AlertDialogPrimitive.Content\n className={cn(\n 'eb-scope eb:fixed eb:top-[50%] eb:left-[50%] eb:z-50 eb:grid eb:w-full eb:max-w-[calc(100%-2rem)] eb:translate-x-[-50%] eb:translate-y-[-50%] eb:gap-4 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-6 eb:text-foreground eb:shadow-lg eb:duration-200 eb:sm:max-w-lg',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </AlertDialogPrimitive.Portal>\n );\n}\n\nexport const AlertDialogTitle = ({ className, ...props }) => (\n <AlertDialogPrimitive.Title className={cn('eb:text-lg eb:font-semibold', className)} {...props} />\n);\nexport const AlertDialogDescription = ({ className, ...props }) => (\n <AlertDialogPrimitive.Description className={cn('eb:text-sm eb:text-muted-foreground', className)} {...props} />\n);\nexport const AlertDialogAction = AlertDialogPrimitive.Action;\nexport const AlertDialogCancel = AlertDialogPrimitive.Cancel;\n\n/* ── Popover ──────────────────────────────────────────────────────────── */\n\nexport function Popover(props) {\n return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nexport function PopoverTrigger(props) {\n return <PopoverPrimitive.Trigger data-slot=\"popover-trigger\" {...props} />;\n}\n\nexport function PopoverContent({ className, align = 'center', sideOffset = 4, ...props }) {\n return (\n <PopoverPrimitive.Portal>\n <PopoverPrimitive.Content\n data-slot=\"popover-content\"\n align={align}\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:w-72 eb:origin-(--radix-popover-content-transform-origin) eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:p-4 eb:text-popover-foreground eb:shadow-md eb:outline-hidden',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </PopoverPrimitive.Portal>\n );\n}\n\n/* ── Dropdown menu ────────────────────────────────────────────────────── */\n\nexport function DropdownMenu(props) {\n return <DropdownMenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />;\n}\n\nexport function DropdownMenuTrigger(props) {\n return <DropdownMenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />;\n}\n\nexport function DropdownMenuContent({ className, sideOffset = 4, ...props }) {\n return (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n data-slot=\"dropdown-menu-content\"\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:max-h-(--radix-dropdown-menu-content-available-height) eb:min-w-[8rem] eb:origin-(--radix-dropdown-menu-content-transform-origin) eb:overflow-x-hidden eb:overflow-y-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:p-1 eb:text-popover-foreground eb:shadow-md',\n FADE_ZOOM,\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n );\n}\n\nexport function DropdownMenuGroup(props) {\n return <DropdownMenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />;\n}\n\nexport function DropdownMenuItem({ className, ...props }) {\n return (\n <DropdownMenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n className={cn(\n \"eb:relative eb:flex eb:cursor-default eb:items-center eb:gap-2 eb:rounded-sm eb:px-2 eb:py-1.5 eb:text-[13px] eb:outline-hidden eb:select-none eb:focus:bg-accent eb:focus:text-accent-foreground eb:data-[disabled]:pointer-events-none eb:data-[disabled]:opacity-50 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport function DropdownMenuLabel({ className, ...props }) {\n return <DropdownMenuPrimitive.Label className={cn('eb:px-2 eb:py-1.5 eb:text-[13px] eb:font-medium', className)} {...props} />;\n}\n\nexport function DropdownMenuSeparator({ className, ...props }) {\n return <DropdownMenuPrimitive.Separator className={cn('eb:-mx-1 eb:my-1 eb:h-px eb:bg-border', className)} {...props} />;\n}\n\n/* ── Select ───────────────────────────────────────────────────────────── */\n\nexport function Select(props) {\n return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nexport function SelectValue(props) {\n return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nexport function SelectTrigger({ className, children, ...props }) {\n return (\n <SelectPrimitive.Trigger\n data-slot=\"select-trigger\"\n className={cn(\n \"eb:flex eb:h-8 eb:w-full eb:items-center eb:justify-between eb:gap-2 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-1 eb:text-[13px] eb:whitespace-nowrap eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:disabled:cursor-not-allowed eb:disabled:opacity-50 eb:data-[placeholder]:text-foreground-muted eb:*:data-[slot=select-value]:line-clamp-1 eb:*:data-[slot=select-value]:flex eb:*:data-[slot=select-value]:items-center eb:*:data-[slot=select-value]:gap-2 eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDownIcon className=\"eb:size-4 eb:opacity-50\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n );\n}\n\nexport function SelectContent({ className, children, position = 'popper', ...props }) {\n return (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n data-slot=\"select-content\"\n position={position}\n className={cn(\n 'eb-scope eb:relative eb:z-50 eb:max-h-(--radix-select-content-available-height) eb:min-w-[8rem] eb:origin-(--radix-select-content-transform-origin) eb:overflow-x-hidden eb:overflow-y-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:text-popover-foreground eb:shadow-md',\n FADE_ZOOM,\n position === 'popper' && 'eb:data-[side=bottom]:translate-y-1 eb:data-[side=top]:-translate-y-1',\n className\n )}\n {...props}\n >\n <SelectPrimitive.Viewport\n className={cn(\n 'eb:p-1',\n position === 'popper' &&\n 'eb:h-[var(--radix-select-trigger-height)] eb:w-full eb:min-w-[var(--radix-select-trigger-width)] eb:scroll-my-1'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n );\n}\n\nexport function SelectItem({ className, children, ...props }) {\n return (\n <SelectPrimitive.Item\n data-slot=\"select-item\"\n className={cn(\n 'eb:relative eb:flex eb:w-full eb:cursor-default eb:items-center eb:gap-2 eb:rounded-sm eb:py-1.5 eb:pr-8 eb:pl-2 eb:text-[13px] eb:outline-hidden eb:select-none eb:focus:bg-accent eb:focus:text-accent-foreground eb:data-[disabled]:pointer-events-none eb:data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"eb:absolute eb:right-2 eb:flex eb:size-3.5 eb:items-center eb:justify-center\">\n <SelectPrimitive.ItemIndicator>\n <CheckIcon className=\"eb:size-4\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </SelectPrimitive.Item>\n );\n}\n","import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { AlertCircle, CheckCircle2, Info, TriangleAlert, X } from 'lucide-react';\nimport { identity, translatorFor } from '../i18n/index.js';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogTitle,\n} from './primitives/overlays.jsx';\nimport { buttonVariants } from './primitives/button.jsx';\nimport { TooltipProvider } from './primitives/misc.jsx';\nimport { cn } from './primitives/cn.js';\n\n/**\n * Interface services shared by every component of the builder:\n *\n * t translation (see src/i18n) ;\n * locale BCP 47 tag used for dates and times ;\n * notify short messages (`success`, `info`, `warning`, `error`) — shown by\n * the builder itself, or handed to the host's own toaster through\n * the `onNotify` prop ;\n * confirm asynchronous confirmation dialog → Promise<boolean>.\n */\n\n/**\n * @typedef {'success'|'info'|'warning'|'error'} NotifyLevel\n * @typedef {{title?: string, description?: string, confirmLabel?: string,\n * cancelLabel?: string, destructive?: boolean}} ConfirmOptions\n */\n\nconst NoticeContext = createContext({ notices: [], dismiss: () => {} });\n\nconst UiContext = createContext({\n t: identity,\n locale: 'en',\n /** @type {(level: NotifyLevel, message: string) => void} */\n notify: () => {},\n /** @type {(options: ConfirmOptions) => Promise<boolean>} */\n confirm: async () => false,\n});\n\nexport const useUi = () => useContext(UiContext);\nexport const useT = () => useContext(UiContext).t;\n\nconst NOTICE_ICON = { success: CheckCircle2, info: Info, warning: TriangleAlert, error: AlertCircle };\nconst NOTICE_TTL = { success: 3500, info: 4000, warning: 6000, error: 7000 };\n\n/** Where the builder's own notices appear (bottom-right of its root element). */\nexport function NoticeArea() {\n const t = useT();\n const { notices, dismiss: onDismiss } = useContext(NoticeContext);\n return (\n <div className=\"eb:pointer-events-none eb:absolute eb:right-3 eb:bottom-3 eb:z-40 eb:flex eb:w-80 eb:max-w-[calc(100%-1.5rem)] eb:flex-col eb:gap-2\">\n {notices.map((notice) => {\n const Icon = NOTICE_ICON[notice.level] || Info;\n return (\n <div\n key={notice.id}\n role={notice.level === 'error' ? 'alert' : 'status'}\n data-level={notice.level}\n className=\"eb:pointer-events-auto eb:flex eb:items-start eb:gap-2 eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:px-3 eb:py-2.5 eb:text-[13px] eb:text-popover-foreground eb:shadow-lg\"\n >\n <Icon\n aria-hidden=\"true\"\n className={cn(\n 'eb:mt-0.5 eb:size-4 eb:shrink-0',\n notice.level === 'error' && 'eb:text-destructive',\n notice.level === 'warning' && 'eb:text-warning',\n notice.level === 'success' && 'eb:text-success',\n notice.level === 'info' && 'eb:text-foreground-muted'\n )}\n />\n <p className=\"eb:min-w-0 eb:flex-1\">{notice.message}</p>\n <button\n type=\"button\"\n aria-label={t('Dismiss')}\n className=\"eb:shrink-0 eb:rounded-sm eb:text-foreground-muted eb:hover:text-foreground\"\n onClick={() => onDismiss(notice.id)}\n >\n <X className=\"eb:size-3.5\" />\n </button>\n </div>\n );\n })}\n </div>\n );\n}\n\n/**\n * @param {{\n * locale?: string,\n * messages?: Record<string, string>,\n * onNotify?: (level: NotifyLevel, message: string) => void,\n * children: import('react').ReactNode,\n * }} props\n */\nexport function UiProvider({ locale = 'en', messages, onNotify, children }) {\n const t = useMemo(() => translatorFor(locale, messages), [locale, messages]);\n\n /* ── Notices ── */\n const [notices, setNotices] = useState([]);\n const timers = useRef(new Map());\n const dismiss = useCallback((id) => {\n clearTimeout(timers.current.get(id));\n timers.current.delete(id);\n setNotices((list) => list.filter((n) => n.id !== id));\n }, []);\n const hostNotify = useRef(onNotify);\n hostNotify.current = onNotify;\n const nextId = useRef(0);\n const notify = useCallback(\n (level, message) => {\n if (hostNotify.current) {\n hostNotify.current(level, message);\n return;\n }\n const id = (nextId.current += 1);\n setNotices((list) => [...list.slice(-3), { id, level, message }]);\n timers.current.set(\n id,\n setTimeout(() => dismiss(id), NOTICE_TTL[level] || 4000)\n );\n },\n [dismiss]\n );\n useEffect(() => {\n const pending = timers.current;\n return () => pending.forEach((timer) => clearTimeout(timer));\n }, []);\n\n /* ── Confirmation ── */\n const [request, setRequest] = useState(null);\n const confirm = useCallback(\n (options = {}) =>\n new Promise((resolve) => {\n setRequest((current) => {\n current?.resolve(false);\n return { options, resolve };\n });\n }),\n []\n );\n const settle = (result) => {\n request?.resolve(result);\n setRequest(null);\n };\n\n const value = useMemo(() => ({ t, locale, notify, confirm }), [t, locale, notify, confirm]);\n const noticeValue = useMemo(() => ({ notices, dismiss }), [notices, dismiss]);\n const options = request?.options || {};\n\n return (\n <UiContext.Provider value={value}>\n <TooltipProvider delayDuration={300}>\n <NoticeContext.Provider value={noticeValue}>{children}</NoticeContext.Provider>\n <AlertDialog open={Boolean(request)} onOpenChange={(open) => !open && settle(false)}>\n <AlertDialogContent>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span\n className={cn(\n 'eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2',\n options.destructive ? 'eb:bg-destructive/10 eb:text-destructive' : 'eb:bg-primary/10 eb:text-primary'\n )}\n >\n <AlertCircle className=\"eb:size-5\" />\n </span>\n <AlertDialogTitle className=\"eb:text-base\">{options.title || t('Confirm')}</AlertDialogTitle>\n </div>\n {options.description && (\n <AlertDialogDescription className=\"eb:text-[13px] eb:leading-relaxed\">{options.description}</AlertDialogDescription>\n )}\n <div className=\"eb:flex eb:flex-col-reverse eb:gap-2 eb:sm:flex-row eb:sm:justify-end\">\n <AlertDialogCancel className={buttonVariants({ variant: 'outline' })} onClick={() => settle(false)}>\n {options.cancelLabel || t('Cancel')}\n </AlertDialogCancel>\n <AlertDialogAction\n className={buttonVariants({ variant: options.destructive ? 'destructive' : 'default' })}\n onClick={() => settle(true)}\n >\n {options.confirmLabel || t('Confirm')}\n </AlertDialogAction>\n </div>\n </AlertDialogContent>\n </AlertDialog>\n </TooltipProvider>\n </UiContext.Provider>\n );\n}\n","import { Separator as SeparatorPrimitive, Tabs as TabsPrimitive, Tooltip as TooltipPrimitive } from 'radix-ui';\nimport { cn } from './cn.js';\n\nexport function Separator({ className, orientation = 'horizontal', decorative = true, ...props }) {\n return (\n <SeparatorPrimitive.Root\n data-slot=\"separator\"\n decorative={decorative}\n orientation={orientation}\n className={cn(\n 'eb:shrink-0 eb:bg-border eb:data-[orientation=horizontal]:h-px eb:data-[orientation=horizontal]:w-full eb:data-[orientation=vertical]:h-full eb:data-[orientation=vertical]:w-px',\n className\n )}\n {...props}\n />\n );\n}\n\nexport function Skeleton({ className, as: Comp = 'div', ...props }) {\n return <Comp data-slot=\"skeleton\" className={cn('eb:animate-pulse eb:rounded-lg2 eb:bg-accent', className)} {...props} />;\n}\n\n/** Small uppercase heading of a panel section. */\nexport function SectionLabel({ className, ...props }) {\n return (\n <span\n data-slot=\"section-label\"\n className={cn('eb:font-mono eb:text-[10px] eb:uppercase eb:tracking-[0.14em] eb:text-foreground-muted', className)}\n {...props}\n />\n );\n}\n\n/** One line of text, cut with an ellipsis when it overflows (full text on hover). */\nexport function TruncatedText({ children, className, as: Comp = 'span', ...props }) {\n return (\n <Comp\n className={cn('eb:block eb:truncate', className)}\n title={typeof children === 'string' ? children : undefined}\n {...props}\n >\n {children}\n </Comp>\n );\n}\n\n/* ── Tabs ─────────────────────────────────────────────────────────────── */\n\nexport function Tabs({ className, ...props }) {\n return <TabsPrimitive.Root data-slot=\"tabs\" className={cn('eb:flex eb:flex-col eb:gap-2', className)} {...props} />;\n}\n\nexport function TabsList({ className, ...props }) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n 'eb:inline-flex eb:h-8 eb:w-fit eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-muted eb:p-[3px] eb:text-muted-foreground',\n className\n )}\n {...props}\n />\n );\n}\n\nexport function TabsTrigger({ className, ...props }) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"eb:inline-flex eb:h-[calc(100%-1px)] eb:flex-1 eb:items-center eb:justify-center eb:gap-1.5 eb:rounded-lg2 eb:border eb:border-transparent eb:px-2 eb:py-1 eb:text-[13px] eb:font-medium eb:whitespace-nowrap eb:text-foreground/60 eb:transition-all eb:hover:text-foreground eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:focus-visible:outline-1 eb:disabled:pointer-events-none eb:disabled:opacity-50 eb:data-[state=active]:bg-background eb:data-[state=active]:text-foreground eb:data-[state=active]:shadow-sm eb:[&_svg]:pointer-events-none eb:[&_svg]:shrink-0 eb:[&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n );\n}\n\n/* ── Tooltip ──────────────────────────────────────────────────────────── */\n\nexport function TooltipProvider({ delayDuration = 0, ...props }) {\n return <TooltipPrimitive.Provider delayDuration={delayDuration} {...props} />;\n}\n\nexport function Tooltip(props) {\n return <TooltipPrimitive.Root {...props} />;\n}\n\nexport function TooltipTrigger(props) {\n return <TooltipPrimitive.Trigger {...props} />;\n}\n\nexport function TooltipContent({ className, sideOffset = 4, children, ...props }) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Content\n data-slot=\"tooltip-content\"\n sideOffset={sideOffset}\n className={cn(\n 'eb-scope eb:z-50 eb:w-fit eb:origin-(--radix-tooltip-content-transform-origin) eb:animate-in eb:rounded-lg2 eb:border eb:border-border eb:bg-popover eb:px-3 eb:py-1.5 eb:text-xs eb:text-balance eb:text-popover-foreground eb:shadow-md eb:fade-in-0 eb:zoom-in-95 eb:data-[state=closed]:animate-out eb:data-[state=closed]:fade-out-0 eb:data-[state=closed]:zoom-out-95',\n className\n )}\n {...props}\n >\n {children}\n </TooltipPrimitive.Content>\n </TooltipPrimitive.Portal>\n );\n}\n\n/** Wraps a control with a tooltip; without a label, renders the control alone. */\nexport function TooltipWrap({ label, side = 'top', children, asChild = true, delayDuration }) {\n if (!label) return children;\n return (\n <Tooltip delayDuration={delayDuration}>\n <TooltipTrigger asChild={asChild}>{children}</TooltipTrigger>\n <TooltipContent side={side} className=\"eb:px-2 eb:py-1 eb:text-[11px]\">\n {label}\n </TooltipContent>\n </Tooltip>\n );\n}\n","// @ts-check\n/**\n * VERSIONS feature: toolbar button (`VersionsMenu`).\n */\n\nimport VersionsMenu from './VersionsMenu.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const versionsFeature = {\n id: 'versions',\n label: 'Versions',\n order: 30,\n toolbar: VersionsMenu,\n};\n","import { useState } from 'react';\nimport { Braces } from 'lucide-react';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/primitives/overlays.jsx';\nimport { tokenOf } from './catalog.js';\nimport VariableDialog from './VariableDialog.jsx';\nimport VariablePicker from './VariablePicker.jsx';\n\n/**\n * VARIABLES — toolbar menu.\n *\n * Inserts the variable's TAG where the user is typing (caret of the text being\n * edited), otherwise at the end of the selected text or button. The\n * unsubscribe link is inserted as a link (or becomes the button's URL). The\n * editor replaces nothing: rendering does, per recipient.\n *\n * When the storage supports it, users create, edit and delete their own\n * variables from here; they are shared by every template.\n *\n * The menu never takes the caret away from the text being edited: it does not\n * give focus back on close, and its mousedown does not reach the document —\n * any mousedown there ends the text editing.\n */\nexport default function VariablesMenu({ context }) {\n const { editor, ready, variables, storage, canManageVariables, reloadVariables } = context;\n const { t, notify } = useUi();\n const [open, setOpen] = useState(false);\n const [dialog, setDialog] = useState(null); // { variable } | { label }\n\n const insert = (variable) => {\n setOpen(false);\n const done =\n variable.kind === 'link'\n ? editor.insertLink(tokenOf(variable), t('Unsubscribe'))\n : editor.insertText(tokenOf(variable));\n if (!done) notify('info', t('Select a text or a button first.'));\n return done;\n };\n\n const manage = canManageVariables\n ? {\n onCreate: (label) => {\n setOpen(false);\n setDialog({ variable: null, label });\n },\n onEdit: (variable) => {\n setOpen(false);\n setDialog({ variable, label: '' });\n },\n }\n : {};\n\n return (\n <>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready}\n // No mousedown: the text being edited keeps its caret (the click still opens the menu).\n onPointerDown={(e) => e.pointerType === 'mouse' && e.preventDefault()}\n >\n <Braces />\n {t('Variables')}\n </Button>\n </PopoverTrigger>\n <PopoverContent\n align=\"end\"\n className=\"eb:w-80 eb:p-0\"\n onCloseAutoFocus={(e) => e.preventDefault()}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <VariablePicker variables={variables} onPick={insert} {...manage} />\n </PopoverContent>\n </Popover>\n {canManageVariables && (\n <VariableDialog\n open={Boolean(dialog)}\n onOpenChange={(next) => !next && setDialog(null)}\n variable={dialog?.variable || null}\n initialLabel={dialog?.label || ''}\n variables={variables}\n storage={storage}\n onSaved={async (variable, created) => {\n await reloadVariables();\n if (created) {\n // A text was being edited: the new variable goes at its caret.\n if (editor.insertText(tokenOf(variable))) {\n notify('success', t('Variable “{name}” created and inserted.', { name: variable.label }));\n } else {\n notify('success', t('Variable “{name}” created.', { name: variable.label }));\n }\n } else {\n notify('success', t('Variable “{name}” saved.', { name: variable.label }));\n }\n }}\n onDeleted={async () => {\n await reloadVariables();\n notify('success', t('Variable deleted.'));\n }}\n />\n )}\n </>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport { Braces, Loader2, Trash2 } from 'lucide-react';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Input, Label } from '../../ui/primitives/fields.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/primitives/overlays.jsx';\nimport { CUSTOM_GROUP, VARIABLE_LIMITS, keyFromLabel, validateCustomVariable } from './catalog.js';\n\n/**\n * Create or edit a CUSTOM variable.\n *\n * Name what the menu shows (\"Order number\");\n * Tag proposed from the name, editable until the variable\n * exists — then frozen: templates contain it;\n * Group free text, existing groups suggested;\n * Sample value used by the preview and test sends;\n * Value if empty what a recipient without a value sees.\n *\n * @param {{\n * open: boolean,\n * onOpenChange: (open: boolean) => void,\n * variable?: import('./catalog.js').EmailVariable|null, // null: creation\n * initialLabel?: string,\n * variables: import('./catalog.js').EmailVariable[],\n * storage: import('../../storage/client.js').TemplateStorage,\n * onSaved: (variable: import('./catalog.js').EmailVariable, created: boolean) => void,\n * onDeleted?: (key: string) => void,\n * }} props\n */\nexport default function VariableDialog({ open, onOpenChange, variable = null, initialLabel = '', variables, storage, onSaved, onDeleted }) {\n const { t, notify, confirm } = useUi();\n const editing = Boolean(variable);\n const [form, setForm] = useState({ label: '', key: '', group: '', sample: '', fallback: '' });\n const [keyTouched, setKeyTouched] = useState(false);\n const [errors, setErrors] = useState({});\n const [busy, setBusy] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n setForm(\n variable\n ? {\n label: variable.label,\n key: variable.key,\n group: variable.group || '',\n sample: variable.sample || '',\n fallback: variable.fallback || '',\n }\n : { label: initialLabel, key: initialLabel ? keyFromLabel(initialLabel) : '', group: '', sample: '', fallback: '' }\n );\n setKeyTouched(false);\n setErrors({});\n }, [open, variable, initialLabel]);\n\n const groups = useMemo(\n () => [...new Set([CUSTOM_GROUP, ...variables.filter((v) => v.custom).map((v) => v.group)])].filter(Boolean),\n [variables]\n );\n\n const set = (field) => (e) => {\n const value = e.target.value;\n setForm((f) => {\n const next = { ...f, [field]: value };\n // The tag follows the name until the user types one.\n if (field === 'label' && !editing && !keyTouched) next.key = value.trim() ? keyFromLabel(value) : '';\n return next;\n });\n if (field === 'key') setKeyTouched(true);\n setErrors((errs) => ({ ...errs, [field]: undefined }));\n };\n\n const submit = async (e) => {\n e.preventDefault();\n const existing = variables.filter((v) => !editing || v.key !== variable.key);\n const check = validateCustomVariable(form, { existing, editing: editing ? variable.key : null, t });\n if (check.errors) {\n setErrors(check.errors);\n return;\n }\n setBusy(true);\n try {\n const saved = await storage.saveVariable(check.variable, { create: !editing });\n onSaved(saved, !editing);\n onOpenChange(false);\n } catch (error) {\n notify('error', error.message);\n } finally {\n setBusy(false);\n }\n };\n\n const remove = async () => {\n const ok = await confirm({\n title: t('Delete the variable “{name}”?', { name: variable.label }),\n description: t('Templates that use it will show its “value if empty”.'),\n confirmLabel: t('Delete'),\n destructive: true,\n });\n if (!ok) return;\n setBusy(true);\n try {\n await storage.deleteVariable(variable.key);\n onDeleted?.(variable.key);\n onOpenChange(false);\n } catch (error) {\n notify('error', error.message);\n } finally {\n setBusy(false);\n }\n };\n\n const field = (name, label, props = {}, hint = null) => (\n <div className=\"eb:space-y-1.5\">\n <Label htmlFor={`eb-var-${name}`}>{label}</Label>\n <Input\n id={`eb-var-${name}`}\n value={form[name]}\n onChange={set(name)}\n aria-invalid={errors[name] ? true : undefined}\n aria-describedby={errors[name] || hint ? `eb-var-${name}-hint` : undefined}\n {...props}\n />\n {(errors[name] || hint) && (\n <p id={`eb-var-${name}-hint`} className={errors[name] ? 'eb:text-[12px] eb:text-destructive' : 'eb:text-[11px] eb:text-foreground-muted'}>\n {errors[name] || hint}\n </p>\n )}\n </div>\n );\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent\n className=\"eb:sm:max-w-[440px]\"\n // A text being edited in the canvas keeps its caret: a mousedown that\n // reaches the document would end the editing.\n onMouseDown={(e) => e.stopPropagation()}\n onCloseAutoFocus={(e) => e.preventDefault()}\n >\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Braces className=\"eb:size-5\" />\n </span>\n <div>\n <DialogTitle className=\"eb:text-base eb:font-normal\">{editing ? t('Edit variable') : t('New variable')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">{t('Available in every template.')}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <form onSubmit={submit} className=\"eb:space-y-3\" noValidate>\n {field('label', t('Name'), { autoFocus: true, maxLength: VARIABLE_LIMITS.label, placeholder: t('Order number') })}\n {field(\n 'key',\n t('Tag'),\n { disabled: editing, maxLength: VARIABLE_LIMITS.key, className: 'eb:font-mono eb:text-[12px]' },\n form.key ? `{{${form.key}}}` : null\n )}\n <div className=\"eb:space-y-1.5\">\n <Label htmlFor=\"eb-var-group\">{t('Group')}</Label>\n <Input\n id=\"eb-var-group\"\n list=\"eb-var-groups\"\n value={form.group}\n onChange={set('group')}\n maxLength={VARIABLE_LIMITS.group}\n placeholder={t(CUSTOM_GROUP)}\n />\n <datalist id=\"eb-var-groups\">\n {groups.map((g) => (\n <option key={g} value={g} />\n ))}\n </datalist>\n </div>\n <div className=\"eb:grid eb:grid-cols-2 eb:gap-3\">\n {field('sample', t('Sample value'), { maxLength: VARIABLE_LIMITS.sample, placeholder: 'CMD-1042' }, t('Preview and tests'))}\n {field('fallback', t('Value if empty'), { maxLength: VARIABLE_LIMITS.fallback }, t('When a recipient has none'))}\n </div>\n <div className=\"eb:flex eb:items-center eb:gap-2 eb:pt-1\">\n {editing && (\n <Button variant=\"ghost\" className=\"eb:text-destructive eb:hover:text-destructive\" onClick={remove} disabled={busy}>\n <Trash2 />\n {t('Delete')}\n </Button>\n )}\n <div className=\"eb:ml-auto eb:flex eb:gap-2\">\n <Button variant=\"outline\" onClick={() => onOpenChange(false)} disabled={busy}>\n {t('Cancel')}\n </Button>\n <Button type=\"submit\" disabled={busy}>\n {busy && <Loader2 className=\"eb:animate-spin\" />}\n {editing ? t('Save') : t('Create')}\n </Button>\n </div>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n","import { forwardRef } from 'react';\nimport { Label as LabelPrimitive } from 'radix-ui';\nimport { cn } from './cn.js';\n\n// forwardRef: React 18 does not pass `ref` as a prop.\nexport const Input = forwardRef(function Input({ className, type, ...props }, ref) {\n return (\n <input\n ref={ref}\n type={type}\n data-slot=\"input\"\n className={cn(\n 'eb:h-8 eb:w-full eb:min-w-0 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-1 eb:text-[13px] eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:placeholder:text-foreground-muted eb:selection:bg-primary eb:selection:text-primary-foreground eb:disabled:pointer-events-none eb:disabled:cursor-not-allowed eb:disabled:opacity-50',\n 'eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50',\n 'eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20',\n className\n )}\n {...props}\n />\n );\n});\n\nexport const Textarea = forwardRef(function Textarea({ className, ...props }, ref) {\n return (\n <textarea\n ref={ref}\n data-slot=\"textarea\"\n className={cn(\n 'eb:flex eb:field-sizing-content eb:min-h-16 eb:w-full eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:px-3 eb:py-2 eb:text-[13px] eb:text-foreground eb:shadow-xs eb:transition-[color,box-shadow] eb:outline-none eb:placeholder:text-foreground-muted eb:focus-visible:border-ring eb:focus-visible:ring-[3px] eb:focus-visible:ring-ring/50 eb:aria-invalid:border-destructive eb:aria-invalid:ring-destructive/20 eb:disabled:cursor-not-allowed eb:disabled:opacity-50',\n className\n )}\n {...props}\n />\n );\n});\n\nexport function Label({ className, ...props }) {\n return (\n <LabelPrimitive.Root\n data-slot=\"label\"\n className={cn(\n 'eb:flex eb:items-center eb:gap-2 eb:text-[13px] eb:leading-none eb:font-medium eb:text-foreground eb:select-none eb:peer-disabled:cursor-not-allowed eb:peer-disabled:opacity-50',\n className\n )}\n {...props}\n />\n );\n}\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { Pencil, Plus, Search } from 'lucide-react';\nimport { useT } from '../../ui/context.jsx';\nimport { cn } from '../../ui/primitives/cn.js';\nimport { tokenOf } from './catalog.js';\n\n/**\n * List of variables with a search field — shared by the toolbar menu and the\n * buttons next to the subject and preview text fields.\n *\n * Keyboard: type to filter, ↑/↓ to move, Enter to insert. A search with no\n * result offers to create the variable under that name.\n *\n * @param {{\n * variables: import('./catalog.js').EmailVariable[],\n * onPick: (variable: import('./catalog.js').EmailVariable) => void,\n * onCreate?: ((label: string) => void) | null,\n * onEdit?: ((variable: import('./catalog.js').EmailVariable) => void) | null,\n * filter?: (variable: import('./catalog.js').EmailVariable) => boolean,\n * }} props\n */\nexport default function VariablePicker({ variables, onPick, onCreate = null, onEdit = null, filter }) {\n const t = useT();\n const [query, setQuery] = useState('');\n const [active, setActive] = useState(0);\n const listRef = useRef(null);\n\n const matches = useMemo(() => {\n const q = query.trim().toLowerCase();\n return variables\n .filter((v) => (filter ? filter(v) : true))\n .filter(\n (v) =>\n !q ||\n t(v.label).toLowerCase().includes(q) ||\n v.key.toLowerCase().includes(q) ||\n t(v.group).toLowerCase().includes(q)\n );\n }, [variables, query, filter, t]);\n const groups = useMemo(() => [...new Set(matches.map((v) => v.group))], [matches]);\n // Display order (grouped) = keyboard order.\n const ordered = useMemo(() => groups.flatMap((g) => matches.filter((v) => v.group === g)), [groups, matches]);\n\n useEffect(() => setActive(0), [query]);\n useEffect(() => {\n listRef.current?.querySelector('[data-active=\"true\"]')?.scrollIntoView({ block: 'nearest' });\n }, [active]);\n\n const onKeyDown = (e) => {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActive((i) => Math.min(i + 1, ordered.length - 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActive((i) => Math.max(i - 1, 0));\n } else if (e.key === 'Enter') {\n e.preventDefault();\n if (ordered[active]) onPick(ordered[active]);\n else if (onCreate && query.trim()) onCreate(query.trim());\n }\n };\n\n return (\n <div className=\"eb:flex eb:max-h-[min(440px,70vh)] eb:flex-col\" data-testid=\"variable-picker\">\n <div className=\"eb:relative eb:border-b eb:border-border eb:p-2\">\n <Search className=\"eb:pointer-events-none eb:absolute eb:top-1/2 eb:left-4 eb:size-3.5 eb:-translate-y-1/2 eb:text-foreground-muted\" />\n <input\n autoFocus\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={onKeyDown}\n placeholder={t('Search variables…')}\n aria-label={t('Search variables…')}\n className=\"eb:h-8 eb:w-full eb:rounded-md eb:bg-surface-75 eb:pr-2 eb:pl-7 eb:text-[13px] eb:text-foreground eb:outline-none eb:placeholder:text-foreground-muted eb:focus-visible:ring-2 eb:focus-visible:ring-ring/40\"\n />\n </div>\n <div ref={listRef} role=\"listbox\" aria-label={t('Variables')} className=\"eb:min-h-0 eb:flex-1 eb:overflow-y-auto eb:p-1\">\n {ordered.length === 0 && (\n <div className=\"eb:px-2 eb:py-3 eb:text-center eb:text-[12px] eb:text-foreground-muted\">\n <p>{t('No variable found.')}</p>\n {onCreate && query.trim() && (\n <button\n type=\"button\"\n onClick={() => onCreate(query.trim())}\n className=\"eb:mt-2 eb:inline-flex eb:items-center eb:gap-1 eb:rounded-md eb:px-2 eb:py-1 eb:text-[12px] eb:font-medium eb:text-primary eb:hover:bg-accent\"\n >\n <Plus className=\"eb:size-3.5\" />\n {t('Create “{name}”', { name: query.trim() })}\n </button>\n )}\n </div>\n )}\n {groups.map((group) => (\n <div key={group} role=\"group\" aria-label={t(group)}>\n <p className=\"eb:px-2 eb:pt-2 eb:pb-1 eb:text-[11px] eb:text-foreground-muted\">{t(group)}</p>\n {ordered\n .filter((v) => v.group === group)\n .map((variable) => {\n const index = ordered.indexOf(variable);\n return (\n <div\n key={variable.key}\n data-active={index === active}\n className={cn(\n 'eb:group/var eb:flex eb:items-center eb:gap-1 eb:rounded-md',\n index === active ? 'eb:bg-accent eb:text-accent-foreground' : 'eb:hover:bg-accent/60'\n )}\n onMouseEnter={() => setActive(index)}\n >\n <button\n type=\"button\"\n role=\"option\"\n aria-selected={index === active}\n data-variable={variable.key}\n onClick={() => onPick(variable)}\n className=\"eb:flex eb:min-w-0 eb:flex-1 eb:items-center eb:gap-2 eb:px-2 eb:py-1.5 eb:text-left eb:text-[13px]\"\n title={variable.description || undefined}\n >\n <span className=\"eb:min-w-0 eb:flex-1 eb:truncate\">{variable.custom ? variable.label : t(variable.label)}</span>\n <code className=\"eb:shrink-0 eb:font-mono eb:text-[10.5px] eb:text-foreground-muted\">{tokenOf(variable)}</code>\n </button>\n {onEdit && variable.custom && (\n <button\n type=\"button\"\n aria-label={t('Edit “{name}”', { name: variable.label })}\n title={t('Edit')}\n onClick={() => onEdit(variable)}\n className=\"eb:mr-1 eb:flex eb:size-6 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-md eb:text-foreground-muted eb:opacity-0 eb:group-hover/var:opacity-100 eb:hover:bg-background eb:hover:text-foreground eb:focus-visible:opacity-100\"\n >\n <Pencil className=\"eb:size-3\" />\n </button>\n )}\n </div>\n );\n })}\n </div>\n ))}\n </div>\n {onCreate && (\n <div className=\"eb:border-t eb:border-border eb:p-1\">\n <button\n type=\"button\"\n onClick={() => onCreate(query.trim())}\n className=\"eb:flex eb:w-full eb:items-center eb:gap-2 eb:rounded-md eb:px-2 eb:py-1.5 eb:text-left eb:text-[13px] eb:font-medium eb:text-primary eb:hover:bg-accent\"\n >\n <Plus className=\"eb:size-4\" />\n {t('New variable')}\n </button>\n </div>\n )}\n </div>\n );\n}\n","// @ts-check\n/**\n * VARIABLES feature: insertion menu (`VariablesMenu`), creation and editing of\n * custom variables (`VariableDialog`). The catalog (`catalog.js`) and the\n * replacement (`service.js`) are shared with the server.\n */\n\nimport VariablesMenu from './VariablesMenu.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const variablesFeature = {\n id: 'variables',\n label: 'Variables',\n order: 10,\n toolbar: VariablesMenu,\n};\n","import { useMemo, useState } from 'react';\nimport { AlertTriangle, CheckCircle2, Eye, Info, Loader2, Monitor, RefreshCw, Smartphone } from 'lucide-react';\nimport { EMAIL_MOBILE_WIDTH } from '../../core/constants.js';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/primitives/overlays.jsx';\nimport { SectionLabel } from '../../ui/primitives/misc.jsx';\nimport { cn } from '../../ui/primitives/cn.js';\n\n/**\n * PREVIEW of the FINAL email — rendered by the server, as it will be stored.\n *\n * The canvas already compiles in the browser; the preview goes through the\n * server compilation (the only one that counts), with sample values for the\n * variables, and lists the quality checks (unsubscribe link, alt texts, links,\n * Gmail clipping size) and the MJML warnings.\n *\n * The HTML is shown in an iframe with an EMPTY sandbox: no script, form,\n * navigation, nor same origin. An email is a complete HTML document: injected\n * into the page it would inherit the application's styles and lie.\n */\n\nconst LEVEL_ICON = { warning: AlertTriangle, info: Info };\n\nexport function QualityList({ quality = [], warnings = [] }) {\n const { t } = useUi();\n if (!quality.length && !warnings.length) {\n return (\n <p className=\"eb:flex eb:items-center eb:gap-1.5 eb:text-[12px] eb:text-foreground-lighter\">\n <CheckCircle2 className=\"eb:size-3.5 eb:text-success\" aria-hidden=\"true\" />\n {t('Nothing to fix.')}\n </p>\n );\n }\n return (\n <ul className=\"eb:space-y-1.5\" aria-label={t('Points to check')}>\n {quality.map((issue) => {\n const Icon = LEVEL_ICON[issue.level] || Info;\n return (\n <li key={issue.code} className=\"eb:flex eb:items-start eb:gap-1.5 eb:text-[12px] eb:text-foreground\">\n <Icon\n className={cn(\n 'eb:mt-0.5 eb:size-3.5 eb:shrink-0',\n issue.level === 'warning' ? 'eb:text-warning' : 'eb:text-foreground-muted'\n )}\n aria-hidden=\"true\"\n />\n {issue.message}\n </li>\n );\n })}\n {warnings.slice(0, 5).map((w, i) => (\n <li key={`mjml-${i}`} className=\"eb:flex eb:items-start eb:gap-1.5 eb:text-[12px] eb:text-foreground-lighter\">\n <Info className=\"eb:mt-0.5 eb:size-3.5 eb:shrink-0 eb:text-foreground-muted\" aria-hidden=\"true\" />\n MJML: {w.message}\n </li>\n ))}\n </ul>\n );\n}\n\n/** Sandboxed preview frame, desktop or mobile width. */\nexport function EmailPreview({ html, loading = false, error = null, device = 'desktop', onDeviceChange, onRefresh, hint = true }) {\n const { t } = useUi();\n const isMobile = device === 'mobile';\n // `srcDoc`, not a blob URL: nothing to revoke when the HTML changes.\n const srcDoc = useMemo(() => html || '', [html]);\n\n return (\n <div className=\"eb:flex eb:h-full eb:min-h-0 eb:flex-col\">\n <div className=\"eb:mb-2 eb:flex eb:shrink-0 eb:items-center eb:justify-between eb:gap-2\">\n <div className=\"eb:inline-flex eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:p-0.5\">\n <Button\n variant={isMobile ? 'ghost' : 'secondary'}\n size=\"sm-compact\"\n onClick={() => onDeviceChange?.('desktop')}\n aria-pressed={!isMobile}\n >\n <Monitor />\n {t('Desktop')}\n </Button>\n <Button\n variant={isMobile ? 'secondary' : 'ghost'}\n size=\"sm-compact\"\n onClick={() => onDeviceChange?.('mobile')}\n aria-pressed={isMobile}\n >\n <Smartphone />\n {t('Mobile')}\n </Button>\n </div>\n {onRefresh && (\n <Button variant=\"outline\" size=\"sm-compact\" onClick={onRefresh} disabled={loading}>\n {loading ? <Loader2 className=\"eb:animate-spin\" /> : <RefreshCw />}\n {t('Refresh')}\n </Button>\n )}\n </div>\n\n <div className=\"eb:min-h-0 eb:flex-1 eb:overflow-auto eb:rounded-lg2 eb:border eb:border-border eb:bg-surface-75 eb:p-3\">\n {error ? (\n <div className=\"eb:flex eb:h-full eb:items-center eb:justify-center eb:p-6 eb:text-center eb:text-[13px] eb:text-destructive\">{error}</div>\n ) : !srcDoc ? (\n <div className=\"eb:flex eb:h-full eb:items-center eb:justify-center eb:p-6 eb:text-center eb:text-[13px] eb:text-foreground-lighter\">\n {loading ? t('Rendering…') : t('Nothing to show yet.')}\n </div>\n ) : (\n <div\n className={cn('eb:mx-auto eb:bg-white', isMobile && 'eb:shadow-sm')}\n style={isMobile ? { width: EMAIL_MOBILE_WIDTH } : undefined}\n >\n <iframe\n sandbox=\"\"\n srcDoc={srcDoc}\n title={t('Email preview')}\n className=\"eb:block eb:w-full eb:border-0 eb:bg-white\"\n style={{ height: isMobile ? 760 : 900 }}\n />\n </div>\n )}\n </div>\n\n {hint && (\n <p className=\"eb:mt-2 eb:shrink-0 eb:text-[11px] eb:leading-relaxed eb:text-foreground-lighter\">\n {t('Indicative preview — check it with “Send test”.')}\n </p>\n )}\n </div>\n );\n}\n\nexport default function PreviewButton({ context }) {\n const { editor, ready, meta, storage } = context;\n const { t } = useUi();\n const [open, setOpen] = useState(false);\n const [device, setDevice] = useState('desktop');\n const [state, setState] = useState({ loading: false, html: '', subject: null, preheader: null, warnings: [], quality: [], error: null });\n\n const refresh = async () => {\n setState((s) => ({ ...s, loading: true, error: null }));\n try {\n const data = await storage.render({ mjml: editor.exportMjml(), subject: meta.subject, preheader: meta.preheader });\n setState({\n loading: false,\n html: data.html,\n // Subject and preview text with their variables filled, when the backend returns them.\n subject: data.subject ?? null,\n preheader: data.preheader ?? null,\n warnings: data.warnings || [],\n quality: data.quality || [],\n error: null,\n });\n } catch (error) {\n setState({ loading: false, html: '', subject: null, preheader: null, warnings: [], quality: [], error: error.message });\n }\n };\n\n return (\n <>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready}\n onClick={() => {\n setOpen(true);\n refresh();\n }}\n >\n <Eye />\n {t('Preview')}\n </Button>\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent className=\"eb:flex eb:h-[85vh] eb:max-h-[85vh] eb:flex-col eb:gap-4 eb:sm:max-w-[67.2rem]\">\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Eye className=\"eb:size-5\" />\n </span>\n <div>\n <DialogTitle className=\"eb:text-base eb:font-normal\">{t('Email preview')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">{t('Final rendering, variables filled with samples.')}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <div className=\"eb:grid eb:min-h-0 eb:flex-1 eb:grid-cols-1 eb:gap-4 eb:md:grid-cols-[minmax(0,1fr)_260px]\">\n <EmailPreview\n html={state.html}\n loading={state.loading}\n error={state.error}\n device={device}\n onDeviceChange={setDevice}\n onRefresh={refresh}\n // The reminder points to \"Send test\": only when it exists.\n hint={typeof storage.sendTest === 'function'}\n />\n <aside className=\"eb:min-h-0 eb:space-y-5 eb:overflow-y-auto\" aria-busy={state.loading}>\n <section className=\"eb:space-y-2\">\n <SectionLabel>{t('Inbox')}</SectionLabel>\n <div className=\"eb:rounded-lg2 eb:border eb:border-border eb:bg-surface-75 eb:px-3 eb:py-2.5\">\n <p className=\"eb:text-[13px] eb:font-medium eb:text-foreground\">{(state.subject ?? meta.subject) || t('No subject')}</p>\n <p className=\"eb:text-[12px] eb:text-foreground-muted\">{(state.preheader ?? meta.preheader) || t('No preview text')}</p>\n </div>\n </section>\n <section className=\"eb:space-y-2\">\n <SectionLabel>{t('To check')}</SectionLabel>\n {!state.loading && !state.error && <QualityList quality={state.quality} warnings={state.warnings} />}\n </section>\n </aside>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","// @ts-check\n/**\n * PREVIEW feature: server rendering of the final email, desktop and mobile,\n * with the quality checks (`PreviewButton`). Shown when the storage can render.\n */\n\nimport PreviewButton from './PreviewButton.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const previewFeature = {\n id: 'preview',\n label: 'Preview',\n order: 40,\n toolbar: PreviewButton,\n isAvailable: (context) => typeof context.storage?.render === 'function',\n};\n","import { useState } from 'react';\nimport { CheckCircle2, Loader2, Send, XCircle } from 'lucide-react';\nimport { useUi } from '../../ui/context.jsx';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Label, Textarea } from '../../ui/primitives/fields.jsx';\nimport { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/primitives/overlays.jsx';\n\n/**\n * TEST SEND — the only real layout check: a browser preview says nothing about\n * what Outlook will do. Sends the MJML on screen, saved or not.\n *\n * The addresses are remembered in the browser for the next test.\n */\n\nconst KEY = 'best-email-builder:test-addresses';\n\nfunction readAddresses(fallback) {\n try {\n return window.localStorage.getItem(KEY) ?? fallback;\n } catch {\n return fallback;\n }\n}\n\nfunction rememberAddresses(value) {\n try {\n window.localStorage.setItem(KEY, value);\n } catch {\n /* private browsing: nothing to remember */\n }\n}\n\nexport default function TestEmailButton({ context }) {\n const { editor, ready, meta, storage, testRecipients = [] } = context;\n const { t, notify } = useUi();\n const [open, setOpen] = useState(false);\n const [addresses, setAddresses] = useState('');\n const [sending, setSending] = useState(false);\n const [report, setReport] = useState(null);\n\n const emails = addresses\n .split(/[,;\\s]+/)\n .map((a) => a.trim())\n .filter(Boolean);\n\n const send = async () => {\n if (!emails.length) return;\n rememberAddresses(addresses);\n setSending(true);\n setReport(null);\n try {\n const result = await storage.sendTest({\n mjml: editor.exportMjml(),\n subject: meta.subject,\n preheader: meta.preheader,\n emails,\n });\n setReport(result);\n if (result.failed > 0) notify('warning', t('{sent} sent, {failed} failed.', { sent: result.sent, failed: result.failed }));\n else notify('success', t('{sent} test(s) sent — check your inbox.', { sent: result.sent }));\n } catch (error) {\n notify('error', error.message);\n } finally {\n setSending(false);\n }\n };\n\n return (\n <>\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n disabled={!ready}\n onClick={() => {\n setAddresses(readAddresses(testRecipients.join(', ')));\n setReport(null);\n setOpen(true);\n }}\n >\n <Send />\n {t('Test')}\n </Button>\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent className=\"eb:sm:max-w-[460px]\">\n <DialogHeader>\n <div className=\"eb:flex eb:items-center eb:gap-3\">\n <span className=\"eb:flex eb:size-10 eb:shrink-0 eb:items-center eb:justify-center eb:rounded-lg2 eb:bg-primary/10 eb:text-primary\">\n <Send className=\"eb:size-5\" />\n </span>\n <div>\n <DialogTitle className=\"eb:text-base eb:font-normal\">{t('Send a test')}</DialogTitle>\n <DialogDescription className=\"eb:text-[13px]\">{t('The email on screen, to reviewers’ addresses.')}</DialogDescription>\n </div>\n </div>\n </DialogHeader>\n <div className=\"eb:space-y-2\">\n <Label htmlFor=\"eb-test-addresses\">{t('Addresses')}</Label>\n <Textarea\n id=\"eb-test-addresses\"\n value={addresses}\n onChange={(e) => setAddresses(e.target.value)}\n placeholder=\"jane@example.com, john@example.com\"\n rows={3}\n />\n </div>\n {report && (\n <ul className=\"eb:space-y-1\" aria-label={t('Results')}>\n {report.results.map((r) => (\n <li key={r.email} className=\"eb:flex eb:items-start eb:gap-1.5 eb:text-[12px] eb:text-foreground\">\n {r.ok ? (\n <CheckCircle2 className=\"eb:mt-0.5 eb:size-3.5 eb:shrink-0 eb:text-success\" aria-hidden=\"true\" />\n ) : (\n <XCircle className=\"eb:mt-0.5 eb:size-3.5 eb:shrink-0 eb:text-destructive\" aria-hidden=\"true\" />\n )}\n <span className=\"eb:min-w-0 eb:break-all\">\n {r.email}\n {r.error ? ` — ${r.error}` : ''}\n </span>\n </li>\n ))}\n {report.invalid.map((email) => (\n <li key={`invalid-${email}`} className=\"eb:text-[12px] eb:text-foreground-muted\">\n {t('Ignored (invalid): {email}', { email })}\n </li>\n ))}\n </ul>\n )}\n <div className=\"eb:flex eb:justify-end eb:gap-2\">\n <Button variant=\"outline\" onClick={() => setOpen(false)}>\n {t('Close')}\n </Button>\n <Button onClick={send} disabled={sending || !emails.length}>\n {sending ? <Loader2 className=\"eb:animate-spin\" /> : <Send />}\n {t('Send')}\n </Button>\n </div>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","// @ts-check\n/**\n * TEST SEND feature (`TestEmailButton`) — rendering and sending by the server\n * (`sendTestEmail`). Shown when the storage can send tests.\n */\n\nimport TestEmailButton from './TestEmailButton.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const testEmailFeature = {\n id: 'test-email',\n label: 'Send a test',\n order: 50,\n toolbar: TestEmailButton,\n isAvailable: (context) => typeof context.storage?.sendTest === 'function',\n};\n","// @ts-check\n/**\n * FEATURES REGISTRY — `emailBuilderFeatures`.\n *\n * A feature (versions, preview, variables, test send…) is a self-contained\n * module. The interface asks this registry what to show; disabling an entry\n * (`enabled: false`) or removing it from here is enough to make it disappear.\n * A toolbar feature may also declare `isAvailable(context)`: the preview, for\n * instance, only appears when the storage can render.\n */\n\nimport { createRegistry } from '../core/registry.js';\nimport { autosaveFeature } from './autosave/index.js';\nimport { versionsFeature } from './versions/index.js';\nimport { variablesFeature } from './variables/index.js';\nimport { previewFeature } from './preview/index.js';\nimport { testEmailFeature } from './test-email/index.js';\n\n/** @typedef {import('../core/EmailEditor.js').EmailBuilderFeature} EmailBuilderFeature */\n\n/** @type {EmailBuilderFeature[]} */\nconst FEATURES = [variablesFeature, autosaveFeature, versionsFeature, previewFeature, testEmailFeature];\n\nexport const emailBuilderFeatures = createRegistry('emailBuilderFeatures', FEATURES);\n\n/** Is a feature enabled? @param {string} id */\nexport function isFeatureEnabled(id) {\n const feature = emailBuilderFeatures.get(id);\n return Boolean(feature && feature.enabled !== false);\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AlertTriangle, Loader2, Save } from 'lucide-react';\nimport { createDefaultEmailEditor } from '../index.js';\nimport { emailBuilderFeatures, isFeatureEnabled } from '../features/index.js';\nimport { DEFAULT_VARIABLES, defineVariables, mergeVariables } from '../features/variables/catalog.js';\nimport { createStarterMjml } from '../features/templates/starter.js';\nimport { createAutosaveScheduler } from '../features/autosave/scheduler.js';\nimport { clearLocalDraft, readLocalDraft, saveLocalDraft } from '../features/autosave/localDraft.js';\nimport { createHttpStorage } from '../storage/client.js';\nimport { NoticeArea, UiProvider, useUi } from './context.jsx';\nimport { Button } from './primitives/button.jsx';\nimport { cn } from './primitives/cn.js';\nimport EmailCanvas from './EmailCanvas.jsx';\nimport BlockSidebar from './BlockSidebar.jsx';\nimport ElementActions from './ElementActions.jsx';\nimport PropertiesPanel from './PropertiesPanel.jsx';\nimport Toolbar from './Toolbar.jsx';\nimport { useEmailEditorState } from './useEmailEditorState.js';\n\n/**\n * THE EMAIL BUILDER — the screen.\n *\n * ┌───────────────────────────────────────────────────────────────┐\n * │ Back · name ↶ ↷ Desktop|Mobile … Save │\n * ├────────────┬───────────────────────────────┬──────────────────┤\n * │ Blocks │ canvas │ Properties │\n * └────────────┴───────────────────────────────┴──────────────────┘\n *\n * Only talks to `EmailEditor` (core/EmailEditor.js) and to the storage\n * (storage/client.js). The engine is loaded when the canvas mounts.\n *\n * ── SAVE ────────────────────────────────────────────────────────────────────\n * \"Save\" (or Ctrl+S, inside the canvas too) sends the PROJECT and its MJML;\n * the server validates, compiles and creates a version. A template changed\n * elsewhere in the meantime is not overwritten: saving a copy is offered.\n *\n * ── INITIAL CONTENT (`initialMjml`, `initialMeta`) ──────────────────────────\n * A new template can start from given MJML instead of the starter template —\n * e.g. a template imported from another format. It counts as modified until\n * the first save.\n *\n * ── AUTOSAVE (feature `autosave`) ───────────────────────────────────────────\n * Template already saved: server save without a version. New template: local\n * draft, offered again at the next opening.\n */\n\nconst EMPTY_META = { name: '', subject: '', preheader: '', description: '' };\n\nfunction metaOf(template) {\n return {\n name: template?.name || '',\n subject: template?.subject || '',\n preheader: template?.preheader || '',\n description: template?.description || '',\n };\n}\n\nconst sameMeta = (a, b) => Object.keys(EMPTY_META).every((k) => (a[k] || '') === (b[k] || ''));\n\nfunction Builder({\n editor: injected,\n storage: injectedStorage,\n templateId: initialTemplateId,\n variables: variablesProp,\n sender,\n starterMjml,\n testRecipients,\n initialMjml,\n initialMeta,\n onClose,\n onSaved,\n onDirtyChange,\n dirtyCheckRef,\n className,\n}) {\n const { t, locale, notify, confirm } = useUi();\n const editor = useMemo(() => injected || createDefaultEmailEditor({ locale }), [injected, locale]);\n const storage = useMemo(() => injectedStorage || createHttpStorage(), [injectedStorage]);\n const systemVariables = useMemo(() => defineVariables(variablesProp || DEFAULT_VARIABLES), [variablesProp]);\n const [customVariables, setCustomVariables] = useState([]);\n const variables = useMemo(() => mergeVariables(systemVariables, customVariables), [systemVariables, customVariables]);\n const canManageVariables = typeof storage.saveVariable === 'function' && typeof storage.listVariables === 'function';\n const reloadVariables = useCallback(async () => {\n if (typeof storage.listVariables !== 'function') return;\n try {\n setCustomVariables(await storage.listVariables());\n } catch (error) {\n notify('error', error.message);\n }\n }, [storage, notify]);\n useEffect(() => {\n reloadVariables();\n }, [reloadVariables]);\n const starter = useMemo(() => starterMjml || createStarterMjml({ sender, t }), [starterMjml, sender, t]);\n const services = useMemo(() => ({ uploadImage: (file) => storage.uploadImage(file) }), [storage]);\n const state = useEmailEditorState(editor);\n const autosaveOn = isFeatureEnabled('autosave');\n const autosaveOptions = emailBuilderFeatures.get('autosave')?.options || {};\n\n const [template, setTemplate] = useState({ id: initialTemplateId, revision: null, savedAt: null, auto: false });\n /** loading → (error) → ready ; `document`: project to mount (null = starter template). */\n const [boot, setBoot] = useState({ status: 'loading', document: null, draft: false, message: null });\n const [meta, setMeta] = useState(EMPTY_META);\n const [savedMeta, setSavedMeta] = useState(EMPTY_META);\n const [saving, setSaving] = useState(null);\n const [showErrors, setShowErrors] = useState(false);\n const [autosaveBlocked, setAutosaveBlocked] = useState(null);\n const [engineError, setEngineError] = useState(null);\n const [attempt, setAttempt] = useState(0);\n\n const ready = state.status === 'ready';\n const metaDirty = !sameMeta(meta, savedMeta);\n const dirty = state.dirty || metaDirty;\n\n const timeOf = useCallback(\n (date) => (date ? new Date(date).toLocaleTimeString(locale, { hour: '2-digit', minute: '2-digit' }) : ''),\n [locale]\n );\n\n /* ── Start: saved template, local draft, or starter template ── */\n const booted = useRef(false);\n useEffect(() => {\n if (booted.current) return;\n booted.current = true;\n (async () => {\n if (initialTemplateId) {\n try {\n const loaded = await storage.load(initialTemplateId);\n setMeta(metaOf(loaded));\n setSavedMeta(metaOf(loaded));\n setTemplate({ id: loaded.id, revision: loaded.revision, savedAt: null, auto: false });\n setBoot({ status: 'ready', document: loaded.document, draft: false, message: null });\n } catch (error) {\n setBoot({ status: 'error', document: null, draft: false, message: error.message });\n }\n return;\n }\n if (initialMjml) {\n setMeta({ ...EMPTY_META, ...initialMeta });\n setBoot({ status: 'ready', document: null, draft: true, message: null });\n return;\n }\n const draft = autosaveOn ? readLocalDraft() : null;\n if (draft) {\n const when = new Date(draft.savedAt).toLocaleString(locale, {\n day: '2-digit',\n month: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n const restore = await confirm({\n title: t('Resume the draft?'),\n description: t('Unsaved template from {when}.', { when }),\n confirmLabel: t('Resume'),\n cancelLabel: t('Start over'),\n });\n if (restore) {\n setMeta({ ...EMPTY_META, ...draft.meta });\n setBoot({ status: 'ready', document: draft.document, draft: true, message: null });\n return;\n }\n clearLocalDraft();\n }\n setBoot({ status: 'ready', document: null, draft: false, message: null });\n })();\n // Initial content is read once, at start-up, like `templateId`.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initialTemplateId, storage, autosaveOn, confirm, t, locale]);\n\n const onReady = useCallback(() => {\n if (!boot.document) editor.loadMjml(initialMjml || starter);\n }, [editor, boot.document, starter, initialMjml]);\n\n // A resumed draft was never saved: it is \"modified\".\n const { markDirty, markClean, checkDirty } = state;\n useEffect(() => {\n if (ready && boot.draft) markDirty();\n }, [ready, boot.draft, markDirty]);\n\n /* ── Modified? (the host screen and \"Back\" need the immediate answer) ── */\n const isDirty = useCallback(\n () => (editor.status === 'ready' && checkDirty()) || metaDirty,\n [editor, checkDirty, metaDirty]\n );\n const reportDirty = useRef(onDirtyChange);\n reportDirty.current = onDirtyChange;\n useEffect(() => {\n reportDirty.current?.(dirty);\n }, [dirty]);\n useEffect(() => {\n if (!dirtyCheckRef) return undefined;\n dirtyCheckRef.current = isDirty;\n return () => {\n dirtyCheckRef.current = null;\n };\n }, [dirtyCheckRef, isDirty]);\n\n // Closing the tab with work in progress: the browser asks.\n useEffect(() => {\n if (!dirty) return undefined;\n const warn = (e) => {\n e.preventDefault();\n e.returnValue = '';\n };\n window.addEventListener('beforeunload', warn);\n return () => window.removeEventListener('beforeunload', warn);\n }, [dirty]);\n\n /* ── Save ────────────────────────────────────────────────────────────── */\n const savingRef = useRef(false);\n const latest = useRef({});\n latest.current = { template, meta, onSaved };\n\n const save = useCallback(\n async ({ auto = false } = {}) => {\n if (savingRef.current || editor.status !== 'ready') return false;\n const { template: current, meta: currentMeta } = latest.current;\n if (!currentMeta.name.trim()) {\n if (!auto) {\n setShowErrors(true);\n editor.select(null);\n notify('error', t('Give the template a name before saving it.'));\n }\n return false;\n }\n const document = editor.getDocument();\n const mjml = editor.exportMjml();\n const payload = { ...currentMeta, document, mjml };\n savingRef.current = true;\n setSaving(auto ? 'auto' : 'manual');\n try {\n const result = current.id\n ? await storage.save(current.id, { ...payload, revision: current.revision, createVersion: !auto })\n : await storage.create(payload);\n setTemplate({ id: result.template.id, revision: result.template.revision, savedAt: new Date(), auto });\n setSavedMeta(currentMeta);\n setShowErrors(false);\n setAutosaveBlocked(null);\n markClean(mjml);\n if (!current.id) clearLocalDraft();\n latest.current.onSaved?.(result.template);\n const warnings = result.warnings || [];\n if (warnings.length) {\n notify(\n 'warning',\n t('Saved, with {count} MJML warning(s): {message}', { count: warnings.length, message: warnings[0].message })\n );\n } else if (!auto) {\n notify(\n 'success',\n result.version ? t('Saved — version {n}.', { n: result.version.versionNumber }) : t('Template saved.')\n );\n }\n return true;\n } catch (error) {\n if (error.status === 409 && current.id) {\n if (auto) {\n setAutosaveBlocked(error.message);\n return false;\n }\n const copy = await confirm({\n title: t('Template changed in the meantime'),\n description: t('{message} Your version can be saved as a copy.', { message: error.message }),\n confirmLabel: t('Save a copy'),\n });\n if (!copy) return false;\n try {\n const result = await storage.create({\n ...payload,\n name: t('{name} (copy)', { name: currentMeta.name }).slice(0, 200),\n });\n const copyMeta = { ...currentMeta, name: result.template.name };\n setMeta(copyMeta);\n setSavedMeta(copyMeta);\n setTemplate({ id: result.template.id, revision: result.template.revision, savedAt: new Date(), auto: false });\n setAutosaveBlocked(null);\n markClean(mjml);\n latest.current.onSaved?.(result.template);\n notify('success', t('Copy saved: “{name}”.', { name: result.template.name }));\n return true;\n } catch (copyError) {\n notify('error', copyError.message);\n return false;\n }\n }\n if (auto) setAutosaveBlocked(error.message);\n else notify('error', error.message);\n return false;\n } finally {\n savingRef.current = false;\n setSaving(null);\n }\n },\n [editor, storage, markClean, notify, confirm, t]\n );\n\n // Ctrl+S: in the page (fields included) and in the canvas (iframe).\n useEffect(() => {\n const onKey = (e) => {\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey && e.key.toLowerCase() === 's') {\n e.preventDefault();\n save();\n }\n };\n window.addEventListener('keydown', onKey, true);\n return () => window.removeEventListener('keydown', onKey, true);\n }, [save]);\n useEffect(() => {\n if (!ready) return undefined;\n return editor.addShortcut('save', 'mod+s', () => save());\n }, [ready, editor, save]);\n\n /* ── Autosave ────────────────────────────────────────────────────────── */\n const scheduler = useMemo(\n () =>\n createAutosaveScheduler({\n run: () => save({ auto: true }),\n idleMs: autosaveOptions.idleMs,\n maxWaitMs: autosaveOptions.maxWaitMs,\n }),\n [save, autosaveOptions.idleMs, autosaveOptions.maxWaitMs]\n );\n useEffect(() => () => scheduler.dispose(), [scheduler]);\n useEffect(() => {\n if (!autosaveOn || !ready || !template.id || autosaveBlocked) return;\n if (dirty) scheduler.notify();\n else scheduler.reset();\n }, [autosaveOn, ready, template.id, autosaveBlocked, dirty, state.changes, meta, scheduler]);\n\n // Never saved template: local draft.\n useEffect(() => {\n if (!autosaveOn || !ready || template.id || !dirty) return undefined;\n const timer = setTimeout(() => {\n if (editor.status === 'ready') saveLocalDraft({ document: editor.getDocument(), meta });\n }, autosaveOptions.draftDelayMs ?? 1500);\n return () => clearTimeout(timer);\n }, [autosaveOn, ready, template.id, dirty, state.changes, meta, editor, autosaveOptions.draftDelayMs]);\n\n /* ── Back ────────────────────────────────────────────────────────────── */\n const back = async () => {\n if (isDirty()) {\n const ok = await confirm({\n title: t('Leave the builder?'),\n description: template.id\n ? t('Unsaved changes will be lost.')\n : t('The draft will be offered again next time.'),\n confirmLabel: t('Leave'),\n destructive: true,\n });\n if (!ok) return;\n }\n onClose?.();\n };\n\n /* ── Render ──────────────────────────────────────────────────────────── */\n const status = !ready\n ? t('Loading…')\n : saving === 'manual'\n ? t('Saving…')\n : saving === 'auto'\n ? t('Autosaving…')\n : autosaveBlocked\n ? t('Autosave paused')\n : dirty\n ? t('Unsaved changes')\n : template.savedAt\n ? template.auto\n ? t('Autosaved at {time}', { time: timeOf(template.savedAt) })\n : t('Saved at {time}', { time: timeOf(template.savedAt) })\n : template.id\n ? t('Saved')\n : t('No changes');\n\n const featureContext = {\n editor,\n storage,\n template,\n meta,\n ready,\n isDirty,\n markDirty,\n save,\n variables,\n systemVariables,\n canManageVariables,\n reloadVariables,\n testRecipients,\n };\n const toolbarFeatures = emailBuilderFeatures.list(\n (f) => f.enabled !== false && Boolean(f.toolbar) && (f.isAvailable ? f.isAvailable(featureContext) : true)\n );\n\n return (\n <div\n className={cn('eb-root eb:relative eb:flex eb:h-full eb:min-h-0 eb:flex-col eb:bg-background eb:text-foreground', className)}\n data-testid=\"email-builder\"\n data-status={state.status}\n data-template-id={template.id || ''}\n >\n <Toolbar\n title={meta.name}\n status={status}\n ready={ready}\n canUndo={state.canUndo}\n canRedo={state.canRedo}\n onUndo={() => editor.undo()}\n onRedo={() => editor.redo()}\n device={state.device}\n onDeviceChange={(device) => editor.setDevice(device)}\n onBack={onClose ? back : undefined}\n actions={\n <>\n {toolbarFeatures.map((feature) => {\n const Action = feature.toolbar;\n return <Action key={feature.id} context={featureContext} />;\n })}\n <Button size=\"sm-compact\" onClick={() => save()} disabled={!ready || saving !== null}>\n {saving === 'manual' ? <Loader2 className=\"eb:animate-spin\" /> : <Save />}\n {t('Save')}\n </Button>\n </>\n }\n />\n <div className=\"eb:grid eb:min-h-0 eb:flex-1 eb:grid-cols-[224px_minmax(0,1fr)_296px] eb:grid-rows-1\">\n <BlockSidebar editor={editor} disabled={!ready} />\n <div className=\"eb:relative eb:min-w-0 eb:bg-surface-75\" aria-busy={!ready}>\n {boot.status === 'error' || engineError ? (\n <div role=\"alert\" className=\"eb:flex eb:h-full eb:flex-col eb:items-center eb:justify-center eb:gap-2 eb:p-6 eb:text-center\">\n <AlertTriangle className=\"eb:size-6 eb:text-destructive\" aria-hidden=\"true\" />\n <p className=\"eb:text-[13px] eb:text-foreground\">\n {boot.status === 'error' ? t('The template could not be loaded.') : t('The builder could not start.')}\n </p>\n <p className=\"eb:max-w-sm eb:text-[12px] eb:text-foreground-muted\">{boot.message || engineError}</p>\n {engineError && (\n <Button\n variant=\"outline\"\n size=\"sm-compact\"\n onClick={() => {\n setEngineError(null);\n setAttempt((n) => n + 1);\n }}\n >\n {t('Retry')}\n </Button>\n )}\n </div>\n ) : (\n <>\n {boot.status === 'ready' && (\n <EmailCanvas\n key={attempt}\n editor={editor}\n document={boot.document}\n onReady={onReady}\n onError={(error) => setEngineError(error.message)}\n />\n )}\n {!ready && (\n <div className=\"eb:absolute eb:inset-0 eb:flex eb:items-center eb:justify-center eb:bg-surface-75\" role=\"status\" aria-live=\"polite\">\n <Loader2 className=\"eb:size-6 eb:animate-spin eb:text-foreground-muted\" aria-hidden=\"true\" />\n <span className=\"eb:sr-only\">{t('Loading the builder')}</span>\n </div>\n )}\n </>\n )}\n </div>\n <PropertiesPanel\n editor={editor}\n selection={ready ? state.selection : null}\n meta={meta}\n onMetaChange={setMeta}\n changes={state.changes}\n showErrors={showErrors}\n actions={<ElementActions editor={editor} selection={state.selection} />}\n services={services}\n variables={variables}\n />\n </div>\n <NoticeArea />\n </div>\n );\n}\n\n/**\n * @param {{\n * storage?: import('../storage/client.js').TemplateStorage,\n * templateId?: string|number|null,\n * editor?: import('../core/EmailEditor.js').EmailEditor,\n * locale?: string,\n * messages?: Record<string, string>,\n * onNotify?: (level: 'success'|'info'|'warning'|'error', message: string) => void,\n * variables?: import('../features/variables/catalog.js').EmailVariable[],\n * sender?: import('../features/templates/starter.js').StarterSender,\n * starterMjml?: string,\n * testRecipients?: string[],\n * initialMjml?: string,\n * initialMeta?: {name?: string, subject?: string, preheader?: string, description?: string},\n * onClose?: () => void,\n * onSaved?: (template: object) => void,\n * onDirtyChange?: (dirty: boolean) => void,\n * dirtyCheckRef?: {current: null | (() => boolean)},\n * className?: string,\n * }} props\n */\nexport default function EmailBuilder({ locale = 'en', messages, onNotify, ...props }) {\n return (\n <UiProvider locale={locale} messages={messages} onNotify={onNotify}>\n <Builder {...props} templateId={props.templateId ?? null} />\n </UiProvider>\n );\n}\n","// @ts-check\n/**\n * Starter template of a new email.\n *\n * A complete email rather than a blank page: header (logo or sender name),\n * headline, text, button, and a FOOTER with the sender's postal address and the\n * unsubscribe link — the two mentions a bulk email must carry (CAN-SPAM, GDPR)\n * and that get forgotten when starting from nothing.\n *\n * Written with the same settings as the blocks (`blocks/`), with longhand\n * paddings (see core/mjmlAttributes): what the canvas shows is what gets sent.\n */\n\nimport { identity } from '../../i18n/index.js';\nimport { DEFAULT_BUTTON_URL, FONT_STACK, PALETTE } from '../../blocks/shared.js';\n\n/**\n * @typedef {{\n * name?: string,\n * address?: string,\n * logoUrl?: string,\n * logoWidth?: number,\n * }} StarterSender\n */\n\nfunction escapeXml(text) {\n return String(text ?? '')\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\nconst SIDE = 'padding-left=\"32px\" padding-right=\"32px\"';\nconst TEXT = `font-family=\"${FONT_STACK}\" color=\"${PALETTE.ink}\"`;\n\n/**\n * @param {{\n * sender?: StarterSender,\n * buttonUrl?: string,\n * t?: import('../../i18n/index.js').Translate,\n * }} [options]\n */\nexport function createStarterMjml({ sender = {}, buttonUrl = DEFAULT_BUTTON_URL, t = identity } = {}) {\n const name = escapeXml(sender.name || t('Your company'));\n const footer = [name, sender.address ? escapeXml(sender.address) : ''].filter(Boolean).join(' · ');\n const header = sender.logoUrl\n ? `<mj-image src=\"${escapeXml(sender.logoUrl)}\" alt=\"${name}\" width=\"${Number(sender.logoWidth) || 140}px\" align=\"left\" ${SIDE}></mj-image>`\n : `<mj-text ${TEXT} font-size=\"18px\" line-height=\"24px\" font-weight=\"bold\" ${SIDE}>${name}</mj-text>`;\n\n return [\n '<mjml>',\n `<mj-body background-color=\"${PALETTE.canvas}\" width=\"600px\">`,\n // Header: logo or sender name.\n `<mj-section background-color=\"${PALETTE.surface}\" padding-top=\"28px\" padding-bottom=\"8px\">`,\n '<mj-column>',\n header,\n '</mj-column>',\n '</mj-section>',\n // Body: headline, text, button.\n `<mj-section background-color=\"${PALETTE.surface}\" padding-top=\"8px\" padding-bottom=\"28px\">`,\n '<mj-column>',\n `<mj-text ${TEXT} font-size=\"24px\" line-height=\"32px\" font-weight=\"bold\" ${SIDE}>${escapeXml(t('Your headline'))}</mj-text>`,\n `<mj-text ${TEXT} font-size=\"15px\" line-height=\"24px\" ${SIDE}>` +\n `${escapeXml(t('Hello {name},', { name: '{{contact.firstname}}' }))}<br /><br />${escapeXml(t('Your text.'))}</mj-text>`,\n `<mj-button href=\"${escapeXml(buttonUrl)}\" background-color=\"${PALETTE.navy}\" color=\"${PALETTE.white}\" ` +\n `font-family=\"${FONT_STACK}\" font-size=\"15px\" font-weight=\"bold\" border-radius=\"6px\" ` +\n `inner-padding=\"12px 28px\" align=\"left\" ${SIDE}>${escapeXml(t('Learn more'))}</mj-button>`,\n '</mj-column>',\n '</mj-section>',\n // Footer: sender and unsubscribe link.\n '<mj-section padding-top=\"20px\" padding-bottom=\"28px\">',\n '<mj-column>',\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"12px\" line-height=\"18px\" color=\"#6d7484\" align=\"center\" ${SIDE}>` +\n `${footer}<br />` +\n `<a href=\"{{ unsubscribe }}\" style=\"color:#6d7484;text-decoration:underline;\">${escapeXml(t('Unsubscribe'))}</a>` +\n '</mj-text>',\n '</mj-column>',\n '</mj-section>',\n '</mj-body>',\n '</mjml>',\n ].join('');\n}\n\n/** The starter template with default (English) texts. */\nexport const STARTER_MJML = createStarterMjml();\n","// @ts-check\n/**\n * AUTOSAVE scheduler — no React, no global timer.\n *\n * Two delays, because one is not enough:\n * - `idleMs` after the LAST change (do not save in the middle of a\n * sentence);\n * - `maxWaitMs` since the FIRST unsaved change: someone editing without a\n * pause for ten minutes must still get their work saved.\n *\n * `notify()` on every change, `reset()` after any save (automatic or not),\n * `dispose()` on unmount. Timers are injectable for tests.\n */\n\n/**\n * @param {{\n * run: () => (void | Promise<unknown>),\n * idleMs?: number,\n * maxWaitMs?: number,\n * now?: () => number,\n * setTimer?: (fn: () => void, ms: number) => any,\n * clearTimer?: (handle: any) => void,\n * }} options\n */\nexport function createAutosaveScheduler({\n run,\n idleMs = 20_000,\n maxWaitMs = 120_000,\n now = () => Date.now(),\n setTimer = (fn, ms) => setTimeout(fn, ms),\n clearTimer = (handle) => clearTimeout(handle),\n}) {\n /** @type {number|null} */\n let firstChangeAt = null;\n let handle = null;\n let disposed = false;\n\n function clear() {\n if (handle !== null) clearTimer(handle);\n handle = null;\n }\n\n function fire() {\n handle = null;\n firstChangeAt = null;\n if (!disposed) run();\n }\n\n return {\n notify() {\n if (disposed) return;\n const at = now();\n if (firstChangeAt === null) firstChangeAt = at;\n const remainingMax = Math.max(0, firstChangeAt + maxWaitMs - at);\n clear();\n handle = setTimer(fire, Math.min(idleMs, remainingMax));\n },\n reset() {\n clear();\n firstChangeAt = null;\n },\n get pending() {\n return handle !== null;\n },\n dispose() {\n disposed = true;\n clear();\n },\n };\n}\n","// @ts-check\n/**\n * LOCAL DRAFT of a template that has never been saved.\n *\n * A new template does not exist on the server yet: server-side autosave cannot\n * help it, and creating an \"untitled\" record on every open would clutter the\n * template library. Its work is therefore kept in the browser (document +\n * metadata such as label, subject, preview text), and offered the next time a\n * new template is opened, as long as it was never saved.\n *\n * Cleared on the first successful save. Ignored after seven days, or when it\n * cannot be read (written by another version of the builder).\n */\n\nimport { readDocument } from '../../core/document.js';\n\nconst KEY = 'best-email-builder:new-template-draft';\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\n/** @param {Storage|null|undefined} store */\nfunction usable(store) {\n return store && typeof store.getItem === 'function' ? store : null;\n}\n\nfunction defaultStore() {\n try {\n return typeof window !== 'undefined' ? window.localStorage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * @param {{document: object, meta: object}} draft\n * @param {Storage|null} [store]\n */\nexport function saveLocalDraft({ document, meta }, store = defaultStore()) {\n const target = usable(store);\n if (!target) return false;\n try {\n target.setItem(KEY, JSON.stringify({ savedAt: Date.now(), document, meta }));\n return true;\n } catch {\n // Quota exceeded, private browsing: a lost draft is not an error.\n return false;\n }\n}\n\n/**\n * @param {Storage|null} [store]\n * @returns {{savedAt: number, document: import('../../core/document.js').EmailDocument, meta: Record<string, string>}|null}\n */\nexport function readLocalDraft(store = defaultStore(), { now = Date.now() } = {}) {\n const target = usable(store);\n if (!target) return null;\n try {\n const raw = target.getItem(KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed || now - Number(parsed.savedAt) > MAX_AGE_MS) {\n target.removeItem(KEY);\n return null;\n }\n return { savedAt: Number(parsed.savedAt), document: readDocument(parsed.document), meta: parsed.meta || {} };\n } catch {\n target.removeItem(KEY);\n return null;\n }\n}\n\n/** @param {Storage|null} [store] */\nexport function clearLocalDraft(store = defaultStore()) {\n try {\n usable(store)?.removeItem(KEY);\n } catch {\n /* nothing to clear */\n }\n}\n","// @ts-check\n/**\n * STORAGE on the browser side — the interface only knows this contract.\n *\n * load(id) → template (document, mjml, revision…)\n * create(payload) → { template, warnings }\n * duplicate(id) → { template, warnings }\n * save(id, payload) → { template, warnings, version }\n * listVersions(id) → versions, newest first\n * getVersion(id, versionId) → version, project included\n * uploadImage(file) → { path }: RELATIVE path of the uploaded image\n * render(input) → { html, warnings, quality } (optional: preview)\n * sendTest(input) → { sent, failed, invalid, results } (optional: test send)\n * listVariables() → custom variables (optional: user-defined\n * saveVariable(variable) → saved variable variables, shared by\n * deleteVariable(key) → void every template)\n *\n * Two implementations: HTTP (talks to `createEmailBuilderHandler` from\n * `best-email-builder/server`, or to any backend with the same routes) and memory\n * (stories, tests, demos). The interface cannot tell them apart.\n *\n * The document ALWAYS travels serialized then re-read (`readDocument`): a\n * project that would not survive JSON shows up in the memory implementation\n * already, not in production.\n */\n\nimport { readDocument } from '../core/document.js';\nimport { DEFAULT_ASSETS_PATH } from '../renderer/links.js';\nimport { IMAGE_TYPES, imageUploadError } from '../validation/images.js';\nimport { DEFAULT_VARIABLES, validateCustomVariable } from '../features/variables/catalog.js';\n\n/**\n * @typedef {import('../core/document.js').EmailDocument} EmailDocument\n * @typedef {import('../features/variables/catalog.js').EmailVariable} EmailVariable\n *\n * @typedef {{\n * id: number|string,\n * name: string,\n * description?: string|null,\n * subject?: string|null,\n * preheader?: string|null,\n * revision?: string|null,\n * document?: EmailDocument,\n * mjml?: string,\n * html?: string,\n * createdAt?: string,\n * updatedAt?: string|null,\n * }} StoredTemplate\n *\n * @typedef {{\n * name?: string,\n * description?: string|null,\n * subject?: string|null,\n * preheader?: string|null,\n * document: EmailDocument,\n * mjml: string,\n * revision?: string|null,\n * createVersion?: boolean,\n * }} SavePayload\n *\n * @typedef {{\n * id: number|string,\n * versionNumber: number,\n * name?: string,\n * subject?: string|null,\n * createdBy?: string|null,\n * createdAt?: string,\n * }} TemplateVersion\n *\n * @typedef {{mjml: string, subject?: string|null, preheader?: string|null}} RenderInput\n * @typedef {{html: string, warnings: {message: string}[], quality: {code: string, level: string, message: string}[]}} RenderResult\n * @typedef {{email: string, ok: boolean, error: string|null}} TestResult\n * @typedef {{sent: number, failed: number, invalid: string[], results: TestResult[]}} SendTestResult\n *\n * @typedef {{\n * load: (id: number|string) => Promise<StoredTemplate>,\n * create: (payload: SavePayload & {name: string}) => Promise<{template: StoredTemplate, warnings: object[]}>,\n * duplicate: (id: number|string) => Promise<{template: StoredTemplate, warnings: object[]}>,\n * save: (id: number|string, payload: SavePayload) => Promise<{template: StoredTemplate, warnings: object[], version: {id: number|string, versionNumber: number}|null}>,\n * listVersions: (id: number|string) => Promise<TemplateVersion[]>,\n * getVersion: (id: number|string, versionId: number|string) => Promise<TemplateVersion & {document: EmailDocument, mjml: string}>,\n * uploadImage: (file: Blob & {name?: string}) => Promise<{path: string}>,\n * render?: (input: RenderInput) => Promise<RenderResult>,\n * sendTest?: (input: RenderInput & {emails: string[]}) => Promise<SendTestResult>,\n * listVariables?: () => Promise<EmailVariable[]>,\n * saveVariable?: (variable: Partial<EmailVariable>, options?: {create?: boolean}) => Promise<EmailVariable>,\n * deleteVariable?: (key: string) => Promise<void>,\n * }} TemplateStorage\n */\n\nexport class StorageError extends Error {\n /** @param {string} message @param {number} status @param {string} [code] */\n constructor(message, status, code) {\n super(message);\n this.name = 'StorageError';\n this.status = status;\n this.code = code;\n }\n}\n\n/** @param {{type?: string, size?: number}} file */\nfunction assertUploadable(file) {\n const error = imageUploadError(file);\n if (error) throw new StorageError(error, 415, 'UNSUPPORTED_IMAGE');\n}\n\n/** Re-reads the document of a received template (JSON → validated envelope). */\nfunction withDocument(template) {\n if (!template || !template.document) return template;\n return { ...template, document: readDocument(template.document) };\n}\n\n/**\n * Client for the routes of `createEmailBuilderHandler` (`best-email-builder/server`).\n *\n * @param {{\n * baseUrl?: string,\n * headers?: Record<string, string> | (() => Record<string, string>),\n * fetch?: typeof fetch,\n * }} [options]\n * @returns {TemplateStorage}\n */\nexport function createHttpStorage({ baseUrl = '/api/email-builder', headers = {}, fetch: fetchImpl } = {}) {\n const root = baseUrl.replace(/\\/+$/, '');\n const doFetch = fetchImpl || ((input, init) => fetch(input, init));\n const extraHeaders = () => (typeof headers === 'function' ? headers() : headers);\n\n /** @param {Response} res */\n async function unwrap(res) {\n const json = await res.json().catch(() => ({}));\n if (!res.ok || json.error) {\n throw new StorageError(json.error || `Request failed (HTTP ${res.status})`, res.status, json.code);\n }\n return json.data;\n }\n\n /** @param {string} path @param {RequestInit} [init] */\n async function call(path, init) {\n const res = await doFetch(`${root}${path}`, {\n ...init,\n headers: { 'Content-Type': 'application/json', ...extraHeaders(), ...(init?.headers || {}) },\n });\n return unwrap(res);\n }\n\n /** @param {SavePayload} payload */\n function body(payload) {\n return JSON.stringify({ ...payload, document: readDocument(payload.document) });\n }\n\n return {\n load: async (id) => withDocument(await call(`/templates/${encodeURIComponent(id)}`)),\n create: async (payload) => call('/templates', { method: 'POST', body: body(payload) }),\n duplicate: async (id) => call('/templates', { method: 'POST', body: JSON.stringify({ duplicateOf: id }) }),\n save: async (id, payload) => call(`/templates/${encodeURIComponent(id)}`, { method: 'PUT', body: body(payload) }),\n listVersions: async (id) => call(`/templates/${encodeURIComponent(id)}/versions`),\n getVersion: async (id, versionId) =>\n withDocument(await call(`/templates/${encodeURIComponent(id)}/versions/${encodeURIComponent(versionId)}`)),\n render: async (input) => call('/render', { method: 'POST', body: JSON.stringify(input) }),\n sendTest: async (input) => call('/test', { method: 'POST', body: JSON.stringify(input) }),\n listVariables: async () => call('/variables'),\n saveVariable: async (variable, { create = false } = {}) =>\n create\n ? call('/variables', { method: 'POST', body: JSON.stringify(variable) })\n : call(`/variables/${encodeURIComponent(String(variable.key))}`, { method: 'PUT', body: JSON.stringify(variable) }),\n deleteVariable: async (key) => {\n await call(`/variables/${encodeURIComponent(key)}`, { method: 'DELETE' });\n },\n async uploadImage(file) {\n assertUploadable(file);\n const form = new FormData();\n form.append('file', file, file.name || 'image');\n // No Content-Type: the browser sets the multipart boundary itself.\n const res = await doFetch(`${root}/assets`, { method: 'POST', body: form, headers: extraHeaders() });\n const data = await unwrap(res);\n return { path: data.path };\n },\n };\n}\n\n/**\n * In-memory storage, same contract. Documents are kept SERIALIZED.\n * `render` and `sendTest` cannot run in a browser (MJML compiles on the\n * server): pass implementations to enable the preview and test buttons.\n *\n * @param {{\n * render?: TemplateStorage['render'],\n * sendTest?: TemplateStorage['sendTest'],\n * assetsPath?: string,\n * systemVariables?: EmailVariable[],\n * }} [options] `systemVariables`: keys a custom variable may not take\n * @returns {TemplateStorage & {dump: () => object}}\n */\nexport function createMemoryStorage({ render, sendTest, assetsPath = DEFAULT_ASSETS_PATH, systemVariables = DEFAULT_VARIABLES } = {}) {\n /** @type {Map<string, any>} */\n const rows = new Map();\n /** @type {Map<string, any[]>} */\n const versions = new Map();\n /** @type {Map<string, Blob>} */\n const images = new Map();\n /** @type {Map<string, EmailVariable>} */\n const customVariables = new Map();\n let nextId = 1;\n let tick = Date.parse('2026-01-01T00:00:00.000Z');\n const now = () => new Date((tick += 1000)).toISOString();\n\n /** @param {any} row */\n function toTemplate(row) {\n return {\n id: row.id,\n name: row.name,\n description: row.description,\n subject: row.subject,\n preheader: row.preheader,\n revision: row.revision,\n document: readDocument(row.documentJson),\n mjml: row.mjml,\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n }\n\n /** @param {any} row */\n function snapshot(row) {\n const list = versions.get(String(row.id)) || [];\n const entry = {\n id: list.length + 1,\n versionNumber: list.length + 1,\n name: row.name,\n subject: row.subject,\n createdBy: null,\n createdAt: row.revision,\n documentJson: row.documentJson,\n mjml: row.mjml,\n };\n versions.set(String(row.id), [...list, entry]);\n return { id: entry.id, versionNumber: entry.versionNumber };\n }\n\n /** @param {number|string} id */\n function rowOf(id) {\n const row = rows.get(String(id));\n if (!row) throw new StorageError('Template not found', 404, 'NOT_FOUND');\n return row;\n }\n\n /** @type {TemplateStorage & {dump: () => object}} */\n const storage = {\n async load(id) {\n return toTemplate(rowOf(id));\n },\n async create(payload) {\n if (!payload.name?.trim()) throw new StorageError('Name required', 400, 'NAME_REQUIRED');\n const at = now();\n const row = {\n id: nextId++,\n name: payload.name.trim(),\n description: payload.description ?? null,\n subject: payload.subject ?? null,\n preheader: payload.preheader ?? null,\n documentJson: JSON.stringify(readDocument(payload.document)),\n mjml: payload.mjml,\n createdAt: at,\n updatedAt: null,\n revision: at,\n };\n rows.set(String(row.id), row);\n snapshot(row);\n return { template: toTemplate(row), warnings: [] };\n },\n async duplicate(id) {\n const source = rowOf(id);\n return storage.create({\n name: `${source.name} (copy)`,\n description: source.description,\n subject: source.subject,\n preheader: source.preheader,\n document: readDocument(source.documentJson),\n mjml: source.mjml,\n });\n },\n async save(id, payload) {\n const row = rowOf(id);\n if (payload.revision && payload.revision !== row.revision) {\n throw new StorageError('Template changed in the meantime — reload it before saving', 409, 'CONFLICT');\n }\n const at = now();\n Object.assign(row, {\n ...(payload.name !== undefined ? { name: payload.name } : {}),\n ...(payload.description !== undefined ? { description: payload.description } : {}),\n ...(payload.subject !== undefined ? { subject: payload.subject } : {}),\n ...(payload.preheader !== undefined ? { preheader: payload.preheader } : {}),\n documentJson: JSON.stringify(readDocument(payload.document)),\n mjml: payload.mjml,\n updatedAt: at,\n revision: at,\n });\n const version = payload.createVersion ? snapshot(row) : null;\n const { document: _omit, ...template } = toTemplate(row);\n return { template, warnings: [], version };\n },\n async listVersions(id) {\n rowOf(id);\n return [...(versions.get(String(id)) || [])].reverse().map(({ documentJson: _d, mjml: _m, ...v }) => v);\n },\n async getVersion(id, versionId) {\n const entry = (versions.get(String(id)) || []).find((v) => String(v.id) === String(versionId));\n if (!entry) throw new StorageError('Version not found', 404, 'NOT_FOUND');\n const { documentJson, ...version } = entry;\n return { ...version, document: readDocument(documentJson) };\n },\n async uploadImage(file) {\n assertUploadable(file);\n // Same key as the server: 32 hex characters of the hash + extension.\n const digest = await crypto.subtle.digest('SHA-256', await file.arrayBuffer());\n const hex = [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');\n const path = `${assetsPath}${hex.slice(0, 32)}.${IMAGE_TYPES[file.type]}`;\n images.set(path, file);\n return { path };\n },\n async listVariables() {\n return [...customVariables.values()].map((v) => ({ ...v }));\n },\n async saveVariable(input, { create = false } = {}) {\n const existing = [...systemVariables, ...customVariables.values()];\n if (!create && !customVariables.has(String(input?.key))) {\n throw new StorageError('Variable not found', 404, 'NOT_FOUND');\n }\n const base = create ? {} : customVariables.get(String(input.key));\n const { variable, errors } = validateCustomVariable({ ...base, ...input }, { existing, editing: create ? null : input.key });\n if (errors) throw new StorageError(Object.values(errors)[0], 400, 'INVALID_VARIABLE');\n customVariables.set(variable.key, variable);\n return { ...variable };\n },\n async deleteVariable(key) {\n if (!customVariables.delete(String(key))) throw new StorageError('Variable not found', 404, 'NOT_FOUND');\n },\n ...(render ? { render } : {}),\n ...(sendTest ? { sendTest } : {}),\n dump: () => ({\n rows: [...rows.values()],\n versions: Object.fromEntries(versions),\n images: [...images.keys()],\n variables: [...customVariables.values()],\n }),\n };\n return storage;\n}\n","import { useEffect, useRef } from 'react';\nimport { cn } from './primitives/cn.js';\n\n/**\n * Canvas area: the node where the editor mounts its engine.\n *\n * Only knows `EmailEditor`: `initialize` on mount, `destroy` on unmount.\n * React strict mode's double mount is absorbed by the editor (an\n * initialization made stale by a `destroy` never reports ready).\n *\n * `document` is only read on mount: reloading a document goes through\n * `editor.loadDocument`, not through a new render.\n */\nexport default function EmailCanvas({ editor, document = null, onReady, onError, className }) {\n const ref = useRef(null);\n const documentRef = useRef(document);\n const callbacks = useRef({ onReady, onError });\n callbacks.current = { onReady, onError };\n\n useEffect(() => {\n if (!editor || !ref.current) return undefined;\n let alive = true;\n editor\n .initialize({ container: ref.current, document: documentRef.current })\n .then(() => {\n if (alive && editor.status === 'ready') callbacks.current.onReady?.(editor);\n })\n .catch((error) => {\n if (alive) callbacks.current.onError?.(error);\n });\n return () => {\n alive = false;\n editor.destroy();\n };\n }, [editor]);\n\n return <div ref={ref} className={cn('eb-canvas eb:h-full eb:w-full', className)} data-testid=\"eb-canvas\" />;\n}\n","import { SectionLabel } from './primitives/misc.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport {\n Columns2,\n Columns3,\n Image as ImageIcon,\n MoveVertical,\n RectangleHorizontal,\n SeparatorHorizontal,\n Square,\n Type,\n} from 'lucide-react';\nimport { cn } from './primitives/cn.js';\nimport { useT } from './context.jsx';\n\n/**\n * Block sidebar, left of the canvas.\n *\n * Two gestures for the same block:\n * - CLICK: the editor inserts it at the logical place (inside the selected\n * column, after the selected element, otherwise at the end of the email);\n * - DRAG onto the canvas: the engine follows the pointer and rejects the\n * drop targets MJML does not allow.\n *\n * Blocks come from the registry (`editor.listBlocks()`): a block removed from\n * the registry disappears from here without touching this file. Only the icon\n * table is local (names come from the registry, components from here).\n */\n\nconst ICONS = {\n Type,\n Image: ImageIcon,\n RectangleHorizontal,\n SeparatorHorizontal,\n MoveVertical,\n Square,\n Columns2,\n Columns3,\n};\n\nconst GROUPS = [\n { kind: 'content', title: 'Content' },\n { kind: 'layout', title: 'Layout' },\n];\n\nfunction BlockTile({ block, disabled, onAdd, onDragStart, onDragEnd }) {\n const t = useT();\n const Icon = ICONS[block.icon] || Square;\n return (\n <TooltipWrap label={block.description ? t(block.description) : block.description}>\n <button\n type=\"button\"\n draggable={!disabled}\n disabled={disabled}\n onClick={() => onAdd(block.id)}\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'copy';\n e.dataTransfer.setData('text/plain', block.id);\n onDragStart(block.id, e.nativeEvent);\n }}\n onDragEnd={(e) => onDragEnd(e.dataTransfer?.dropEffect === 'none')}\n data-block-id={block.id}\n className={cn(\n 'eb:flex eb:h-20 eb:cursor-grab eb:select-none eb:flex-col eb:items-center eb:justify-center eb:gap-1.5 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:px-2 eb:text-center eb:transition-colors eb:active:cursor-grabbing',\n 'eb:hover:border-primary/50 eb:hover:bg-primary/5 eb:focus-visible:outline-none eb:focus-visible:ring-2 eb:focus-visible:ring-ring/50',\n disabled && 'eb:cursor-not-allowed eb:opacity-50'\n )}\n >\n <Icon className=\"eb:h-5 eb:w-5 eb:text-foreground-lighter\" aria-hidden=\"true\" />\n <span className=\"eb:text-[12px] eb:text-foreground\">{t(block.label)}</span>\n </button>\n </TooltipWrap>\n );\n}\n\nexport default function BlockSidebar({ editor, disabled = false }) {\n const t = useT();\n const blocks = editor.listBlocks();\n\n return (\n <aside aria-label={t('Blocks')} className=\"eb:min-h-0 eb:space-y-5 eb:overflow-y-auto eb:border-r eb:border-border eb:p-3\">\n {GROUPS.map((group) => {\n const items = blocks.filter((b) => b.kind === group.kind && b.mjml);\n if (!items.length) return null;\n return (\n <section key={group.kind} className=\"eb:space-y-2\">\n <SectionLabel>{t(group.title)}</SectionLabel>\n <div className=\"eb:grid eb:grid-cols-2 eb:gap-2\">\n {items.map((block) => (\n <BlockTile\n key={block.id}\n block={block}\n disabled={disabled}\n onAdd={(id) => editor.addBlock(id)}\n onDragStart={(id, event) => editor.startBlockDrag(id, event)}\n onDragEnd={(cancel) => editor.endBlockDrag(cancel)}\n />\n ))}\n </div>\n </section>\n );\n })}\n </aside>\n );\n}\n","import { Button } from './primitives/button.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport { ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Copy, Trash2 } from 'lucide-react';\nimport { useT } from './context.jsx';\n\n/**\n * Actions on the selected element: move, duplicate, delete.\n *\n * Same gestures as the canvas toolbar (above the element) and the keyboard\n * (Del), but readable and keyboard-accessible from the panel. No confirmation\n * before deleting: \"Undo\" (Ctrl+Z) reverts it.\n *\n * A column moves left or right, everything else up or down.\n */\nexport default function ElementActions({ editor, selection }) {\n const t = useT();\n if (!selection || (!selection.canRemove && !selection.canDuplicate)) return null;\n const horizontal = selection.tagName === 'mj-column';\n const [Prev, Next] = horizontal ? [ArrowLeft, ArrowRight] : [ArrowUp, ArrowDown];\n const [prevLabel, nextLabel] = horizontal\n ? [t('Move left'), t('Move right')]\n : [t('Move up'), t('Move down')];\n\n return (\n <div className=\"eb:flex eb:items-center eb:gap-0.5 eb:border-b eb:border-border eb:px-3 eb:py-1.5\" role=\"toolbar\" aria-label={t('Element actions')}>\n <TooltipWrap label={prevLabel}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={prevLabel}\n disabled={!selection.canMoveUp}\n onClick={() => editor.move(-1, selection.id)}\n >\n <Prev />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={nextLabel}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={nextLabel}\n disabled={!selection.canMoveDown}\n onClick={() => editor.move(1, selection.id)}\n >\n <Next />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={t('Duplicate')}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={t('Duplicate')}\n disabled={!selection.canDuplicate}\n onClick={() => editor.duplicate(selection.id)}\n >\n <Copy />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={t('Delete (Del)')}>\n <Button\n variant=\"ghost\"\n size=\"icon-sm-compact\"\n aria-label={t('Delete')}\n disabled={!selection.canRemove}\n onClick={() => editor.remove(selection.id)}\n className=\"eb:ml-auto eb:text-foreground-muted eb:hover:bg-destructive/10 eb:hover:text-destructive\"\n >\n <Trash2 />\n </Button>\n </TooltipWrap>\n </div>\n );\n}\n","import { useMemo, useRef } from 'react';\nimport { Button } from './primitives/button.jsx';\nimport { Input } from './primitives/fields.jsx';\nimport { Label } from './primitives/fields.jsx';\nimport { Textarea } from './primitives/fields.jsx';\nimport { SectionLabel } from './primitives/misc.jsx';\nimport { TruncatedText as FadedText } from './primitives/misc.jsx';\nimport { X } from 'lucide-react';\nimport { GROUPS } from '../blocks/shared.js';\nimport { PropertyField } from './fields.jsx';\nimport { useT } from './context.jsx';\nimport VariableInsertButton from '../features/variables/VariableInsertButton.jsx';\n\n/**\n * Properties panel, right of the canvas.\n *\n * an element is selected -> its properties, by group (those of its block in\n * the registry); a button also gets its label here;\n * nothing is selected -> the TEMPLATE (name, subject, preview text) and\n * the page (background, width), i.e. the email body.\n *\n * `actions`: the element action bar (move, duplicate, delete), provided by\n * the host screen.\n */\n\nconst GROUP_ORDER = Object.values(GROUPS);\n\n/** A block's properties, grouped in panel order. */\nfunction grouped(properties) {\n const map = new Map();\n for (const property of properties) {\n if (!map.has(property.group)) map.set(property.group, []);\n map.get(property.group).push(property);\n }\n return [...map.entries()].sort(\n ([a], [b]) =>\n (GROUP_ORDER.indexOf(a) + 1 || 99) - (GROUP_ORDER.indexOf(b) + 1 || 99)\n );\n}\n\nfunction PropertyGroups({ editor, element, block, idPrefix, services = null }) {\n const t = useT();\n return grouped(block?.properties || []).map(([group, properties]) => (\n <section key={group} className=\"eb:space-y-3\">\n <SectionLabel>{t(group)}</SectionLabel>\n {properties.map((property) => (\n <PropertyField\n key={`${element.id}:${property.key}`}\n idPrefix={idPrefix}\n property={property}\n value={element.values[property.key]}\n services={services}\n onCommit={(value) => editor.updateProperties({ [property.key]: value }, element.id)}\n />\n ))}\n </section>\n ));\n}\n\nconst LABEL_PROPERTY = { key: 'content', label: 'Label', type: 'text', group: GROUPS.content };\n\nfunction PanelHeader({ title, onClose }) {\n const t = useT();\n return (\n <header className=\"eb:sticky eb:top-0 eb:z-10 eb:flex eb:h-11 eb:shrink-0 eb:items-center eb:gap-2 eb:border-b eb:border-border eb:bg-background eb:px-4\">\n <h3 className=\"eb:min-w-0 eb:flex-1 eb:text-[13px] eb:font-medium eb:text-foreground\">\n <FadedText>{title}</FadedText>\n </h3>\n {onClose && (\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onClose} aria-label={t('Deselect')}>\n <X />\n </Button>\n )}\n </header>\n );\n}\n\n/** Nothing selected: the template and the page. */\nfunction TemplateSettings({ editor, meta, onMetaChange, changes, showErrors, variables = null }) {\n const t = useT();\n const subjectRef = useRef(null);\n const preheaderRef = useRef(null);\n const rootId = editor.getRootId();\n // `changes`: the page is re-read after every change (background, width).\n const root = useMemo(() => (rootId ? editor.getElement(rootId) : null), [editor, rootId, changes]); // eslint-disable-line react-hooks/exhaustive-deps\n const bodyBlock = root?.blockId ? editor.getBlock(root.blockId) : null;\n const field = (key) => (e) => onMetaChange({ ...meta, [key]: e.target.value });\n\n return (\n <>\n <PanelHeader title={t('Email')} />\n <div className=\"eb:space-y-5 eb:p-4\">\n <section className=\"eb:space-y-3\">\n <SectionLabel>{t('Template')}</SectionLabel>\n <div className=\"eb:space-y-1.5\">\n <Label htmlFor=\"eb-meta-name\" className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {t('Name')} <span className=\"eb:text-destructive\">*</span>\n </Label>\n <Input\n id=\"eb-meta-name\"\n maxLength={200}\n value={meta.name}\n onChange={field('name')}\n aria-invalid={(showErrors && !meta.name.trim()) || undefined}\n />\n {showErrors && !meta.name.trim() && (\n <p className=\"eb:text-[12px] eb:text-destructive\">{t('Name is required')}</p>\n )}\n </div>\n <div className=\"eb:space-y-1.5\">\n <div className=\"eb:flex eb:h-6 eb:items-center eb:justify-between\">\n <Label htmlFor=\"eb-meta-subject\" className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {t('Subject')}\n </Label>\n {variables && (\n <VariableInsertButton\n variables={variables}\n inputRef={subjectRef}\n value={meta.subject}\n onChange={(subject) => onMetaChange({ ...meta, subject })}\n label={t('Insert a variable in the subject')}\n />\n )}\n </div>\n <Input ref={subjectRef} id=\"eb-meta-subject\" maxLength={250} value={meta.subject} onChange={field('subject')} />\n </div>\n <div className=\"eb:space-y-1.5\">\n <div className=\"eb:flex eb:h-6 eb:items-center eb:justify-between\">\n <Label htmlFor=\"eb-meta-preheader\" className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {t('Preview text')}\n </Label>\n {variables && (\n <VariableInsertButton\n variables={variables}\n inputRef={preheaderRef}\n value={meta.preheader}\n onChange={(preheader) => onMetaChange({ ...meta, preheader })}\n label={t('Insert a variable in the preview text')}\n />\n )}\n </div>\n <Textarea\n ref={preheaderRef}\n id=\"eb-meta-preheader\"\n rows={2}\n maxLength={250}\n value={meta.preheader}\n onChange={field('preheader')}\n placeholder={t('Shown after the subject in the inbox')}\n />\n </div>\n </section>\n {root && bodyBlock && <PropertyGroups editor={editor} element={root} block={bodyBlock} idPrefix=\"eb-page\" />}\n </div>\n </>\n );\n}\n\nexport default function PropertiesPanel({\n editor,\n selection,\n meta,\n onMetaChange,\n changes,\n actions = null,\n showErrors = false,\n services = null,\n variables = null,\n}) {\n const t = useT();\n const block = selection?.blockId ? editor.getBlock(selection.blockId) : null;\n\n return (\n <aside aria-label={t('Properties')} className=\"eb:min-h-0 eb:overflow-y-auto eb:border-l eb:border-border\" data-testid=\"eb-properties\">\n {!selection ? (\n <TemplateSettings\n editor={editor}\n meta={meta}\n onMetaChange={onMetaChange}\n changes={changes}\n showErrors={showErrors}\n variables={variables}\n />\n ) : (\n <>\n <PanelHeader title={t(selection.label)} onClose={() => editor.select(null)} />\n {actions}\n <div className=\"eb:space-y-5 eb:p-4\">\n {selection.tagName === 'mj-button' && (\n <section className=\"eb:space-y-3\">\n <SectionLabel>{t(GROUPS.content)}</SectionLabel>\n <PropertyField\n key={`${selection.id}:content`}\n idPrefix=\"eb-prop\"\n property={LABEL_PROPERTY}\n value={selection.content || ''}\n onCommit={(value) => editor.setContent(value || '', selection.id)}\n />\n </section>\n )}\n {selection.tagName === 'mj-text' && (\n <p className=\"eb:text-[12px] eb:text-foreground-muted\">{t('Double-click the text to edit it.')}</p>\n )}\n <PropertyGroups editor={editor} element={selection} block={block} idPrefix=\"eb-prop\" services={services} />\n </div>\n </>\n )}\n </aside>\n );\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { Input } from './primitives/fields.jsx';\nimport { Textarea } from './primitives/fields.jsx';\nimport { Label } from './primitives/fields.jsx';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from './primitives/overlays.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport { ColorPicker } from './primitives/color-picker.jsx';\nimport { Button } from './primitives/button.jsx';\nimport { AlignCenter, AlignJustify, AlignLeft, AlignRight, Loader2, Upload } from 'lucide-react';\nimport { cn } from './primitives/cn.js';\nimport { isSafeUrl } from '../validation/urls.js';\nimport { imageUploadError } from '../validation/images.js';\nimport { parseSpacing, formatSpacing } from '../core/mjmlAttributes.js';\nimport { useT } from './context.jsx';\n\n/**\n * Properties panel fields - one per `BlockProperty` type.\n *\n * -- ONE EDIT = ONE UNDO STEP -----------------------------------------------\n * Each field keeps a local draft and only hands it to the editor once the\n * edit is FINISHED: on blur or Enter for text, after a 250 ms pause for a\n * color being dragged. Typing \"Hello\" must not leave five steps in the\n * history, nor recompile the canvas on every keystroke. Escape restores the\n * original value.\n *\n * -- WHAT CANNOT BE SENT IS REJECTED HERE -----------------------------------\n * An address the server would refuse (`javascript:`, non-https image) is\n * flagged under the field and not passed on; a color with transparency loses\n * its alpha channel, which no version of Outlook reads.\n *\n * -- IMAGES -----------------------------------------------------------------\n * An image is UPLOADED (application storage, `uploadImage`) or given as an\n * https address. Never `data:`: it would bloat the email.\n */\n\nconst COLOR_DEBOUNCE_MS = 250;\n\n/** `#RGB` or `#RRGGBB`; a `#RRGGBBAA` is reduced to `#RRGGBB`. */\nexport function emailColor(value) {\n const v = String(value || '').trim();\n if (/^#[0-9a-f]{3}$/i.test(v) || /^#[0-9a-f]{6}$/i.test(v)) return v.toLowerCase();\n if (/^#[0-9a-f]{8}$/i.test(v)) return v.slice(0, 7).toLowerCase();\n return null;\n}\n\n/**\n * A field's draft, realigned with the editor value when it changes from\n * elsewhere (undo, redo) - except while typing, which must not be\n * overwritten under the user's fingers.\n */\nfunction useDraft(value, toDraft) {\n const [draft, setDraft] = useState(() => toDraft(value));\n const ref = useRef(null);\n const convert = useRef(toDraft);\n convert.current = toDraft;\n useEffect(() => {\n const el = ref.current;\n const focused = el && el.ownerDocument?.activeElement && el.contains(el.ownerDocument.activeElement);\n if (!focused) setDraft(convert.current(value));\n }, [value]);\n return [draft, setDraft, ref];\n}\n\nconst asText = (v) => v || '';\n\nfunction FieldLabel({ id, children }) {\n return (\n <Label htmlFor={id} className=\"eb:text-[12px] eb:font-normal eb:text-foreground-lighter\">\n {children}\n </Label>\n );\n}\n\nfunction FieldError({ children }) {\n return children ? <p className=\"eb:text-[12px] eb:text-destructive\">{children}</p> : null;\n}\n\n/** Text, address, long text: draft committed on blur or Enter. */\nfunction TextField({ id, property, value, onCommit, addon = null, error = null }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asText);\n const isUrl = property.type === 'url' || property.type === 'image';\n const kind = property.type === 'image' ? 'image' : 'link';\n const invalid = isUrl && draft.trim() !== '' && !isSafeUrl(draft, kind);\n\n const commit = () => {\n const next = draft.trim();\n if (invalid || next === (value || '')) return;\n onCommit(next || null);\n };\n const keyDown = (e) => {\n if (e.key === 'Escape') {\n setDraft(value || '');\n e.currentTarget.blur();\n } else if (e.key === 'Enter' && property.type !== 'textarea') {\n e.preventDefault();\n commit();\n }\n };\n\n const shared = {\n id,\n value: draft,\n placeholder: property.placeholder ? t(property.placeholder) : property.placeholder,\n onChange: (e) => setDraft(e.target.value),\n onBlur: commit,\n onKeyDown: keyDown,\n 'aria-invalid': invalid || undefined,\n };\n return (\n <div ref={ref} className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n {property.type === 'textarea' ? (\n <Textarea rows={3} {...shared} />\n ) : addon ? (\n <div className=\"eb:flex eb:gap-2\">\n <Input {...shared} className=\"eb:min-w-0 eb:flex-1\" />\n {addon}\n </div>\n ) : (\n <Input {...shared} />\n )}\n <FieldError>{invalid ? (kind === 'image' ? t('An https:// address is required') : t('Address not allowed')) : error}</FieldError>\n </div>\n );\n}\n\n/** Image: https address, or a file uploaded to the application storage. */\nfunction ImageField({ id, property, value, onCommit, services }) {\n const t = useT();\n const inputRef = useRef(/** @type {HTMLInputElement|null} */ (null));\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState(/** @type {string|null} */ (null));\n const upload = services?.uploadImage;\n\n const pick = async (event) => {\n const file = event.target.files?.[0];\n event.target.value = '';\n if (!file || !upload) return;\n const refused = imageUploadError(file, { t });\n setError(refused);\n if (refused) return;\n setBusy(true);\n try {\n const { path } = await upload(file);\n onCommit(path);\n } catch (err) {\n setError(err?.message || t('Upload failed'));\n } finally {\n setBusy(false);\n }\n };\n\n const addon = upload ? (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n accept=\"image/png,image/jpeg,image/gif\"\n className=\"eb:sr-only\"\n tabIndex={-1}\n aria-hidden=\"true\"\n data-testid={`${id}-file`}\n onChange={pick}\n />\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n disabled={busy}\n onClick={() => inputRef.current?.click()}\n >\n {busy ? <Loader2 className=\"eb:animate-spin\" /> : <Upload />}\n {t('Upload')}\n </Button>\n </>\n ) : null;\n\n return <TextField id={id} property={property} value={value} onCommit={onCommit} addon={addon} error={error} />;\n}\n\n/** Number in pixels, clamped. Empty = MJML default value. */\nconst asNumber = (v) => {\n const n = Number.parseFloat(String(v || ''));\n return Number.isFinite(n) ? String(n) : '';\n};\n\nfunction SizeField({ id, property, value, onCommit }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asNumber);\n\n const commit = (raw = draft) => {\n if (String(raw).trim() === '') {\n if (value) onCommit(null);\n return;\n }\n let n = Number.parseFloat(String(raw));\n if (!Number.isFinite(n)) return;\n if (property.min !== undefined) n = Math.max(property.min, n);\n if (property.max !== undefined) n = Math.min(property.max, n);\n setDraft(String(n));\n const next = `${n}${property.unit || 'px'}`;\n if (next !== value) onCommit(next);\n };\n\n return (\n <div ref={ref} className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <div className=\"eb:relative\">\n <Input\n id={id}\n type=\"number\"\n inputMode=\"numeric\"\n min={property.min}\n max={property.max}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onBlur={() => commit()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commit();\n if (e.key === 'Escape') setDraft(asNumber(value));\n }}\n className=\"eb:pr-9 eb:tabular-nums\"\n />\n <span className=\"eb:pointer-events-none eb:absolute eb:right-3 eb:top-1/2 eb:-translate-y-1/2 eb:text-[12px] eb:text-foreground-muted\">\n {property.unit || 'px'}\n </span>\n </div>\n </div>\n );\n}\n\n/** Color: swatch + hex code, committed after a short pause. */\nfunction ColorField({ id, property, value, onCommit }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asText);\n const timer = useRef(null);\n const latest = useRef({ value, onCommit });\n latest.current = { value, onCommit };\n\n useEffect(() => () => clearTimeout(timer.current), []);\n\n const change = (next) => {\n setDraft(next);\n clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n const color = emailColor(next);\n if (!String(next || '').trim()) {\n if (latest.current.value) latest.current.onCommit(null);\n } else if (color && color !== latest.current.value) {\n latest.current.onCommit(color);\n }\n }, COLOR_DEBOUNCE_MS);\n };\n\n return (\n <div ref={ref} className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <ColorPicker id={id} value={draft} onChange={change} />\n </div>\n );\n}\n\n/** Radix does not accept an empty option (\"default value\"): use a sentinel. */\nconst DEFAULT_OPTION = '__default__';\n\nfunction SelectField({ id, property, value, onCommit }) {\n const t = useT();\n const current = value || DEFAULT_OPTION;\n return (\n <div className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <Select\n value={current}\n onValueChange={(next) => {\n const v = next === DEFAULT_OPTION ? '' : next;\n if (v !== (value || '')) onCommit(v || null);\n }}\n >\n <SelectTrigger id={id} className=\"eb:w-full\">\n <SelectValue placeholder={t('Default')} />\n </SelectTrigger>\n <SelectContent>\n {!(property.options || []).some((o) => !o.value) && (\n <SelectItem value={DEFAULT_OPTION}>{t('Default')}</SelectItem>\n )}\n {(property.options || []).map((o) => (\n <SelectItem key={o.value || DEFAULT_OPTION} value={o.value || DEFAULT_OPTION}>\n {t(o.label)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n}\n\nconst ALIGN_ICONS = { left: AlignLeft, center: AlignCenter, right: AlignRight, justify: AlignJustify };\n\n/** Alignment: toggle group (solid `bg-primary` on the active one). */\nfunction AlignField({ id, property, value, onCommit }) {\n const t = useT();\n return (\n <div className=\"eb:space-y-1.5\">\n <FieldLabel id={id}>{t(property.label)}</FieldLabel>\n <div\n id={id}\n role=\"radiogroup\"\n aria-label={t(property.label)}\n className=\"eb:flex eb:w-fit eb:items-center eb:gap-0.5 eb:rounded-lg2 eb:border eb:border-border-strong eb:bg-surface-75 eb:p-0.5\"\n >\n {(property.options || []).map((option) => {\n const Icon = ALIGN_ICONS[option.value] || AlignLeft;\n const active = value === option.value;\n return (\n <TooltipWrap key={option.value} label={t(option.label)}>\n <button\n type=\"button\"\n role=\"radio\"\n aria-checked={active}\n aria-label={t(option.label)}\n onClick={() => !active && onCommit(option.value)}\n className={cn(\n 'eb:inline-flex eb:h-7 eb:w-7 eb:items-center eb:justify-center eb:rounded-lg2 eb:transition-colors',\n active\n ? 'eb:bg-primary eb:text-primary-foreground'\n : 'eb:text-foreground-lighter eb:hover:bg-surface-200 eb:hover:text-foreground'\n )}\n >\n <Icon className=\"eb:h-3.5 eb:w-3.5\" />\n </button>\n </TooltipWrap>\n );\n })}\n </div>\n </div>\n );\n}\n\nconst SIDE_LABELS = [\n ['top', 'Top'],\n ['right', 'Right'],\n ['bottom', 'Bottom'],\n ['left', 'Left'],\n];\n\n/** Spacing: four sides in pixels, rewritten in their shortest form. */\nconst asSides = (v) => parseSpacing(v || '').map((s) => String(Number.parseFloat(s) || 0));\n\nfunction SpacingField({ id, property, value, onCommit }) {\n const t = useT();\n const [draft, setDraft, ref] = useDraft(value, asSides);\n\n const commit = (sides = draft) => {\n const next = formatSpacing(sides.map((s) => `${Math.max(0, Math.min(200, Number.parseFloat(s) || 0))}px`));\n if (next !== (value || '')) onCommit(next);\n };\n\n return (\n <fieldset ref={ref} className=\"eb:space-y-1.5\">\n <legend className=\"eb:mb-1.5 eb:text-[12px] eb:text-foreground-lighter\">{t(property.label)}</legend>\n <div className=\"eb:grid eb:grid-cols-4 eb:gap-1.5\">\n {SIDE_LABELS.map(([side, label], i) => (\n <div key={side} className=\"eb:space-y-1\">\n <Input\n id={`${id}-${side}`}\n type=\"number\"\n min={0}\n max={200}\n aria-label={t('{label} — {side}', { label: t(property.label), side: t(label) })}\n title={t(label)}\n value={draft[i]}\n onChange={(e) => setDraft((d) => d.map((v, j) => (j === i ? e.target.value : v)))}\n onBlur={() => commit()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commit();\n }}\n className=\"eb:px-2 eb:text-center eb:tabular-nums\"\n />\n <span className=\"eb:block eb:text-center eb:text-[10.5px] eb:text-foreground-muted\">{t(label)}</span>\n </div>\n ))}\n </div>\n </fieldset>\n );\n}\n\nconst FIELDS = {\n text: TextField,\n textarea: TextField,\n url: TextField,\n image: ImageField,\n size: SizeField,\n color: ColorField,\n select: SelectField,\n align: AlignField,\n spacing: SpacingField,\n};\n\n/**\n * Field of a property. The caller's `key` (element + property) remounts it on\n * every selection change: a draft never carries over from one element to another.\n */\nexport function PropertyField({ property, value, onCommit, idPrefix = 'eb', services = null }) {\n const Field = FIELDS[property.type] || TextField;\n const id = `${idPrefix}-${property.key}`;\n return <Field id={id} property={property} value={value} onCommit={onCommit} services={services} />;\n}\n","import { useState } from 'react';\nimport { HexAlphaColorPicker } from 'react-colorful';\nimport { Check } from 'lucide-react';\nimport { useT } from '../context.jsx';\nimport { Input } from './fields.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from './overlays.jsx';\nimport { cn } from './cn.js';\n\nconst PRESET_COLORS = [\n '#8B5CF6', '#A78BFA', '#6366F1', '#3B82F6', '#06B6D4', '#17A2B8',\n '#10B981', '#22C55E', '#28A745', '#84CC16', '#EAB308', '#FFC107',\n '#F59E0B', '#F97316', '#EF4444', '#DC3545', '#EC4899', '#6B7280',\n];\n\n// Shown by the picker while the typed value is not a colour yet (\"#8B\", empty).\nconst FALLBACK_COLOR = '#8B5CF6';\n\nconst isValidHex = (v) => /^#([0-9A-Fa-f]{8}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{3})$/.test(v || '');\n\nfunction normalizeHex(v) {\n if (!v) return '';\n let s = v.trim();\n if (s && !s.startsWith('#')) s = `#${s}`;\n return s.toUpperCase();\n}\n\n/**\n * Colour field: a swatch opening a full-spectrum picker (with alpha), a hex\n * input and presets. `value` is `#RRGGBB` or `#RRGGBBAA`; `onChange(hex)`.\n */\nexport function ColorPicker({ value, onChange, id, className }) {\n const t = useT();\n const [open, setOpen] = useState(false);\n const valid = isValidHex(value);\n const normalized = valid ? normalizeHex(value) : '';\n const emit = (hex) => onChange(normalizeHex(hex));\n\n return (\n <div className={cn('eb:flex eb:gap-2', className)}>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={t('Pick a colour')}\n title={t('Pick a colour')}\n className=\"eb-checker eb:relative eb:h-8 eb:w-[44px] eb:shrink-0 eb:overflow-hidden eb:rounded-lg2 eb:shadow-sm eb:ring-1 eb:ring-black/10 eb:ring-inset eb:transition-transform eb:hover:scale-[1.04]\"\n >\n <span className=\"eb:absolute eb:inset-0\" style={{ backgroundColor: valid ? value : 'transparent' }} aria-hidden />\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"eb:w-64 eb:space-y-3 eb:p-3\">\n <div className=\"eb-picker\">\n <HexAlphaColorPicker color={valid ? value : FALLBACK_COLOR} onChange={emit} />\n </div>\n <div className=\"eb:flex eb:items-center eb:gap-2\">\n <span\n className=\"eb-checker eb:relative eb:size-8 eb:shrink-0 eb:overflow-hidden eb:rounded-lg2 eb:ring-1 eb:ring-black/10 eb:ring-inset\"\n aria-hidden\n >\n <span className=\"eb:absolute eb:inset-0\" style={{ backgroundColor: valid ? value : 'transparent' }} />\n </span>\n <Input\n value={value || ''}\n onChange={(e) => emit(e.target.value)}\n placeholder=\"#RRGGBB\"\n maxLength={9}\n aria-label={t('Hex code')}\n className=\"eb:h-8 eb:flex-1 eb:font-mono eb:text-[12px] eb:uppercase\"\n />\n </div>\n <div className=\"eb:grid eb:grid-cols-6 eb:gap-1.5 eb:border-t eb:border-border eb:pt-2.5\">\n {PRESET_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => onChange(c)}\n title={c}\n aria-label={c}\n className=\"eb:relative eb:size-6 eb:rounded-lg2 eb:ring-1 eb:ring-black/10 eb:ring-inset eb:transition-transform eb:hover:scale-110\"\n style={{ backgroundColor: c }}\n >\n {normalized === c && (\n <Check className=\"eb:absolute eb:inset-0 eb:m-auto eb:size-3.5 eb:text-white eb:drop-shadow-[0_1px_1px_rgba(0,0,0,0.6)]\" />\n )}\n </button>\n ))}\n </div>\n </PopoverContent>\n </Popover>\n <Input\n id={id}\n value={value || ''}\n onChange={(e) => onChange(e.target.value)}\n maxLength={9}\n placeholder=\"#RRGGBB\"\n className=\"eb:h-8 eb:flex-1 eb:font-mono eb:text-[13px]\"\n />\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Braces } from 'lucide-react';\nimport { Button } from '../../ui/primitives/button.jsx';\nimport { Popover, PopoverContent, PopoverTrigger } from '../../ui/primitives/overlays.jsx';\nimport { tokenOf } from './catalog.js';\nimport VariablePicker from './VariablePicker.jsx';\n\n/**\n * `{ }` button next to a plain-text field (subject, preview text): inserts a\n * variable at the field's caret, or at its end.\n *\n * @param {{\n * variables: import('./catalog.js').EmailVariable[],\n * inputRef: {current: HTMLInputElement|HTMLTextAreaElement|null},\n * value: string,\n * onChange: (value: string) => void,\n * label: string,\n * }} props\n */\nexport default function VariableInsertButton({ variables, inputRef, value, onChange, label }) {\n const [open, setOpen] = useState(false);\n\n const insert = (variable) => {\n const input = inputRef.current;\n const text = String(value || '');\n const token = tokenOf(variable);\n const start = input?.selectionStart ?? text.length;\n const end = input?.selectionEnd ?? text.length;\n const next = `${text.slice(0, start)}${token}${text.slice(end)}`;\n onChange(next);\n setOpen(false);\n // Caret right after the inserted tag.\n requestAnimationFrame(() => {\n if (!input) return;\n input.focus();\n input.setSelectionRange(start + token.length, start + token.length);\n });\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button variant=\"ghost\" size=\"icon-xs\" aria-label={label} title={label}>\n <Braces />\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"eb:w-72 eb:p-0\" onCloseAutoFocus={(e) => e.preventDefault()}>\n {/* Links have no meaning in a subject line. */}\n <VariablePicker variables={variables} onPick={insert} filter={(v) => v.kind !== 'link'} />\n </PopoverContent>\n </Popover>\n );\n}\n","import { Button } from './primitives/button.jsx';\nimport { Separator } from './primitives/misc.jsx';\nimport { Tabs, TabsList, TabsTrigger } from './primitives/misc.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport { TruncatedText as FadedText } from './primitives/misc.jsx';\nimport { ArrowLeft, Monitor, Redo2, Smartphone, Undo2 } from 'lucide-react';\nimport { useT } from './context.jsx';\n\n/**\n * Builder toolbar.\n *\n * left: back, template name and its status;\n * center: undo / redo, device (desktop, mobile);\n * right: actions provided by the host screen (`actions`: variables,\n * preview, test, save - each one comes from its feature).\n */\nexport default function Toolbar({\n title,\n status,\n ready,\n canUndo,\n canRedo,\n onUndo,\n onRedo,\n device,\n onDeviceChange,\n onBack,\n actions = null,\n}) {\n const t = useT();\n return (\n <div className=\"eb:flex eb:h-12 eb:shrink-0 eb:items-center eb:gap-3 eb:border-b eb:border-border eb:px-3\">\n <Button variant=\"ghost\" size=\"sm-compact\" onClick={onBack}>\n <ArrowLeft />\n {t('Back')}\n </Button>\n <Separator orientation=\"vertical\" className=\"eb:h-5\" />\n <div className=\"eb:min-w-0 eb:max-w-[320px] eb:flex-1\">\n <p className=\"eb:text-[13px] eb:font-medium eb:text-foreground\">\n <FadedText>{title || t('New template')}</FadedText>\n </p>\n <p className=\"eb:text-[11px] eb:text-foreground-muted\" role=\"status\" aria-live=\"polite\">\n {status}\n </p>\n </div>\n\n <div className=\"eb:flex eb:items-center eb:gap-2\">\n <div className=\"eb:flex eb:items-center eb:gap-0.5\">\n <TooltipWrap label={t('Undo (Ctrl+Z)')}>\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onUndo} disabled={!ready || !canUndo} aria-label={t('Undo')}>\n <Undo2 />\n </Button>\n </TooltipWrap>\n <TooltipWrap label={t('Redo (Ctrl+Y)')}>\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onRedo} disabled={!ready || !canRedo} aria-label={t('Redo')}>\n <Redo2 />\n </Button>\n </TooltipWrap>\n </div>\n <Tabs value={device} onValueChange={onDeviceChange}>\n <TabsList aria-label={t('Device')}>\n <TabsTrigger value=\"desktop\" disabled={!ready}>\n <Monitor />\n {t('Desktop')}\n </TabsTrigger>\n <TabsTrigger value=\"mobile\" disabled={!ready}>\n <Smartphone />\n {t('Mobile')}\n </TabsTrigger>\n </TabsList>\n </Tabs>\n </div>\n\n <div className=\"eb:ml-auto eb:flex eb:items-center eb:gap-2\">{actions}</div>\n </div>\n );\n}\n","'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * React state of an `EmailEditor`: status, selection, undo/redo, device, and\n * \"modified since the last clean point\".\n *\n * The UI reads the editor ONLY through this hook (and its methods): no\n * component subscribes to the engine.\n *\n * -- \"MODIFIED\" IS MEASURED, NOT COUNTED ------------------------------------\n * Counting `change` events does not work: the engine also emits them outside\n * any edit (deferred canvas render after a load), and undoing back to the\n * saved state would leave a counter at 2. So the exported MJML is compared to\n * the one of the last clean point (load, or `markClean()` after a save). MJML\n * omits default values: engine noise does not show up in it.\n *\n * `dirty` (display) lags by 150 ms; `checkDirty()` measures RIGHT NOW - it is\n * the one to query before leaving, since a click on \"Back\" can follow an edit\n * by a few milliseconds.\n *\n * `markDirty()` forces the state until the next clean point (restored\n * version: identical to nothing saved, but still to be saved).\n * `changes` counts modifications: it is used to re-read what depends on them.\n */\n\nconst DIRTY_CHECK_MS = 150;\n\nexport function useEmailEditorState(editor) {\n const [state, setState] = useState(() => ({\n status: editor?.status || 'idle',\n selection: null,\n canUndo: false,\n canRedo: false,\n device: 'desktop',\n changes: 0,\n dirty: false,\n }));\n const clean = useRef(null);\n const forced = useRef(false);\n const timer = useRef(null);\n\n const snapshot = useCallback(() => {\n try {\n return editor.status === 'ready' ? editor.exportMjml() : null;\n } catch {\n return null;\n }\n }, [editor]);\n\n /** Clean point: the given MJML (the one just saved) or the current one. */\n const markClean = useCallback((saved = null) => {\n clean.current = saved ?? snapshot();\n forced.current = false;\n const current = snapshot();\n // Edited WHILE saving: still needs saving.\n setState((s) => ({ ...s, dirty: current !== null && current !== clean.current }));\n }, [snapshot]);\n\n const checkDirty = useCallback(() => {\n if (forced.current) return true;\n const current = snapshot();\n return current !== null && current !== clean.current;\n }, [snapshot]);\n\n const markDirty = useCallback(() => {\n forced.current = true;\n setState((s) => ({ ...s, dirty: true }));\n }, []);\n\n useEffect(() => {\n if (!editor) return undefined;\n const patch = (values) => setState((s) => ({ ...s, ...values }));\n const measure = () => {\n clearTimeout(timer.current);\n timer.current = setTimeout(() => {\n const current = snapshot();\n patch({ dirty: forced.current || (current !== null && current !== clean.current) });\n }, DIRTY_CHECK_MS);\n };\n const offs = [\n editor.on('ready', () => {\n clean.current = snapshot();\n forced.current = false;\n patch({\n status: 'ready',\n device: editor.getDevice(),\n canUndo: editor.canUndo(),\n canRedo: editor.canRedo(),\n selection: editor.getSelection(),\n dirty: false,\n });\n }),\n editor.on('destroy', () => patch({ status: 'idle', selection: null, canUndo: false, canRedo: false })),\n editor.on('selection', (selection) => patch({ selection })),\n editor.on('history', ({ canUndo, canRedo }) => patch({ canUndo, canRedo })),\n editor.on('device', (device) => patch({ device })),\n editor.on('change', () => {\n setState((s) => ({ ...s, changes: s.changes + 1 }));\n measure();\n }),\n editor.on('load', () => {\n clearTimeout(timer.current);\n clean.current = snapshot();\n forced.current = false;\n setState((s) => ({ ...s, changes: s.changes + 1, dirty: false }));\n }),\n ];\n return () => {\n clearTimeout(timer.current);\n offs.forEach((off) => off());\n };\n }, [editor, snapshot]);\n\n return { ...state, markClean, markDirty, checkDirty };\n}\n","import { Component } from 'react';\nimport { AlertTriangle, ArrowLeft, RefreshCw } from 'lucide-react';\nimport { Button } from './primitives/button.jsx';\n\n/**\n * Guard around the builder: a LOADING failure must not take the page down.\n *\n * Applications usually load the builder lazily (engine + MJML are heavy). Its\n * chunk may not arrive: slow server, or a new version deployed while the page\n * was open (the old chunk no longer exists). Without this guard the error\n * reaches the framework — a blank \"Application error\" page.\n *\n * Retry: missing chunk → reload the page (the loader caches the failure);\n * any other failure → mount the builder again.\n *\n * <EmailBuilderBoundary onClose={…} t={…}>\n * <LazyEmailBuilder … />\n * </EmailBuilderBoundary>\n *\n * `t`: translator for its three strings (class component: no hooks).\n */\n\nconst isChunkError = (error) =>\n error?.name === 'ChunkLoadError' || /Loading (CSS )?chunk .* failed/i.test(String(error?.message || ''));\n\nconst english = (text) => text;\n\nexport default class EmailBuilderBoundary extends Component {\n constructor(props) {\n super(props);\n this.state = { error: null, attempt: 0 };\n }\n\n static getDerivedStateFromError(error) {\n return { error };\n }\n\n componentDidCatch(error) {\n console.warn('[best-email-builder] the builder could not load', error);\n }\n\n retry = () => {\n if (isChunkError(this.state.error)) {\n window.location.reload();\n return;\n }\n this.setState((s) => ({ error: null, attempt: s.attempt + 1 }));\n };\n\n render() {\n const { error, attempt } = this.state;\n const t = this.props.t || english;\n if (!error) {\n return (\n <div key={attempt} style={{ height: '100%' }}>\n {this.props.children}\n </div>\n );\n }\n return (\n <div\n role=\"alert\"\n className=\"eb-root eb:flex eb:h-full eb:flex-col eb:items-center eb:justify-center eb:gap-3 eb:p-6 eb:text-center\"\n >\n <AlertTriangle className=\"eb:size-6 eb:text-destructive\" aria-hidden=\"true\" />\n <p className=\"eb:text-[13px] eb:text-foreground\">{t('The builder could not load.')}</p>\n <div className=\"eb:flex eb:gap-2\">\n {this.props.onClose && (\n <Button variant=\"outline\" size=\"sm\" onClick={this.props.onClose}>\n <ArrowLeft />\n {t('Back')}\n </Button>\n )}\n <Button size=\"sm\" onClick={this.retry}>\n <RefreshCw />\n {t('Retry')}\n </Button>\n </div>\n </div>\n );\n }\n}\n","// @ts-check\n/**\n * BEST EMAIL BUILDER — entry point.\n *\n * src/\n * core/ EmailEditor contract, versioned document, registries\n * adapters/ the engine (GrapesJS + MJML) — the only place that knows it\n * blocks/ one folder per block + the `emailBlocks` registry\n * features/ one folder per feature + `emailBuilderFeatures`\n * ui/ the React UI, which only talks to EmailEditor\n * storage/ reading/writing templates (client and server)\n * renderer/ MJML → final HTML (server compilation, variables, links)\n * validation/ what a template is allowed to contain\n *\n * See `docs/ARCHITECTURE.md`.\n */\n\nimport { createEmailEditor } from './core/EmailEditor.js';\nimport { createGrapesJsAdapter } from './adapters/grapesjs/GrapesJsAdapter.js';\nimport { emailBlocks } from './blocks/index.js';\nimport { emailBuilderFeatures } from './features/index.js';\n\nexport { createEmailEditor } from './core/EmailEditor.js';\nexport { emailBlocks } from './blocks/index.js';\nexport { emailBuilderFeatures, isFeatureEnabled } from './features/index.js';\n\n/**\n * An editor wired to the default engine and the built-in registries.\n *\n * @param {{locale?: string}} [options] `locale`: engine UI locale (`'en'` by default)\n */\nexport function createDefaultEmailEditor(options = {}) {\n const { locale } = options;\n return createEmailEditor({\n adapter: createGrapesJsAdapter({ locale }),\n blocks: emailBlocks,\n features: emailBuilderFeatures,\n });\n}\n\n/* ── React interface ─────────────────────────────────────────────────────── */\nexport { default as EmailBuilder } from './ui/EmailBuilder.jsx';\nexport { default as EmailBuilderBoundary } from './ui/EmailBuilderBoundary.jsx';\nexport { default as EmailCanvas } from './ui/EmailCanvas.jsx';\nexport { UiProvider, useUi, useT } from './ui/context.jsx';\n\n/* ── Storage (browser) ───────────────────────────────────────────────────── */\nexport { createHttpStorage, createMemoryStorage, StorageError } from './storage/client.js';\n\n/* ── Engine, document, registries ────────────────────────────────────────── */\nexport { createGrapesJsAdapter } from './adapters/grapesjs/GrapesJsAdapter.js';\nexport { createRegistry } from './core/registry.js';\nexport { readDocument, createDocument, serializeDocument, EmailDocumentError } from './core/document.js';\nexport { EMAIL_BUILDER_VERSION, EMAIL_DOCUMENT_SCHEMA_VERSION, EMAIL_DEVICES } from './core/constants.js';\n\n/* ── Variables, templates, rendering helpers shared with the server ──────── */\nexport {\n DEFAULT_VARIABLES,\n CUSTOM_GROUP,\n defineVariables,\n mergeVariables,\n keyFromLabel,\n validateCustomVariable,\n tokenOf,\n} from './features/variables/catalog.js';\nexport { applyVariables, applyVariablesToText, usedVariables, unknownVariables } from './features/variables/service.js';\nexport { createStarterMjml, STARTER_MJML } from './features/templates/starter.js';\nexport { isAssetPath, absoluteAssetUrls, DEFAULT_ASSETS_PATH } from './renderer/links.js';\n\n/* ── Translations ────────────────────────────────────────────────────────── */\nexport { createTranslator, translatorFor, LOCALES } from './i18n/index.js';\n"],"mappings":"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","names":["MJML","MJML","MJML","MJML","useState","jsx","jsx","jsxs","options","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","useState","useState","Braces","useEffect","useMemo","useState","jsx","Input","Textarea","jsx","jsxs","useState","useEffect","useMemo","field","useEffect","useMemo","useRef","useState","jsx","jsxs","useState","useRef","useMemo","useEffect","jsx","jsxs","useState","Braces","useMemo","useState","CheckCircle2","Info","Loader2","Fragment","jsx","jsxs","Info","CheckCircle2","useMemo","Loader2","useState","useState","CheckCircle2","Loader2","Fragment","jsx","jsxs","useState","CheckCircle2","Loader2","useCallback","useEffect","useMemo","useRef","useState","AlertTriangle","Loader2","KEY","useEffect","useRef","jsx","useRef","useEffect","jsx","jsxs","GROUPS","Trash2","jsx","jsxs","Trash2","useMemo","useRef","X","useEffect","useRef","useState","useState","jsx","jsxs","useState","Loader2","Fragment","jsx","jsxs","useState","useRef","useEffect","Loader2","useState","Braces","jsx","jsxs","useState","Braces","Fragment","jsx","jsxs","X","useRef","useMemo","bodyBlock","ArrowLeft","Monitor","Smartphone","jsx","jsxs","ArrowLeft","Monitor","Smartphone","useCallback","useEffect","useRef","useState","Fragment","jsx","jsxs","useMemo","useState","useCallback","useEffect","useRef","Loader2","AlertTriangle","AlertTriangle","ArrowLeft","RefreshCw","jsx","jsxs","AlertTriangle","ArrowLeft","RefreshCw"]}