best-email-builder 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +190 -0
  2. package/README.md +290 -20
  3. package/dist/ai-server.js +68 -0
  4. package/dist/ai-server.js.map +1 -0
  5. package/dist/ai.js +852 -0
  6. package/dist/ai.js.map +1 -0
  7. package/dist/builder.js +16 -8
  8. package/dist/chunk-2RZHGAH5.js +64 -0
  9. package/dist/chunk-2RZHGAH5.js.map +1 -0
  10. package/dist/chunk-3LKF4QBL.js +595 -0
  11. package/dist/chunk-3LKF4QBL.js.map +1 -0
  12. package/dist/chunk-5SASKCUC.js +251 -0
  13. package/dist/chunk-5SASKCUC.js.map +1 -0
  14. package/dist/{chunk-JOC752I3.js → chunk-6D3SLT5W.js} +27 -29
  15. package/dist/chunk-6D3SLT5W.js.map +1 -0
  16. package/dist/chunk-7U6BAKM7.js +119 -0
  17. package/dist/chunk-7U6BAKM7.js.map +1 -0
  18. package/dist/chunk-DFNHICTF.js +1359 -0
  19. package/dist/chunk-DFNHICTF.js.map +1 -0
  20. package/dist/chunk-ECHGJZ2W.js +327 -0
  21. package/dist/chunk-ECHGJZ2W.js.map +1 -0
  22. package/dist/chunk-KXJJSVN5.js +98 -0
  23. package/dist/chunk-KXJJSVN5.js.map +1 -0
  24. package/dist/{chunk-ZSUHOCCE.js → chunk-LXR4QTGP.js} +123 -579
  25. package/dist/chunk-LXR4QTGP.js.map +1 -0
  26. package/dist/{chunk-BVOVAEEJ.js → chunk-LYMJ2TBX.js} +2 -2
  27. package/dist/chunk-MPX5CWTZ.js +1687 -0
  28. package/dist/chunk-MPX5CWTZ.js.map +1 -0
  29. package/dist/chunk-PB7YZ3WP.js +5635 -0
  30. package/dist/chunk-PB7YZ3WP.js.map +1 -0
  31. package/dist/chunk-UFKCLU2D.js +255 -0
  32. package/dist/chunk-UFKCLU2D.js.map +1 -0
  33. package/dist/index.js +51 -20
  34. package/dist/index.js.map +1 -1
  35. package/dist/library.js +12 -7
  36. package/dist/server.js +513 -214
  37. package/dist/server.js.map +1 -1
  38. package/dist/styles.css +1 -1
  39. package/dist/types/ai/ConnectAi.d.ts +12 -0
  40. package/dist/types/ai/GenerateButton.d.ts +4 -0
  41. package/dist/types/ai/RewriteText.d.ts +5 -0
  42. package/dist/types/ai/SubjectIdeas.d.ts +25 -0
  43. package/dist/types/ai/chip.d.ts +1 -0
  44. package/dist/types/ai/claude.d.ts +21 -0
  45. package/dist/types/ai/createAi.d.ts +66 -0
  46. package/dist/types/ai/draft.d.ts +163 -0
  47. package/dist/types/ai/generator.d.ts +123 -0
  48. package/dist/types/ai/i18n/fr.d.ts +2 -0
  49. package/dist/types/ai/i18n/index.d.ts +2 -0
  50. package/dist/types/ai/index.d.ts +9 -0
  51. package/dist/types/ai/keys.d.ts +46 -0
  52. package/dist/types/ai/prompt.d.ts +76 -0
  53. package/dist/types/ai/providers.d.ts +67 -0
  54. package/dist/types/ai/purposes.d.ts +48 -0
  55. package/dist/types/ai/rewrite.d.ts +83 -0
  56. package/dist/types/ai/server.d.ts +9 -0
  57. package/dist/types/ai/subjects.d.ts +97 -0
  58. package/dist/types/blocks/shared.d.ts +20 -0
  59. package/dist/types/core/EmailEditor.d.ts +72 -19
  60. package/dist/types/core/constants.d.ts +1 -1
  61. package/dist/types/core/mjmlDefaults.d.ts +13 -0
  62. package/dist/types/core/scrollbars.d.ts +1 -1
  63. package/dist/types/defaultEditor.d.ts +4 -1
  64. package/dist/types/engine/NativeAdapter.d.ts +28 -0
  65. package/dist/types/engine/canvas/CanvasView.d.ts +88 -0
  66. package/dist/types/engine/canvas/canvasStyles.d.ts +3 -0
  67. package/dist/types/engine/canvas/icons.d.ts +14 -0
  68. package/dist/types/engine/canvas/morph.d.ts +21 -0
  69. package/dist/types/engine/canvasMjml.d.ts +30 -0
  70. package/dist/types/engine/mjml.d.ts +31 -0
  71. package/dist/types/engine/model.d.ts +130 -0
  72. package/dist/types/engine/placement.d.ts +69 -0
  73. package/dist/types/engine/richText.d.ts +15 -0
  74. package/dist/types/engine/unwrapModule.d.ts +29 -0
  75. package/dist/types/features/brand/BrandButton.d.ts +4 -0
  76. package/dist/types/features/brand/brand.d.ts +108 -0
  77. package/dist/types/features/brand/extract.d.ts +61 -0
  78. package/dist/types/features/brand/index.d.ts +2 -0
  79. package/dist/types/features/brand/messages.d.ts +13 -0
  80. package/dist/types/features/brand/useBrand.d.ts +22 -0
  81. package/dist/types/features/preview/PreviewButton.d.ts +1 -1
  82. package/dist/types/features/preview/darkMode.d.ts +65 -0
  83. package/dist/types/features/variables/VariablePicker.d.ts +3 -2
  84. package/dist/types/i18n/index.d.ts +8 -0
  85. package/dist/types/index.d.ts +5 -2
  86. package/dist/types/server/brand.d.ts +32 -0
  87. package/dist/types/server/brandImport.d.ts +93 -0
  88. package/dist/types/server/compileMjml.d.ts +2 -0
  89. package/dist/types/server/handler.d.ts +26 -0
  90. package/dist/types/server/index.d.ts +5 -1
  91. package/dist/types/storage/client.d.ts +57 -3
  92. package/dist/types/ui/EmailBuilder.d.ts +5 -1
  93. package/dist/types/ui/EmailStudio.d.ts +6 -1
  94. package/dist/types/ui/PropertiesPanel.d.ts +2 -1
  95. package/dist/types/ui/fields.d.ts +2 -1
  96. package/dist/types/ui/primitives/button.d.ts +1 -1
  97. package/dist/types/ui/primitives/color-picker.d.ts +2 -1
  98. package/dist/types/ui/primitives/searchShortcut.d.ts +16 -0
  99. package/dist/types/ui/useLayoutWidth.d.ts +1 -1
  100. package/package.json +27 -7
  101. package/dist/chunk-3M36VVXS.js +0 -665
  102. package/dist/chunk-3M36VVXS.js.map +0 -1
  103. package/dist/chunk-57CTQNTK.js +0 -56
  104. package/dist/chunk-57CTQNTK.js.map +0 -1
  105. package/dist/chunk-ILRAQTHS.js +0 -3677
  106. package/dist/chunk-ILRAQTHS.js.map +0 -1
  107. package/dist/chunk-JOC752I3.js.map +0 -1
  108. package/dist/chunk-ZSUHOCCE.js.map +0 -1
  109. package/dist/types/adapters/grapesjs/GrapesJsAdapter.d.ts +0 -33
  110. package/dist/types/adapters/grapesjs/engineConfig.d.ts +0 -148
  111. package/dist/types/adapters/grapesjs/unwrapModule.d.ts +0 -18
  112. /package/dist/{chunk-BVOVAEEJ.js.map → chunk-LYMJ2TBX.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/events.js","../src/core/mjmlAttributes.js","../src/core/EmailEditor.js","../src/core/registry.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/heading/index.js","../src/blocks/navbar/index.js","../src/blocks/hero/index.js","../src/blocks/columns/index.js","../src/blocks/index.js","../src/features/autosave/index.js","../src/features/versions/VersionsMenu.jsx","../src/features/versions/index.js","../src/features/variables/VariablesMenu.jsx","../src/features/variables/VariableDialog.jsx","../src/features/variables/VariablePicker.jsx","../src/features/variables/index.js","../src/features/preview/index.js","../src/features/test-email/TestEmailButton.jsx","../src/features/test-email/index.js","../src/features/templates/TemplateGallery.jsx","../src/features/templates/index.js","../src/features/index.js","../src/adapters/grapesjs/engineConfig.js","../src/adapters/grapesjs/unwrapModule.js","../src/adapters/grapesjs/GrapesJsAdapter.js","../src/defaultEditor.js","../src/ui/EmailCanvas.jsx","../src/ui/EmailBuilder.jsx","../src/features/autosave/scheduler.js","../src/features/autosave/localDraft.js","../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/Drawer.jsx","../src/ui/useEmailEditorState.js","../src/ui/EmailBuilderBoundary.jsx"],"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 * `insertOnly`: a preset of another block's element (a Heading is an\n * `mj-text`): offered in the sidebar, but a selected element of that tag is\n * described by the main block.\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 * insertOnly?: 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: (mjml?: string|null) => 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: (mjml?: string|null) => 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 /**\n * Block describing a tag: structure first (a section stays a section),\n * presets (`insertOnly`) never.\n */\n function blockForTag(tagName) {\n const all = blocks.list((b) => !b.insertOnly);\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 /**\n * The email (or the given MJML) compiled by the CANVAS compiler — for\n * display only (thumbnails, inspection). The HTML that is stored and sent\n * is always compiled by the server.\n */\n exportHtml(mjml = null) {\n requireReady('exportHtml');\n return adapter.exportHtml(mjml === null || mjml === undefined ? null : String(mjml));\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 * 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 * 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 // A background image keeps the color under it: shown when images are blocked.\n { key: 'background-url', label: 'Background image', type: 'image', group: GROUPS.colors },\n {\n key: 'background-size',\n label: 'Image size',\n type: 'select',\n group: GROUPS.colors,\n options: [\n { value: 'cover', label: 'Fill the section' },\n { value: 'contain', label: 'Whole image' },\n { value: 'auto', label: 'Original size' },\n ],\n },\n {\n key: 'background-position',\n label: 'Image position',\n type: 'select',\n group: GROUPS.colors,\n options: [\n { value: 'center center', label: 'Center' },\n { value: 'center top', label: 'Top' },\n { value: 'center bottom', label: 'Bottom' },\n ],\n },\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, GROUPS, 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 {\n key: 'font-weight',\n label: 'Weight',\n type: 'select',\n group: GROUPS.typography,\n options: [\n { value: 'normal', label: 'Normal' },\n { value: 'bold', label: 'Bold' },\n ],\n },\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 * HEADING - an `mj-text` set as a title.\n *\n * Not a tag of its own: MJML has no heading element, and a `<h1>` inside\n * `mj-text` would bring each email client's default margins and sizes. It is\n * a text written large and bold - the same element as the Text block, so once\n * added it is described by that block (`insertOnly`): same panel, same\n * properties, weight included.\n */\n\nimport { FONT_STACK, PALETTE, inWhiteSection } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML =\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"26px\" line-height=\"34px\" font-weight=\"bold\" ` +\n `color=\"${PALETTE.navy}\" align=\"left\">Your headline</mj-text>`;\n\n/** @type {EmailBlock} */\nexport const headingBlock = {\n id: 'heading',\n label: 'Heading',\n description: 'Large bold title',\n icon: 'Heading',\n kind: 'content',\n tagName: 'mj-text',\n insertOnly: true,\n order: 5,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n editableContent: true,\n properties: [],\n};\n","// @ts-check\n/**\n * MENU - `mj-navbar` and its `mj-navbar-link` links.\n *\n * A row of text links (shop, blog, contact…) under the logo. No \"hamburger\"\n * mode: MJML builds it with a hidden checkbox, an `<input>` that several\n * clients strip and the template validator refuses; a short row of links\n * wraps on a phone by itself.\n *\n * Each link is edited like a button: its label in the panel, its URL, its\n * color. Duplicate a link to add one.\n */\n\nimport { FONT_STACK, PALETTE, inWhiteSection, prop } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @param {string} label @param {string} href */\nfunction link(label, href) {\n return (\n `<mj-navbar-link href=\"${href}\" font-family=\"${FONT_STACK}\" font-size=\"14px\" color=\"${PALETTE.navy}\" ` +\n `padding-top=\"8px\" padding-right=\"12px\" padding-bottom=\"8px\" padding-left=\"12px\">${label}</mj-navbar-link>`\n );\n}\n\nconst MJML =\n '<mj-navbar align=\"center\">' +\n link('Shop', 'https://example.com/shop') +\n link('Blog', 'https://example.com/blog') +\n link('Contact', 'https://example.com/contact') +\n '</mj-navbar>';\n\n/** @type {EmailBlock} */\nexport const navbarBlock = {\n id: 'navbar',\n label: 'Menu',\n description: 'Row of links to your site',\n icon: 'Menu',\n kind: 'content',\n tagName: 'mj-navbar',\n order: 70,\n mjml: MJML,\n sectionMjml: inWhiteSection(MJML),\n properties: [prop.align()],\n};\n\n/** One link of the menu: selectable, not addable (duplicate it instead). */\n/** @type {EmailBlock} */\nexport const navbarLinkBlock = {\n id: 'navbar-link',\n label: 'Menu link',\n icon: 'Link',\n kind: 'structure',\n tagName: 'mj-navbar-link',\n order: 904,\n editableContent: true,\n properties: [\n prop.href('Link URL'),\n prop.color('Text'),\n prop.fontFamily(),\n prop.fontSize(10, 24),\n prop.padding(),\n ],\n};\n","// @ts-check\n/**\n * HERO - a full-width banner: a background image (or color) under a title, a\n * sentence and a button.\n *\n * A SECTION with a background image, not `mj-hero`: the canvas engine draws\n * `mj-hero` squeezed into a narrow strip, so the screen would lie about the\n * email. A section background is drawn the same in both, and MJML adds the\n * VML that Outlook on Windows needs to show it.\n *\n * The background color stays set under the image: clients that block images\n * show it instead, and the white text stays readable on it. Once added, the\n * banner is a section like any other (`blocks/structure`): its image, size and\n * position are set there.\n */\n\nimport { DEFAULT_BUTTON_URL, FONT_STACK, PALETTE } from '../shared.js';\n\n/** @typedef {import('../../core/EmailEditor.js').EmailBlock} EmailBlock */\n\nconst MJML =\n `<mj-section background-color=\"${PALETTE.navy}\" background-size=\"cover\" background-position=\"center center\" ` +\n 'background-repeat=\"no-repeat\" padding-top=\"56px\" padding-bottom=\"56px\">' +\n '<mj-column>' +\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"30px\" line-height=\"38px\" font-weight=\"bold\" ` +\n `color=\"${PALETTE.white}\" align=\"center\" padding-left=\"32px\" padding-right=\"32px\">Your big announcement</mj-text>` +\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"16px\" line-height=\"24px\" color=\"${PALETTE.border}\" ` +\n 'align=\"center\" padding-left=\"32px\" padding-right=\"32px\">One sentence that makes people want to read on.</mj-text>' +\n `<mj-button href=\"${DEFAULT_BUTTON_URL}\" background-color=\"${PALETTE.white}\" color=\"${PALETTE.navy}\" ` +\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 '</mj-column>' +\n '</mj-section>';\n\n/** @type {EmailBlock} */\nexport const heroBlock = {\n id: 'hero',\n label: 'Hero banner',\n description: 'Background image with a title and a button',\n icon: 'GalleryHorizontal',\n kind: 'layout',\n tagName: 'mj-section',\n order: 110,\n mjml: MJML,\n properties: [],\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 { DEFAULT_BUTTON_URL, FONT_STACK, 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');\nexport const fourColumnsBlock = layout(4, 'Columns4');\n\n/**\n * Image on one side, title, text and button on the other - the usual\n * \"product\" or \"article\" row. Stacked on mobile, image first.\n */\nconst IMAGE_TEXT_MJML =\n `<mj-section background-color=\"${PALETTE.surface}\">` +\n '<mj-column vertical-align=\"middle\"><mj-image align=\"center\"></mj-image></mj-column>' +\n '<mj-column vertical-align=\"middle\">' +\n `<mj-text font-family=\"${FONT_STACK}\" font-size=\"20px\" line-height=\"28px\" font-weight=\"bold\" ` +\n `color=\"${PALETTE.navy}\" align=\"left\">Title</mj-text>` +\n textMjml('A few words about it.') +\n `<mj-button href=\"${DEFAULT_BUTTON_URL}\" background-color=\"${PALETTE.navy}\" color=\"${PALETTE.white}\" ` +\n `font-family=\"${FONT_STACK}\" font-size=\"14px\" font-weight=\"bold\" border-radius=\"6px\" ` +\n 'inner-padding=\"10px 22px\" align=\"left\">Learn more</mj-button>' +\n '</mj-column>' +\n '</mj-section>';\n\n/** @type {EmailBlock} */\nexport const imageTextBlock = {\n id: 'image-text',\n label: 'Image + text',\n description: 'Image beside a title, text and button',\n icon: 'LayoutPanelLeft',\n kind: 'layout',\n tagName: 'mj-section',\n order: 105,\n mjml: IMAGE_TEXT_MJML,\n properties: [],\n};\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 { headingBlock } from './heading/index.js';\nimport { socialBlock, socialElementBlock } from './social/index.js';\nimport { navbarBlock, navbarLinkBlock } from './navbar/index.js';\nimport { heroBlock } from './hero/index.js';\nimport {\n fourColumnsBlock,\n imageTextBlock,\n oneColumnBlock,\n threeColumnsBlock,\n twoColumnsBlock,\n} from './columns/index.js';\n\n/** @typedef {import('../core/EmailEditor.js').EmailBlock} EmailBlock */\n\n/** @type {EmailBlock[]} */\nconst BLOCKS = [\n headingBlock,\n textBlock,\n imageBlock,\n buttonBlock,\n dividerBlock,\n spacerBlock,\n socialBlock,\n navbarBlock,\n oneColumnBlock,\n twoColumnsBlock,\n threeColumnsBlock,\n fourColumnsBlock,\n imageTextBlock,\n heroBlock,\n bodyBlock,\n sectionBlock,\n columnBlock,\n socialElementBlock,\n navbarLinkBlock,\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","// @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 { 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","// @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","import { useMemo, useState } from 'react';\nimport { LayoutTemplate } from 'lucide-react';\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 { withThumbnailImages } from './gallery.js';\n\n/**\n * TEMPLATE GALLERY — toolbar button and dialog.\n *\n * Each card shows the template as it renders: its MJML compiled by the canvas\n * compiler (`editor.exportHtml(mjml)`), displayed in an iframe with an EMPTY\n * sandbox and scaled down. Picking one REPLACES the email in the editor —\n * after confirmation when there are unsaved changes — and fills the subject\n * and preview text only when they are empty: what the user typed stays.\n *\n * A saved template that gets a new content counts as modified: it is the\n * next save that keeps it.\n */\n\nconst THUMBNAIL_SCALE = 0.38;\nconst EMAIL_WIDTH = 600;\n\nfunction Thumbnail({ html, title }) {\n return (\n <div\n className=\"eb:relative eb:h-[220px] eb:overflow-hidden eb:rounded-md eb:border eb:border-border eb:bg-surface-75\"\n aria-hidden=\"true\"\n >\n <iframe\n title={title}\n sandbox=\"\"\n srcDoc={html}\n tabIndex={-1}\n loading=\"lazy\"\n className=\"eb:pointer-events-none eb:absolute eb:top-0 eb:left-1/2 eb:origin-top eb:border-0\"\n style={{\n width: EMAIL_WIDTH,\n height: 220 / THUMBNAIL_SCALE,\n transform: `translateX(-50%) scale(${THUMBNAIL_SCALE})`,\n }}\n />\n </div>\n );\n}\n\nexport default function TemplateGalleryButton({ context }) {\n const { editor, ready, templates, isDirty, markDirty, template, setMeta } = context;\n const { t, confirm, notify } = useUi();\n const [open, setOpen] = useState(false);\n\n const cards = useMemo(() => {\n if (!open || !ready) return [];\n return templates.map((entry) => {\n try {\n return { ...entry, html: editor.exportHtml(withThumbnailImages(entry.mjml)).html };\n } catch {\n return { ...entry, html: '' };\n }\n });\n }, [open, ready, templates, editor]);\n\n const apply = async (entry) => {\n if (isDirty()) {\n setOpen(false);\n const ok = await confirm({\n title: t('Replace the current email?'),\n description: t('Unsaved changes will be replaced.'),\n confirmLabel: t('Replace'),\n destructive: true,\n });\n if (!ok) return;\n }\n editor.loadMjml(entry.mjml);\n setMeta((meta) => ({\n ...meta,\n subject: meta.subject || entry.subject,\n preheader: meta.preheader || entry.preheader,\n }));\n if (template.id) markDirty();\n setOpen(false);\n notify('success', t('“{name}” template applied.', { name: entry.name }));\n };\n\n return (\n <>\n <Button variant=\"outline\" size=\"sm-compact\" disabled={!ready} onClick={() => setOpen(true)}>\n <LayoutTemplate />\n {t('Templates')}\n </Button>\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent className=\"eb:max-h-[calc(100dvh-2rem)] eb:overflow-y-auto eb:sm:max-w-4xl\" data-testid=\"eb-template-gallery\">\n <DialogHeader>\n <DialogTitle>{t('Start from a template')}</DialogTitle>\n <DialogDescription>{t('Picking a template replaces the email being edited.')}</DialogDescription>\n </DialogHeader>\n <ul className=\"eb:grid eb:grid-cols-1 eb:gap-3 eb:sm:grid-cols-2 eb:md:grid-cols-3\">\n {cards.map((card) => (\n <li key={card.id}>\n <button\n type=\"button\"\n onClick={() => apply(card)}\n data-template-id={card.id}\n className=\"eb:group eb:flex eb:w-full eb:flex-col eb:gap-2 eb:rounded-lg2 eb:border eb:border-border eb:bg-background eb:p-2 eb:text-left eb:transition-colors 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 >\n <Thumbnail html={card.html} title={card.name} />\n <span className=\"eb:px-1\">\n <span className=\"eb:block eb:text-[13px] eb:font-medium eb:text-foreground\">{card.name}</span>\n <span className=\"eb:block eb:text-[12px] eb:text-foreground-muted\">{card.description}</span>\n </span>\n </button>\n </li>\n ))}\n </ul>\n </DialogContent>\n </Dialog>\n </>\n );\n}\n","// @ts-check\n/**\n * TEMPLATES feature: the gallery of ready-made emails (`TemplateGalleryButton`).\n * Shown when the builder has templates to offer (`templates` prop, `[]` hides\n * it).\n */\n\nimport TemplateGalleryButton from './TemplateGallery.jsx';\n\n/** @type {import('../../core/EmailEditor.js').EmailBuilderFeature} */\nexport const templatesFeature = {\n id: 'templates',\n label: 'Templates',\n order: 5,\n toolbar: TemplateGalleryButton,\n isAvailable: (context) => Array.isArray(context.templates) && context.templates.length > 0,\n};\n","// @ts-check\n/**\n * FEATURES REGISTRY — `emailBuilderFeatures`.\n *\n * A feature (templates, 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';\nimport { templatesFeature } from './templates/index.js';\n\n/** @typedef {import('../core/EmailEditor.js').EmailBuilderFeature} EmailBuilderFeature */\n\n/** @type {EmailBuilderFeature[]} */\nconst FEATURES = [\n templatesFeature,\n variablesFeature,\n autosaveFeature,\n versionsFeature,\n previewFeature,\n testEmailFeature,\n];\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","// @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\nimport { FRAME_SCROLLBAR_CSS } from '../../core/scrollbars.js';\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${FRAME_SCROLLBAR_CSS}\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.23.6';\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', 'mj-navbar-link']);\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(mjml = null) {\n const source = mjml ?? adapter.exportMjml();\n const result = requireEditor().runCommand('mjml-code-to-html', { mjml: source }) || {};\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 * The editor wired to the default engine and the built-in registries. In a\n * module of its own so the builder can use it without importing the package\n * entry (and, through it, the template bank).\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\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","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 { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { AlertTriangle, Loader2, Plus, Save, SlidersHorizontal } from 'lucide-react';\nimport { createDefaultEmailEditor } from '../defaultEditor.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 { TEMPLATE_GALLERY, buildGallery } from '../features/templates/gallery.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 Drawer from './Drawer.jsx';\nimport { useEmailEditorState } from './useEmailEditorState.js';\nimport { useLayoutWidth } from './useLayoutWidth.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 * ── NARROW SCREENS (`useLayoutWidth`) ───────────────────────────────────────\n * Measured on the builder's own box. Below the wide layout the properties\n * move to a drawer and the toolbar takes two rows; on a phone the blocks go to\n * a drawer too, and a bar under the canvas opens them (\"Add a block\", \"Edit\").\n * Adding a block from the sidebar opens its properties.\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 templates: galleryProp,\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 templates = useMemo(\n () => buildGallery({ templates: galleryProp ?? TEMPLATE_GALLERY, sender: sender || {}, t }),\n [galleryProp, sender, t]\n );\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 rootRef = useRef(null);\n const layout = useLayoutWidth(rootRef);\n const compact = layout !== 'wide';\n const blocksInDrawer = layout === 'narrow';\n /** Open drawer of the compact layouts: 'blocks', 'properties' or null. */\n const [drawer, setDrawer] = useState(null);\n const closeDrawer = useCallback(() => setDrawer(null), []);\n useEffect(() => {\n if (!compact) setDrawer(null);\n else if (!blocksInDrawer) setDrawer((d) => (d === 'blocks' ? null : d));\n }, [compact, blocksInDrawer]);\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, compact };\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 setDrawer((d) => (d === null && latest.current.compact ? 'properties' : d));\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 setMeta,\n templates,\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 const properties = (\n <PropertiesPanel\n onDismiss={compact ? closeDrawer : null}\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 );\n\n return (\n <div\n ref={rootRef}\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-layout={layout}\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 compact={compact}\n actions={toolbarFeatures.map((feature) => {\n const Action = feature.toolbar;\n return <Action key={feature.id} context={featureContext} />;\n })}\n primary={\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 <div\n className={cn(\n 'eb:relative eb:grid eb:min-h-0 eb:flex-1 eb:grid-rows-1',\n layout === 'wide' && 'eb:grid-cols-[224px_minmax(0,1fr)_296px]',\n layout === 'medium' && 'eb:grid-cols-[200px_minmax(0,1fr)]',\n layout === 'narrow' && 'eb:grid-cols-1'\n )}\n >\n {!blocksInDrawer && <BlockSidebar editor={editor} disabled={!ready} onAdded={compact ? () => setDrawer('properties') : undefined} />}\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 {!compact && properties}\n {blocksInDrawer && (\n <Drawer open={drawer === 'blocks'} side=\"left\" title={t('Add a block')} onClose={closeDrawer} testId=\"eb-blocks-drawer\">\n <BlockSidebar editor={editor} disabled={!ready} onAdded={() => setDrawer('properties')} />\n </Drawer>\n )}\n {compact && (\n <Drawer\n open={drawer === 'properties'}\n side=\"right\"\n title={t('Properties')}\n onClose={closeDrawer}\n testId=\"eb-properties-drawer\"\n header={false}\n >\n {properties}\n </Drawer>\n )}\n </div>\n {compact && (\n <div className=\"eb:flex eb:shrink-0 eb:items-center eb:gap-2 eb:border-t eb:border-border eb:px-2 eb:py-2\" data-testid=\"eb-compact-bar\">\n {blocksInDrawer && (\n <Button variant=\"outline\" size=\"sm-compact\" disabled={!ready} onClick={() => setDrawer('blocks')}>\n <Plus />\n {t('Add a block')}\n </Button>\n )}\n <Button\n variant={state.selection ? 'default' : 'outline'}\n size=\"sm-compact\"\n className=\"eb:ml-auto eb:min-w-0\"\n disabled={!ready}\n onClick={() => setDrawer('properties')}\n >\n <SlidersHorizontal />\n <span className=\"eb:truncate\">\n {ready && state.selection ? t('Edit: {element}', { element: t(state.selection.label) }) : t('Email settings')}\n </span>\n </Button>\n </div>\n )}\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 * templates?: import('../features/templates/gallery.js').GalleryTemplate[],\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 * 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","import { SectionLabel } from './primitives/misc.jsx';\nimport { TooltipWrap } from './primitives/misc.jsx';\nimport {\n Columns2,\n Columns3,\n Columns4,\n GalleryHorizontal,\n Heading,\n Image as ImageIcon,\n LayoutPanelLeft,\n Menu,\n MoveVertical,\n RectangleHorizontal,\n SeparatorHorizontal,\n Share2,\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 Heading,\n Type,\n Share2,\n Menu,\n Columns4,\n LayoutPanelLeft,\n GalleryHorizontal,\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, onAdded }) {\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) => {\n if (editor.addBlock(id)) onAdded?.(id);\n }}\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 or a menu link 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. `onDismiss`: the panel is shown in a drawer — its header\n * button closes the drawer rather than deselecting.\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, closeLabel = 'Deselect' }) {\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(closeLabel)}>\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, onDismiss = 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')} onClose={onDismiss} closeLabel=\"Close\" />\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 onDismiss = 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 onDismiss={onDismiss}\n />\n ) : (\n <>\n <PanelHeader\n title={t(selection.label)}\n onClose={onDismiss || (() => editor.select(null))}\n closeLabel={onDismiss ? 'Close' : 'Deselect'}\n />\n {actions}\n <div className=\"eb:space-y-5 eb:p-4\">\n {selection.content !== null && selection.content !== undefined && (\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 { cn } from './primitives/cn.js';\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 - each one comes from its feature), then `primary`\n * (save).\n *\n * `compact` (builder narrower than its wide layout): two rows. The first keeps\n * what is always needed - back, name, save; the second holds history, device\n * and the feature actions, and scrolls sideways rather than overflow the page.\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 primary = null,\n compact = false,\n}) {\n const t = useT();\n\n const identity = (\n <>\n <Button\n variant=\"ghost\"\n size={compact ? 'icon-sm-compact' : 'sm-compact'}\n onClick={onBack}\n aria-label={compact ? t('Back') : undefined}\n >\n <ArrowLeft />\n {!compact && t('Back')}\n </Button>\n <Separator orientation=\"vertical\" className=\"eb:h-5\" />\n <div className={cn('eb:min-w-0 eb:flex-1', !compact && 'eb:max-w-[320px]')}>\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 );\n\n const editing = (\n <div className=\"eb:flex eb:shrink-0 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} aria-label={compact ? t('Desktop') : undefined}>\n <Monitor />\n {!compact && t('Desktop')}\n </TabsTrigger>\n <TabsTrigger value=\"mobile\" disabled={!ready} aria-label={compact ? t('Mobile') : undefined}>\n <Smartphone />\n {!compact && t('Mobile')}\n </TabsTrigger>\n </TabsList>\n </Tabs>\n </div>\n );\n\n if (compact) {\n return (\n <div className=\"eb:shrink-0 eb:border-b eb:border-border\" data-layout=\"compact\">\n <div className=\"eb:flex eb:h-12 eb:items-center eb:gap-2 eb:px-2\">\n {identity}\n {primary}\n </div>\n <div className=\"eb:flex eb:items-center eb:gap-2 eb:overflow-x-auto eb:px-2 eb:pb-2\" data-testid=\"eb-toolbar-actions\">\n {editing}\n <Separator orientation=\"vertical\" className=\"eb:h-5 eb:shrink-0\" />\n <div className=\"eb:flex eb:shrink-0 eb:items-center eb:gap-2\">{actions}</div>\n </div>\n </div>\n );\n }\n\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 {identity}\n {editing}\n <div className=\"eb:ml-auto eb:flex eb:items-center eb:gap-2\" data-testid=\"eb-toolbar-actions\">\n {actions}\n {primary}\n </div>\n </div>\n );\n}\n","import { useEffect } from 'react';\nimport { X } from 'lucide-react';\nimport { Button } from './primitives/button.jsx';\nimport { cn } from './primitives/cn.js';\nimport { useT } from './context.jsx';\n\n/**\n * Side drawer of the compact layouts: the blocks or the properties slide over\n * the canvas instead of squeezing it.\n *\n * Rendered INSIDE the builder (not in a portal): it covers the editing area\n * only, the toolbar stays usable. A tap on the shaded canvas or Escape closes\n * it. `header={false}` when the content has its own header with a close\n * button (the properties panel). While closed it stays mounted but hidden (`hidden`), so a panel keeps\n * its scroll position and its fields their drafts.\n */\nexport default function Drawer({ open, side = 'left', title, onClose, children, testId, header = true }) {\n const t = useT();\n useEffect(() => {\n if (!open) return undefined;\n const onKey = (e) => {\n if (e.key === 'Escape') onClose();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [open, onClose]);\n\n return (\n <div className={cn('eb:absolute eb:inset-0 eb:z-20', !open && 'eb:hidden')} data-testid={testId} data-open={open ? 'true' : 'false'}>\n <div className=\"eb:absolute eb:inset-0 eb:bg-black/30\" onClick={onClose} aria-hidden=\"true\" />\n <section\n role=\"dialog\"\n aria-label={title}\n className={cn(\n 'eb:absolute eb:inset-y-0 eb:flex eb:w-[min(340px,88%)] eb:flex-col eb:bg-background eb:shadow-lg',\n side === 'left' ? 'eb:left-0 eb:border-r eb:border-border' : 'eb:right-0 eb:border-l eb:border-border'\n )}\n >\n {header && (\n <header className=\"eb:flex eb:h-10 eb:shrink-0 eb:items-center eb:justify-between eb:border-b eb:border-border eb:px-3\">\n <h3 className=\"eb:text-[13px] eb:font-medium eb:text-foreground\">{title}</h3>\n <Button variant=\"ghost\" size=\"icon-sm-compact\" onClick={onClose} aria-label={t('Close')}>\n <X />\n </Button>\n </header>\n )}\n <div className=\"eb:grid eb:min-h-0 eb:flex-1\">{children}</div>\n </section>\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"],"mappings":"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","names":["MJML","MJML","MJML","MJML","MJML","MJML","MJML","useState","Braces","useState","jsx","jsxs","useState","field","useEffect","useMemo","useState","jsx","jsxs","useState","useMemo","useEffect","jsx","jsxs","useState","Braces","useState","Loader2","Fragment","jsx","jsxs","useState","Loader2","useMemo","useState","Fragment","jsx","jsxs","useState","useMemo","useEffect","useRef","jsx","useRef","useEffect","useCallback","useEffect","useMemo","useRef","useState","Loader2","Plus","KEY","jsx","jsxs","GROUPS","Trash2","jsx","jsxs","Trash2","useMemo","useRef","useEffect","useRef","useState","useState","jsx","jsxs","useState","Loader2","Fragment","jsx","jsxs","useState","useRef","useEffect","Loader2","useState","Braces","jsx","jsxs","useState","Braces","Fragment","jsx","jsxs","useRef","useMemo","bodyBlock","ArrowLeft","Fragment","jsx","jsxs","ArrowLeft","useEffect","X","jsx","jsxs","useEffect","X","useEffect","useRef","useState","Fragment","jsx","jsxs","useMemo","useState","useCallback","useEffect","useRef","layout","Loader2","Plus","AlertTriangle","ArrowLeft","jsx","jsxs","AlertTriangle","ArrowLeft"]}