@emabuild/core 0.3.0 → 0.4.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 (33) hide show
  1. package/dist/canvas/column-renderer.d.ts.map +1 -1
  2. package/dist/canvas/content-renderer.d.ts.map +1 -1
  3. package/dist/canvas/editor-canvas.d.ts +2 -0
  4. package/dist/canvas/editor-canvas.d.ts.map +1 -1
  5. package/dist/canvas/row-renderer.d.ts.map +1 -1
  6. package/dist/{form-tool-C7760Hvm.js → form-tool-DsPgMShR.js} +2 -2
  7. package/dist/{form-tool-C7760Hvm.js.map → form-tool-DsPgMShR.js.map} +1 -1
  8. package/dist/{html-tool-4zZO2hqE.js → html-tool-BxhBGl4L.js} +2 -2
  9. package/dist/{html-tool-4zZO2hqE.js.map → html-tool-BxhBGl4L.js.map} +1 -1
  10. package/dist/{index-zy5NbC2E.js → index-2S5kBS5_.js} +302 -169
  11. package/dist/index-2S5kBS5_.js.map +1 -0
  12. package/dist/index.js +1 -1
  13. package/dist/mail-editor.d.ts.map +1 -1
  14. package/dist/{menu-tool-Cu5D_VYs.js → menu-tool-IZqYp8Vb.js} +2 -2
  15. package/dist/{menu-tool-Cu5D_VYs.js.map → menu-tool-IZqYp8Vb.js.map} +1 -1
  16. package/dist/properties/property-panel.d.ts.map +1 -1
  17. package/dist/properties/widgets/image-upload-widget.d.ts +4 -0
  18. package/dist/properties/widgets/image-upload-widget.d.ts.map +1 -0
  19. package/dist/properties/widgets/index.d.ts +1 -0
  20. package/dist/properties/widgets/index.d.ts.map +1 -1
  21. package/dist/sidebar/editor-sidebar.d.ts.map +1 -1
  22. package/dist/{social-tool-kPuP-4n6.js → social-tool-C1FeCyUm.js} +2 -2
  23. package/dist/{social-tool-kPuP-4n6.js.map → social-tool-C1FeCyUm.js.map} +1 -1
  24. package/dist/state/editor-store.d.ts +6 -1
  25. package/dist/state/editor-store.d.ts.map +1 -1
  26. package/dist/{table-tool-CcWFvTSc.js → table-tool-BD72-Fuj.js} +2 -2
  27. package/dist/{table-tool-CcWFvTSc.js.map → table-tool-BD72-Fuj.js.map} +1 -1
  28. package/dist/{timer-tool-CG1oul_Z.js → timer-tool-Dpw9p0uW.js} +2 -2
  29. package/dist/{timer-tool-CG1oul_Z.js.map → timer-tool-Dpw9p0uW.js.map} +1 -1
  30. package/dist/{video-tool-CttMka8Z.js → video-tool-CHhPfHaS.js} +2 -2
  31. package/dist/{video-tool-CttMka8Z.js.map → video-tool-CHhPfHaS.js.map} +1 -1
  32. package/package.json +26 -13
  33. package/dist/index-zy5NbC2E.js.map +0 -1
@@ -1,5 +1,5 @@
1
- import { css as _, LitElement as T, nothing as v, html as d } from "lit";
2
- import { property as x, customElement as S, state as E } from "lit/decorators.js";
1
+ import { css as _, LitElement as T, nothing as x, html as d } from "lit";
2
+ import { property as v, customElement as S, state as E } from "lit/decorators.js";
3
3
  import { unsafeHTML as ie } from "lit/directives/unsafe-html.js";
4
4
  import { styleMap as He } from "lit/directives/style-map.js";
5
5
  import { repeat as ye } from "lit/directives/repeat.js";
@@ -67,14 +67,14 @@ function V(e, t) {
67
67
  const i = $e(o.r, o.g, o.b), n = $e(r.r, r.g, r.b);
68
68
  return (Math.max(i, n) + 0.05) / (Math.min(i, n) + 0.05);
69
69
  }
70
- function Le(e) {
70
+ function ze(e) {
71
71
  if (typeof e != "string") return !1;
72
72
  const t = e.trim().toLowerCase();
73
73
  return t !== "" && t !== "transparent" && t !== "none" && t !== "inherit";
74
74
  }
75
75
  function Ce(...e) {
76
76
  for (const t of e)
77
- if (Le(t)) return t;
77
+ if (ze(t)) return t;
78
78
  return "#ffffff";
79
79
  }
80
80
  function te(e, t = 0) {
@@ -122,10 +122,10 @@ let U = class extends T {
122
122
  const e = this.checkAccessibility(), t = e.filter((i) => i.severity === "error"), o = e.filter((i) => i.severity === "warning"), r = e.filter((i) => i.severity === "info");
123
123
  return d`
124
124
  <div class="summary">
125
- ${t.length > 0 ? d`<span class="score-pill errors"><span class="score-dot error"></span>${t.length}</span>` : v}
126
- ${o.length > 0 ? d`<span class="score-pill warnings"><span class="score-dot warning"></span>${o.length}</span>` : v}
127
- ${r.length > 0 ? d`<span class="score-pill infos"><span class="score-dot info"></span>${r.length}</span>` : v}
128
- ${t.length === 0 && o.length === 0 ? d`<span class="score-pill pass"><span class="score-dot pass"></span>Pass</span>` : v}
125
+ ${t.length > 0 ? d`<span class="score-pill errors"><span class="score-dot error"></span>${t.length}</span>` : x}
126
+ ${o.length > 0 ? d`<span class="score-pill warnings"><span class="score-dot warning"></span>${o.length}</span>` : x}
127
+ ${r.length > 0 ? d`<span class="score-pill infos"><span class="score-dot info"></span>${r.length}</span>` : x}
128
+ ${t.length === 0 && o.length === 0 ? d`<span class="score-pill pass"><span class="score-dot pass"></span>Pass</span>` : x}
129
129
  </div>
130
130
 
131
131
  ${e.length === 0 ? d`
@@ -138,15 +138,15 @@ let U = class extends T {
138
138
  ${t.length > 0 ? d`
139
139
  <div class="section-title">Errors</div>
140
140
  <div class="issues-list">${t.map((i) => this.renderIssue(i))}</div>
141
- ` : v}
141
+ ` : x}
142
142
  ${o.length > 0 ? d`
143
143
  <div class="section-title">Warnings</div>
144
144
  <div class="issues-list">${o.map((i) => this.renderIssue(i))}</div>
145
- ` : v}
145
+ ` : x}
146
146
  ${r.length > 0 ? d`
147
147
  <div class="section-title">Info</div>
148
148
  <div class="issues-list">${r.map((i) => this.renderIssue(i))}</div>
149
- ` : v}
149
+ ` : x}
150
150
  `}
151
151
  `;
152
152
  }
@@ -162,9 +162,9 @@ let U = class extends T {
162
162
  <div class="issue-body">
163
163
  <div class="issue-rule">${e.rule}</div>
164
164
  <div class="issue-msg">${e.message}</div>
165
- ${e.element ? d`<div class="issue-element">${e.element}</div>` : v}
166
- ${e.rule === "heading-structure" ? d`<button class="issue-fix" @click=${this.handleFixHeading}>+ Add heading</button>` : v}
167
- ${e.rule === "preheader" ? d`<button class="issue-fix" @click=${this.handleFixPreheader}>Fix</button>` : v}
165
+ ${e.element ? d`<div class="issue-element">${e.element}</div>` : x}
166
+ ${e.rule === "heading-structure" ? d`<button class="issue-fix" @click=${this.handleFixHeading}>+ Add heading</button>` : x}
167
+ ${e.rule === "preheader" ? d`<button class="issue-fix" @click=${this.handleFixPreheader}>Fix</button>` : x}
168
168
  </div>
169
169
  </div>
170
170
  `;
@@ -274,10 +274,10 @@ U.styles = _`
274
274
  .all-clear-sub { font-size: 11px; color: #9ca3af; margin-top: 4px; }
275
275
  `;
276
276
  xe([
277
- x({ attribute: !1 })
277
+ v({ attribute: !1 })
278
278
  ], U.prototype, "store", 1);
279
279
  xe([
280
- x({ attribute: !1 })
280
+ v({ attribute: !1 })
281
281
  ], U.prototype, "toolRegistry", 2);
282
282
  U = xe([
283
283
  S("me-a11y-checker")
@@ -297,9 +297,9 @@ function ve(e) {
297
297
  (f.src || "") && !C.trim() ? t.push({ severity: "error", rule: "img-alt", message: "Missing alt text.", element: w, elementId: m.id }) : C && C.length > 125 && t.push({ severity: "warning", rule: "img-alt-length", message: `Alt text ${C.length} chars (max 125).`, element: w, elementId: m.id });
298
298
  }
299
299
  if (y === "text" || y === "heading" || y === "paragraph") {
300
- const C = Le(f.color) ? f.color : n, A = Ce(f.backgroundColor, $), I = V(C, A);
300
+ const C = ze(f.color) ? f.color : n, A = Ce(f.backgroundColor, $), I = V(C, A);
301
301
  if (I !== null) {
302
- const Y = te(f.fontSize, 14), je = ["700", "800", "900"].includes(f.fontWeight || ""), ke = Y >= 18 || Y >= 14 && je ? 3 : 4.5;
302
+ const Q = te(f.fontSize, 14), Oe = ["700", "800", "900"].includes(f.fontWeight || ""), ke = Q >= 18 || Q >= 14 && Oe ? 3 : 4.5;
303
303
  I < ke && t.push({ severity: I < 3 ? "error" : "warning", rule: "color-contrast", message: `Ratio ${I.toFixed(1)}:1 (min ${ke}:1). "${C}" on "${A}".`, element: w, elementId: m.id });
304
304
  }
305
305
  const W = te(f.fontSize, 14);
@@ -312,8 +312,8 @@ function ve(e) {
312
312
  I !== null && I < 4.5 && t.push({ severity: I < 3 ? "error" : "warning", rule: "color-contrast", message: `Button contrast ${I.toFixed(1)}:1 (min 4.5:1).`, element: w, elementId: m.id });
313
313
  const W = V(C, $);
314
314
  W !== null && W < 3 && t.push({ severity: "warning", rule: "btn-visibility", message: `Button blends with background (${W.toFixed(1)}:1).`, element: w, elementId: m.id }), (f.text || "").trim() || t.push({ severity: "error", rule: "link-text", message: "Button has no visible text.", element: w, elementId: m.id });
315
- const ee = (f.buttonPadding || "10px 20px").split(/\s+/), Y = te(f.fontSize, 14) + te(ee[0], 10) * 2;
316
- Y < 44 && t.push({ severity: "info", rule: "touch-target", message: `Button height ~${Y}px (min 44px).`, element: w, elementId: m.id });
315
+ const ee = (f.buttonPadding || "10px 20px").split(/\s+/), Q = te(f.fontSize, 14) + te(ee[0], 10) * 2;
316
+ Q < 44 && t.push({ severity: "info", rule: "touch-target", message: `Button height ~${Q}px (min 44px).`, element: w, elementId: m.id });
317
317
  }
318
318
  if (y === "heading" && (s = !0, a.push(f.headingType || "h1")), y === "text" || y === "paragraph") {
319
319
  const C = f.text || "", A = C.match(/<a[^>]*>(\s|&nbsp;)*<\/a>/gi);
@@ -422,7 +422,7 @@ class Ge {
422
422
  this.undoStack = [], this.redoStack = [];
423
423
  }
424
424
  }
425
- function Qe() {
425
+ function Ye() {
426
426
  return {
427
427
  counters: { u_row: 0, u_column: 0 },
428
428
  body: {
@@ -467,7 +467,7 @@ function Qe() {
467
467
  schemaVersion: 16
468
468
  };
469
469
  }
470
- function Ye(e, t) {
470
+ function Qe(e, t) {
471
471
  const o = e.next("u_row"), r = t.map(() => {
472
472
  const i = e.next("u_column");
473
473
  return {
@@ -546,7 +546,13 @@ function ce(e, t) {
546
546
  }
547
547
  class Ze {
548
548
  constructor() {
549
- this.history = new Ge(), this.counterManager = qe(), this.channelSubscribers = /* @__PURE__ */ new Map(), this.events = new Ne(), this._mergeTags = [], this._a11yIssueIds = /* @__PURE__ */ new Set(), this._selectedId = null, this._hoveredId = null, this._viewMode = "desktop", this._activeTab = "content", this.design = Qe();
549
+ this.history = new Ge(), this.counterManager = qe(), this.channelSubscribers = /* @__PURE__ */ new Map(), this.events = new Ne(), this._mergeTags = [], this._callbacks = /* @__PURE__ */ new Map(), this._a11yIssueIds = /* @__PURE__ */ new Set(), this._selectedId = null, this._hoveredId = null, this._viewMode = "desktop", this._activeTab = "content", this.pendingChannels = /* @__PURE__ */ new Set(), this.rafId = null, this.design = Ye();
550
+ }
551
+ setCallback(t, o) {
552
+ this._callbacks.set(t, o);
553
+ }
554
+ getCallback(t) {
555
+ return this._callbacks.get(t);
550
556
  }
551
557
  get a11yIssueIds() {
552
558
  return this._a11yIssueIds;
@@ -582,14 +588,18 @@ class Ze {
582
588
  const o = ["design", "selection", "hover", "viewMode", "activeTab"];
583
589
  return this.subscribeChannels(o, t);
584
590
  }
585
- /** Notify only subscribers of specific channels */
586
591
  notifyChannels(...t) {
587
- const o = /* @__PURE__ */ new Set();
588
- for (const r of t) {
589
- const i = this.channelSubscribers.get(r);
590
- if (i) for (const n of i) o.add(n);
591
- }
592
- for (const r of o) r();
592
+ for (const o of t) this.pendingChannels.add(o);
593
+ this.rafId === null && (this.rafId = requestAnimationFrame(() => {
594
+ this.rafId = null;
595
+ const o = /* @__PURE__ */ new Set();
596
+ for (const r of this.pendingChannels) {
597
+ const i = this.channelSubscribers.get(r);
598
+ if (i) for (const n of i) o.add(n);
599
+ }
600
+ this.pendingChannels.clear();
601
+ for (const r of o) r();
602
+ }));
593
603
  }
594
604
  // ── Getters ────────────────────────────────────────────────
595
605
  /** Get the full design document */
@@ -651,7 +661,9 @@ class Ze {
651
661
  this._selectedId = t, this.notifyChannels("selection");
652
662
  }
653
663
  hover(t) {
654
- this._hoveredId = t, this.notifyChannels("hover");
664
+ this._hoveredId = t;
665
+ const o = this.channelSubscribers.get("hover");
666
+ if (o) for (const r of o) r();
655
667
  }
656
668
  setViewMode(t) {
657
669
  this._viewMode = t, this.notifyChannels("viewMode");
@@ -793,7 +805,7 @@ class Ze {
793
805
  // ── Factory Methods (delegate to design-factory) ───────────
794
806
  /** Create a new row with the given column layout */
795
807
  createRow(t) {
796
- const o = Ye(this.counterManager, t);
808
+ const o = Qe(this.counterManager, t);
797
809
  return this.syncCounters(), o;
798
810
  }
799
811
  /** Create a new content block for the given tool type */
@@ -1165,7 +1177,7 @@ function Pe(e) {
1165
1177
  color: p(e, "textColor", "#ffffff")
1166
1178
  };
1167
1179
  }
1168
- function fo(e, t) {
1180
+ function bo(e, t) {
1169
1181
  if (typeof e != "string") return t;
1170
1182
  try {
1171
1183
  return JSON.parse(e);
@@ -1440,7 +1452,7 @@ const it = [
1440
1452
  image: {
1441
1453
  title: "Image",
1442
1454
  options: {
1443
- src: { label: "Image URL", defaultValue: "", widget: "text" },
1455
+ src: { label: "Image URL", defaultValue: "", widget: "image_upload" },
1444
1456
  alt: { label: "Alt Text", defaultValue: "", widget: "text" },
1445
1457
  href: { label: "Link URL", defaultValue: "", widget: "text" },
1446
1458
  target: { label: "Link Target", defaultValue: "_blank", widget: "text" }
@@ -1631,31 +1643,31 @@ const it = [
1631
1643
  ], Ee = [
1632
1644
  {
1633
1645
  meta: { name: "html", label: "HTML", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>', position: 6 },
1634
- loader: () => import("./html-tool-4zZO2hqE.js").then((e) => e.htmlTool)
1646
+ loader: () => import("./html-tool-BxhBGl4L.js").then((e) => e.htmlTool)
1635
1647
  },
1636
1648
  {
1637
1649
  meta: { name: "social", label: "Social", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>', position: 8 },
1638
- loader: () => import("./social-tool-kPuP-4n6.js").then((e) => e.socialTool)
1650
+ loader: () => import("./social-tool-C1FeCyUm.js").then((e) => e.socialTool)
1639
1651
  },
1640
1652
  {
1641
1653
  meta: { name: "menu", label: "Menu", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="4" y1="6" x2="20" y2="6"/><line x1="4" y1="12" x2="20" y2="12"/><line x1="4" y1="18" x2="20" y2="18"/></svg>', position: 9 },
1642
- loader: () => import("./menu-tool-Cu5D_VYs.js").then((e) => e.menuTool)
1654
+ loader: () => import("./menu-tool-IZqYp8Vb.js").then((e) => e.menuTool)
1643
1655
  },
1644
1656
  {
1645
1657
  meta: { name: "video", label: "Video", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>', position: 10 },
1646
- loader: () => import("./video-tool-CttMka8Z.js").then((e) => e.videoTool)
1658
+ loader: () => import("./video-tool-CHhPfHaS.js").then((e) => e.videoTool)
1647
1659
  },
1648
1660
  {
1649
1661
  meta: { name: "timer", label: "Timer", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>', position: 11 },
1650
- loader: () => import("./timer-tool-CG1oul_Z.js").then((e) => e.timerTool)
1662
+ loader: () => import("./timer-tool-Dpw9p0uW.js").then((e) => e.timerTool)
1651
1663
  },
1652
1664
  {
1653
1665
  meta: { name: "table", label: "Table", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M3 9h18"/><path d="M3 15h18"/><path d="M9 3v18"/><path d="M15 3v18"/></svg>', position: 12 },
1654
- loader: () => import("./table-tool-CcWFvTSc.js").then((e) => e.tableTool)
1666
+ loader: () => import("./table-tool-BD72-Fuj.js").then((e) => e.tableTool)
1655
1667
  },
1656
1668
  {
1657
1669
  meta: { name: "form", label: "Form", icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M7 7h10"/><path d="M7 12h10"/><path d="M7 17h6"/></svg>', position: 13 },
1658
- loader: () => import("./form-tool-C7760Hvm.js").then((e) => e.formTool)
1670
+ loader: () => import("./form-tool-DsPgMShR.js").then((e) => e.formTool)
1659
1671
  }
1660
1672
  ];
1661
1673
  function mt(e, t, o) {
@@ -2077,12 +2089,12 @@ function At(...e) {
2077
2089
  }
2078
2090
  return t;
2079
2091
  }
2080
- var Mt = Object.defineProperty, zt = Object.getOwnPropertyDescriptor, se = (e, t, o, r) => {
2081
- for (var i = r > 1 ? void 0 : r ? zt(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2092
+ var Mt = Object.defineProperty, Lt = Object.getOwnPropertyDescriptor, se = (e, t, o, r) => {
2093
+ for (var i = r > 1 ? void 0 : r ? Lt(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2082
2094
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
2083
2095
  return r && i && Mt(t, o, i), i;
2084
2096
  };
2085
- let O = class extends T {
2097
+ let j = class extends T {
2086
2098
  constructor() {
2087
2099
  super(...arguments), this.visible = !1, this.mergeTags = [], this.mergeDropdownOpen = !1, this._outsideClickHandler = (e) => {
2088
2100
  if (!this.mergeDropdownOpen) return;
@@ -2179,14 +2191,14 @@ let O = class extends T {
2179
2191
  `)}
2180
2192
  `)}
2181
2193
  </div>
2182
- ` : v}
2194
+ ` : x}
2183
2195
  </div>
2184
- ` : v}
2196
+ ` : x}
2185
2197
  </div>
2186
2198
  `;
2187
2199
  }
2188
2200
  };
2189
- O.styles = _`
2201
+ j.styles = _`
2190
2202
  :host {
2191
2203
  position: fixed;
2192
2204
  z-index: 10000;
@@ -2286,21 +2298,21 @@ O.styles = _`
2286
2298
  }
2287
2299
  `;
2288
2300
  se([
2289
- x({ type: Boolean })
2290
- ], O.prototype, "visible", 2);
2301
+ v({ type: Boolean })
2302
+ ], j.prototype, "visible", 2);
2291
2303
  se([
2292
- x({ attribute: !1 })
2293
- ], O.prototype, "mergeTags", 2);
2304
+ v({ attribute: !1 })
2305
+ ], j.prototype, "mergeTags", 2);
2294
2306
  se([
2295
2307
  E()
2296
- ], O.prototype, "mergeDropdownOpen", 2);
2297
- O = se([
2308
+ ], j.prototype, "mergeDropdownOpen", 2);
2309
+ j = se([
2298
2310
  S("me-inline-toolbar")
2299
- ], O);
2300
- var Lt = Object.defineProperty, Bt = Object.getOwnPropertyDescriptor, J = (e, t, o, r) => {
2311
+ ], j);
2312
+ var zt = Object.defineProperty, Bt = Object.getOwnPropertyDescriptor, J = (e, t, o, r) => {
2301
2313
  for (var i = r > 1 ? void 0 : r ? Bt(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2302
2314
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
2303
- return r && i && Lt(t, o, i), i;
2315
+ return r && i && zt(t, o, i), i;
2304
2316
  };
2305
2317
  const Ae = /* @__PURE__ */ new Set(["text", "heading", "paragraph"]);
2306
2318
  function Me(e) {
@@ -2344,17 +2356,27 @@ let M = class extends T {
2344
2356
  this.classList.remove("hovered"), this.store.hover(null);
2345
2357
  }
2346
2358
  handleDelete(e) {
2347
- e.stopPropagation(), this.store.removeContent(this.content.id);
2359
+ e.stopPropagation(), this.classList.add("removing");
2360
+ const t = this.content.id;
2361
+ this.addEventListener("animationend", () => this.store.removeContent(t), { once: !0 });
2348
2362
  }
2349
2363
  handleDuplicate(e) {
2350
- e.stopPropagation(), this.store.duplicateContent(this.content.id);
2364
+ e.stopPropagation();
2365
+ const t = this.store.duplicateContent(this.content.id);
2366
+ t && requestAnimationFrame(() => {
2367
+ const o = this.parentElement;
2368
+ if (o?.shadowRoot) {
2369
+ const r = o.shadowRoot.querySelector(`[data-content-id="${t.id}"]`);
2370
+ r?.classList.add("just-duplicated"), setTimeout(() => r?.classList.remove("just-duplicated"), 600);
2371
+ }
2372
+ });
2351
2373
  }
2352
2374
  /** Called from the drag handle only (not the whole block) */
2353
2375
  handleDragStart(e) {
2354
- e.stopPropagation(), e.dataTransfer.setData("application/maileditor-content", this.content.id), e.dataTransfer.effectAllowed = "move", this.style.opacity = "0.4", D.startContentDrag(this.content.id, this);
2376
+ e.stopPropagation(), e.dataTransfer.setData("application/maileditor-content", this.content.id), e.dataTransfer.effectAllowed = "move", this.style.opacity = "0.4", this.style.transform = "scale(0.97)", D.startContentDrag(this.content.id, this);
2355
2377
  }
2356
2378
  handleDragEnd() {
2357
- D.reset();
2379
+ this.style.transform = "", D.reset();
2358
2380
  }
2359
2381
  // ── Inline editing ───────────────────────────────────────
2360
2382
  startEditing() {
@@ -2392,7 +2414,7 @@ let M = class extends T {
2392
2414
  }
2393
2415
  // ── Lifecycle ────────────────────────────────────────────
2394
2416
  connectedCallback() {
2395
- super.connectedCallback(), this.store && (this.hoverUnsub = this.store.subscribeChannels(["hover"], () => {
2417
+ super.connectedCallback(), this.classList.add("just-dropped"), setTimeout(() => this.classList.remove("just-dropped"), 400), this.store && (this.hoverUnsub = this.store.subscribeChannels(["hover"], () => {
2396
2418
  this.store.hoveredId === this.content?.id ? this.classList.add("hovered") : this.matches(":hover") || this.classList.remove("hovered");
2397
2419
  }));
2398
2420
  }
@@ -2428,7 +2450,7 @@ let M = class extends T {
2428
2450
  ${l}
2429
2451
  <div class="action-bar">
2430
2452
  <span class="action-bar-label">${this.content.type}</span>
2431
- <button class="action-btn" @click=${this.handleDuplicate} title="Duplicate">&#9851;</button>
2453
+ <button class="action-btn" @click=${this.handleDuplicate} title="Duplicate">&#10697;</button>
2432
2454
  <button class="action-btn" @click=${this.handleDelete} title="Delete">&#10005;</button>
2433
2455
  </div>
2434
2456
  <div class="content-wrapper" style="padding:${h};"
@@ -2484,6 +2506,20 @@ M.styles = _`
2484
2506
  :host(.just-dropped) {
2485
2507
  animation: dropIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
2486
2508
  }
2509
+ :host(.just-duplicated) {
2510
+ animation: duplicateFlash 0.5s ease-out;
2511
+ }
2512
+ @keyframes duplicateFlash {
2513
+ 0% { background: var(--me-primary-10, rgba(93,118,139,0.1)); transform: scale(1.01); }
2514
+ 100% { background: transparent; transform: scale(1); }
2515
+ }
2516
+ :host(.removing) {
2517
+ animation: fadeRemove 0.25s ease-out forwards;
2518
+ pointer-events: none;
2519
+ }
2520
+ @keyframes fadeRemove {
2521
+ to { opacity: 0; transform: scale(0.96) translateY(-4px); height: 0; margin: 0; padding: 0; overflow: hidden; }
2522
+ }
2487
2523
  :host(.hidden-in-view) { opacity: 0.3; position: relative; }
2488
2524
  .hidden-badge {
2489
2525
  position: absolute; top: 4px; right: 4px; z-index: 5;
@@ -2554,13 +2590,13 @@ M.styles = _`
2554
2590
  .inline-editable:focus { outline: none; }
2555
2591
  `;
2556
2592
  J([
2557
- x({ attribute: !1 })
2593
+ v({ attribute: !1 })
2558
2594
  ], M.prototype, "content", 2);
2559
2595
  J([
2560
- x({ attribute: !1 })
2596
+ v({ attribute: !1 })
2561
2597
  ], M.prototype, "store", 1);
2562
2598
  J([
2563
- x({ attribute: !1 })
2599
+ v({ attribute: !1 })
2564
2600
  ], M.prototype, "toolRegistry", 2);
2565
2601
  J([
2566
2602
  E()
@@ -2568,12 +2604,12 @@ J([
2568
2604
  M = J([
2569
2605
  S("me-content-renderer")
2570
2606
  ], M);
2571
- var Wt = Object.defineProperty, Ot = Object.getOwnPropertyDescriptor, X = (e, t, o, r) => {
2572
- for (var i = r > 1 ? void 0 : r ? Ot(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2607
+ var Wt = Object.defineProperty, jt = Object.getOwnPropertyDescriptor, X = (e, t, o, r) => {
2608
+ for (var i = r > 1 ? void 0 : r ? jt(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2573
2609
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
2574
2610
  return r && i && Wt(t, o, i), i;
2575
2611
  };
2576
- let z = class extends T {
2612
+ let L = class extends T {
2577
2613
  constructor() {
2578
2614
  super(...arguments), this.storeCtrl = new B(this, ["design"]), this.widthPercent = 100;
2579
2615
  }
@@ -2600,7 +2636,7 @@ let z = class extends T {
2600
2636
  `;
2601
2637
  }
2602
2638
  };
2603
- z.styles = _`
2639
+ L.styles = _`
2604
2640
  :host {
2605
2641
  display: block;
2606
2642
  min-height: 40px;
@@ -2611,12 +2647,17 @@ z.styles = _`
2611
2647
  align-items: center;
2612
2648
  justify-content: center;
2613
2649
  min-height: 60px;
2614
- border: 2px dashed #d1d5db;
2615
- border-radius: 4px;
2616
- color: #9ca3af;
2617
- font-size: 13px;
2650
+ border: 2px dashed var(--me-grey-300, #d1d5db);
2651
+ border-radius: 8px;
2652
+ color: var(--me-grey-400, #9ca3af);
2653
+ font-size: 12px;
2618
2654
  font-family: sans-serif;
2619
2655
  margin: 4px;
2656
+ animation: emptyBreath 3s ease-in-out infinite;
2657
+ }
2658
+ @keyframes emptyBreath {
2659
+ 0%, 100% { border-color: var(--me-grey-300, #d1d5db); opacity: 0.6; }
2660
+ 50% { border-color: var(--me-primary, #5d768b); opacity: 1; }
2620
2661
  }
2621
2662
  .drop-indicator {
2622
2663
  height: 3px;
@@ -2631,31 +2672,31 @@ z.styles = _`
2631
2672
  }
2632
2673
  `;
2633
2674
  X([
2634
- x({ attribute: !1 })
2635
- ], z.prototype, "column", 2);
2675
+ v({ attribute: !1 })
2676
+ ], L.prototype, "column", 2);
2636
2677
  X([
2637
- x({ attribute: !1 })
2638
- ], z.prototype, "store", 1);
2678
+ v({ attribute: !1 })
2679
+ ], L.prototype, "store", 1);
2639
2680
  X([
2640
- x({ attribute: !1 })
2641
- ], z.prototype, "toolRegistry", 2);
2681
+ v({ attribute: !1 })
2682
+ ], L.prototype, "toolRegistry", 2);
2642
2683
  X([
2643
- x({ type: Number })
2644
- ], z.prototype, "widthPercent", 2);
2645
- z = X([
2684
+ v({ type: Number })
2685
+ ], L.prototype, "widthPercent", 2);
2686
+ L = X([
2646
2687
  S("me-column-renderer")
2647
- ], z);
2648
- var jt = Object.defineProperty, Ht = Object.getOwnPropertyDescriptor, ae = (e, t, o, r) => {
2688
+ ], L);
2689
+ var Ot = Object.defineProperty, Ht = Object.getOwnPropertyDescriptor, ae = (e, t, o, r) => {
2649
2690
  for (var i = r > 1 ? void 0 : r ? Ht(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2650
2691
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
2651
- return r && i && jt(t, o, i), i;
2692
+ return r && i && Ot(t, o, i), i;
2652
2693
  };
2653
- let j = class extends T {
2694
+ let O = class extends T {
2654
2695
  constructor() {
2655
2696
  super(...arguments), this.storeCtrl = new B(this, ["design", "viewMode"]), this.handleDragStart = (e) => {
2656
- e.stopPropagation(), e.dataTransfer.setData("application/maileditor-row", this.row.id), e.dataTransfer.effectAllowed = "move", this.style.opacity = "0.4", D.startRowDrag(this.row.id, this);
2697
+ e.stopPropagation(), e.dataTransfer.setData("application/maileditor-row", this.row.id), e.dataTransfer.effectAllowed = "move", this.style.opacity = "0.4", this.style.transform = "scale(0.98)", D.startRowDrag(this.row.id, this);
2657
2698
  }, this.handleDragEnd = () => {
2658
- D.reset();
2699
+ this.style.transform = "", D.reset();
2659
2700
  };
2660
2701
  }
2661
2702
  set store(e) {
@@ -2678,7 +2719,9 @@ let j = class extends T {
2678
2719
  e.stopPropagation(), this.store.duplicateRow(this.row.id);
2679
2720
  }
2680
2721
  handleDelete(e) {
2681
- e.stopPropagation(), this.store.removeRow(this.row.id);
2722
+ e.stopPropagation(), this.classList.add("removing");
2723
+ const t = this.row.id;
2724
+ this.addEventListener("animationend", () => this.store.removeRow(t), { once: !0 });
2682
2725
  }
2683
2726
  render() {
2684
2727
  if (!this.store) return d``;
@@ -2736,13 +2779,20 @@ let j = class extends T {
2736
2779
  `;
2737
2780
  }
2738
2781
  };
2739
- j.styles = _`
2782
+ O.styles = _`
2740
2783
  :host {
2741
2784
  display: block;
2742
2785
  position: relative;
2743
- transition: opacity 0.2s ease;
2786
+ transition: opacity 0.2s ease, transform 0.25s ease;
2744
2787
  }
2745
2788
  :host(.hidden-in-view) { opacity: 0.3; }
2789
+ :host(.removing) {
2790
+ animation: rowRemove 0.25s ease-out forwards;
2791
+ pointer-events: none;
2792
+ }
2793
+ @keyframes rowRemove {
2794
+ to { opacity: 0; transform: scaleY(0.8); height: 0; margin: 0; overflow: hidden; }
2795
+ }
2746
2796
  .row-hidden-badge {
2747
2797
  position: absolute; top: 4px; left: 4px; z-index: 5;
2748
2798
  background: #f59e0b; color: white; font-size: 10px; font-weight: 600;
@@ -2850,23 +2900,23 @@ j.styles = _`
2850
2900
  }
2851
2901
  `;
2852
2902
  ae([
2853
- x({ attribute: !1 })
2854
- ], j.prototype, "row", 2);
2903
+ v({ attribute: !1 })
2904
+ ], O.prototype, "row", 2);
2855
2905
  ae([
2856
- x({ attribute: !1 })
2857
- ], j.prototype, "store", 1);
2906
+ v({ attribute: !1 })
2907
+ ], O.prototype, "store", 1);
2858
2908
  ae([
2859
- x({ attribute: !1 })
2860
- ], j.prototype, "toolRegistry", 2);
2861
- j = ae([
2909
+ v({ attribute: !1 })
2910
+ ], O.prototype, "toolRegistry", 2);
2911
+ O = ae([
2862
2912
  S("me-row-renderer")
2863
- ], j);
2913
+ ], O);
2864
2914
  var Vt = Object.defineProperty, Ft = Object.getOwnPropertyDescriptor, Z = (e, t, o, r) => {
2865
2915
  for (var i = r > 1 ? void 0 : r ? Ft(t, o) : t, n = e.length - 1, s; n >= 0; n--)
2866
2916
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
2867
2917
  return r && i && Vt(t, o, i), i;
2868
2918
  };
2869
- let L = class extends T {
2919
+ let z = class extends T {
2870
2920
  constructor() {
2871
2921
  super(...arguments), this.storeCtrl = new B(this, ["design", "viewMode"]), this.quickAddIndex = null, this.quickAddPos = { x: 0, y: 0 }, this.boundCloseQuickAdd = this.closeQuickAdd.bind(this);
2872
2922
  }
@@ -2885,6 +2935,11 @@ let L = class extends T {
2885
2935
  handleCanvasClick() {
2886
2936
  this.store.select(null);
2887
2937
  }
2938
+ /** Flash the canvas border to confirm undo/redo */
2939
+ flashUndo() {
2940
+ const e = this.shadowRoot?.querySelector(".canvas-body");
2941
+ e && (e.classList.add("undo-flash"), e.addEventListener("animationend", () => e.classList.remove("undo-flash"), { once: !0 }));
2942
+ }
2888
2943
  setViewMode(e) {
2889
2944
  this.store.setViewMode(e);
2890
2945
  }
@@ -2989,8 +3044,19 @@ let L = class extends T {
2989
3044
  >
2990
3045
  ${e.length === 0 ? d`
2991
3046
  <div class="empty-canvas">
2992
- <div class="empty-icon">&#9776;</div>
2993
- <div>Drag a content block here</div>
3047
+ <div class="empty-icon">
3048
+ <svg viewBox="0 0 24 24"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="12" y1="8" x2="12" y2="16"/><line x1="8" y1="12" x2="16" y2="12"/></svg>
3049
+ </div>
3050
+ <div class="empty-title">Start building your email</div>
3051
+ <div class="empty-sub">Drag elements from the sidebar, use the + button, or start with a template</div>
3052
+ <div class="empty-actions">
3053
+ <button class="empty-action primary" @click=${() => this.quickAddTool("heading", 0)}>Add Heading</button>
3054
+ <button class="empty-action" @click=${() => this.quickAddTool("text", 0)}>Add Text</button>
3055
+ <button class="empty-action" @click=${() => this.quickAddLayout([1, 1], 0)}>2 Columns</button>
3056
+ </div>
3057
+ <div class="empty-shortcut">
3058
+ <kbd>Ctrl</kbd>+<kbd>Z</kbd> undo · <kbd>Ctrl</kbd>+<kbd>D</kbd> duplicate · <kbd>Del</kbd> remove
3059
+ </div>
2994
3060
  </div>
2995
3061
  ${this.renderRowGap(0)}
2996
3062
  ` : d`
@@ -3010,7 +3076,7 @@ let L = class extends T {
3010
3076
  `;
3011
3077
  }
3012
3078
  };
3013
- L.styles = _`
3079
+ z.styles = _`
3014
3080
  :host {
3015
3081
  display: block;
3016
3082
  flex: 1;
@@ -3027,21 +3093,48 @@ L.styles = _`
3027
3093
  background: #ffffff;
3028
3094
  min-height: 200px;
3029
3095
  position: relative;
3096
+ transition: max-width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
3097
+ }
3098
+ .canvas-body.undo-flash {
3099
+ animation: undoFlash 0.3s ease-out;
3100
+ }
3101
+ @keyframes undoFlash {
3102
+ 0% { box-shadow: inset 0 0 0 2px var(--me-primary-30, rgba(93,118,139,0.3)); }
3103
+ 100% { box-shadow: none; }
3030
3104
  }
3031
3105
  .empty-canvas {
3032
- display: flex;
3033
- flex-direction: column;
3034
- align-items: center;
3035
- justify-content: center;
3036
- min-height: 300px;
3037
- color: var(--me-grey-400);
3038
- font-family: sans-serif;
3039
- font-size: 14px;
3040
- gap: 8px;
3106
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
3107
+ min-height: 300px; color: var(--me-grey-400); font-family: sans-serif; gap: 12px;
3108
+ padding: 40px 20px; text-align: center;
3041
3109
  }
3042
3110
  .empty-icon {
3043
- font-size: 40px;
3044
- opacity: 0.4;
3111
+ width: 56px; height: 56px; border-radius: 50%;
3112
+ background: var(--me-primary-5, rgba(93,118,139,0.05));
3113
+ display: flex; align-items: center; justify-content: center;
3114
+ animation: emptyPulse 3s ease-in-out infinite;
3115
+ }
3116
+ .empty-icon svg { width: 24px; height: 24px; stroke: var(--me-primary); fill: none; stroke-width: 1.5; }
3117
+ @keyframes emptyPulse {
3118
+ 0%, 100% { opacity: 0.6; transform: scale(0.95); }
3119
+ 50% { opacity: 1; transform: scale(1); }
3120
+ }
3121
+ .empty-title { font-size: 14px; font-weight: 600; color: var(--me-grey-600); }
3122
+ .empty-sub { font-size: 12px; color: var(--me-grey-400); max-width: 240px; line-height: 1.5; }
3123
+ .empty-actions { display: flex; gap: 8px; margin-top: 8px; }
3124
+ .empty-action {
3125
+ padding: 6px 14px; border-radius: var(--me-radius, 8px); border: 1px solid var(--me-grey-200);
3126
+ background: white; color: var(--me-grey-600); font-size: 11px; font-weight: 600;
3127
+ cursor: pointer; transition: all var(--me-transition, 150ms ease); font-family: sans-serif;
3128
+ }
3129
+ .empty-action:hover { border-color: var(--me-primary); color: var(--me-primary); background: var(--me-primary-5); }
3130
+ .empty-action.primary { background: var(--me-primary); color: white; border-color: var(--me-primary); }
3131
+ .empty-action.primary:hover { background: var(--me-primary-dark, #4a6070); }
3132
+ .empty-shortcut {
3133
+ font-size: 10px; color: var(--me-grey-300); margin-top: 12px; font-family: sans-serif;
3134
+ }
3135
+ .empty-shortcut kbd {
3136
+ background: var(--me-grey-100); border: 1px solid var(--me-grey-200);
3137
+ border-radius: 3px; padding: 1px 4px; font-size: 10px; font-family: monospace;
3045
3138
  }
3046
3139
  .view-toggle {
3047
3140
  display: flex;
@@ -3191,21 +3284,21 @@ L.styles = _`
3191
3284
  }
3192
3285
  `;
3193
3286
  Z([
3194
- x({ attribute: !1 })
3195
- ], L.prototype, "store", 1);
3287
+ v({ attribute: !1 })
3288
+ ], z.prototype, "store", 1);
3196
3289
  Z([
3197
- x({ attribute: !1 })
3198
- ], L.prototype, "toolRegistry", 2);
3290
+ v({ attribute: !1 })
3291
+ ], z.prototype, "toolRegistry", 2);
3199
3292
  Z([
3200
3293
  E()
3201
- ], L.prototype, "quickAddIndex", 2);
3294
+ ], z.prototype, "quickAddIndex", 2);
3202
3295
  Z([
3203
3296
  E()
3204
- ], L.prototype, "quickAddPos", 2);
3205
- L = Z([
3297
+ ], z.prototype, "quickAddPos", 2);
3298
+ z = Z([
3206
3299
  S("me-editor-canvas")
3207
- ], L);
3208
- var Ut = Object.defineProperty, qt = Object.getOwnPropertyDescriptor, Oe = (e, t, o, r) => {
3300
+ ], z);
3301
+ var Ut = Object.defineProperty, qt = Object.getOwnPropertyDescriptor, je = (e, t, o, r) => {
3209
3302
  for (var i = r > 1 ? void 0 : r ? qt(t, o) : t, n = e.length - 1, s; n >= 0; n--)
3210
3303
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
3211
3304
  return r && i && Ut(t, o, i), i;
@@ -3365,10 +3458,10 @@ K.styles = _`
3365
3458
  50% { box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.2); }
3366
3459
  }
3367
3460
  `;
3368
- Oe([
3369
- x({ attribute: !1 })
3461
+ je([
3462
+ v({ attribute: !1 })
3370
3463
  ], K.prototype, "store", 1);
3371
- K = Oe([
3464
+ K = je([
3372
3465
  S("me-body-settings")
3373
3466
  ], K);
3374
3467
  var Nt = Object.defineProperty, Gt = Object.getOwnPropertyDescriptor, le = (e, t, o, r) => {
@@ -3376,7 +3469,7 @@ var Nt = Object.defineProperty, Gt = Object.getOwnPropertyDescriptor, le = (e, t
3376
3469
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
3377
3470
  return r && i && Nt(t, o, i), i;
3378
3471
  };
3379
- const ze = {
3472
+ const Le = {
3380
3473
  text: { label: "Text", tools: ["text", "heading", "paragraph"] },
3381
3474
  media: { label: "Media", tools: ["image", "video"] },
3382
3475
  actions: { label: "Actions", tools: ["button", "social", "menu"] },
@@ -3432,10 +3525,10 @@ let H = class extends T {
3432
3525
  for (const l of e) o.set(l.name, l);
3433
3526
  const r = (l) => !t || l.label.toLowerCase().includes(t) || l.name.toLowerCase().includes(t);
3434
3527
  let i = !1;
3435
- const n = Object.entries(ze).map(([, l]) => {
3528
+ const n = Object.entries(Le).map(([, l]) => {
3436
3529
  const u = l.tools.map((h) => o.get(h)).filter((h) => !!h && r(h));
3437
3530
  return u.length > 0 && (i = !0), { label: l.label, tools: u };
3438
- }), s = new Set(Object.values(ze).flatMap((l) => l.tools)), a = e.filter((l) => !s.has(l.name) && r(l));
3531
+ }), s = new Set(Object.values(Le).flatMap((l) => l.tools)), a = e.filter((l) => !s.has(l.name) && r(l));
3439
3532
  a.length > 0 && (i = !0);
3440
3533
  const c = !t || "layout".includes(t) || "row".includes(t) || "column".includes(t);
3441
3534
  return d`
@@ -3451,7 +3544,7 @@ let H = class extends T {
3451
3544
  </div>
3452
3545
  <div class="tab-content">
3453
3546
  ${n.map(
3454
- (l) => l.tools.length === 0 ? v : d`
3547
+ (l) => l.tools.length === 0 ? x : d`
3455
3548
  <div class="category">
3456
3549
  <div class="category-title">${l.label}</div>
3457
3550
  <div class="tool-grid">
@@ -3489,7 +3582,7 @@ let H = class extends T {
3489
3582
  }
3490
3583
  renderA11yBadge() {
3491
3584
  const { errors: e, warnings: t, infos: o } = this.getA11ySeverities();
3492
- return !e && !t && !o ? v : d`<span class="tab-badge">${e ? d`<span class="tab-dot error"></span>` : v}${t ? d`<span class="tab-dot warning"></span>` : v}${o ? d`<span class="tab-dot info"></span>` : v}</span>`;
3585
+ return !e && !t && !o ? x : d`<span class="tab-badge">${e ? d`<span class="tab-dot error"></span>` : x}${t ? d`<span class="tab-dot warning"></span>` : x}${o ? d`<span class="tab-dot info"></span>` : x}</span>`;
3493
3586
  }
3494
3587
  renderToolItem(e) {
3495
3588
  return d`
@@ -3579,6 +3672,11 @@ H.styles = _`
3579
3672
  padding: 0 12px 16px;
3580
3673
  flex: 1;
3581
3674
  overflow-y: auto;
3675
+ animation: tabFadeIn 0.2s ease-out;
3676
+ }
3677
+ @keyframes tabFadeIn {
3678
+ from { opacity: 0; transform: translateY(4px); }
3679
+ to { opacity: 1; transform: translateY(0); }
3582
3680
  }
3583
3681
 
3584
3682
  /* ── Category groups ── */
@@ -3674,10 +3772,10 @@ H.styles = _`
3674
3772
  }
3675
3773
  `;
3676
3774
  le([
3677
- x({ attribute: !1 })
3775
+ v({ attribute: !1 })
3678
3776
  ], H.prototype, "store", 1);
3679
3777
  le([
3680
- x({ attribute: !1 })
3778
+ v({ attribute: !1 })
3681
3779
  ], H.prototype, "toolRegistry", 2);
3682
3780
  le([
3683
3781
  E()
@@ -3685,7 +3783,7 @@ le([
3685
3783
  H = le([
3686
3784
  S("me-editor-sidebar")
3687
3785
  ], H);
3688
- function Qt(e, t, o) {
3786
+ function Yt(e, t, o) {
3689
3787
  const r = e && /^#[0-9a-fA-F]{3,8}$/.test(e) ? e : "#000000";
3690
3788
  return d`
3691
3789
  <div class="prop-row">
@@ -3699,7 +3797,7 @@ function Qt(e, t, o) {
3699
3797
  </div>
3700
3798
  `;
3701
3799
  }
3702
- function Yt(e, t, o, r) {
3800
+ function Qt(e, t, o, r) {
3703
3801
  const i = r?.options || [];
3704
3802
  return d`
3705
3803
  <div class="prop-row">
@@ -3810,10 +3908,41 @@ function ro(e, t, o, r) {
3810
3908
  </div>
3811
3909
  `;
3812
3910
  }
3813
- var io = Object.defineProperty, no = Object.getOwnPropertyDescriptor, we = (e, t, o, r) => {
3814
- for (var i = r > 1 ? void 0 : r ? no(t, o) : t, n = e.length - 1, s; n >= 0; n--)
3911
+ function io(e, t, o, r) {
3912
+ const i = () => {
3913
+ r && r({
3914
+ done: (n) => {
3915
+ n?.url && t(n.url);
3916
+ }
3917
+ });
3918
+ };
3919
+ return d`
3920
+ <div class="prop-row">
3921
+ <label class="prop-label">${o}</label>
3922
+ ${e ? d`
3923
+ <div style="margin-bottom:6px;border-radius:6px;overflow:hidden;border:1px solid var(--me-grey-200,#e5e7eb);background:var(--me-grey-50,#f9fafb);">
3924
+ <img src=${e} alt="Preview" style="display:block;width:100%;max-height:120px;object-fit:cover;" />
3925
+ </div>
3926
+ ` : x}
3927
+ <div style="display:flex;gap:4px;">
3928
+ <input class="prop-input" type="text" .value=${e ?? ""} placeholder="https://..."
3929
+ style="flex:1;${r ? "border-radius:8px 0 0 8px;" : ""}"
3930
+ @change=${(n) => t(n.target.value)} />
3931
+ ${r ? d`
3932
+ <button @click=${i}
3933
+ style="padding:0 10px;border:1px solid var(--me-grey-200,#e5e7eb);border-left:none;border-radius:0 8px 8px 0;background:var(--me-grey-50,#f9fafb);cursor:pointer;color:var(--me-grey-600,#4b5563);font-size:11px;font-weight:600;transition:all 150ms ease;white-space:nowrap;"
3934
+ title="Upload image">
3935
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:middle;"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
3936
+ </button>
3937
+ ` : x}
3938
+ </div>
3939
+ </div>
3940
+ `;
3941
+ }
3942
+ var no = Object.defineProperty, so = Object.getOwnPropertyDescriptor, we = (e, t, o, r) => {
3943
+ for (var i = r > 1 ? void 0 : r ? so(t, o) : t, n = e.length - 1, s; n >= 0; n--)
3815
3944
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
3816
- return r && i && io(t, o, i), i;
3945
+ return r && i && no(t, o, i), i;
3817
3946
  };
3818
3947
  let q = class extends T {
3819
3948
  constructor() {
@@ -3861,19 +3990,21 @@ let q = class extends T {
3861
3990
  const r = e.values[t] ?? o.defaultValue, i = this.onChange(e.id, t);
3862
3991
  switch (o.widget) {
3863
3992
  case "color_picker":
3864
- return Qt(r, i, o.label);
3993
+ return Yt(r, i, o.label);
3865
3994
  case "toggle":
3866
3995
  return eo(r, i, o.label);
3867
3996
  case "rich_text":
3868
3997
  return oo(r, i, o.label);
3869
3998
  case "dropdown":
3870
- return Yt(r, i, o.label, o.widgetParams);
3999
+ return Qt(r, i, o.label, o.widgetParams);
3871
4000
  case "alignment":
3872
4001
  return Kt(r, i, o.label);
3873
4002
  case "padding":
3874
4003
  return Zt(r, i, o.label);
3875
4004
  case "number_unit":
3876
4005
  return ro(r, i, o.label, o.widgetParams);
4006
+ case "image_upload":
4007
+ return io(r, i, o.label, this.store.getCallback("image"));
3877
4008
  case "text":
3878
4009
  default:
3879
4010
  return to(r, i, o.label);
@@ -3959,27 +4090,29 @@ q.styles = _`
3959
4090
  .color-swatch:hover { border-color: var(--me-primary); }
3960
4091
  `;
3961
4092
  we([
3962
- x({ attribute: !1 })
4093
+ v({ attribute: !1 })
3963
4094
  ], q.prototype, "store", 1);
3964
4095
  we([
3965
- x({ attribute: !1 })
4096
+ v({ attribute: !1 })
3966
4097
  ], q.prototype, "toolRegistry", 2);
3967
4098
  q = we([
3968
4099
  S("me-property-panel")
3969
4100
  ], q);
3970
- var so = Object.defineProperty, ao = Object.getOwnPropertyDescriptor, Q = (e, t, o, r) => {
3971
- for (var i = r > 1 ? void 0 : r ? ao(t, o) : t, n = e.length - 1, s; n >= 0; n--)
4101
+ var ao = Object.defineProperty, lo = Object.getOwnPropertyDescriptor, Y = (e, t, o, r) => {
4102
+ for (var i = r > 1 ? void 0 : r ? lo(t, o) : t, n = e.length - 1, s; n >= 0; n--)
3972
4103
  (s = e[n]) && (i = (r ? s(t, o, i) : s(i)) || i);
3973
- return r && i && so(t, o, i), i;
4104
+ return r && i && ao(t, o, i), i;
3974
4105
  };
3975
4106
  let P = class extends T {
3976
4107
  constructor() {
3977
4108
  super(...arguments), this.options = {}, this.store = new Ze(), this.toolRegistry = new et(), this.dragManager = null, this.callbacks = /* @__PURE__ */ new Map(), this.unsubscribe = null, this.sidebarCollapsed = !1, this.a11yHasErrors = !1, this.a11yHasWarnings = !1, this.a11yHasInfos = !1, this.a11yDebounceTimer = null, this._handleKeydown = (e) => {
3978
- const t = e.metaKey || e.ctrlKey, r = e.composedPath().some((i) => {
3979
- const n = i, s = n?.tagName;
3980
- return !!(s === "INPUT" || s === "TEXTAREA" || s === "SELECT" || n?.isContentEditable);
4109
+ const t = e.metaKey || e.ctrlKey, r = e.composedPath().some((n) => {
4110
+ const s = n, a = s?.tagName;
4111
+ return !!(a === "INPUT" || a === "TEXTAREA" || a === "SELECT" || s?.isContentEditable);
3981
4112
  });
3982
- r && !t || (t && e.key === "z" && !e.shiftKey ? (e.preventDefault(), this.store.undo()) : t && (e.key === "y" || e.key === "z" && e.shiftKey) ? (e.preventDefault(), this.store.redo()) : (e.key === "Delete" || e.key === "Backspace") && this.store.selectedId && !r ? (e.preventDefault(), this.store.removeContent(this.store.selectedId)) : e.key === "Escape" && this.store.select(null));
4113
+ if (r && !t) return;
4114
+ const i = this.shadowRoot?.querySelector("me-editor-canvas");
4115
+ t && e.key === "z" && !e.shiftKey ? (e.preventDefault(), this.store.undo(), i?.flashUndo?.()) : t && (e.key === "y" || e.key === "z" && e.shiftKey) ? (e.preventDefault(), this.store.redo(), i?.flashUndo?.()) : t && e.key === "d" && !e.shiftKey && this.store.selectedId && !r ? (e.preventDefault(), this.store.duplicateContent(this.store.selectedId)) : (e.key === "Delete" || e.key === "Backspace") && this.store.selectedId && !r ? (e.preventDefault(), this.store.removeContent(this.store.selectedId)) : e.key === "Escape" && this.store.select(null);
3983
4116
  };
3984
4117
  }
3985
4118
  updateA11yState() {
@@ -4051,7 +4184,7 @@ let P = class extends T {
4051
4184
  registerTab(e) {
4052
4185
  }
4053
4186
  registerCallback(e, t) {
4054
- this.callbacks.set(e, t);
4187
+ this.callbacks.set(e, t), this.store.setCallback(e, t);
4055
4188
  }
4056
4189
  setMergeTags(e) {
4057
4190
  this.store.setMergeTags(e);
@@ -4106,11 +4239,11 @@ let P = class extends T {
4106
4239
  </button>
4107
4240
  ${this.sidebarCollapsed && (this.a11yHasErrors || this.a11yHasWarnings || this.a11yHasInfos) ? d`
4108
4241
  <div class="a11y-dots">
4109
- ${this.a11yHasErrors ? d`<div class="a11y-dot error"></div>` : v}
4110
- ${this.a11yHasWarnings ? d`<div class="a11y-dot warning"></div>` : v}
4111
- ${this.a11yHasInfos ? d`<div class="a11y-dot info"></div>` : v}
4242
+ ${this.a11yHasErrors ? d`<div class="a11y-dot error"></div>` : x}
4243
+ ${this.a11yHasWarnings ? d`<div class="a11y-dot warning"></div>` : x}
4244
+ ${this.a11yHasInfos ? d`<div class="a11y-dot info"></div>` : x}
4112
4245
  </div>
4113
- ` : v}
4246
+ ` : x}
4114
4247
  <me-editor-canvas
4115
4248
  .store=${this.store}
4116
4249
  .toolRegistry=${this.toolRegistry}
@@ -4257,47 +4390,47 @@ P.styles = _`
4257
4390
  40% { opacity: 0.9; transform: scale(1.05); }
4258
4391
  }
4259
4392
  `;
4260
- Q([
4261
- x({ type: Object })
4393
+ Y([
4394
+ v({ type: Object })
4262
4395
  ], P.prototype, "options", 2);
4263
- Q([
4396
+ Y([
4264
4397
  E()
4265
4398
  ], P.prototype, "sidebarCollapsed", 2);
4266
- Q([
4399
+ Y([
4267
4400
  E()
4268
4401
  ], P.prototype, "a11yHasErrors", 2);
4269
- Q([
4402
+ Y([
4270
4403
  E()
4271
4404
  ], P.prototype, "a11yHasWarnings", 2);
4272
- Q([
4405
+ Y([
4273
4406
  E()
4274
4407
  ], P.prototype, "a11yHasInfos", 2);
4275
- P = Q([
4408
+ P = Y([
4276
4409
  S("mail-editor")
4277
4410
  ], P);
4278
4411
  function R(e, t) {
4279
4412
  customElements.get(e) || customElements.define(e, t);
4280
4413
  }
4281
4414
  R("mail-editor", P);
4282
- R("me-editor-canvas", L);
4283
- R("me-row-renderer", j);
4284
- R("me-column-renderer", z);
4415
+ R("me-editor-canvas", z);
4416
+ R("me-row-renderer", O);
4417
+ R("me-column-renderer", L);
4285
4418
  R("me-content-renderer", M);
4286
4419
  R("me-editor-sidebar", H);
4287
4420
  R("me-body-settings", K);
4288
4421
  R("me-property-panel", q);
4289
- R("me-inline-toolbar", O);
4422
+ R("me-inline-toolbar", j);
4290
4423
  R("me-a11y-checker", U);
4291
- const bo = customElements.get("mail-editor") !== void 0;
4424
+ const mo = customElements.get("mail-editor") !== void 0;
4292
4425
  export {
4293
- bo as E,
4426
+ mo as E,
4294
4427
  P as M,
4295
4428
  et as T,
4296
4429
  Ze as a,
4297
4430
  N as e,
4298
4431
  Pt as f,
4299
- fo as j,
4432
+ bo as j,
4300
4433
  p as s,
4301
4434
  Et as t
4302
4435
  };
4303
- //# sourceMappingURL=index-zy5NbC2E.js.map
4436
+ //# sourceMappingURL=index-2S5kBS5_.js.map