better-react-email-editor 0.1.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +381 -0
  3. package/dist/index.cjs +2 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.js +4190 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/styles.css +1634 -0
  8. package/dist/types/components/BetterEmailEditor.d.ts +34 -0
  9. package/dist/types/components/BlockProperties.d.ts +7 -0
  10. package/dist/types/components/BlocksTab.d.ts +13 -0
  11. package/dist/types/components/BodyTab.d.ts +9 -0
  12. package/dist/types/components/Canvas.d.ts +15 -0
  13. package/dist/types/components/CanvasOverlay.d.ts +10 -0
  14. package/dist/types/components/ContentPanel.d.ts +19 -0
  15. package/dist/types/components/ContentTab.d.ts +17 -0
  16. package/dist/types/components/LayersPanel.d.ts +9 -0
  17. package/dist/types/components/PreviewDialog.d.ts +15 -0
  18. package/dist/types/components/PropertiesPanel.d.ts +12 -0
  19. package/dist/types/components/Sidebar.d.ts +14 -0
  20. package/dist/types/components/TextProperties.d.ts +7 -0
  21. package/dist/types/components/TopBar.d.ts +37 -0
  22. package/dist/types/components/fields.d.ts +103 -0
  23. package/dist/types/components/icons.d.ts +21 -0
  24. package/dist/types/components/inspectors/ButtonInspector.d.ts +2 -0
  25. package/dist/types/components/inspectors/ColumnsInspector.d.ts +3 -0
  26. package/dist/types/components/inspectors/DefaultInspector.d.ts +3 -0
  27. package/dist/types/components/inspectors/HeadingInspector.d.ts +2 -0
  28. package/dist/types/components/inspectors/ImageInspector.d.ts +2 -0
  29. package/dist/types/components/inspectors/SimpleInspectors.d.ts +6 -0
  30. package/dist/types/components/inspectors/SocialLinksInspector.d.ts +2 -0
  31. package/dist/types/components/inspectors/groups.d.ts +22 -0
  32. package/dist/types/components/useDraggableBlock.d.ts +17 -0
  33. package/dist/types/context.d.ts +115 -0
  34. package/dist/types/core/content.d.ts +28 -0
  35. package/dist/types/core/cx.d.ts +8 -0
  36. package/dist/types/core/dnd.d.ts +73 -0
  37. package/dist/types/core/layers.d.ts +27 -0
  38. package/dist/types/core/paste-handler.d.ts +9 -0
  39. package/dist/types/core/paste.d.ts +22 -0
  40. package/dist/types/core/stores.d.ts +19 -0
  41. package/dist/types/core/style-utils.d.ts +3 -0
  42. package/dist/types/i18n/en.d.ts +247 -0
  43. package/dist/types/i18n/fr.d.ts +3 -0
  44. package/dist/types/i18n/index.d.ts +509 -0
  45. package/dist/types/index.d.ts +37 -0
  46. package/dist/types/nodes/custom-nodes.d.ts +19 -0
  47. package/dist/types/registry/default-nodes.d.ts +7 -0
  48. package/dist/types/registry/default-palette.d.ts +7 -0
  49. package/dist/types/registry/default-templates.d.ts +10 -0
  50. package/dist/types/registry/types.d.ts +56 -0
  51. package/package.json +89 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gyom03
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,381 @@
1
+ # better-react-email-editor
2
+
3
+ **A drag & drop email builder that runs inside your React app.**
4
+
5
+ Your users build emails visually, the way they would in [Unlayer](https://unlayer.com): they drag blocks into a layout, edit text in place and adjust styles from a side panel. Your app gets the email back as JSON, to store and reload, and as email-ready HTML (table layout, inline styles) to send. The editor renders directly in your page, not in an iframe, and is built on [`@react-email/editor`](https://www.npmjs.com/package/@react-email/editor) (Tiptap / ProseMirror for editing, React Email for the HTML).
6
+
7
+ [![Demo: place an image, edit a heading, export the HTML](./docs/demo.webp)](./docs/demo.mp4)
8
+
9
+ ## Features
10
+
11
+ - **Drag & drop**: layouts of 1 to 4 columns and 12 content blocks (heading, text, button, image, divider, spacer, social links, menu, list, quote, HTML, card), plus prebuilt rows (header, hero, products, features, testimonial, footer).
12
+ - **Canvas**: hover and selection frames, a move handle, a toolbar (select parent, duplicate, delete) and keyboard shortcuts (`Esc` selects the parent, `Delete` removes the block).
13
+ - **Layers panel**: the email as a tree. You can select, reorder and nest blocks by drag & drop, with keyboard navigation.
14
+ - **Properties panel**: one panel per block type (typography, spacing, background, border, links, column widths, social networks, HTML…) and a breadcrumb of the hierarchy.
15
+ - **Inline text editing**: floating menu and `/` commands.
16
+ - **Copy / paste** of blocks and text, and undo / redo.
17
+ - **Export**: one button opens the rendered email: desktop and mobile preview, HTML (copy or download) and plain text.
18
+ - **Modular**: replace, restyle or rearrange any part, and add your own blocks, palette items, templates and properties panels.
19
+ - **i18n**: English and French are built in, and you can override any string.
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install better-react-email-editor @react-email/editor react-email \
25
+ @tiptap/core @tiptap/pm @tiptap/react @tiptap/html @tiptap/extension-placeholder
26
+ ```
27
+
28
+ `react` and `react-dom` (18 or 19), `@react-email/editor`, `react-email` and the `@tiptap/*` packages are peer dependencies. Your app and the editor must share one copy of each.
29
+
30
+ ## Quick start
31
+
32
+ ```tsx
33
+ import { BetterEmailEditor } from 'better-react-email-editor';
34
+ import '@react-email/editor/themes/default.css';
35
+ import 'better-react-email-editor/styles.css';
36
+
37
+ export function NewsletterEditor() {
38
+ return (
39
+ <div style={{ height: '100vh' }}>
40
+ <BetterEmailEditor
41
+ locale="en" // or "fr"
42
+ onChange={(value) => save(value)} // { doc, settings }
43
+ uploadImage={async (file) => ({ url: await uploadToS3(file) })}
44
+ />
45
+ </div>
46
+ );
47
+ }
48
+ ```
49
+
50
+ The editor fills its parent, so give the parent a height.
51
+
52
+ ### Loading, saving and exporting
53
+
54
+ ```tsx
55
+ const ref = useRef<EmailEditorHandle>(null);
56
+
57
+ <BetterEmailEditor ref={ref} defaultValue={savedValue} onChange={setDraft} />;
58
+
59
+ const value = ref.current.getValue(); // { doc, settings } — store it as JSON
60
+ ref.current.setValue(otherValue); // replace the content
61
+ const { html, text } = await ref.current.exportEmail(); // ready-to-send email
62
+ ```
63
+
64
+ | `EmailEditorHandle` | Description |
65
+ | --- | --- |
66
+ | `editor` | The underlying Tiptap `Editor`. |
67
+ | `getValue()` / `setValue(value)` | Read or replace `{ doc, settings }`. `setValue` also accepts a bare Tiptap document. |
68
+ | `getJSON()` | The Tiptap document only. |
69
+ | `exportEmail()` | `Promise<{ html, text, unformattedHtml }>`, including the preview text. |
70
+ | `getHtml()` / `getText()` | Shortcuts for `exportEmail()`. |
71
+ | `insertBlocks(json[])` | Appends blocks at the end of the email. |
72
+
73
+ `defaultValue` is read on mount. The editor is uncontrolled, because re-applying a document on every keystroke would reset the cursor. Use `setValue` to replace the content later.
74
+
75
+ ## Props
76
+
77
+ `BetterEmailEditor` accepts every `EditorRoot` prop, plus the layout props listed further down.
78
+
79
+ | Prop | Type | Default | Description |
80
+ | --- | --- | --- | --- |
81
+ | `defaultValue` | `EmailValue \| JSONContent` | empty email | Initial content, read on mount. |
82
+ | `onChange` | `(value: EmailValue) => void` | | Called on every document or settings change. Debounce it yourself if you save to a server. |
83
+ | `onReady` | `(handle) => void` | | Called once the editor exists. |
84
+ | `locale` | `'en' \| 'fr' \| string` | `'en'` | UI language. |
85
+ | `messages` | `PartialMessages` | | Overrides any UI string, deep-merged over the locale. |
86
+ | `uploadImage` | `(file) => Promise<{ url }>` | inline data URL | Stores uploaded or pasted images. |
87
+ | `nodes` | `NodeDefinition[]` | `defaultNodes` | Block types: label, icon, properties panel, layers preview, extensions. |
88
+ | `palette` | `PaletteItem[]` | `defaultPalette` | Tiles of the **Content** tab. |
89
+ | `paletteGroups` | `PaletteGroup[]` | Layout, Content | Groups of tiles. |
90
+ | `templates` | `TemplateItem[]` | `defaultTemplates` | Prebuilt rows of the **Blocks** tab. |
91
+ | `starterDocument` | `(i18n) => JSONContent` | demo email | Loaded by the top bar's **Template** button. |
92
+ | `extensions` | `Extensions` | | Extra Tiptap extensions, read on mount. |
93
+ | `theme` | `EditorThemeInput` | `defaultTheme` | Email theme for new documents, read on mount. |
94
+ | `editable` | `boolean` | `true` | |
95
+ | `device` / `defaultDevice` / `onDeviceChange` | `'desktop' \| 'mobile'` | `'desktop'` | Canvas width, controlled or not. |
96
+ | `layersOpen` / `defaultLayersOpen` / `onLayersOpenChange` | `boolean` | `true` | Layers panel visibility, controlled or not. |
97
+ | `className` / `style` | | | Applied to the root element. |
98
+
99
+ Layout props, `BetterEmailEditor` only:
100
+
101
+ | Prop | Description |
102
+ | --- | --- |
103
+ | `showTopBar`, `showLayers`, `showSidebar` | Hide a part (all `true` by default). |
104
+ | `slotProps` | Props for each part, e.g. `{ sidebar: { className: 'my-sidebar' }, topBar: { actions: <MyButton /> } }`. |
105
+ | `components` | Replace a part entirely: `{ TopBar, LayersPanel, Canvas, Sidebar }`. |
106
+
107
+ ## Components
108
+
109
+ Every component below accepts `className` and `style`, and must be rendered inside `EditorRoot` (or `BetterEmailEditor`).
110
+
111
+ | Component | What it is |
112
+ | --- | --- |
113
+ | `EditorRoot` | Provider: creates the editor and shares it. Renders a `div.bree`. |
114
+ | `Canvas` | The editable email, with its overlay (frames, handle, toolbar, drop indicator). Props: `overlay`, `bubbleMenu`, `slashCommands`. |
115
+ | `TopBar` | Top bar: desktop / mobile toggle and the export button. Props: `brand` (left side, empty by default), `actions` (extra controls before the export button), or `children` to replace its content. |
116
+ | `DeviceToggle`, `ExportHtmlButton` | The default top bar controls. |
117
+ | `LayersToggle`, `UndoRedo`, `TemplateButton`, `ImportButton`, `ExportJsonButton`, `PreviewButton` | Optional controls, not shown by default: add them through `actions` or your own bar. |
118
+ | `LayersPanel` | Layers tree. Props: `title`, and `onClose` to show a close button. |
119
+ | `Sidebar` | Right panel. Switches between three screens; override any of them with `renderDocument`, `renderNode` or `renderText`. |
120
+ | `ContentPanel` | Screen shown when nothing is selected: tabs. Prop `tabs` picks or reorders `'content' \| 'blocks' \| 'body'` and accepts your own tabs. |
121
+ | `ContentTab` / `PaletteTile` | Palette of draggable tiles. |
122
+ | `BlocksTab` / `TemplateCard` | Prebuilt rows. |
123
+ | `BodyTab` | Email-wide settings: background, width, default colors, preview text. |
124
+ | `PropertiesPanel` | Properties shell: header, close button, breadcrumb. |
125
+ | `BlockProperties` | Properties of the selected block, using the inspector registered for its type. |
126
+ | `TextProperties` | Properties of a text selection. |
127
+ | `PreviewDialog` | Preview and export modal. |
128
+ | `ImageInspector`, `ButtonInspector`, `HeadingInspector`, `SocialLinksInspector`, `ColumnsInspector`, `SpacerInspector`, `HtmlInspector`, `DividerInspector`, `ContainerInspector`, `DefaultInspector` | Properties panel of each block type. |
129
+ | `TypographyGroup`, `SpacingGroup`, `BoxGroup` | Reusable groups of controls. |
130
+ | `Group`, `Field`, `TextInput`, `TextArea`, `NumberInput`, `RangeInput`, `ColorInput`, `Select`, `Segmented`, `AlignInput`, `PaddingInput` | Form controls, to build your own panels. |
131
+
132
+ Hooks:
133
+
134
+ - `useEmailEditor()` gives the editor, `t` (messages), `locale`, registries, `device`, `layersOpen`, `settings`, `handle`…
135
+ - `useI18n()` gives `{ locale, t }`.
136
+ - `useDraggableBlock(label, content)` turns any element into a source of blocks: drag it onto the canvas or click it.
137
+ - `useDeselect()` clears the selection.
138
+
139
+ ### Custom layout
140
+
141
+ ```tsx
142
+ import { EditorRoot, Canvas, Sidebar, UndoRedo, DeviceToggle, ExportHtmlButton } from 'better-react-email-editor';
143
+
144
+ <EditorRoot locale="fr" defaultValue={value} onChange={save} className="my-editor">
145
+ <div style={{ display: 'flex', height: '100%' }}>
146
+ <main style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
147
+ <Canvas style={{ flex: 1 }} />
148
+ <footer>
149
+ <UndoRedo />
150
+ <DeviceToggle />
151
+ <ExportHtmlButton />
152
+ </footer>
153
+ </main>
154
+ <Sidebar style={{ width: 320 }} />
155
+ </div>
156
+ </EditorRoot>;
157
+ ```
158
+
159
+ ![A custom layout](./docs/custom-layout.png)
160
+
161
+ The playground contains this example: `npm run dev`, then open `/?example=custom`.
162
+
163
+ ## Styling
164
+
165
+ All classes are prefixed with `bree-`, and the stylesheet never touches global elements. Restyle a part through its `className` or `style`, or theme the whole editor with CSS custom properties:
166
+
167
+ ```css
168
+ .my-editor {
169
+ --bree-accent: #7c3aed;
170
+ --bree-accent-hover: #6d28d9;
171
+ --bree-accent-soft: #f5f3ff;
172
+ --bree-font: 'Inter', sans-serif;
173
+ --bree-sidebar-width: 320px;
174
+ }
175
+ ```
176
+
177
+ | Variable | Default |
178
+ | --- | --- |
179
+ | `--bree-bg`, `--bree-bg-subtle` | `#ffffff`, `#f8fafc` |
180
+ | `--bree-border`, `--bree-border-strong` | `#e5e7eb`, `#d1d5db` |
181
+ | `--bree-text`, `--bree-text-secondary`, `--bree-muted` | `#111827`, `#334155`, `#6b7280` |
182
+ | `--bree-accent`, `--bree-accent-hover`, `--bree-accent-soft` | `#2563eb`, `#1d4ed8`, `#eff6ff` |
183
+ | `--bree-danger` | `#dc2626` |
184
+ | `--bree-radius` | `8px` |
185
+ | `--bree-canvas-bg` | `#eef1f5` |
186
+ | `--bree-topbar-height`, `--bree-sidebar-width`, `--bree-layers-width` | `56px`, `360px`, `270px` |
187
+ | `--bree-font` | Inter, system-ui… |
188
+
189
+ The default layout is a CSS grid on `.bree-layout`. The color picker popover is rendered in a portal; it carries the `bree` class, so the variables apply to it too. Its `popoverClassName` prop adds your own class.
190
+
191
+ ## Languages
192
+
193
+ ```tsx
194
+ <BetterEmailEditor locale="fr" />
195
+
196
+ // Override a few strings
197
+ <BetterEmailEditor locale="en" messages={{ topBar: { exportHtml: 'Export' }, palette: { card: 'Callout' } }} />
198
+
199
+ // Add a language: provide every string, starting from `en`
200
+ import { en, type Messages } from 'better-react-email-editor';
201
+ const de: Messages = { ...en, topBar: { ...en.topBar, preview: 'Vorschau' /* … */ } };
202
+ <BetterEmailEditor locale="de" messages={de} />
203
+ ```
204
+
205
+ `en` and `fr` are exported. `messages` covers the UI, the default content inserted by the palette and templates, the placeholders and the `/` commands.
206
+
207
+ ## Extending
208
+
209
+ ### A palette item
210
+
211
+ ```tsx
212
+ import { content, defaultPalette, type PaletteItem } from 'better-react-email-editor';
213
+
214
+ const promo: PaletteItem = {
215
+ id: 'promo',
216
+ group: 'brand', // new group, or 'layout' / 'content'
217
+ label: ({ locale }) => (locale === 'fr' ? 'Bandeau promo' : 'Promo banner'),
218
+ icon: <PercentIcon />,
219
+ content: () => [content.section('padding:20px;background-color:#fef3c7', content.heading(2, '20% off'))],
220
+ };
221
+
222
+ <BetterEmailEditor
223
+ palette={[promo, ...defaultPalette]}
224
+ paletteGroups={[{ id: 'brand', title: 'My brand' }, ...defaultPaletteGroups]}
225
+ />;
226
+ ```
227
+
228
+ `content` provides helpers to build the document JSON: `paragraph`, `heading`, `button`, `image`, `columns`, `column`, `sized`, `section`, `padding`, `link`, `text`, `doc` and `placeholderImage`.
229
+
230
+ ### A template (prebuilt row)
231
+
232
+ ```tsx
233
+ const signature: TemplateItem = {
234
+ id: 'signature',
235
+ label: 'Signature',
236
+ description: 'Name, role and logo',
237
+ content: () => [content.paragraph('Jane Doe — CEO')],
238
+ };
239
+
240
+ <BetterEmailEditor templates={[...defaultTemplates, signature]} />;
241
+ ```
242
+
243
+ ### A properties panel
244
+
245
+ Replace the panel of an existing block, or give one to a new block:
246
+
247
+ ```tsx
248
+ import { defaultNodes, Group, Field, TextInput, SpacingGroup, type InspectorProps } from 'better-react-email-editor';
249
+
250
+ function MyButtonInspector({ ctx, className, style }: InspectorProps) {
251
+ return (
252
+ <div className={className} style={style}>
253
+ <Group title="Link">
254
+ <Field label="URL" stacked>
255
+ <TextInput value={String(ctx.getAttr('href') ?? '')} onChange={(v) => ctx.setAttr('href', v)} />
256
+ </Field>
257
+ </Group>
258
+ <SpacingGroup ctx={ctx} />
259
+ </div>
260
+ );
261
+ }
262
+
263
+ const nodes = defaultNodes.map((node) => (node.type === 'button' ? { ...node, inspector: MyButtonInspector } : node));
264
+
265
+ <BetterEmailEditor nodes={nodes} />;
266
+ ```
267
+
268
+ `ctx` is the `@react-email/editor` inspector context: `getAttr`, `setAttr`, `getStyle`, `setStyle`, `batchSetStyle`, `presetColors`, `nodeType` and `nodePos`.
269
+
270
+ ### A new block type
271
+
272
+ Create the node with `EmailNode.create` from `@react-email/editor/core`. It needs an editor rendering and an email rendering (`renderToReactEmail`). Then register it:
273
+
274
+ ```tsx
275
+ const countdownNode: NodeDefinition = {
276
+ type: 'countdown',
277
+ label: ({ locale }) => (locale === 'fr' ? 'Compte à rebours' : 'Countdown'),
278
+ icon: TimerIcon,
279
+ inspector: CountdownInspector,
280
+ preview: (node) => node.attrs.date,
281
+ extensions: [Countdown], // your EmailNode
282
+ };
283
+
284
+ <BetterEmailEditor nodes={[...defaultNodes, countdownNode]} palette={[...defaultPalette, countdownTile]} />;
285
+ ```
286
+
287
+ See `src/nodes/custom-nodes.tsx` for complete examples (spacer, social links, raw HTML).
288
+
289
+ ### Adding or removing controls
290
+
291
+ The default top bar only has the device toggle and the export button. Add the optional controls back, or remove parts:
292
+
293
+ ```tsx
294
+ import { UndoRedo, PreviewButton, ExportJsonButton, LayersToggle } from 'better-react-email-editor';
295
+
296
+ <BetterEmailEditor
297
+ slotProps={{
298
+ topBar: { brand: <img src="/logo.svg" alt="Acme" height={28} />, actions: <><UndoRedo /><ExportJsonButton /><PreviewButton /></> },
299
+ }}
300
+ />
301
+
302
+ <BetterEmailEditor
303
+ palette={defaultPalette.filter((item) => item.id !== 'html')}
304
+ showLayers={false}
305
+ slotProps={{ sidebar: { renderDocument: (ctx) => <ContentPanel ctx={ctx} tabs={['content', 'body']} /> } }}
306
+ />
307
+ ```
308
+
309
+ To let users hide and show the layers panel, add a `LayersToggle` and give the panel a close button:
310
+
311
+ ```tsx
312
+ const [layersOpen, setLayersOpen] = useState(true);
313
+
314
+ <BetterEmailEditor
315
+ layersOpen={layersOpen}
316
+ onLayersOpenChange={setLayersOpen}
317
+ slotProps={{ topBar: { actions: <LayersToggle /> }, layersPanel: { onClose: () => setLayersOpen(false) } }}
318
+ />;
319
+ ```
320
+
321
+ ## Headless core
322
+
323
+ The drag & drop engine has no UI and can be reused: `findDropTarget`, `applyDrop`, `appendBlocks`, `unitAt`, `selectedUnit`, `selectUnit`, `duplicateUnit`, `deleteUnit`, `parentUnit`, `BLOCK_CONTAINERS` and `COLUMN_PARENTS`.
324
+
325
+ How it fits into ProseMirror:
326
+
327
+ - The model is the package's: `container` (the email) holds the blocks. The drop zones are `container`, `section` and `columnsColumn`. The rows `twoColumns`, `threeColumns` and `fourColumns` hold columns.
328
+ - `findDropTarget()` walks down from the container to the deepest zone under the pointer, then picks the gap between two children. The schema validates every drop (`node.canReplace`), so a block never lands somewhere invalid.
329
+ - `dragover` and `drop` are captured on the canvas before ProseMirror sees them. Native text drags stay with ProseMirror.
330
+ - Insertions and moves are plain transactions, so undo / redo work with no extra code.
331
+
332
+ ## Development
333
+
334
+ ```bash
335
+ npm install
336
+ npm run dev # playground on http://localhost:5173 (?lang=fr, ?example=custom)
337
+ npm run build # library → dist/ (ESM, CJS, types, styles.css)
338
+ npm run typecheck
339
+ npm run lint
340
+ ```
341
+
342
+ ```
343
+ src/
344
+ index.ts public API
345
+ context.tsx EditorRoot, hooks, imperative handle
346
+ components/ one file per screen: TopBar, LayersPanel, Canvas (+ CanvasOverlay),
347
+ Sidebar, ContentPanel, ContentTab, BlocksTab, BodyTab, PropertiesPanel,
348
+ BlockProperties, TextProperties, PreviewDialog, fields, inspectors/
349
+ registry/ default nodes, palette, templates and starter email
350
+ nodes/ custom email nodes (spacer, social links, HTML)
351
+ core/ headless drag & drop engine, paste handling, JSON helpers
352
+ i18n/ en.ts, fr.ts
353
+ styles.css
354
+ playground/ demo app consuming the library from its sources
355
+ scripts/ Playwright scenarios
356
+ ```
357
+
358
+ The scenarios in `scripts/` drive the playground in French with Playwright. They use the Edge installed locally, through `playwright-core`.
359
+
360
+ ```bash
361
+ npx vite --port 5179 &
362
+ node scripts/e2e.mjs # also e2e2 … e2e10, e2e-custom, check-padding; screenshots in ./screenshots
363
+ ```
364
+
365
+ ## Known limitations
366
+
367
+ These are workarounds for `@react-email/editor`:
368
+
369
+ - The package has no block drag & drop; this library adds it.
370
+ - The package's `Button.parseHTML` ignores the `data-href` and alignment it writes, so `EmailButton` (in `core/paste.ts`) reads them back. Without it, a copy-pasted button loses its link.
371
+ - Pasting with a block selected inserts **after** the block instead of replacing it.
372
+ - `Divider` rejects insertions while a divider is selected. The selection is released before a drop or a duplication.
373
+ - The package's floating menus for buttons and images duplicate the properties panel, so CSS hides them.
374
+ - `TrailingNode` leaves an empty paragraph after non-text blocks. It stays collapsed until the caret enters it.
375
+ - `EmailEditor` always places its editing area before its children. `EditorRoot` creates the editor itself, so `Canvas` can sit anywhere in your layout; it reproduces the package's paste sanitizer, which is not exported.
376
+
377
+ Further ideas: host PNG social icons (Gmail does not display SVG), add media queries to stack columns on mobile in the exported HTML, and add more blocks (video thumbnail, countdown).
378
+
379
+ ## License
380
+
381
+ [MIT](./LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,o)=>(o=n==null?{}:e(i(n)),s(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n));let l=require("react"),u=require("@tiptap/extension-placeholder"),d=require("@tiptap/react"),f=require("@react-email/editor/core"),p=require("@react-email/editor/extensions"),m=require("@react-email/editor/plugins"),h=require("@tiptap/pm/model"),g=require("@tiptap/pm/state"),_=require("@tiptap/html"),v=require("@react-email/editor/ui"),y=require("react/jsx-runtime"),b=require("@radix-ui/react-popover");b=c(b,1);let x=require("react-colorful"),S=require("@tiptap/core"),C=require("react-email"),w=require("react-dom");function T(...e){return e.filter(Boolean).join(` `)}var E=new Set([`container`,`section`,`columnsColumn`]),D=new Set([`twoColumns`,`threeColumns`,`fourColumns`]),O=`application/x-email-block`;function k(e,t){let n=e.nodeDOM(t);return n instanceof HTMLElement?n.getBoundingClientRect():null}function ee(e,t,n){let r=[];return t.forEach((t,i)=>{let a=n+1+i,o=k(e,a);o&&r.push({node:t,pos:a,rect:o})}),r}function A(e){return e.type.name===`paragraph`&&e.childCount===0}function j(e){let t=null;return e.forEach((e,n)=>{!t&&e.type.name===`container`&&(t={node:e,pos:n})}),t}function te(e,t,n,r,i){let a=j(e.state.doc);if(!a)return null;let o=e=>!!i&&e>=i.from&&e<i.to,s=(i,a)=>{let c=ee(e,i,a),l=k(e,a);if(!l)return null;for(let r of c){let{rect:i}=r,a=Math.min(12,i.height/4),c=n>i.top+a&&n<i.bottom-a,l=t>=i.left&&t<=i.right;if(!c||!l||o(r.pos))continue;let u=r.node.type.name;if(E.has(u)){let e=s(r.node,r.pos);if(e)return e}else if(D.has(u)){let n=ee(e,r.node,r.pos),i=n.find(e=>t>=e.rect.left&&t<=e.rect.right)??(t<n[0]?.rect.left?n[0]:n[n.length-1]);if(i&&!o(i.pos)){let e=s(i.node,i.pos);if(e)return e}}}if(c.length===1&&A(c[0].node)&&!o(c[0].pos)){let e=c[0];return i.type.validContent(r)?{pos:e.pos,replaceTo:e.pos+e.node.nodeSize,line:{top:e.rect.top,left:l.left,width:l.width},emptyZone:{top:l.top,left:l.left,width:l.width,height:Math.max(l.height,40)}}:null}let u=c.length;for(let e=0;e<c.length;e++){let{rect:t}=c[e];if(n<t.top+t.height/2){u=e;break}}let d=u,f=u<c.length?(e=>{let t=0,n=-1;return i.forEach((r,i)=>{a+1+i===e&&(n=t),t++}),n})(c[u].pos):i.childCount;if(!i.canReplace(f,f,r))return null;let p=d<c.length?c[d].pos:a+i.nodeSize-1,m;return m=c.length===0?l.top+4:d===0?c[0].rect.top:d===c.length?c[c.length-1].rect.bottom:(c[d-1].rect.bottom+c[d].rect.top)/2,{pos:p,line:{top:m,left:l.left,width:l.width}}};return s(a.node,a.pos)}function ne(e,t){let{schema:n,doc:r}=e.state;if(t.kind===`new`)try{return h.Fragment.fromArray(t.content().map(e=>n.nodeFromJSON(e)))}catch(e){return console.error(`Invalid block content`,e),null}let i=r.nodeAt(t.pos);return i?h.Fragment.from(i):null}function re(e,t){let n=e.doc.nodeAt(t);n&&(n.isAtom||n.type.name===`horizontalRule`?e.setSelection(g.NodeSelection.create(e.doc,t)):e.setSelection(g.TextSelection.near(e.doc.resolve(t+1))))}function M(e){let{selection:t,doc:n}=e.state;t instanceof g.NodeSelection&&e.dispatch(e.state.tr.setSelection(g.Selection.near(n.resolve(t.from))))}function ie(e,t){if(t.replaceTo!==void 0)return t;let n=e.resolve(t.pos),r=n.parent,i=r.lastChild;return n.index()!==r.childCount||!i||r.childCount<2||!A(i)?t:{...t,pos:t.pos-i.nodeSize}}function N(e,t,n){let{view:r}=e;M(r);let i=ne(r,t);if(!i)return!1;let a=ie(r.state.doc,n),o=r.state.tr;if(t.kind===`new`)a.replaceTo===void 0?o.insert(a.pos,i):o.replaceWith(a.pos,a.replaceTo,i),re(o,a.pos);else{let e=r.state.doc.nodeAt(t.pos);if(!e)return!1;let n=t.pos,i=n+e.nodeSize;if(a.replaceTo===void 0&&(a.pos===n||a.pos===i))return!1;ae(o,n,i);let s=o.mapping.map(a.pos,-1);if(a.replaceTo!==void 0){let t=o.mapping.map(a.replaceTo,1);o.replaceWith(s,t,e)}else o.insert(s,e);re(o,s)}return r.dispatch(o.scrollIntoView()),r.focus(),!0}function ae(e,t,n){let r=e.doc.resolve(t).parent;r.childCount===1&&E.has(r.type.name)?e.replaceWith(t,n,e.doc.type.schema.nodes.paragraph.create()):e.delete(t,n)}function P(e,t,n=!0){if(t<0||t>e.content.size)return null;let r=[],i=e.nodeAt(t);n&&i&&r.push({pos:t,node:i});let a=e.resolve(t);for(let e=a.depth;e>0;e--)r.push({pos:a.before(e),node:a.node(e)});for(let t of r){let n=e.resolve(t.pos).parent.type.name;if(E.has(n)||D.has(n))return t}return null}function oe(e){return e.node.type.name===`columnsColumn`}function se(e,t){let n=e.resolve(t.pos);for(let r=n.depth;r>0;r--){let i=P(e,n.before(r));if(i&&i.pos!==t.pos)return i}return null}function F(e){let{selection:t,doc:n}=e.state;return t instanceof g.NodeSelection?P(n,t.from)??{pos:t.from,node:t.node}:P(n,t.from,!1)}function I(e,t){let{view:n}=e,r=n.state.tr.setSelection(g.NodeSelection.create(n.state.doc,t.pos));n.dispatch(r),n.focus()}function ce(e,t){let{view:n}=e;M(n);let r=n.state.doc.nodeAt(t.pos);if(!r)return;let i=t.pos+r.nodeSize,a=n.state.tr.insert(i,r.copy(r.content));a.setSelection(g.NodeSelection.create(a.doc,i)),n.dispatch(a.scrollIntoView()),n.focus()}function le(e,t){let{view:n}=e,r=n.state.doc.nodeAt(t.pos);if(!r)return;let i=n.state.tr;ae(i,t.pos,t.pos+r.nodeSize),n.dispatch(i)}function ue(e,t){let n=j(e.state.doc);if(!n)return;let r=n.node.lastChild,i=n.pos+n.node.nodeSize-1;N(e,{kind:`new`,label:``,content:()=>t},r&&A(r)&&n.node.childCount>1?{pos:i-r.nodeSize,replaceTo:i,line:{top:0,left:0,width:0}}:{pos:i,line:{top:0,left:0,width:0}})}var de=p.Button.extend({parseHTML(){return[{tag:`a[data-id="react-email-button"]`,getAttrs:e=>{if(typeof e==`string`)return!1;let t=e,n=t.parentElement?.className.match(/align-(left|center|right)/)?.[1],r=t.className.replace(/\bnode-button\b/g,``).trim();return{href:t.getAttribute(`href`)??t.dataset.href??`#`,alignment:n??`left`,class:r||`button`,style:t.getAttribute(`style`)}}}]}});function fe(e,t){let n=t.clipboardData?.getData(`text/html`)??``,r=n.includes(`data-pm-slice`);if((t.clipboardData?.files?.length??0)>0)return!1;let{view:i}=e,{state:a}=i,{selection:o}=a;if(o instanceof g.NodeSelection&&o.node.isBlock){let e=o.node,t=e.type.name===`columnsColumn`?o.from+e.nodeSize-1:o.from+e.nodeSize,n=a.doc.resolve(t),r=a.schema.nodes.paragraph;if(D.has(n.parent.type.name)||!n.parent.canReplaceWith(n.index(),n.index(),r))return!1;i.dispatch(a.tr.setSelection(g.TextSelection.near(n)));let s=i.state.tr.insert(t,r.create());s.setSelection(g.TextSelection.create(s.doc,t+1)),i.dispatch(s)}return r?(t.preventDefault(),t.stopPropagation(),i.pasteHTML(n),!0):!1}var pe=/class="[^"]*node-/,L=[`script`,`iframe`,`object`,`embed`,`meta`,`base`],me=[`href`,`src`],he={a:[`href`,`target`,`rel`],img:[`src`,`alt`,`width`,`height`],td:[`colspan`,`rowspan`],th:[`colspan`,`rowspan`,`scope`],table:[`border`,`cellpadding`,`cellspacing`],"*":[`id`]};function R(e,t){let n=e.trim().toLowerCase();return n.startsWith(`javascript:`)||n.startsWith(`vbscript:`)?!1:!n.startsWith(`data:`)||t&&n.startsWith(`data:image/`)}function ge(e){let t=new Set([...he[e.tagName.toLowerCase()]??[],...he[`*`]]);for(let n of Array.from(e.attributes))(n.name.startsWith(`data-`)||!t.has(n.name))&&e.removeAttribute(n.name)}function _e(e){e.nodeType===Node.ELEMENT_NODE&&ge(e);for(let t of Array.from(e.childNodes))_e(t)}function ve(e){let t=new DOMParser().parseFromString(e,`text/html`);for(let e of L)for(let n of Array.from(t.body.getElementsByTagName(e)))n.remove();for(let e of Array.from(t.body.querySelectorAll(`[href], [src]`))){let t=e.tagName.toLowerCase()===`img`;for(let n of me){let r=e.getAttribute(n);r!==null&&!R(r,t)&&e.removeAttribute(n)}}return pe.test(e)||_e(t.body),t.body.innerHTML}function ye(e){return(t,n,r)=>{if(r.content.childCount===1)return!1;let i=n.clipboardData?.getData?.(`text/html`);if(!i)return!1;n.preventDefault();let a=(0,_.generateJSON)(ve(i),e),o=t.state.schema.nodeFromJSON(a);return t.dispatch(t.state.tr.replaceSelectionWith(o,!1)),!0}}function be(){let e=null;return{get:()=>e,start:t=>{e=t},end:()=>{e=null}}}function xe(){let e=null,t=new Set;return{get:()=>e,set:n=>{if(n!==e){e=n;for(let e of t)e()}},subscribe:e=>(t.add(e),()=>{t.delete(e)})}}var Se={topBar:{layers:`Layers`,toggleLayers:`Show / hide layers`,undo:`Undo (Ctrl+Z)`,redo:`Redo (Ctrl+Y)`,canvasWidth:`Canvas width`,desktop:`Desktop`,mobile:`Mobile`,template:`Template`,confirmTemplate:`Replace the content with the starter template?`,import:`Import`,exportJson:`Save JSON`,preview:`Preview`,exportHtml:`Export HTML`,invalidFile:e=>`Invalid file: ${e}`},preview:{dialogLabel:`Preview and export`,desktop:`Desktop`,mobile:`Mobile`,html:`HTML`,text:`Plain text`,copy:`Copy`,copied:`Copied ✓`,download:`Download .html`,close:`Close`,rendering:`Rendering the email…`,renderError:e=>`Render error: ${e}`,iframeTitle:`Email preview`},sidebar:{label:`Side panel`,tabContent:`Content`,tabBlocks:`Blocks`,tabBody:`Body`,layoutTitle:`Layout`,contentTitle:`Content`,dragHint:`Drag an item into the email. A click adds it at the end.`,tileTitle:e=>`Drag “${e}” into the email (or click to add it at the end)`,propertiesEyebrow:`Properties`,closeProperties:`Close (back to content)`,breadcrumb:`Hierarchy`,selectedText:`Selected text`},body:{general:`General`,previewText:`Preview text`,previewTextPlaceholder:`Shown after the subject line in the inbox`,background:`Background`,backgroundColor:`Background color`,outerPadding:`Outer padding`,content:`Content`,width:`Width`,contentColor:`Content color`,innerPadding:`Inner padding`,radius:`Corner radius`,defaultStyles:`Default styles`,text:`Text`,headings:`Headings`,links:`Links`,buttonBackground:`Button background`,buttonText:`Button text`},inspector:{typography:`Typography`,color:`Color`,size:`Size`,weight:`Weight`,weightLight:`Light`,weightNormal:`Normal`,weightSemibold:`Semibold`,weightBold:`Bold`,weightExtrabold:`Extra bold`,lineHeight:`Line height`,alignment:`Alignment`,spacing:`Spacing`,padding:`Padding`,box:`Background & border`,backgroundColor:`Background color`,radius:`Corner radius`,border:`Border`,borderColor:`Border color`,image:`Image`,uploadImage:`Upload an image…`,imageUrl:`Image URL`,altText:`Alt text`,altPlaceholder:`Describe the image`,layout:`Layout`,autoWidth:`Auto width`,width:`Width`,action:`Action`,clickLink:`Link on click`,linkUrl:`Link URL`,button:`Button`,textColor:`Text color`,textSize:`Text size`,buttonPadding:`Button padding`,networks:`Networks`,removeNetwork:`Remove`,addNetwork:`+ Add a network`,appearance:`Appearance`,iconSize:`Icon size`,gap:`Spacing`,columns:`Columns`,distribution:`Distribution`,equal:`Equal`,columnGap:`Gap between columns`,columnsHint:`Click inside a column to set its background and padding.`,spacer:`Spacer`,height:`Height`,htmlCode:`HTML code`,htmlHint:`The HTML is inserted as is in the exported email.`,line:`Line`,thickness:`Thickness`,lineStyle:`Style`,heading:`Heading`,level:`Level`,formatting:`Formatting`,bold:`Bold`,italic:`Italic`,underline:`Underline`,strike:`Strikethrough`,link:`Link`,url:`URL`,linkColor:`Link color`},fields:{colorDefault:`Default`,chooseColor:e=>`Pick a color (${e})`,hexCode:`Hex code`,eyedropper:`Eyedropper: pick a color on screen`,documentColors:`Document colors`,palette:`Palette`,resetColor:`Reset to default`,alignLeft:`Left`,alignCenter:`Center`,alignRight:`Right`,top:`Top`,right:`Right`,bottom:`Bottom`,left:`Left`,moreOptions:`More options`,auto:`auto`},layers:{title:`Layers`,expandAll:`Expand all`,collapseAll:`Collapse all`,close:`Close layers`,tree:`Email structure`,emptyEmail:`The email is empty.`,emptyZone:`Empty — drop content here`,column:e=>`Column ${e}`,fixedHint:`Columns stay in their row`,itemHint:`Click to select, drag to move`,expand:`Expand`,collapse:`Collapse`,uploadedImage:`uploaded image`,empty:`empty`},canvas:{dropHere:`Drop here`,dropLabel:e=>e?`Drop “${e}” here`:`Drop here`,emptyZone:`Drag content here`,move:`Drag to move`,moveLabel:e=>`Move: ${e}`,selectParent:e=>`Select: ${e}`,duplicate:`Duplicate`,delete:`Delete`},placeholder:{heading:`Heading`,paragraph:`Write, or type “/” for commands`},nodes:{body:`Body`,paragraph:`Text`,heading:`Heading`,image:`Image`,button:`Button`,horizontalRule:`Divider`,spacer:`Spacer`,socialLinks:`Social links`,htmlBlock:`HTML`,section:`Section`,twoColumns:`Row · 2 columns`,threeColumns:`Row · 3 columns`,fourColumns:`Row · 4 columns`,columnsColumn:`Column`,bulletList:`List`,orderedList:`Numbered list`,listItem:`List item`,blockquote:`Quote`,codeBlock:`Code`,table:`Table`,container:`Email`},palette:{oneColumn:`1 column`,twoColumns:`2 columns`,threeColumns:`3 columns`,fourColumns:`4 columns`,heading:`Heading`,text:`Text`,button:`Button`,image:`Image`,divider:`Divider`,spacer:`Spacer`,social:`Social`,menu:`Menu`,list:`List`,quote:`Quote`,html:`HTML`,card:`Card`},templates:{header:`Header`,headerDescription:`Logo on the left, menu on the right`,hero:`Hero`,heroDescription:`Big heading, tagline and button`,products:`Products`,productsDescription:`Two product cards side by side`,features:`Features`,featuresDescription:`Three columns with heading + text`,testimonial:`Testimonial`,testimonialDescription:`Highlighted customer quote`,footer:`Footer`,footerDescription:`Social links, address and unsubscribe`},content:{heading:`Your heading here`,text:`This is a new text block. Click it to edit the content, select text to format it.`,button:`Click here`,image:`Image`,menuHome:`Home`,menuShop:`Shop`,menuBlog:`Blog`,menuContact:`Contact`,listItems:[`First item`,`Second item`,`Third item`],quote:`“A quote that highlights your message.”`,html:`<p style="margin:0;text-align:center;font-family:sans-serif">Your custom <strong>HTML</strong></p>`,cardTitle:`Did you know?`,cardText:`A card draws attention to an important piece of information.`,logo:`LOGO`,heroTitle:`What’s new this season`,heroText:`Discover our selection made for you, available today.`,heroButton:`Discover`,productA:`Product A`,productB:`Product B`,productText:`A short description of the product.`,productButton:`Buy`,features:[`Free shipping`,`Free returns`,`24/7 support`],featureText:`A clear and concise argument.`,testimonialQuote:`“Flawless service, I recommend it with my eyes closed.”`,testimonialAuthor:`— Camille, customer since 2021`,footerAddress:`Acme Inc. · 10 Main Street, Springfield`,unsubscribe:`Unsubscribe`,starterTitle:`Our favourites`},slashCommands:{}},Ce={topBar:{layers:`Calques`,toggleLayers:`Afficher / masquer les calques`,undo:`Annuler (Ctrl+Z)`,redo:`Rétablir (Ctrl+Y)`,canvasWidth:`Largeur du canvas`,desktop:`Bureau`,mobile:`Mobile`,template:`Modèle`,confirmTemplate:`Remplacer le contenu par le modèle de départ ?`,import:`Importer`,exportJson:`Enregistrer JSON`,preview:`Aperçu`,exportHtml:`Exporter HTML`,invalidFile:e=>`Fichier invalide : ${e}`},preview:{dialogLabel:`Aperçu et export`,desktop:`Bureau`,mobile:`Mobile`,html:`HTML`,text:`Texte brut`,copy:`Copier`,copied:`Copié ✓`,download:`Télécharger .html`,close:`Fermer`,rendering:`Rendu de l’email…`,renderError:e=>`Erreur de rendu : ${e}`,iframeTitle:`Aperçu de l’email`},sidebar:{label:`Panneau latéral`,tabContent:`Contenu`,tabBlocks:`Blocs`,tabBody:`Corps`,layoutTitle:`Mise en page`,contentTitle:`Contenus`,dragHint:`Glissez un élément dans l’email. Un clic l’ajoute à la fin.`,tileTitle:e=>`Glissez « ${e} » dans l’email (ou cliquez pour l’ajouter à la fin)`,propertiesEyebrow:`Propriétés`,closeProperties:`Fermer (retour aux contenus)`,breadcrumb:`Hiérarchie`,selectedText:`Texte sélectionné`},body:{general:`Général`,previewText:`Texte d’aperçu`,previewTextPlaceholder:`Affiché après l’objet dans la boîte de réception`,background:`Arrière-plan`,backgroundColor:`Couleur de fond`,outerPadding:`Marge extérieure`,content:`Contenu`,width:`Largeur`,contentColor:`Couleur du contenu`,innerPadding:`Marge intérieure`,radius:`Arrondi`,defaultStyles:`Styles par défaut`,text:`Texte`,headings:`Titres`,links:`Liens`,buttonBackground:`Fond des boutons`,buttonText:`Texte des boutons`},inspector:{typography:`Typographie`,color:`Couleur`,size:`Taille`,weight:`Graisse`,weightLight:`Fin`,weightNormal:`Normal`,weightSemibold:`Semi-gras`,weightBold:`Gras`,weightExtrabold:`Extra-gras`,lineHeight:`Interligne`,alignment:`Alignement`,spacing:`Espacement`,padding:`Marge intérieure`,box:`Fond et bordure`,backgroundColor:`Couleur de fond`,radius:`Arrondi`,border:`Bordure`,borderColor:`Couleur de bordure`,image:`Image`,uploadImage:`Importer une image…`,imageUrl:`URL de l’image`,altText:`Texte alternatif`,altPlaceholder:`Décrivez l’image`,layout:`Disposition`,autoWidth:`Largeur auto`,width:`Largeur`,action:`Action`,clickLink:`Lien au clic`,linkUrl:`URL du lien`,button:`Bouton`,textColor:`Couleur du texte`,textSize:`Taille du texte`,buttonPadding:`Marges du bouton`,networks:`Réseaux`,removeNetwork:`Retirer`,addNetwork:`+ Ajouter un réseau`,appearance:`Apparence`,iconSize:`Taille des icônes`,gap:`Espacement`,columns:`Colonnes`,distribution:`Répartition`,equal:`Égales`,columnGap:`Espace entre colonnes`,columnsHint:`Cliquez dans une colonne pour régler son fond et ses marges.`,spacer:`Espacement`,height:`Hauteur`,htmlCode:`Code HTML`,htmlHint:`Le HTML est inséré tel quel dans l’email exporté.`,line:`Ligne`,thickness:`Épaisseur`,lineStyle:`Style`,heading:`Titre`,level:`Niveau`,formatting:`Mise en forme`,bold:`Gras`,italic:`Italique`,underline:`Souligné`,strike:`Barré`,link:`Lien`,url:`URL`,linkColor:`Couleur du lien`},fields:{colorDefault:`Par défaut`,chooseColor:e=>`Choisir une couleur (${e})`,hexCode:`Code hexadécimal`,eyedropper:`Pipette : prendre une couleur à l’écran`,documentColors:`Couleurs du document`,palette:`Palette`,resetColor:`Revenir à la valeur par défaut`,alignLeft:`Gauche`,alignCenter:`Centre`,alignRight:`Droite`,top:`Haut`,right:`Droite`,bottom:`Bas`,left:`Gauche`,moreOptions:`Plus d’options`,auto:`auto`},layers:{title:`Calques`,expandAll:`Tout déplier`,collapseAll:`Tout replier`,close:`Fermer les calques`,tree:`Structure de l’email`,emptyEmail:`L’email est vide.`,emptyZone:`Vide — déposez du contenu ici`,column:e=>`Colonne ${e}`,fixedHint:`Les colonnes restent dans leur ligne`,itemHint:`Cliquer pour sélectionner, glisser pour déplacer`,expand:`Déplier`,collapse:`Replier`,uploadedImage:`image importée`,empty:`vide`},canvas:{dropHere:`Déposer ici`,dropLabel:e=>e?`Déposer « ${e} » ici`:`Déposer ici`,emptyZone:`Glissez du contenu ici`,move:`Glisser pour déplacer`,moveLabel:e=>`Déplacer : ${e}`,selectParent:e=>`Sélectionner : ${e}`,duplicate:`Dupliquer`,delete:`Supprimer`},placeholder:{heading:`Titre`,paragraph:`Écrivez, ou tapez « / » pour les commandes`},nodes:{body:`Corps`,paragraph:`Texte`,heading:`Titre`,image:`Image`,button:`Bouton`,horizontalRule:`Séparateur`,spacer:`Espacement`,socialLinks:`Réseaux sociaux`,htmlBlock:`HTML`,section:`Section`,twoColumns:`Ligne · 2 colonnes`,threeColumns:`Ligne · 3 colonnes`,fourColumns:`Ligne · 4 colonnes`,columnsColumn:`Colonne`,bulletList:`Liste`,orderedList:`Liste numérotée`,listItem:`Élément de liste`,blockquote:`Citation`,codeBlock:`Code`,table:`Tableau`,container:`Email`},palette:{oneColumn:`1 colonne`,twoColumns:`2 colonnes`,threeColumns:`3 colonnes`,fourColumns:`4 colonnes`,heading:`Titre`,text:`Texte`,button:`Bouton`,image:`Image`,divider:`Séparateur`,spacer:`Espacement`,social:`Réseaux`,menu:`Menu`,list:`Liste`,quote:`Citation`,html:`HTML`,card:`Encadré`},templates:{header:`En-tête`,headerDescription:`Logo à gauche, menu à droite`,hero:`Hero`,heroDescription:`Grand titre, accroche et bouton`,products:`Produits`,productsDescription:`Deux cartes produit côte à côte`,features:`Avantages`,featuresDescription:`Trois colonnes titre + texte`,testimonial:`Témoignage`,testimonialDescription:`Citation client mise en avant`,footer:`Pied de page`,footerDescription:`Réseaux sociaux, adresse et désinscription`},content:{heading:`Votre titre ici`,text:`Ceci est un nouveau bloc de texte. Cliquez dessus pour modifier le contenu, sélectionnez du texte pour le mettre en forme.`,button:`Cliquez ici`,image:`Image`,menuHome:`Accueil`,menuShop:`Boutique`,menuBlog:`Blog`,menuContact:`Contact`,listItems:[`Premier point`,`Deuxième point`,`Troisième point`],quote:`« Une citation qui met en valeur votre message. »`,html:`<p style="margin:0;text-align:center;font-family:sans-serif">Votre <strong>HTML</strong> personnalisé</p>`,cardTitle:`Le saviez-vous ?`,cardText:`Un encadré attire l’œil sur une information importante.`,logo:`LOGO`,heroTitle:`Les nouveautés de la saison`,heroText:`Découvrez notre sélection pensée pour vous, disponible dès aujourd’hui.`,heroButton:`Découvrir`,productA:`Produit A`,productB:`Produit B`,productText:`Une courte description du produit.`,productButton:`Acheter`,features:[`Livraison offerte`,`Retours gratuits`,`Support 7j/7`],featureText:`Un argument clair et concis.`,testimonialQuote:`« Service impeccable, je recommande les yeux fermés. »`,testimonialAuthor:`— Camille, cliente depuis 2021`,footerAddress:`Acme SAS · 10 rue de la Paix, 75002 Paris`,unsubscribe:`Se désinscrire`,starterTitle:`Nos coups de cœur`},slashCommands:{Text:{title:`Texte`,description:`Paragraphe simple`},Title:{title:`Titre`,description:`Grand titre`},Subtitle:{title:`Sous-titre`,description:`Titre moyen`},Heading:{title:`Intertitre`,description:`Petit titre`},"Bullet list":{title:`Liste à puces`,description:`Liste non ordonnée`},"Numbered list":{title:`Liste numérotée`,description:`Liste ordonnée`},Quote:{title:`Citation`,description:`Bloc de citation`},"Code block":{title:`Bloc de code`,description:`Extrait de code`},Button:{title:`Bouton`,description:`Bouton cliquable`},Divider:{title:`Séparateur`,description:`Ligne horizontale`},Section:{title:`Section`,description:`Section de contenu`},"2 columns":{title:`2 colonnes`,description:`Mise en page sur deux colonnes`},"3 columns":{title:`3 colonnes`,description:`Mise en page sur trois colonnes`},"4 columns":{title:`4 colonnes`,description:`Mise en page sur quatre colonnes`}}},we={en:Se,fr:Ce};function Te(e,t){return typeof e==`function`?e(t):e}function Ee(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function De(e,t){if(!Ee(t)||!Ee(e))return t??e;let n={...e};for(let[e,r]of Object.entries(t))r!==void 0&&(n[e]=Ee(r)&&Ee(n[e])?De(n[e],r):r);return n}function Oe(e,t){let n=we[e]??Se;return t?De(n,t):n}var ke=o({CopyIcon:()=>je,DesktopIcon:()=>Ie,GripIcon:()=>Ae,LayersIcon:()=>Re,MobileIcon:()=>Le,OneColumnIcon:()=>Ue,ParentIcon:()=>Ne,PipetteIcon:()=>ze,RedoIcon:()=>Fe,SocialIcon:()=>He,SpacerIcon:()=>Be,SpacerTileIcon:()=>Ve,TrashIcon:()=>Me,UndoIcon:()=>Pe}),z=(e,t=2)=>({viewBox:`0 0 24 24`,width:e,height:e,fill:`none`,stroke:`currentColor`,strokeWidth:t,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":!0}),Ae=({size:e=14})=>(0,y.jsx)(`svg`,{viewBox:`0 0 24 24`,width:e,height:e,fill:`currentColor`,"aria-hidden":!0,children:[6,12,18].map(e=>(0,y.jsxs)(`g`,{children:[(0,y.jsx)(`circle`,{cx:`9`,cy:e,r:`1.6`}),(0,y.jsx)(`circle`,{cx:`15`,cy:e,r:`1.6`})]},e))}),je=({size:e=14})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`rect`,{x:`8`,y:`8`,width:`12`,height:`12`,rx:`2`}),(0,y.jsx)(`path`,{d:`M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2`})]}),Me=({size:e=14})=>(0,y.jsx)(`svg`,{...z(e),children:(0,y.jsx)(`path`,{d:`M4 7h16M10 11v6M14 11v6M6 7l1 12a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-12M9 7V4h6v3`})}),Ne=({size:e=14})=>(0,y.jsx)(`svg`,{...z(e),children:(0,y.jsx)(`path`,{d:`M12 19V5M6 11l6-6 6 6`})}),Pe=({size:e=16})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`path`,{d:`M9 14 4 9l5-5`}),(0,y.jsx)(`path`,{d:`M4 9h10.5a5.5 5.5 0 0 1 0 11H11`})]}),Fe=({size:e=16})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`path`,{d:`m15 14 5-5-5-5`}),(0,y.jsx)(`path`,{d:`M20 9H9.5a5.5 5.5 0 0 0 0 11H13`})]}),Ie=({size:e=16})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`rect`,{x:`3`,y:`4`,width:`18`,height:`12`,rx:`2`}),(0,y.jsx)(`path`,{d:`M8 20h8M12 16v4`})]}),Le=({size:e=16})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`rect`,{x:`7`,y:`2`,width:`10`,height:`20`,rx:`2`}),(0,y.jsx)(`path`,{d:`M11 18h2`})]}),Re=({size:e=16})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`path`,{d:`m12 3 9 5-9 5-9-5 9-5Z`}),(0,y.jsx)(`path`,{d:`m3 13 9 5 9-5`})]}),ze=({size:e=15})=>(0,y.jsxs)(`svg`,{...z(e),children:[(0,y.jsx)(`path`,{d:`m2 22 1-1h3l9-9`}),(0,y.jsx)(`path`,{d:`M3 21v-3l9-9`}),(0,y.jsx)(`path`,{d:`m15 6 3.4-3.4a2.1 2.1 0 1 1 3 3L18 9l.4.4a2.1 2.1 0 1 1-3 3l-3.8-3.8a2.1 2.1 0 1 1 3-3l.4.4Z`})]}),Be=({size:e=14})=>(0,y.jsx)(`svg`,{...z(e),children:(0,y.jsx)(`path`,{d:`M4 4h16M4 20h16M12 8v8`})}),Ve=({size:e=22})=>(0,y.jsx)(`svg`,{...z(e,1.8),children:(0,y.jsx)(`path`,{d:`M4 4h16M4 20h16M12 7v10M9 9.5 12 7l3 2.5M9 14.5l3 2.5 3-2.5`})}),He=({size:e=22})=>(0,y.jsxs)(`svg`,{...z(e,1.8),children:[(0,y.jsx)(`circle`,{cx:`6`,cy:`12`,r:`2.5`}),(0,y.jsx)(`circle`,{cx:`18`,cy:`6`,r:`2.5`}),(0,y.jsx)(`circle`,{cx:`18`,cy:`18`,r:`2.5`}),(0,y.jsx)(`path`,{d:`m8.2 10.8 7.6-3.6M8.2 13.2l7.6 3.6`})]}),Ue=({size:e=22})=>(0,y.jsx)(`svg`,{...z(e,1.8),children:(0,y.jsx)(`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`})});function B({title:e,children:t,defaultOpen:n=!0,className:r,style:i}){let[a,o]=(0,l.useState)(n);return(0,y.jsxs)(`section`,{className:T(`bree-group`,r),style:i,children:[(0,y.jsxs)(`button`,{type:`button`,className:`bree-group-header`,onClick:()=>o(!a),"aria-expanded":a,children:[(0,y.jsx)(`span`,{children:e}),(0,y.jsx)(`span`,{className:T(`bree-chevron`,a&&`bree-open`),"aria-hidden":!0,children:`›`})]}),a&&(0,y.jsx)(`div`,{className:`bree-group-body`,children:t})]})}function V({label:e,children:t,stacked:n,className:r,style:i}){return(0,y.jsxs)(`label`,{className:T(`bree-field`,n&&`bree-stacked`,r),style:i,children:[(0,y.jsx)(`span`,{className:`bree-field-label`,children:e}),(0,y.jsx)(`span`,{className:`bree-field-control`,children:t})]})}function We(e){let[t,n]=(0,l.useState)(e),[r,i]=(0,l.useState)(e);return Object.is(e,r)||(i(e),n(e)),[t,n]}function H({value:e,onChange:t,placeholder:n,type:r=`text`,className:i,style:a}){let[o,s]=We(e);return(0,y.jsx)(`input`,{className:T(`bree-input`,i),style:a,type:r,value:o,placeholder:n,onChange:e=>s(e.target.value),onBlur:()=>o!==e&&t(o),onKeyDown:e=>{e.key===`Enter`&&t(o)}})}function Ge({value:e,onChange:t,rows:n=8,className:r,style:i}){let[a,o]=We(e);return(0,y.jsx)(`textarea`,{className:T(`bree-input bree-textarea`,r),style:i,rows:n,value:a,spellCheck:!1,onChange:e=>o(e.target.value),onBlur:()=>a!==e&&t(a)})}function Ke(e){if(e==null||e===``||e===`auto`)return``;let t=Number.parseFloat(String(e));return Number.isFinite(t)?t:``}function U({value:e,onChange:t,unit:n=`px`,min:r=0,max:i,step:a=1,placeholder:o,className:s,style:c}){let l=$(),[u,d]=We(String(Ke(e))),f=e=>{if(e.trim()===``)return t(``);let n=Number.parseFloat(e);Number.isFinite(n)&&t(Math.max(r,i===void 0?n:Math.min(i,n)))};return(0,y.jsxs)(`span`,{className:T(`bree-number`,s),style:c,children:[(0,y.jsx)(`input`,{className:`bree-input`,inputMode:`decimal`,value:u,placeholder:o??l.fields.auto,onChange:e=>d(e.target.value),onBlur:()=>f(u),onKeyDown:e=>{if(e.key===`Enter`&&f(u),e.key===`ArrowUp`||e.key===`ArrowDown`){e.preventDefault();let t=(Ke(u)||0)+(e.key===`ArrowUp`?a:-a)*(e.shiftKey?10:1);d(String(t)),f(String(t))}}}),n&&(0,y.jsx)(`span`,{className:`bree-unit`,children:n})]})}function qe({value:e,onChange:t,min:n,max:r,unit:i=`px`,className:a,style:o}){let s=Ke(e)||n;return(0,y.jsxs)(`span`,{className:T(`bree-range`,a),style:o,children:[(0,y.jsx)(`input`,{type:`range`,min:n,max:r,value:s,onChange:e=>t(Number(e.target.value))}),(0,y.jsxs)(`span`,{className:`bree-range-value`,children:[s,i]})]})}var Je=[`#111827`,`#374151`,`#6b7280`,`#d1d5db`,`#f3f4f6`,`#ffffff`,`#ef4444`,`#f97316`,`#f59e0b`,`#10b981`,`#0ea5e9`,`#2563eb`,`#4f46e5`,`#7c3aed`,`#db2777`,`#eef2ff`,`#ecfdf5`,`#fef3c7`];function Ye(e){let t=e.trim().toLowerCase();if(/^#[0-9a-f]{6}$/.test(t))return t;if(/^#[0-9a-f]{3}$/.test(t))return`#${[...t.slice(1)].map(e=>e+e).join(``)}`;let n=t.match(/^rgba?\(\s*(\d+)[\s,]+(\d+)[\s,]+(\d+)/);return n?`#${n.slice(1,4).map(e=>Number(e).toString(16).padStart(2,`0`)).join(``)}`:null}function W({value:e,onChange:t,presets:n=[],swatches:r=Je,placeholder:i,className:a,style:o,popoverClassName:s}){let c=$(),u=i??c.fields.colorDefault,d=typeof e==`string`?e:``,f=Ye(d),[p,m]=(0,l.useState)(!1),[h,g]=(0,l.useState)(f??`#ffffff`),_=(0,l.useRef)(t);(0,l.useEffect)(()=>{_.current=t});let S=(0,l.useRef)(null),C=(0,l.useRef)(0),w=()=>{window.clearTimeout(C.current),C.current=0,S.current&&_.current(S.current),S.current=null},E=e=>{g(e),S.current=e,C.current||=window.setTimeout(w,60)},D=e=>{S.current=null,window.clearTimeout(C.current),C.current=0,g(Ye(e)??h),_.current(e)},O=typeof window<`u`?window.EyeDropper:void 0,k=[...new Set(n.map(e=>Ye(e)).filter(e=>!!e))].slice(0,9);return(0,y.jsxs)(b.Root,{open:p,onOpenChange:e=>{e?g(f??`#ffffff`):w(),m(e)},children:[(0,y.jsxs)(`span`,{className:T(`bree-color-field`,a),style:o,children:[(0,y.jsx)(b.Trigger,{asChild:!0,children:(0,y.jsx)(`button`,{type:`button`,className:T(`bree-color-trigger`,!f&&`bree-empty`),style:f?{background:f}:void 0,"aria-label":c.fields.chooseColor(d||u)})}),(0,y.jsx)(H,{value:d,onChange:t,placeholder:u})]}),(0,y.jsx)(b.Portal,{children:(0,y.jsx)(v.EditorFocusScope,{children:(0,y.jsxs)(b.Content,{className:T(`bree bree-color-popover`,s),side:`left`,align:`start`,sideOffset:10,collisionPadding:12,onOpenAutoFocus:e=>e.preventDefault(),children:[(0,y.jsx)(x.HexColorPicker,{color:h,onChange:E}),(0,y.jsxs)(`div`,{className:`bree-color-popover-row`,children:[(0,y.jsx)(`span`,{className:`bree-color-preview`,style:{background:h}}),(0,y.jsxs)(`label`,{className:`bree-hex-field`,children:[(0,y.jsx)(`span`,{children:`#`}),(0,y.jsx)(x.HexColorInput,{color:h,onChange:D,"aria-label":c.fields.hexCode})]}),O&&(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button`,title:c.fields.eyedropper,onClick:()=>new O().open().then(e=>D(e.sRGBHex)).catch(()=>{}),children:(0,y.jsx)(ze,{})})]}),k.length>0&&(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`span`,{className:`bree-color-popover-title`,children:c.fields.documentColors}),(0,y.jsx)(`div`,{className:`bree-swatches`,children:k.map(e=>(0,y.jsx)(`button`,{type:`button`,className:`bree-swatch`,style:{background:e},title:e,onClick:()=>D(e)},e))})]}),(0,y.jsx)(`span`,{className:`bree-color-popover-title`,children:c.fields.palette}),(0,y.jsx)(`div`,{className:`bree-swatches`,children:r.map(e=>(0,y.jsx)(`button`,{type:`button`,className:T(`bree-swatch`,e===h&&`bree-active`),style:{background:e},title:e,onClick:()=>D(e)},e))}),(0,y.jsx)(`button`,{type:`button`,className:`bree-color-reset`,onClick:()=>{S.current=null,_.current(``),m(!1)},children:c.fields.resetColor})]})})})]})}function Xe({value:e,onChange:t,options:n,className:r,style:i}){return(0,y.jsx)(`select`,{className:T(`bree-input bree-select`,r),style:i,value:e,onChange:e=>t(e.target.value),children:n.map(([e,t])=>(0,y.jsx)(`option`,{value:e,children:t},e))})}function Ze({value:e,onChange:t,options:n,ariaLabel:r,className:i,style:a}){return(0,y.jsx)(`span`,{className:T(`bree-segmented`,i),style:a,role:`radiogroup`,"aria-label":r,children:n.map(n=>(0,y.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":e===n.value,title:n.title,className:T(e===n.value&&`bree-active`),onClick:()=>t(n.value),children:n.label},n.value))})}function Qe({value:e,onChange:t,className:n,style:r}){let i=$();return(0,y.jsx)(Ze,{className:n,style:r,value:e||`left`,onChange:t,options:[{value:`left`,label:(0,y.jsx)(v.AlignLeftIcon,{size:14}),title:i.fields.alignLeft},{value:`center`,label:(0,y.jsx)(v.AlignCenterIcon,{size:14}),title:i.fields.alignCenter},{value:`right`,label:(0,y.jsx)(v.AlignRightIcon,{size:14}),title:i.fields.alignRight}]})}function $e({get:e,set:t,className:n,style:r}){let i=$(),a=[`Top`,`Right`,`Bottom`,`Left`],o=a.map(t=>Ke(e(t))),s=o.every(e=>e===o[0]),[c,u]=(0,l.useState)(!s),d={Top:i.fields.top,Right:i.fields.right,Bottom:i.fields.bottom,Left:i.fields.left};return(0,y.jsxs)(`div`,{className:T(`bree-padding`,n),style:r,children:[c?(0,y.jsx)(`div`,{className:`bree-padding-grid`,children:a.map((e,n)=>(0,y.jsxs)(`label`,{className:`bree-padding-side`,children:[(0,y.jsx)(`span`,{children:d[e]}),(0,y.jsx)(U,{value:o[n],onChange:n=>t([[e,n]])})]},e))}):(0,y.jsx)(U,{value:o[0],onChange:e=>t(a.map(t=>[t,e]))}),(0,y.jsxs)(`label`,{className:`bree-checkbox`,children:[(0,y.jsx)(`input`,{type:`checkbox`,checked:c,onChange:e=>u(e.target.checked)}),i.fields.moreOptions]})]})}var G=e=>e;function et({ctx:e,alignment:t,setAlignment:n,className:r,style:i}){let a=$().inspector;return(0,y.jsxs)(B,{title:a.typography,className:r,style:i,children:[(0,y.jsx)(V,{label:a.color,stacked:!0,children:(0,y.jsx)(W,{value:e.getStyle(G(`color`)),presets:e.presetColors,onChange:t=>e.setStyle(G(`color`),t)})}),(0,y.jsx)(V,{label:a.size,children:(0,y.jsx)(U,{value:e.getStyle(G(`fontSize`)),onChange:t=>e.setStyle(G(`fontSize`),t),min:8,max:96})}),(0,y.jsx)(V,{label:a.weight,children:(0,y.jsx)(Xe,{value:String(e.getStyle(G(`fontWeight`))??`400`),onChange:t=>e.setStyle(G(`fontWeight`),t),options:[[`300`,a.weightLight],[`400`,a.weightNormal],[`600`,a.weightSemibold],[`700`,a.weightBold],[`800`,a.weightExtrabold]]})}),(0,y.jsx)(V,{label:a.lineHeight,children:(0,y.jsx)(U,{value:e.getStyle(G(`lineHeight`)),unit:`%`,onChange:t=>e.setStyle(G(`lineHeight`),t),min:80,max:300,step:5})}),n&&(0,y.jsx)(V,{label:a.alignment,children:(0,y.jsx)(Qe,{value:t??`left`,onChange:n})})]})}function K({ctx:e,title:t,className:n,style:r}){let i=$();return(0,y.jsx)(B,{title:t??i.inspector.spacing,className:n,style:r,children:(0,y.jsx)(V,{label:i.inspector.padding,stacked:!0,children:(0,y.jsx)($e,{get:t=>e.getStyle(G(`padding${t}`))??e.getStyle(G(`padding`)),set:t=>e.batchSetStyle([{prop:G(`padding`),value:``},...t.map(([e,t])=>({prop:G(`padding${e}`),value:t}))])})})})}function tt({ctx:e,className:t,style:n}){let r=$().inspector;return(0,y.jsxs)(B,{title:r.box,className:t,style:n,children:[(0,y.jsx)(V,{label:r.backgroundColor,stacked:!0,children:(0,y.jsx)(W,{value:e.getStyle(G(`backgroundColor`)),presets:e.presetColors,onChange:t=>e.setStyle(G(`backgroundColor`),t)})}),(0,y.jsx)(V,{label:r.radius,children:(0,y.jsx)(U,{value:e.getStyle(G(`borderRadius`)),onChange:t=>e.setStyle(G(`borderRadius`),t)})}),(0,y.jsx)(V,{label:r.border,children:(0,y.jsx)(U,{value:e.getStyle(G(`borderWidth`)),onChange:t=>e.batchSetStyle([{prop:G(`borderWidth`),value:t},{prop:G(`borderStyle`),value:t?`solid`:``}])})}),(0,y.jsx)(V,{label:r.borderColor,stacked:!0,children:(0,y.jsx)(W,{value:e.getStyle(G(`borderColor`)),presets:e.presetColors,onChange:t=>e.setStyle(G(`borderColor`),t)})})]})}function nt({ctx:e,className:t,style:n}){let r=$().inspector;return(0,y.jsxs)(`div`,{className:T(`bree-inspector`,t),style:n,children:[(0,y.jsx)(B,{title:r.action,children:(0,y.jsx)(V,{label:r.linkUrl,stacked:!0,children:(0,y.jsx)(H,{value:String(e.getAttr(`href`)??``),onChange:t=>e.setAttr(`href`,t),placeholder:`https://`})})}),(0,y.jsxs)(B,{title:r.button,children:[(0,y.jsx)(V,{label:r.alignment,children:(0,y.jsx)(Qe,{value:String(e.getAttr(`alignment`)??`left`),onChange:t=>e.setAttr(`alignment`,t)})}),(0,y.jsx)(V,{label:r.backgroundColor,stacked:!0,children:(0,y.jsx)(W,{value:e.getStyle(G(`backgroundColor`)),presets:e.presetColors,onChange:t=>e.setStyle(G(`backgroundColor`),t)})}),(0,y.jsx)(V,{label:r.textColor,stacked:!0,children:(0,y.jsx)(W,{value:e.getStyle(G(`color`)),presets:e.presetColors,onChange:t=>e.setStyle(G(`color`),t)})}),(0,y.jsx)(V,{label:r.textSize,children:(0,y.jsx)(U,{value:e.getStyle(G(`fontSize`)),onChange:t=>e.setStyle(G(`fontSize`),t),min:8,max:48})}),(0,y.jsx)(V,{label:r.radius,children:(0,y.jsx)(U,{value:e.getStyle(G(`borderRadius`)),onChange:t=>e.setStyle(G(`borderRadius`),t)})})]}),(0,y.jsx)(K,{ctx:e,title:r.buttonPadding})]})}function rt({ctx:e,className:t,style:n}){let{editor:r,t:i}=Q(),a=i.inspector,o={twoColumns:2,threeColumns:3,fourColumns:4}[e.nodeType]??2,s=o===2?[[`50 / 50`,[50,50]],[`33 / 67`,[33,67]],[`67 / 33`,[67,33]],[`25 / 75`,[25,75]]]:o===3?[[a.equal,[33.33,33.33,33.34]],[`25 / 50 / 25`,[25,50,25]]]:[[a.equal,[25,25,25,25]]],c=t=>{let{state:n}=r,i=n.doc.nodeAt(e.nodePos.pos);if(!i)return;let a=n.tr;i.forEach((n,r,i)=>{let o=e.nodePos.pos+1+r,s=String(n.attrs.style??``).split(`;`).filter(e=>e.trim()&&!e.trim().startsWith(`width`)).join(`;`);a.setNodeMarkup(o,void 0,{...n.attrs,style:`${s?`${s};`:``}width:${t[i]}%`})}),n.selection instanceof g.NodeSelection&&a.setSelection(g.NodeSelection.create(a.doc,e.nodePos.pos)),r.view.dispatch(a)};return(0,y.jsx)(`div`,{className:T(`bree-inspector`,t),style:n,children:(0,y.jsxs)(B,{title:a.columns,children:[(0,y.jsx)(V,{label:a.distribution,stacked:!0,children:(0,y.jsx)(`div`,{className:`bree-ratio-grid`,children:s.map(([e,t])=>(0,y.jsxs)(`button`,{type:`button`,className:`bree-ratio`,onClick:()=>c(t),children:[(0,y.jsx)(`span`,{className:`bree-ratio-bars`,children:t.map((e,t)=>(0,y.jsx)(`i`,{style:{flex:e}},t))}),e]},e))})}),(0,y.jsx)(V,{label:a.columnGap,children:(0,y.jsx)(U,{value:e.getAttr(`cellspacing`)??0,onChange:t=>e.setAttr(`cellspacing`,t===``?null:t)})}),(0,y.jsx)(`p`,{className:`bree-hint`,children:a.columnsHint})]})})}function it({ctx:e,className:t,style:n}){let r=$();return(0,y.jsxs)(`div`,{className:T(`bree-inspector`,t),style:n,children:[(0,y.jsx)(B,{title:r.inspector.heading,children:(0,y.jsx)(V,{label:r.inspector.level,children:(0,y.jsx)(Ze,{value:String(e.getAttr(`level`)??1),onChange:t=>e.setAttr(`level`,Number(t)),options:[{value:`1`,label:`H1`},{value:`2`,label:`H2`},{value:`3`,label:`H3`}]})})}),(0,y.jsx)(et,{ctx:e,alignment:String(e.getAttr(`alignment`)??`left`),setAlignment:t=>e.setAttr(`alignment`,t)}),(0,y.jsx)(K,{ctx:e}),(0,y.jsx)(tt,{ctx:e})]})}function at({ctx:e,className:t,style:n}){let{t:r,uploadImage:i}=Q(),a=r.inspector,o=String(e.getAttr(`width`)??`auto`);return(0,y.jsxs)(`div`,{className:T(`bree-inspector`,t),style:n,children:[(0,y.jsxs)(B,{title:a.image,children:[(0,y.jsx)(`div`,{className:`bree-image-preview`,children:e.getAttr(`src`)?(0,y.jsx)(`img`,{src:String(e.getAttr(`src`)),alt:``}):null}),(0,y.jsxs)(`label`,{className:`bree-button-like`,children:[a.uploadImage,(0,y.jsx)(`input`,{type:`file`,accept:`image/*`,hidden:!0,onChange:async t=>{let n=t.target.files?.[0];n&&e.setAttr(`src`,(await i(n)).url),t.target.value=``}})]}),(0,y.jsx)(V,{label:a.imageUrl,stacked:!0,children:(0,y.jsx)(H,{value:String(e.getAttr(`src`)??``),onChange:t=>e.setAttr(`src`,t)})}),(0,y.jsx)(V,{label:a.altText,stacked:!0,children:(0,y.jsx)(H,{value:String(e.getAttr(`alt`)??``),onChange:t=>e.setAttr(`alt`,t),placeholder:a.altPlaceholder})})]}),(0,y.jsxs)(B,{title:a.layout,children:[(0,y.jsx)(V,{label:a.autoWidth,children:(0,y.jsx)(`input`,{type:`checkbox`,checked:o===`auto`,onChange:t=>e.setAttr(`width`,t.target.checked?`auto`:`300`)})}),o!==`auto`&&(0,y.jsx)(V,{label:a.width,children:(0,y.jsx)(qe,{value:o,min:20,max:900,onChange:t=>e.setAttr(`width`,String(t))})}),(0,y.jsx)(V,{label:a.alignment,children:(0,y.jsx)(Qe,{value:String(e.getAttr(`alignment`)??`center`),onChange:t=>e.setAttr(`alignment`,t)})}),(0,y.jsx)(V,{label:a.radius,children:(0,y.jsx)(U,{value:e.getStyle(G(`borderRadius`)),onChange:t=>e.setStyle(G(`borderRadius`),t)})})]}),(0,y.jsx)(B,{title:a.action,children:(0,y.jsx)(V,{label:a.clickLink,stacked:!0,children:(0,y.jsx)(H,{value:String(e.getAttr(`href`)??``),onChange:t=>e.setAttr(`href`,t||null),placeholder:`https://`})})}),(0,y.jsx)(K,{ctx:e})]})}function ot({ctx:e,className:t,style:n}){let r=$();return(0,y.jsx)(`div`,{className:T(`bree-inspector`,t),style:n,children:(0,y.jsx)(B,{title:r.inspector.spacer,children:(0,y.jsx)(V,{label:r.inspector.height,children:(0,y.jsx)(qe,{value:e.getAttr(`height`),min:4,max:160,onChange:t=>e.setAttr(`height`,t)})})})})}function st({ctx:e,className:t,style:n}){let r=$();return(0,y.jsx)(`div`,{className:T(`bree-inspector`,t),style:n,children:(0,y.jsxs)(B,{title:r.inspector.htmlCode,children:[(0,y.jsx)(Ge,{value:String(e.getAttr(`html`)??``),onChange:t=>e.setAttr(`html`,t),rows:14}),(0,y.jsx)(`p`,{className:`bree-hint`,children:r.inspector.htmlHint})]})})}function ct({ctx:e,className:t,style:n}){let r=$().inspector;return(0,y.jsx)(`div`,{className:T(`bree-inspector`,t),style:n,children:(0,y.jsxs)(B,{title:r.line,children:[(0,y.jsx)(V,{label:r.color,stacked:!0,children:(0,y.jsx)(W,{value:e.getStyle(G(`borderTopColor`)),presets:e.presetColors,onChange:t=>e.setStyle(G(`borderTopColor`),t)})}),(0,y.jsx)(V,{label:r.thickness,children:(0,y.jsx)(U,{value:e.getStyle(G(`borderTopWidth`))??1,onChange:t=>e.batchSetStyle([{prop:G(`borderTopWidth`),value:t},{prop:G(`borderTopStyle`),value:`solid`}]),min:1,max:12})}),(0,y.jsx)(V,{label:r.lineStyle,children:(0,y.jsx)(Ze,{value:String(e.getStyle(G(`borderTopStyle`))??`solid`),onChange:t=>e.setStyle(G(`borderTopStyle`),t),options:[{value:`solid`,label:`———`},{value:`dashed`,label:`- - -`},{value:`dotted`,label:`· · ·`}]})})]})})}function lt({ctx:e,className:t,style:n}){return(0,y.jsxs)(`div`,{className:T(`bree-inspector`,t),style:n,children:[(0,y.jsx)(tt,{ctx:e}),(0,y.jsx)(K,{ctx:e})]})}function ut(e){if(typeof e!=`string`||!e.trim())return{};let t={};for(let n of e.split(`;`)){let e=n.indexOf(`:`);if(e===-1)continue;let r=n.slice(0,e).trim(),i=n.slice(e+1).trim();r&&i&&(t[r.replace(/-([a-z])/g,(e,t)=>t.toUpperCase())]=i)}return t}var dt={style:{default:null,parseHTML:e=>e.getAttribute(`style`),renderHTML:e=>e.style?{style:e.style}:{}}},ft=f.EmailNode.create({name:`spacer`,group:`block`,atom:!0,selectable:!0,addAttributes(){return{...dt,height:{default:32,parseHTML:e=>Number(e.dataset.height)||32,renderHTML:e=>({"data-height":e.height})}}},parseHTML(){return[{tag:`div[data-type="spacer"]`}]},renderHTML({node:e,HTMLAttributes:t}){return[`div`,(0,S.mergeAttributes)(t,{"data-type":`spacer`,class:`node-spacer`,style:`height:${Number(e.attrs.height)}px`})]},renderToReactEmail({node:e}){let t=Number(e.attrs?.height??32);return(0,y.jsx)(C.Section,{style:{height:t,lineHeight:`${t}px`,fontSize:`1px`,...ut(e.attrs?.style)},children:`\xA0`})}}),pt={facebook:{label:`Facebook`,slug:`facebook`,color:`1877F2`},instagram:{label:`Instagram`,slug:`instagram`,color:`E4405F`},x:{label:`X`,slug:`x`,color:`000000`},linkedin:{label:`LinkedIn`,slug:`linkedin`,color:`0A66C2`},youtube:{label:`YouTube`,slug:`youtube`,color:`FF0000`},tiktok:{label:`TikTok`,slug:`tiktok`,color:`000000`},github:{label:`GitHub`,slug:`github`,color:`181717`}},mt={linkedin:`https://cdn.jsdelivr.net/npm/simple-icons@9.21.0/icons/linkedin.svg`};function ht(e){if(mt[e])return mt[e];let t=pt[e]??pt.facebook;return`https://cdn.simpleicons.org/${t.slug}/${t.color}`}function gt(e){if(Array.isArray(e))return e;if(typeof e==`string`)try{return JSON.parse(e)}catch{return[]}return[]}var _t=f.EmailNode.create({name:`socialLinks`,group:`block`,atom:!0,selectable:!0,addAttributes(){return{...dt,links:{default:[{network:`facebook`,url:`https://facebook.com/`},{network:`instagram`,url:`https://instagram.com/`},{network:`x`,url:`https://x.com/`},{network:`linkedin`,url:`https://linkedin.com/`}],parseHTML:e=>gt(e.dataset.links),renderHTML:e=>({"data-links":JSON.stringify(e.links??[])})},size:{default:28},gap:{default:12},alignment:{default:`center`}}},parseHTML(){return[{tag:`div[data-type="social-links"]`}]},renderHTML({node:e,HTMLAttributes:t}){let n=Number(e.attrs.size),r=Number(e.attrs.gap),i=gt(e.attrs.links);return[`div`,(0,S.mergeAttributes)(t,{"data-type":`social-links`,class:`node-socialLinks`,alignment:e.attrs.alignment}),...i.map((e,t)=>[`span`,{class:`node-socialLinks-item`,style:`margin-left:${t===0?0:r}px`},[`img`,{src:ht(e.network),width:String(n),height:String(n),alt:pt[e.network]?.label??e.network}]])]},renderToReactEmail({node:e}){let t=Number(e.attrs?.size??28),n=Number(e.attrs?.gap??12),r=gt(e.attrs?.links),i=e.attrs?.alignment??`center`;return(0,y.jsx)(C.Section,{style:ut(e.attrs?.style),children:(0,y.jsx)(C.Row,{children:(0,y.jsx)(C.Column,{align:i,children:r.map((e,r)=>(0,y.jsx)(C.Link,{href:e.url,style:{display:`inline-block`,marginLeft:r===0?0:n},children:(0,y.jsx)(C.Img,{src:ht(e.network),width:t,height:t,alt:pt[e.network]?.label??e.network})},`${e.network}-${r}`))})})})}}),vt=f.EmailNode.create({name:`htmlBlock`,group:`block`,atom:!0,selectable:!0,addAttributes(){return{html:{default:`<p style="margin:0;text-align:center;font-family:sans-serif">Your custom <strong>HTML</strong></p>`,parseHTML:e=>e.dataset.html??e.innerHTML,renderHTML:()=>({})}}},parseHTML(){return[{tag:`div[data-type="html-block"]`}]},renderHTML({node:e,HTMLAttributes:t}){return[`div`,(0,S.mergeAttributes)(t,{"data-type":`html-block`,class:`node-htmlBlock`,"data-html":e.attrs.html})]},addNodeView(){return({node:e})=>{let t=document.createElement(`div`);return t.className=`node-htmlBlock`,t.dataset.type=`html-block`,t.innerHTML=e.attrs.html,{dom:t,update(n){return n.type===e.type&&(t.innerHTML=n.attrs.html,!0)},ignoreMutation:()=>!0}}},renderToReactEmail({node:e}){return(0,y.jsx)(`div`,{dangerouslySetInnerHTML:{__html:e.attrs?.html??``}})}});function yt({ctx:e,className:t,style:n}){let r=$().inspector,i=e.getAttr(`links`),a=Array.isArray(i)?i:[],o=t=>e.setAttr(`links`,t);return(0,y.jsxs)(`div`,{className:T(`bree-inspector`,t),style:n,children:[(0,y.jsxs)(B,{title:r.networks,children:[(0,y.jsx)(`div`,{className:`bree-social-list`,children:a.map((e,t)=>(0,y.jsxs)(`div`,{className:`bree-social-row`,children:[(0,y.jsx)(Xe,{value:e.network,onChange:e=>o(a.map((n,r)=>r===t?{...n,network:e}:n)),options:Object.entries(pt).map(([e,t])=>[e,t.label])}),(0,y.jsx)(H,{value:e.url,onChange:e=>o(a.map((n,r)=>r===t?{...n,url:e}:n))}),(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button`,title:r.removeNetwork,onClick:()=>o(a.filter((e,n)=>n!==t)),children:(0,y.jsx)(v.XIcon,{size:14})})]},t))}),(0,y.jsx)(`button`,{type:`button`,className:`bree-button-like`,onClick:()=>o([...a,{network:`youtube`,url:`https://youtube.com/`}]),children:r.addNetwork})]}),(0,y.jsxs)(B,{title:r.appearance,children:[(0,y.jsx)(V,{label:r.iconSize,children:(0,y.jsx)(qe,{value:e.getAttr(`size`),min:16,max:64,onChange:t=>e.setAttr(`size`,t)})}),(0,y.jsx)(V,{label:r.gap,children:(0,y.jsx)(qe,{value:e.getAttr(`gap`),min:0,max:40,onChange:t=>e.setAttr(`gap`,t)})}),(0,y.jsx)(V,{label:r.alignment,children:(0,y.jsx)(Qe,{value:String(e.getAttr(`alignment`)??`center`),onChange:t=>e.setAttr(`alignment`,t)})})]}),(0,y.jsx)(K,{ctx:e})]})}function bt(e,t=36){let n=e.replace(/\s+/g,` `).trim();return n.length>t?`${n.slice(0,t)}…`:n}var xt=(e,{t})=>bt(e.textContent)||t.layers.empty,St=()=>``,Ct=[{type:`paragraph`,icon:v.TypeIcon},{type:`heading`,icon:v.Heading1Icon,inspector:it},{type:`image`,icon:v.ImageIcon,inspector:at,preview:(e,{t})=>{let{attrs:n}=e;if(n.alt)return bt(n.alt);let r=String(n.src??``);if(r.startsWith(`data:`))return t.layers.uploadedImage;try{let e=new URL(r);return bt(e.searchParams.get(`text`)??decodeURIComponent(e.pathname.split(`/`).pop()??``))}catch{return``}}},{type:`button`,icon:v.MousePointerClickIcon,inspector:nt},{type:`horizontalRule`,icon:v.MinusIcon,inspector:ct,preview:St},{type:`spacer`,icon:Be,inspector:ot,preview:e=>`${e.attrs.height}px`,extensions:[ft]},{type:`socialLinks`,icon:v.LinkIcon,inspector:yt,preview:e=>Array.isArray(e.attrs.links)?e.attrs.links.map(e=>e.network).join(`, `):``,extensions:[_t]},{type:`htmlBlock`,icon:v.SquareCodeIcon,inspector:st,preview:e=>bt(String(e.attrs.html??``).replace(/<[^>]+>/g,` `)),extensions:[vt]},{type:`section`,icon:v.LayoutIcon,inspector:lt,preview:St},{type:`columnsColumn`,icon:v.PanelLeftIcon,inspector:lt,preview:St},{type:`twoColumns`,icon:v.Columns2Icon,inspector:rt,preview:St},{type:`threeColumns`,icon:v.Columns3Icon,inspector:rt,preview:St},{type:`fourColumns`,icon:v.Columns4Icon,inspector:rt,preview:St},{type:`bulletList`,icon:v.ListIcon},{type:`orderedList`,icon:v.ListOrderedIcon},{type:`blockquote`,icon:v.TextQuoteIcon},{type:`codeBlock`,icon:v.CodeIcon},{type:`table`,icon:v.TableIcon}],wt=o({button:()=>Tt,column:()=>Dt,columns:()=>X,doc:()=>Nt,heading:()=>Y,image:()=>Et,link:()=>jt,padding:()=>At,paragraph:()=>J,placeholderImage:()=>Mt,section:()=>kt,sized:()=>Ot,text:()=>q}),q=(e,t)=>({type:`text`,text:e,...t?{marks:t}:{}}),J=(e=``,t={})=>({type:`paragraph`,attrs:t,content:typeof e==`string`?e?[q(e)]:[]:e}),Y=(e,t,n={})=>({type:`heading`,attrs:{level:e,...n},content:[q(t)]}),Tt=(e,t={})=>({type:`button`,attrs:{href:`https://example.com`,alignment:`center`,...t},content:[q(e)]}),Et=(e,t={})=>({type:`image`,attrs:{src:e,alt:``,alignment:`center`,...t}}),Dt=(...e)=>({type:`columnsColumn`,content:e.length?e:[J()]}),Ot=(e,t)=>({...e,attrs:{...e.attrs,style:`width:${t}%`}}),X=(e,t,n)=>({type:{2:`twoColumns`,3:`threeColumns`,4:`fourColumns`}[e],...n?{attrs:n}:{},content:t??Array.from({length:e},()=>Dt())}),kt=(e,...t)=>({type:`section`,attrs:{style:e},content:t}),At=(e,t=e)=>`padding-top:${e}px;padding-right:${t}px;padding-bottom:${e}px;padding-left:${t}px`,jt=e=>[{type:`link`,attrs:{href:e}}],Mt=(e,t,n=`Image`)=>`https://placehold.co/${e}x${t}/e2e8f0/64748b/png?text=${encodeURIComponent(n)}`,Nt=(...e)=>({type:`doc`,content:e}),Pt=({t:e},t=`center`)=>J([q(e.content.menuHome,jt(`https://example.com`)),q(` · `),q(e.content.menuShop,jt(`https://example.com/shop`)),q(` · `),q(e.content.menuBlog,jt(`https://example.com/blog`)),q(` · `),q(e.content.menuContact,jt(`https://example.com/contact`))],{alignment:t}),Ft=[{id:`layout`,title:({t:e})=>e.sidebar.layoutTitle},{id:`content`,title:({t:e})=>e.sidebar.contentTitle}],It=[{id:`section`,group:`layout`,label:({t:e})=>e.palette.oneColumn,icon:(0,y.jsx)(Ue,{}),content:()=>[kt(At(16),J())]},{id:`columns-2`,group:`layout`,label:({t:e})=>e.palette.twoColumns,icon:(0,y.jsx)(v.Columns2Icon,{size:22}),content:()=>[X(2)]},{id:`columns-3`,group:`layout`,label:({t:e})=>e.palette.threeColumns,icon:(0,y.jsx)(v.Columns3Icon,{size:22}),content:()=>[X(3)]},{id:`columns-4`,group:`layout`,label:({t:e})=>e.palette.fourColumns,icon:(0,y.jsx)(v.Columns4Icon,{size:22}),content:()=>[X(4)]},{id:`heading`,group:`content`,label:({t:e})=>e.palette.heading,icon:(0,y.jsx)(v.Heading1Icon,{size:22}),content:({t:e})=>[Y(2,e.content.heading)]},{id:`text`,group:`content`,label:({t:e})=>e.palette.text,icon:(0,y.jsx)(v.TypeIcon,{size:22}),content:({t:e})=>[J(e.content.text)]},{id:`button`,group:`content`,label:({t:e})=>e.palette.button,icon:(0,y.jsx)(v.MousePointerClickIcon,{size:22}),content:({t:e})=>[Tt(e.content.button)]},{id:`image`,group:`content`,label:({t:e})=>e.palette.image,icon:(0,y.jsx)(v.ImageIcon,{size:22}),content:({t:e})=>[Et(Mt(600,300,e.content.image))]},{id:`divider`,group:`content`,label:({t:e})=>e.palette.divider,icon:(0,y.jsx)(v.MinusIcon,{size:22}),content:()=>[{type:`horizontalRule`}]},{id:`spacer`,group:`content`,label:({t:e})=>e.palette.spacer,icon:(0,y.jsx)(Ve,{}),content:()=>[{type:`spacer`,attrs:{height:32}}]},{id:`social`,group:`content`,label:({t:e})=>e.palette.social,icon:(0,y.jsx)(He,{}),content:()=>[{type:`socialLinks`}]},{id:`menu`,group:`content`,label:({t:e})=>e.palette.menu,icon:(0,y.jsx)(v.PanelTopIcon,{size:22}),content:e=>[Pt(e)]},{id:`list`,group:`content`,label:({t:e})=>e.palette.list,icon:(0,y.jsx)(v.ListIcon,{size:22}),content:({t:e})=>[{type:`bulletList`,content:e.content.listItems.map(e=>({type:`listItem`,content:[J(e)]}))}]},{id:`quote`,group:`content`,label:({t:e})=>e.palette.quote,icon:(0,y.jsx)(v.TextQuoteIcon,{size:22}),content:({t:e})=>[{type:`blockquote`,content:[J(e.content.quote)]}]},{id:`html`,group:`content`,label:({t:e})=>e.palette.html,icon:(0,y.jsx)(v.SquareCodeIcon,{size:22}),content:({t:e})=>[{type:`htmlBlock`,attrs:{html:e.content.html}}]},{id:`card`,group:`content`,label:({t:e})=>e.palette.card,icon:(0,y.jsx)(v.LayoutIcon,{size:22}),content:({t:e})=>[kt(`${At(24)};background-color:#f1f5f9;border-radius:12px`,Y(3,e.content.cardTitle),J(e.content.cardText))]}];function Z({variant:e}){return(0,y.jsxs)(`span`,{className:`bree-block-thumb bree-thumb-${e}`,"aria-hidden":!0,children:[(0,y.jsx)(`i`,{}),(0,y.jsx)(`i`,{}),(0,y.jsx)(`i`,{})]})}var Lt=[{id:`header`,label:({t:e})=>e.templates.header,description:({t:e})=>e.templates.headerDescription,thumbnail:(0,y.jsx)(Z,{variant:`header`}),content:e=>[X(2,[Ot(Dt(Et(Mt(140,40,e.t.content.logo),{alignment:`left`,width:`140`})),33),Ot(Dt(Pt(e,`right`)),67)])]},{id:`hero`,label:({t:e})=>e.templates.hero,description:({t:e})=>e.templates.heroDescription,thumbnail:(0,y.jsx)(Z,{variant:`hero`}),content:({t:e})=>[kt(`${At(40,24)};background-color:#eef2ff;border-radius:12px`,Y(1,e.content.heroTitle,{alignment:`center`}),J(e.content.heroText,{alignment:`center`}),Tt(e.content.heroButton,{style:`background-color:#4f46e5;color:#ffffff;${At(12,24)};border-radius:8px`}))]},{id:`products`,label:({t:e})=>e.templates.products,description:({t:e})=>e.templates.productsDescription,thumbnail:(0,y.jsx)(Z,{variant:`products`}),content:({t:e})=>[X(2,[e.content.productA,e.content.productB].map(t=>Dt(Et(Mt(280,200,t)),Y(3,t,{alignment:`center`}),J(e.content.productText,{alignment:`center`}),Tt(e.content.productButton))),{cellspacing:16})]},{id:`features`,label:({t:e})=>e.templates.features,description:({t:e})=>e.templates.featuresDescription,thumbnail:(0,y.jsx)(Z,{variant:`features`}),content:({t:e})=>[X(3,e.content.features.map(t=>Dt(Y(3,t,{alignment:`center`}),J(e.content.featureText,{alignment:`center`}))))]},{id:`testimonial`,label:({t:e})=>e.templates.testimonial,description:({t:e})=>e.templates.testimonialDescription,thumbnail:(0,y.jsx)(Z,{variant:`testimonial`}),content:({t:e})=>[kt(`${At(24)};background-color:#f8fafc;border-radius:12px`,{type:`blockquote`,content:[J(e.content.testimonialQuote)]},J(e.content.testimonialAuthor,{alignment:`right`,style:`color:#64748b`}))]},{id:`footer`,label:({t:e})=>e.templates.footer,description:({t:e})=>e.templates.footerDescription,thumbnail:(0,y.jsx)(Z,{variant:`footer`}),content:({t:e})=>[{type:`horizontalRule`},{type:`socialLinks`},J(e.content.footerAddress,{alignment:`center`,style:`color:#94a3b8;font-size:12px`}),J([q(e.content.unsubscribe,jt(`https://example.com/unsubscribe`))],{alignment:`center`,style:`font-size:12px`})]}],Rt=(e,t)=>Lt.find(t=>t.id===e)?.content(t)??[];function zt(e){let t={type:`spacer`,attrs:{height:16}};return{type:`doc`,content:[...Rt(`header`,e),t,...Rt(`hero`,e),t,Y(2,e.t.content.starterTitle,{alignment:`center`}),...Rt(`products`,e),t,...Rt(`footer`,e)]}}var Bt=(0,l.createContext)(null);function Q(){let e=(0,l.useContext)(Bt);if(!e)throw Error(`useEmailEditor must be used inside <EditorRoot> or <BetterEmailEditor>.`);return e}function Vt(){return(0,l.useContext)(Bt)}function $(){return(0,l.useContext)(Bt)?.t??Se}function Ht(){let{locale:e,t}=Q();return(0,l.useMemo)(()=>({locale:e,t}),[e,t])}var Ut=(0,m.extendTheme)(`basic`,{body:{backgroundColor:`#eef1f5`,padding:`32px 16px`},container:{backgroundColor:`#ffffff`,padding:`24px`,borderRadius:`12px`}}),Wt=e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>t({url:String(r.result)}),r.onerror=n,r.readAsDataURL(e)}),Gt={type:`doc`,content:[{type:`paragraph`}]};function Kt(e){return typeof e==`object`&&!!e&&`doc`in e}function qt(e){return e?Kt(e)?{doc:e.doc,settings:{...e.settings,previewText:e.settings?.previewText??``}}:{doc:e,settings:{previewText:``}}:{doc:Gt,settings:{previewText:``}}}function Jt(e,t,n){let[r,i]=(0,l.useState)(t);return[e===void 0?r:e,(0,l.useCallback)(t=>{e===void 0&&i(t),n?.(t)},[e,n])]}var Yt=(0,l.forwardRef)(function({defaultValue:e,onChange:t,onReady:n,locale:r=`en`,messages:i,nodes:a=Ct,palette:o=It,paletteGroups:s=Ft,templates:c=Lt,starterDocument:h=zt,extensions:g,theme:_=Ut,uploadImage:v=Wt,editable:b=!0,device:x,defaultDevice:S=`desktop`,onDeviceChange:C,layersOpen:w,defaultLayersOpen:E=!0,onLayersOpenChange:D,className:O,style:k,children:ee},A){let j=(0,l.useMemo)(()=>Oe(r,i),[r,i]),[te]=(0,l.useState)(()=>qt(e)),[ne,re]=(0,l.useState)(te.settings),M=(0,l.useRef)(ne),ie=(0,l.useRef)(j),N=(0,l.useRef)(t),ae=(0,l.useRef)(n),P=(0,l.useRef)(v);(0,l.useLayoutEffect)(()=>{ie.current=j,N.current=t,ae.current=n,P.current=v});let[oe,se]=Jt(x,S,C),[F,I]=Jt(w,E,D),[ce]=(0,l.useState)(()=>({dragSession:be(),hoverStore:xe()})),le=(0,l.useCallback)(e=>P.current(e),[]),fe=(0,m.useEditorImage)({uploadImage:le}),[pe]=(0,l.useState)(()=>[p.StarterKit.configure({TiptapStarterKit:{dropcursor:!1},Button:!1}),de,u.Placeholder.configure({placeholder:({node:e})=>e.type.name===`heading`?ie.current.placeholder.heading:ie.current.placeholder.paragraph,includeChildren:!0}),m.EmailTheming.configure({theme:_}),...a.flatMap(e=>e.extensions??[]),...g??[],fe]),L=(0,d.useEditor)({extensions:pe,content:te.doc,editable:b,immediatelyRender:!1,editorProps:{handlePaste:ye(pe)}},[]);(0,l.useEffect)(()=>{L?.setEditable(b)},[L,b]);let me=(0,l.useCallback)(()=>({doc:L?.getJSON()??Gt,settings:M.current}),[L]),he=(0,l.useCallback)(e=>{let t={...M.current,...e};M.current=t,re(t),L&&N.current?.({doc:L.getJSON(),settings:t})},[L]),R=(0,l.useMemo)(()=>{let e=async()=>L?(0,f.composeReactEmail)({editor:L,preview:M.current.previewText||void 0}):{html:``,text:``,unformattedHtml:``};return{editor:L,getValue:me,getJSON:()=>L?.getJSON()??Gt,setValue:e=>{let t=qt(e);M.current=t.settings,re(t.settings),L?.commands.setContent(t.doc,{emitUpdate:!0})},exportEmail:e,getHtml:async()=>(await e()).html,getText:async()=>(await e()).text,insertBlocks:e=>{L&&ue(L,e)}}},[L,me]);(0,l.useImperativeHandle)(A,()=>R,[R]),(0,l.useEffect)(()=>{if(!L)return;ae.current?.(R);let e=()=>N.current?.(me());return L.on(`update`,e),()=>{L.off(`update`,e)}},[L,R,me]);let ge=(0,l.useMemo)(()=>new Map(a.map(e=>[e.type,e])),[a]),_e=(0,l.useMemo)(()=>{if(!L)return null;let e={locale:r,t:j};return{...e,editor:L,handle:R,nodes:ge,nodeLabel:t=>{let n=ge.get(t)?.label;return n?Te(n,e):j.nodes[t]??t},palette:o,paletteGroups:s,templates:c,starterDocument:h,uploadImage:le,...ce,device:oe,setDevice:se,layersOpen:F,setLayersOpen:I,settings:ne,updateSettings:he}},[L,r,j,R,ge,o,s,c,h,le,ce,oe,se,F,I,ne,he]),ve=(0,l.useMemo)(()=>({editor:L}),[L]),Se={"--bree-empty-zone-label":JSON.stringify(j.canvas.emptyZone),...k};return(0,y.jsx)(`div`,{className:T(`bree bree-root`,O),style:Se,lang:r,children:_e&&(0,y.jsx)(d.EditorContext.Provider,{value:ve,children:(0,y.jsx)(Bt.Provider,{value:_e,children:ee})})})});function Xt(e,t){let n=e.getBoundingClientRect();return{top:t.top-n.top+e.scrollTop,left:t.left-n.left+e.scrollLeft,width:t.width,height:t.height??0}}function Zt(e,t,n){if(!n)return null;let r=e.view.nodeDOM(n.pos);return r instanceof HTMLElement?Xt(t,r.getBoundingClientRect()):null}function Qt(e,t,n){let r=e.view.posAtCoords({left:t,top:n});return r&&r.inside>=0?P(e.state.doc,r.inside):null}function $t(e){let t=e.node.type.name;return E.has(t)||D.has(t)}function en({editor:e,host:t}){let{dragSession:n,hoverStore:r,nodeLabel:i,t:a}=Q(),o=(0,l.useRef)(i);(0,l.useLayoutEffect)(()=>{o.current=i});let s=(0,l.useSyncExternalStore)(r.subscribe,r.get),c=s===null?null:e.state.doc.nodeAt(s),u=s!==null&&c?{pos:s,node:c}:null,[f,p]=(0,l.useState)(null),[m,h]=(0,l.useState)(null),[,g]=(0,l.useState)(0),_=(0,l.useCallback)(()=>g(e=>e+1),[]),b=(0,d.useEditorState)({editor:e,selector:({editor:e})=>{if(!e?.isFocused)return null;let t=F(e);return t?`${t.pos}:${t.node.type.name}:${e.state.doc.content.size}`:null}})?F(e):null;(0,l.useEffect)(()=>{let n=()=>_(),i=()=>{r.set(null),_()};e.on(`update`,i);let a=new ResizeObserver(n);return a.observe(e.view.dom),t.addEventListener(`load`,n,!0),window.addEventListener(`resize`,n),()=>{e.off(`update`,i),a.disconnect(),t.removeEventListener(`load`,n,!0),window.removeEventListener(`resize`,n)}},[e,t,_,r]),(0,l.useEffect)(()=>{let i=0,a=t=>{n.get()||t.target.closest(`.bree-ov-toolbar, .bree-ov-handle, .bree-ov-tag`)||(cancelAnimationFrame(i),i=requestAnimationFrame(()=>{r.set(Qt(e,t.clientX,t.clientY)?.pos??null)}))},o=()=>r.set(null);return t.addEventListener(`mousemove`,a),t.addEventListener(`mouseleave`,o),()=>{cancelAnimationFrame(i),t.removeEventListener(`mousemove`,a),t.removeEventListener(`mouseleave`,o)}},[e,t,n,r]),(0,l.useEffect)(()=>{let n=n=>{if(n.button!==0||n.shiftKey||n.metaKey||n.ctrlKey||n.target.closest(`.bree-ov-layer`))return;if([t,e.view.dom,e.view.dom.parentElement].includes(n.target)){n.preventDefault();let t=document.activeElement;t instanceof HTMLElement&&t.blur(),e.commands.blur();return}let r=Qt(e,n.clientX,n.clientY);r&&$t(r)&&(n.preventDefault(),I(e,r))},r=t=>{e.view.dom.contains(t.target)&&fe(e,t)};return t.addEventListener(`mousedown`,n,!0),t.addEventListener(`paste`,r,!0),()=>{t.removeEventListener(`mousedown`,n,!0),t.removeEventListener(`paste`,r,!0)}},[e,t]),(0,l.useEffect)(()=>{let i=0,a=null,s=null,c=t=>{let r=n.get();if(!r||(a!==r&&(a=r,s=ne(e.view,r)),!s))return null;let i=r.kind===`move`?{from:r.pos,to:r.pos+(e.state.doc.nodeAt(r.pos)?.nodeSize??0)}:void 0;return te(e.view,t.clientX,t.clientY,s,i)},l=e=>{let t=n.get();t&&(e.preventDefault(),e.stopPropagation(),e.dataTransfer&&(e.dataTransfer.dropEffect=t.kind===`move`?`move`:`copy`),cancelAnimationFrame(i),i=requestAnimationFrame(()=>p(c(e))))},u=t=>{let a=n.get();if(!a)return;t.preventDefault(),t.stopPropagation(),cancelAnimationFrame(i);let o=c(t);o&&N(e,a,o),e.view.dragging=null,n.end(),p(null),h(null),r.set(null)},d=e=>{n.get()&&(t.contains(e.relatedTarget)||(cancelAnimationFrame(i),p(null)))},f=()=>{cancelAnimationFrame(i),n.end(),p(null),h(null),r.set(null)},m=t=>{let r=t.target;if(n.get()||r.tagName!==`IMG`||!e.view.dom.contains(r))return;let i=e.view.posAtDOM(r,0),a=P(e.state.doc,i);a&&!oe(a)&&(n.start({kind:`move`,pos:a.pos,label:o.current(a.node.type.name)}),requestAnimationFrame(()=>h(a.pos)))},g=t=>{if(t.key!==`Escape`||!e.isFocused)return;let n=F(e),r=n?se(e.state.doc,n):null;if(t.preventDefault(),r)I(e,r);else{let t=document.activeElement;t instanceof HTMLElement&&t.blur(),e.commands.blur()}};return t.addEventListener(`dragstart`,m,!0),t.addEventListener(`keydown`,g,!0),t.addEventListener(`dragover`,l,!0),t.addEventListener(`drop`,u,!0),t.addEventListener(`dragleave`,d,!0),document.addEventListener(`dragend`,f),()=>{cancelAnimationFrame(i),t.removeEventListener(`dragstart`,m,!0),t.removeEventListener(`keydown`,g,!0),t.removeEventListener(`dragover`,l,!0),t.removeEventListener(`drop`,u,!0),t.removeEventListener(`dragleave`,d,!0),document.removeEventListener(`dragend`,f)}},[e,t,n,r]);let x=(t,r)=>{let a=e.view.nodeDOM(r.pos);if(n.start({kind:`move`,pos:r.pos,label:i(r.node.type.name)}),t.dataTransfer.setData(O,`move`),t.dataTransfer.effectAllowed=`move`,a instanceof HTMLElement){let e=a.getBoundingClientRect();t.dataTransfer.setDragImage(a,Math.min(24,e.width/2),Math.min(24,e.height/2))}requestAnimationFrame(()=>h(r.pos))},S=m!==null,C=u&&u.pos!==b?.pos?Zt(e,t,u):null,w=Zt(e,t,b),E=S?Zt(e,t,P(e.state.doc,m)):null,D=b?se(e.state.doc,b):null;return(0,y.jsxs)(`div`,{className:`bree-ov-layer`,children:[C&&u&&(0,y.jsx)(`div`,{className:T(`bree-ov-frame bree-ov-hover`,S&&`bree-ov-ghost`),style:C,children:(0,y.jsx)(`button`,{type:`button`,className:`bree-ov-tag`,onMouseDown:t=>{t.preventDefault(),I(e,u)},children:i(u.node.type.name)})}),w&&b&&(0,y.jsxs)(`div`,{className:T(`bree-ov-frame bree-ov-selected`,S&&`bree-ov-ghost`),style:w,children:[(0,y.jsx)(`span`,{className:`bree-ov-tag bree-ov-tag-selected`,children:i(b.node.type.name)}),!oe(b)&&(0,y.jsx)(v.EditorFocusScope,{children:(0,y.jsx)(`span`,{className:`bree-ov-handle`,role:`button`,tabIndex:-1,draggable:!0,title:a.canvas.move,"aria-label":a.canvas.moveLabel(i(b.node.type.name)),onDragStart:e=>x(e,b),children:(0,y.jsx)(Ae,{})})}),(0,y.jsx)(v.EditorFocusScope,{children:(0,y.jsxs)(`div`,{className:`bree-ov-toolbar`,onMouseDown:e=>e.preventDefault(),children:[D&&(0,y.jsx)(`button`,{type:`button`,className:`bree-ov-tool`,title:a.canvas.selectParent(i(D.node.type.name)),onClick:()=>I(e,D),children:(0,y.jsx)(Ne,{})}),!oe(b)&&(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`button`,{type:`button`,className:`bree-ov-tool`,title:a.canvas.duplicate,onClick:()=>ce(e,b),children:(0,y.jsx)(je,{})}),(0,y.jsx)(`button`,{type:`button`,className:`bree-ov-tool bree-ov-danger`,title:a.canvas.delete,onClick:()=>le(e,b),children:(0,y.jsx)(Me,{})})]})]})})]}),E&&(0,y.jsx)(`div`,{className:`bree-ov-frame bree-ov-source`,style:E}),f&&(0,y.jsx)(tn,{host:t,target:f,label:n.get()?.label??``,messages:a})]})}function tn({host:e,target:t,label:n,messages:r}){if(t.emptyZone){let i=Xt(e,t.emptyZone);return(0,y.jsx)(`div`,{className:`bree-ov-dropzone`,style:i,children:(0,y.jsxs)(`span`,{children:[(0,y.jsx)(v.PlusIcon,{size:14}),` `,r.canvas.dropLabel(n)]})})}if(!t.line)return null;let i=Xt(e,{...t.line,height:0});return(0,y.jsx)(`div`,{className:`bree-ov-dropline`,style:{top:i.top,left:i.left,width:i.width},children:(0,y.jsx)(`span`,{className:`bree-ov-dropline-label`,children:r.canvas.dropHere})})}function nn({overlay:e=!0,bubbleMenu:t=!0,slashCommands:n=!0,className:r,style:i,children:a}){let{editor:o,device:s,t:c}=Q(),[u,f]=(0,l.useState)(null),p=(0,l.useMemo)(()=>Array.isArray(n)?n:v.defaultSlashCommands.map(e=>({...e,...c.slashCommands[e.title]})),[n,c]);return(0,y.jsxs)(`div`,{ref:f,className:T(`bree-canvas`,r),style:i,"data-device":s,children:[(0,y.jsx)(d.EditorContent,{editor:o,className:`bree-canvas-content`}),t&&(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(v.BubbleMenu,{hideWhenActiveNodes:[`button`,`horizontalRule`],hideWhenActiveMarks:[`link`]}),(0,y.jsx)(v.BubbleMenu.LinkDefault,{}),(0,y.jsx)(v.BubbleMenu.ButtonDefault,{}),(0,y.jsx)(v.BubbleMenu.ImageDefault,{})]}),n!==!1&&(0,y.jsx)(v.SlashCommand,{items:p}),e&&u&&(0,y.jsx)(en,{editor:o,host:u}),a]})}function rn(e,t){let n=e.child(t);return t===e.childCount-1&&e.childCount>1&&A(n)&&e.child(t-1).type.name!==`paragraph`}function an(e,t,n,r){let i=[];return e.forEach((a,o,s)=>{if(rn(e,s))return;let c=t+1+o,l=a.type.name,u=`${r}${s}`,d=E.has(l),f=d&&a.childCount===1&&A(a.firstChild),p=d||D.has(l);i.push({key:u,pos:c,node:a,depth:n,index:s+1,children:p&&!f?an(a,c,n+1,`${u}.`):[],accepts:d,fixed:l===`columnsColumn`,empty:f})}),i}function on(e){let t=j(e);return t?an(t.node,t.pos,0,``):[]}function sn(e,t){return e.fixed?`inside`:e.accepts?t<.25?`before`:t>.75?`after`:`inside`:t<.5?`before`:`after`}function cn(e,t,n,r,i){let a,o;if(n===`inside`){if(!t.accepts)return null;t.empty?(a=t.pos+1,o=a+t.node.firstChild.nodeSize):a=t.pos+t.node.nodeSize-1}else{if(t.fixed)return null;a=n===`before`?t.pos:t.pos+t.node.nodeSize}if(i&&a>=i.from&&a<=i.to)return null;let s=e.resolve(a),c=s.index();return s.parent.canReplace(c,o===void 0?c:c+1,r)?{pos:a,replaceTo:o}:null}function ln({onClose:e,title:t,className:n,style:r}){let{editor:i,t:a,locale:o,nodes:s,nodeLabel:c,dragSession:u,hoverStore:f}=Q(),p=e=>e.node.type.name===`columnsColumn`?a.layers.column(e.index):c(e.node.type.name),m=e=>(s.get(e.node.type.name)?.preview??xt)(e.node,{locale:o,t:a}),h=(0,d.useEditorState)({editor:i,selector:({editor:e})=>e?.state.doc??null,equalityFn:(e,t)=>e===t}),g=(0,d.useEditorState)({editor:i,selector:({editor:e})=>e?.isFocused?F(e)?.pos??null:null}),_=(0,l.useSyncExternalStore)(f.subscribe,f.get),b=(0,l.useMemo)(()=>h?on(h):[],[h]),[x,S]=(0,l.useState)(()=>new Set),[C,w]=(0,l.useState)(null),E=(0,l.useRef)(null);(0,l.useEffect)(()=>{g!==null&&E.current?.querySelector(`[aria-selected="true"]`)?.scrollIntoView({block:`nearest`})},[g]);let D=e=>S(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n}),k=e=>{I(i,{pos:e.pos,node:e.node});let t=i.view.nodeDOM(e.pos);t instanceof HTMLElement&&t.scrollIntoView({block:`nearest`,behavior:`smooth`})},ee=(e,t)=>{let n=u.get();if(!n)return null;let r=ne(i.view,n);if(!r)return null;let a=e.currentTarget.getBoundingClientRect(),o=sn(t,(e.clientY-a.top)/a.height),s=n.kind===`move`?i.state.doc.nodeAt(n.pos):null,c=n.kind===`move`&&s?{from:n.pos,to:n.pos+s.nodeSize}:void 0,l=cn(i.state.doc,t,o,r,c);return l?{zone:o,target:l,payload:n}:null},A=()=>{u.end(),w(null)},j=e=>e.map(e=>{let t=s.get(e.node.type.name)?.icon??v.LayoutIcon,n=e.children.length>0,r=x.has(e.key),o=m(e),c=C?.key===e.key?C.zone:null;return(0,y.jsxs)(`div`,{role:`none`,children:[(0,y.jsxs)(`div`,{role:`treeitem`,tabIndex:g===e.pos||g===null&&e.key===`0`?0:-1,"aria-level":e.depth+1,"aria-selected":g===e.pos,"aria-expanded":n?!r:void 0,className:T(`bree-layer`,g===e.pos&&`bree-selected`,_===e.pos&&`bree-hovered`,c&&`bree-drop-${c}`,e.fixed&&`bree-fixed`),style:{paddingLeft:6+e.depth*16},draggable:!e.fixed,title:e.fixed?a.layers.fixedHint:a.layers.itemHint,onClick:()=>k(e),onKeyDown:t=>{if(t.key===`Enter`||t.key===` `)t.preventDefault(),k(e);else if(t.key===`ArrowLeft`&&n&&!r||t.key===`ArrowRight`&&r)D(e.key);else if(t.key===`ArrowDown`||t.key===`ArrowUp`){t.preventDefault();let e=[...E.current?.querySelectorAll(`[role="treeitem"]`)??[]];e[e.indexOf(t.currentTarget)+(t.key===`ArrowDown`?1:-1)]?.focus()}},onMouseEnter:()=>f.set(e.pos),onMouseLeave:()=>f.set(null),onDragStart:t=>{t.stopPropagation(),u.start({kind:`move`,pos:e.pos,label:p(e)}),t.dataTransfer.setData(O,`move`),t.dataTransfer.effectAllowed=`move`},onDragEnd:A,onDragOver:t=>{let n=ee(t,e);if(!n){C?.key===e.key&&w(null);return}t.preventDefault(),t.dataTransfer.dropEffect=n.payload.kind===`move`?`move`:`copy`,(C?.key!==e.key||C.zone!==n.zone)&&w({key:e.key,zone:n.zone})},onDrop:t=>{let n=ee(t,e);t.preventDefault(),n&&N(i,n.payload,n.target),A()},children:[n?(0,y.jsx)(`button`,{type:`button`,className:T(`bree-layer-caret`,!r&&`bree-open`),"aria-label":r?a.layers.expand:a.layers.collapse,tabIndex:-1,onClick:t=>{t.stopPropagation(),D(e.key)},children:`›`}):(0,y.jsx)(`span`,{className:`bree-layer-caret-spacer`}),(0,y.jsx)(`span`,{className:`bree-layer-icon`,children:(0,y.jsx)(t,{size:14})}),(0,y.jsx)(`span`,{className:`bree-layer-label`,children:p(e)}),o&&(0,y.jsx)(`span`,{className:`bree-layer-preview`,children:o})]}),e.empty&&(0,y.jsx)(`div`,{className:`bree-layer-empty`,style:{paddingLeft:6+(e.depth+1)*16+18},children:a.layers.emptyZone}),n&&!r&&(0,y.jsx)(`div`,{role:`group`,children:j(e.children)})]},e.key)});return(0,y.jsx)(v.EditorFocusScope,{children:(0,y.jsxs)(`aside`,{className:T(`bree-layers`,n),style:r,"aria-label":t??a.layers.title,tabIndex:-1,onDragLeave:e=>!e.currentTarget.contains(e.relatedTarget)&&w(null),children:[(0,y.jsxs)(`header`,{className:`bree-layers-header`,children:[(0,y.jsx)(`h2`,{children:t??a.layers.title}),(0,y.jsxs)(`div`,{className:`bree-layers-actions`,children:[(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button bree-small`,title:a.layers.expandAll,onClick:()=>S(new Set),children:`⊞`}),(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button bree-small`,title:a.layers.collapseAll,onClick:()=>{let e=new Set,t=n=>n.forEach(n=>{n.children.length&&e.add(n.key),t(n.children)});t(b),S(e)},children:`⊟`}),e&&(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button bree-small`,title:a.layers.close,onClick:e,children:(0,y.jsx)(v.XIcon,{size:14})})]})]}),(0,y.jsx)(`div`,{className:`bree-layers-list`,role:`tree`,"aria-label":a.layers.tree,ref:E,children:b.length?j(b):(0,y.jsx)(`p`,{className:`bree-hint`,children:a.layers.emptyEmail})})]})})}function un({ctx:e,className:t,style:n}){return(0,y.jsxs)(`div`,{className:T(`bree-inspector`,t),style:n,children:[(0,y.jsx)(et,{ctx:e,alignment:String(e.getAttr(`alignment`)??`left`),setAlignment:t=>e.setAttr(`alignment`,t)}),(0,y.jsx)(K,{ctx:e}),(0,y.jsx)(tt,{ctx:e})]})}function dn(){let{editor:e}=Q();return()=>{let t=document.activeElement;t instanceof HTMLElement&&t.blur(),e.commands.blur()}}function fn({title:e,children:t,breadcrumb:n=!0,className:r,style:i}){let{t:a,nodeLabel:o}=Q(),s=dn();return(0,y.jsxs)(`div`,{className:T(`bree-properties`,r),style:i,children:[(0,y.jsxs)(`header`,{className:`bree-properties-header`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`span`,{className:`bree-eyebrow`,children:a.sidebar.propertiesEyebrow}),(0,y.jsx)(`h2`,{children:e})]}),(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button`,title:a.sidebar.closeProperties,onClick:s,children:(0,y.jsx)(v.XIcon,{size:16})})]}),n&&(0,y.jsx)(v.Inspector.Breadcrumb,{children:e=>e.length>1&&(0,y.jsx)(`nav`,{className:`bree-breadcrumb`,"aria-label":a.sidebar.breadcrumb,children:e.map((t,n)=>(0,y.jsxs)(`span`,{className:`bree-crumb`,children:[n>0&&(0,y.jsx)(`span`,{className:`bree-crumb-sep`,children:`/`}),(0,y.jsx)(`button`,{type:`button`,disabled:n===e.length-1,onClick:t.focus,children:o(t.node.nodeType)})]},`${t.node.nodeType}-${t.node.nodePos.pos}`))})}),(0,y.jsx)(`div`,{className:`bree-panel-scroll`,children:t})]})}function pn({ctx:e,className:t,style:n}){let{nodes:r,nodeLabel:i}=Q(),a=r.get(e.nodeType)?.inspector??un;return(0,y.jsx)(fn,{title:i(e.nodeType),className:t,style:n,children:(0,y.jsx)(a,{ctx:e},`${e.nodeType}-${e.nodePos.pos}`)})}function mn(e,t){let{editor:n,dragSession:r}=Q();return{draggable:!0,onDragStart:n=>{r.start({kind:`new`,label:e,content:t}),n.dataTransfer.setData(O,e),n.dataTransfer.effectAllowed=`copy`},onDragEnd:()=>r.end(),onClick:()=>ue(n,t())}}function hn({template:e,className:t,style:n}){let r=Ht(),i=Te(e.label,r),a=mn(i,()=>e.content(r));return(0,y.jsxs)(`button`,{type:`button`,className:T(`bree-block-card`,t),style:n,...a,children:[e.thumbnail??(0,y.jsx)(Z,{variant:`default`}),(0,y.jsxs)(`span`,{className:`bree-block-text`,children:[(0,y.jsx)(`strong`,{children:i}),e.description&&(0,y.jsx)(`span`,{children:Te(e.description,r)})]})]})}function gn({templates:e,className:t,style:n}){let r=Q();return(0,y.jsx)(`div`,{className:T(`bree-block-list`,t),style:n,children:(e??r.templates).map(e=>(0,y.jsx)(hn,{template:e},e.id))})}function _n({ctx:e,className:t,style:n}){let{settings:r,updateSettings:i,t:a}=Q(),o=a.body,{findStyleValue:s,setGlobalStyle:c}=e;return(0,y.jsxs)(`div`,{className:T(`bree-body-tab`,t),style:n,children:[(0,y.jsx)(B,{title:o.general,children:(0,y.jsx)(V,{label:o.previewText,stacked:!0,children:(0,y.jsx)(H,{value:r.previewText,onChange:e=>i({previewText:e}),placeholder:o.previewTextPlaceholder})})}),(0,y.jsxs)(B,{title:o.background,children:[(0,y.jsx)(V,{label:o.backgroundColor,stacked:!0,children:(0,y.jsx)(W,{value:s(`body`,`backgroundColor`),onChange:e=>c(`body`,`backgroundColor`,e)})}),(0,y.jsx)(V,{label:o.outerPadding,children:(0,y.jsx)(U,{value:s(`body`,`padding`),onChange:e=>c(`body`,`padding`,e)})})]}),(0,y.jsxs)(B,{title:o.content,children:[(0,y.jsx)(V,{label:o.width,children:(0,y.jsx)(U,{value:s(`container`,`width`),onChange:e=>c(`container`,`width`,e),min:320,max:900})}),(0,y.jsx)(V,{label:o.contentColor,stacked:!0,children:(0,y.jsx)(W,{value:s(`container`,`backgroundColor`),onChange:e=>c(`container`,`backgroundColor`,e)})}),(0,y.jsx)(V,{label:o.innerPadding,children:(0,y.jsx)(U,{value:s(`container`,`padding`),onChange:e=>c(`container`,`padding`,e)})}),(0,y.jsx)(V,{label:o.radius,children:(0,y.jsx)(U,{value:s(`container`,`borderRadius`),onChange:e=>c(`container`,`borderRadius`,e)})})]}),(0,y.jsxs)(B,{title:o.defaultStyles,children:[(0,y.jsx)(V,{label:o.text,stacked:!0,children:(0,y.jsx)(W,{value:s(`paragraph`,`color`),onChange:e=>c(`paragraph`,`color`,e)})}),(0,y.jsx)(V,{label:o.headings,stacked:!0,children:(0,y.jsx)(W,{value:s(`h1`,`color`),onChange:t=>e.batchSetGlobalStyle([`h1`,`h2`,`h3`].map(e=>({classReference:e,property:`color`,value:t})))})}),(0,y.jsx)(V,{label:o.links,stacked:!0,children:(0,y.jsx)(W,{value:s(`link`,`color`),onChange:e=>c(`link`,`color`,e)})}),(0,y.jsx)(V,{label:o.buttonBackground,stacked:!0,children:(0,y.jsx)(W,{value:s(`button`,`backgroundColor`),onChange:e=>c(`button`,`backgroundColor`,e)})}),(0,y.jsx)(V,{label:o.buttonText,stacked:!0,children:(0,y.jsx)(W,{value:s(`button`,`color`),onChange:e=>c(`button`,`color`,e)})})]})]})}function vn({item:e,className:t,style:n}){let r=Ht(),i=Te(e.label,r),a=mn(i,()=>e.content(r));return(0,y.jsxs)(`button`,{type:`button`,className:T(`bree-tile`,t),style:n,title:r.t.sidebar.tileTitle(i),...a,children:[(0,y.jsx)(`span`,{className:`bree-tile-icon`,children:e.icon}),(0,y.jsx)(`span`,{className:`bree-tile-label`,children:i})]})}function yn({items:e,groups:t,hint:n,className:r,style:i}){let a=Q(),o=e??a.palette,s=t??a.paletteGroups,c=[...s,...[...new Set(o.map(e=>e.group))].filter(e=>!s.some(t=>t.id===e)).map(e=>({id:e,title:e}))];return(0,y.jsxs)(`div`,{className:T(`bree-content-tab`,r),style:i,children:[c.map(e=>{let t=o.filter(t=>t.group===e.id);return t.length?(0,y.jsxs)(`section`,{children:[(0,y.jsx)(`h3`,{className:`bree-panel-title`,children:Te(e.title,a)}),(0,y.jsx)(`div`,{className:`bree-tiles`,children:t.map(e=>(0,y.jsx)(vn,{item:e},e.id))})]},e.id):null}),n!==null&&(0,y.jsx)(`p`,{className:`bree-hint`,children:n??a.t.sidebar.dragHint})]})}function bn({ctx:e,tabs:t=[`content`,`blocks`,`body`],defaultTab:n,className:r,style:i}){let{t:a}=Q(),o={content:{id:`content`,label:a.sidebar.tabContent,render:()=>(0,y.jsx)(yn,{})},blocks:{id:`blocks`,label:a.sidebar.tabBlocks,render:()=>(0,y.jsx)(gn,{})},body:{id:`body`,label:a.sidebar.tabBody,render:e=>(0,y.jsx)(_n,{ctx:e})}},s=t.map(e=>typeof e==`string`?o[e]:e),[c,u]=(0,l.useState)(n??s[0]?.id),d=s.find(e=>e.id===c)??s[0];return(0,y.jsxs)(`div`,{className:T(`bree-content-panel`,r),style:i,children:[s.length>1&&(0,y.jsx)(`nav`,{className:`bree-tabs`,role:`tablist`,children:s.map(e=>(0,y.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":e.id===d?.id,className:T(e.id===d?.id&&`bree-active`),onClick:()=>u(e.id),children:e.label},e.id))}),(0,y.jsx)(`div`,{className:`bree-panel-scroll`,children:d?.render(e)})]})}function xn({ctx:e,className:t,style:n}){let r=$(),i=r.inspector,a=[{mark:`bold`,Icon:v.BoldIcon,title:i.bold},{mark:`italic`,Icon:v.ItalicIcon,title:i.italic},{mark:`underline`,Icon:v.UnderlineIcon,title:i.underline},{mark:`strike`,Icon:v.StrikethroughIcon,title:i.strike}];return(0,y.jsxs)(fn,{title:r.sidebar.selectedText,className:t,style:n,children:[(0,y.jsx)(B,{title:i.formatting,children:(0,y.jsx)(`div`,{className:`bree-mark-row`,children:a.map(({mark:t,Icon:n,title:r})=>(0,y.jsx)(`button`,{type:`button`,title:r,"aria-pressed":!!e.marks[t],className:T(`bree-mark`,e.marks[t]&&`bree-active`),onClick:()=>e.toggleMark(t),children:(0,y.jsx)(n,{size:14})},t))})}),(0,y.jsx)(et,{ctx:e,alignment:e.alignment,setAlignment:e.setAlignment}),e.isLinkActive&&(0,y.jsxs)(B,{title:i.link,children:[(0,y.jsx)(V,{label:i.url,stacked:!0,children:(0,y.jsx)(`span`,{className:`bree-readonly`,children:e.linkHref})}),(0,y.jsx)(V,{label:i.linkColor,stacked:!0,children:(0,y.jsx)(W,{value:e.linkColor,presets:e.presetColors,onChange:e.setLinkColor})})]})]})}function Sn({renderDocument:e=e=>(0,y.jsx)(bn,{ctx:e}),renderNode:t=e=>(0,y.jsx)(pn,{ctx:e}),renderText:n=e=>(0,y.jsx)(xn,{ctx:e}),className:r,style:i}){let{t:a}=Q();return(0,y.jsxs)(v.Inspector.Root,{className:T(`bree-sidebar`,r),style:i,"aria-label":a.sidebar.label,children:[(0,y.jsx)(v.Inspector.Document,{children:e}),(0,y.jsx)(v.Inspector.Node,{children:t}),(0,y.jsx)(v.Inspector.Text,{children:n})]})}function Cn(e,t,n){let r=URL.createObjectURL(new Blob([t],{type:n})),i=document.createElement(`a`);i.href=r,i.download=e,i.click(),URL.revokeObjectURL(r)}function wn({onClose:e,defaultView:t=`desktop`,views:n=[`desktop`,`mobile`,`html`,`text`],filename:r=`email.html`,className:i,style:a}){let{handle:o,settings:s,t:c}=Q(),[u,d]=(0,l.useState)(t),[f,p]=(0,l.useState)(null),[m,h]=(0,l.useState)(null),[g,_]=(0,l.useState)(!1);(0,l.useEffect)(()=>{let e=!1;return o.exportEmail().then(t=>!e&&p(t)).catch(t=>!e&&h(t instanceof Error?t.message:String(t))),()=>{e=!0}},[o,s.previewText]),(0,l.useEffect)(()=>{let t=t=>t.key===`Escape`&&e();return window.addEventListener(`keydown`,t),()=>window.removeEventListener(`keydown`,t)},[e]);let b=async()=>{f&&(await navigator.clipboard.writeText(u===`text`?f.text:f.html),_(!0),setTimeout(()=>_(!1),1500))},x=c.preview;return(0,w.createPortal)((0,y.jsx)(v.EditorFocusScope,{children:(0,y.jsx)(`div`,{className:`bree bree-modal-backdrop`,onMouseDown:t=>t.target===t.currentTarget&&e(),children:(0,y.jsxs)(`div`,{className:T(`bree-modal`,i),style:a,role:`dialog`,"aria-modal":`true`,"aria-label":x.dialogLabel,children:[(0,y.jsxs)(`header`,{className:`bree-modal-header`,children:[(0,y.jsx)(`nav`,{className:`bree-tabs bree-compact`,role:`tablist`,children:n.map(e=>(0,y.jsx)(`button`,{type:`button`,role:`tab`,"aria-selected":u===e,className:T(u===e&&`bree-active`),onClick:()=>d(e),children:x[e]},e))}),(0,y.jsxs)(`div`,{className:`bree-modal-actions`,children:[f&&(u===`html`||u===`text`)&&(0,y.jsx)(`button`,{type:`button`,className:`bree-btn`,onClick:b,children:g?x.copied:x.copy}),f&&(0,y.jsx)(`button`,{type:`button`,className:`bree-btn bree-primary`,onClick:()=>Cn(r,f.unformattedHtml,`text/html`),children:x.download}),(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button`,onClick:e,title:x.close,children:(0,y.jsx)(v.XIcon,{size:18})})]})]}),(0,y.jsxs)(`div`,{className:`bree-modal-body`,children:[m&&(0,y.jsx)(`p`,{className:`bree-error`,children:x.renderError(m)}),!f&&!m&&(0,y.jsx)(`p`,{className:`bree-loading`,children:x.rendering}),f&&(u===`desktop`||u===`mobile`)&&(0,y.jsx)(`div`,{className:T(`bree-preview-frame`,`bree-preview-${u}`),children:(0,y.jsx)(`iframe`,{title:x.iframeTitle,srcDoc:f.html,sandbox:`allow-same-origin allow-popups`})}),f&&u===`html`&&(0,y.jsx)(`pre`,{className:`bree-code`,children:f.html}),f&&u===`text`&&(0,y.jsx)(`pre`,{className:`bree-code`,children:f.text})]})]})})}),document.body)}function Tn({className:e,style:t}){let{layersOpen:n,setLayersOpen:r,t:i}=Q();return(0,y.jsxs)(`button`,{type:`button`,className:T(`bree-btn bree-ghost bree-layers-toggle`,n&&`bree-active`,e),style:t,"aria-pressed":n,onClick:()=>r(!n),title:i.topBar.toggleLayers,children:[(0,y.jsx)(Re,{}),` `,i.topBar.layers]})}function En({className:e,style:t}){let{editor:n,t:r}=Q(),i=(0,d.useEditorState)({editor:n,selector:({editor:e})=>({undo:!!e?.can().undo(),redo:!!e?.can().redo()})});return(0,y.jsxs)(`div`,{className:T(`bree-btn-group`,e),style:t,children:[(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button`,title:r.topBar.undo,disabled:!i?.undo,onClick:()=>n.chain().focus().undo().run(),children:(0,y.jsx)(Pe,{})}),(0,y.jsx)(`button`,{type:`button`,className:`bree-icon-button`,title:r.topBar.redo,disabled:!i?.redo,onClick:()=>n.chain().focus().redo().run(),children:(0,y.jsx)(Fe,{})})]})}function Dn({className:e,style:t}){let{device:n,setDevice:r,t:i}=Q(),a=[{id:`desktop`,label:i.topBar.desktop,Icon:Ie},{id:`mobile`,label:i.topBar.mobile,Icon:Le}];return(0,y.jsx)(`div`,{className:T(`bree-segmented bree-device-toggle`,e),style:t,role:`radiogroup`,"aria-label":i.topBar.canvasWidth,children:a.map(({id:e,label:t,Icon:i})=>(0,y.jsx)(`button`,{type:`button`,role:`radio`,"aria-checked":n===e,className:T(n===e&&`bree-active`),onClick:()=>r(e),title:t,children:(0,y.jsx)(i,{})},e))})}function On({className:e,style:t}){let{editor:n,starterDocument:r,locale:i,t:a}=Q();return(0,y.jsx)(`button`,{type:`button`,className:T(`bree-btn bree-ghost`,e),style:t,onClick:()=>{confirm(a.topBar.confirmTemplate)&&n.commands.setContent(r({locale:i,t:a}))},children:a.topBar.template})}function kn({className:e,style:t}){let{handle:n,t:r}=Q(),i=(0,l.useRef)(null),a=async e=>{try{n.setValue(JSON.parse(await e.text()))}catch(e){alert(r.topBar.invalidFile(e instanceof Error?e.message:String(e)))}};return(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`button`,{type:`button`,className:T(`bree-btn bree-ghost`,e),style:t,onClick:()=>i.current?.click(),children:r.topBar.import}),(0,y.jsx)(`input`,{ref:i,type:`file`,accept:`application/json,.json`,hidden:!0,onChange:e=>{let t=e.target.files?.[0];t&&a(t),e.target.value=``}})]})}function An({className:e,style:t,filename:n=`email.json`}){let{handle:r,t:i}=Q();return(0,y.jsx)(`button`,{type:`button`,className:T(`bree-btn bree-ghost`,e),style:t,onClick:()=>Cn(n,JSON.stringify(r.getValue(),null,2),`application/json`),children:i.topBar.exportJson})}function jn({view:e=`desktop`,variant:t=`default`,children:n,className:r,style:i}){let{t:a}=Q(),[o,s]=(0,l.useState)(!1);return(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`button`,{type:`button`,className:T(`bree-btn`,t!=="default"&&`bree-${t}`,r),style:i,onClick:()=>s(!0),children:n??a.topBar.preview}),o&&(0,y.jsx)(wn,{defaultView:e,onClose:()=>s(!1)})]})}function Mn(e){let{t}=Q();return(0,y.jsx)(jn,{view:`html`,variant:`primary`,...e,children:t.topBar.exportHtml})}function Nn({brand:e,actions:t,children:n,className:r,style:i}){return(0,y.jsx)(v.EditorFocusScope,{children:(0,y.jsxs)(`header`,{className:T(`bree-topbar`,r),style:i,children:[(0,y.jsx)(`div`,{className:`bree-topbar-start`,children:e}),n??(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)(`div`,{className:`bree-topbar-center`,children:(0,y.jsx)(Dn,{})}),(0,y.jsxs)(`div`,{className:`bree-topbar-actions`,children:[t,(0,y.jsx)(Mn,{})]})]})]})})}function Pn({showTopBar:e=!0,showLayers:t=!0,showSidebar:n=!0,components:r={},slotProps:i={}}){let{layersOpen:a}=Q(),{TopBar:o=Nn,LayersPanel:s=ln,Canvas:c=nn,Sidebar:l=Sn}=r,u=t&&a;return(0,y.jsxs)(`div`,{className:T(`bree-layout`,e&&`bree-with-topbar`,u&&`bree-with-layers`,n&&`bree-with-sidebar`),children:[e&&(0,y.jsx)(o,{...i.topBar}),u&&(0,y.jsx)(s,{...i.layersPanel}),(0,y.jsx)(c,{...i.canvas}),n&&(0,y.jsx)(l,{...i.sidebar})]})}var Fn=(0,l.forwardRef)(function({showTopBar:e,showLayers:t,showSidebar:n,components:r,slotProps:i,...a},o){return(0,y.jsx)(Yt,{ref:o,...a,children:(0,y.jsx)(Pn,{showTopBar:e,showLayers:t,showSidebar:n,components:r,slotProps:i})})});exports.AlignInput=Qe,exports.BLOCK_CONTAINERS=E,exports.BetterEmailEditor=Fn,exports.BlockProperties=pn,exports.BlocksTab=gn,exports.BodyTab=_n,exports.BoxGroup=tt,exports.ButtonInspector=nt,exports.COLUMN_PARENTS=D,exports.Canvas=nn,exports.CanvasOverlay=en,exports.ColorInput=W,exports.ColumnsInspector=rt,exports.ContainerInspector=lt,exports.ContentPanel=bn,exports.ContentTab=yn,exports.DEFAULT_SWATCHES=Je,exports.DefaultInspector=un,exports.DeviceToggle=Dn,exports.DividerInspector=ct,exports.EditorRoot=Yt,exports.EmailButton=de,exports.ExportHtmlButton=Mn,exports.ExportJsonButton=An,exports.Field=V,exports.Group=B,exports.HeadingInspector=it,exports.HtmlBlock=vt,exports.HtmlInspector=st,exports.ImageInspector=at,exports.ImportButton=kn,exports.LayersPanel=ln,exports.LayersToggle=Tn,exports.NumberInput=U,exports.PaddingInput=$e,exports.PaletteTile=vn,exports.PreviewButton=jn,exports.PreviewDialog=wn,exports.PropertiesPanel=fn,exports.RangeInput=qe,exports.SOCIAL_NETWORKS=pt,exports.Segmented=Ze,exports.Select=Xe,exports.Sidebar=Sn,exports.SocialLinks=_t,exports.SocialLinksInspector=yt,exports.Spacer=ft,exports.SpacerInspector=ot,exports.SpacingGroup=K,exports.TemplateButton=On,exports.TemplateCard=hn,exports.TemplateThumbnail=Z,exports.TextArea=Ge,exports.TextInput=H,exports.TextProperties=xn,exports.TopBar=Nn,exports.TypographyGroup=et,exports.UndoRedo=En,exports.appendBlocks=ue,exports.applyDrop=N,Object.defineProperty(exports,"content",{enumerable:!0,get:function(){return wt}}),exports.createStarterDocument=zt,exports.css=G,exports.cx=T,exports.defaultNodes=Ct,exports.defaultPalette=It,exports.defaultPaletteGroups=Ft,exports.defaultTemplates=Lt,exports.defaultTheme=Ut,exports.deleteUnit=le,exports.download=Cn,exports.duplicateUnit=ce,exports.en=Se,exports.findDropTarget=te,exports.fr=Ce,exports.iconUrl=ht,Object.defineProperty(exports,"icons",{enumerable:!0,get:function(){return ke}}),exports.inlineStyleToObject=ut,exports.locales=we,exports.menuParagraph=Pt,exports.parentUnit=se,exports.readFileAsDataUrl=Wt,exports.resolveLabel=Te,exports.resolveMessages=Oe,exports.selectUnit=I,exports.selectedUnit=F,exports.textPreview=xt,exports.toHex=Ye,exports.truncate=bt,exports.unitAt=P,exports.useDeselect=dn,exports.useDraggableBlock=mn,exports.useEmailEditor=Q,exports.useI18n=Ht,exports.useMessages=$,exports.useOptionalEmailEditor=Vt;
2
+ //# sourceMappingURL=index.cjs.map