@kontakto/email-template-editor 2.0.0 → 2.2.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.
package/dist/index.cjs CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  var DOMPurify = require('dompurify');
4
4
  var marked = require('marked');
5
- var React60 = require('react');
5
+ var React58 = require('react');
6
6
  var zod = require('zod');
7
7
  var server = require('react-dom/server');
8
8
  var styles = require('@mui/material/styles');
@@ -18,7 +18,7 @@ var htmlfy = require('htmlfy');
18
18
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
19
19
 
20
20
  var DOMPurify__default = /*#__PURE__*/_interopDefault(DOMPurify);
21
- var React60__default = /*#__PURE__*/_interopDefault(React60);
21
+ var React58__default = /*#__PURE__*/_interopDefault(React58);
22
22
  var hljs__default = /*#__PURE__*/_interopDefault(hljs);
23
23
  var jsonHighlighter__default = /*#__PURE__*/_interopDefault(jsonHighlighter);
24
24
  var xmlHighlighter__default = /*#__PURE__*/_interopDefault(xmlHighlighter);
@@ -166,10 +166,24 @@ function renderMarkdownString(str) {
166
166
  }
167
167
  return sanitizer(html2);
168
168
  }
169
+ function renderInlineMarkdownString(str) {
170
+ const html2 = marked.marked.parseInline(str, {
171
+ async: false,
172
+ breaks: true,
173
+ gfm: true,
174
+ pedantic: false,
175
+ silent: false,
176
+ renderer: new CustomRenderer()
177
+ });
178
+ if (typeof html2 !== "string") {
179
+ throw new Error("marked.parseInline did not return a string");
180
+ }
181
+ return sanitizer(html2);
182
+ }
169
183
  function EmailMarkdown(_a) {
170
184
  var _b = _a, { markdown } = _b, props = __objRest(_b, ["markdown"]);
171
- const data = React60.useMemo(() => renderMarkdownString(markdown), [markdown]);
172
- return /* @__PURE__ */ React60__default.default.createElement("div", __spreadProps(__spreadValues({}, props), { dangerouslySetInnerHTML: { __html: data } }));
185
+ const data = React58.useMemo(() => renderMarkdownString(markdown), [markdown]);
186
+ return /* @__PURE__ */ React58__default.default.createElement("div", __spreadProps(__spreadValues({}, props), { dangerouslySetInnerHTML: { __html: data } }));
173
187
  }
174
188
  var FONT_FAMILY_SCHEMA = zod.z.enum([
175
189
  "MODERN_SANS",
@@ -220,6 +234,8 @@ var TextPropsSchema = zod.z.object({
220
234
  fontSize: zod.z.number().gte(0).optional().nullable(),
221
235
  fontFamily: FONT_FAMILY_SCHEMA,
222
236
  fontWeight: zod.z.enum(["bold", "normal"]).optional().nullable(),
237
+ lineHeight: zod.z.number().gte(0).optional().nullable(),
238
+ letterSpacing: zod.z.number().optional().nullable(),
223
239
  textAlign: zod.z.enum(["left", "center", "right"]).optional().nullable(),
224
240
  padding: PADDING_SCHEMA
225
241
  }).optional().nullable(),
@@ -233,21 +249,23 @@ var TextPropsDefaults = {
233
249
  text: ""
234
250
  };
235
251
  function Text({ style, props }) {
236
- var _a, _b, _c, _d, _e, _f;
252
+ var _a, _b, _c, _d, _e, _f, _g;
237
253
  const wStyle = {
238
254
  color: (_a = style == null ? void 0 : style.color) != null ? _a : void 0,
239
255
  backgroundColor: (_b = style == null ? void 0 : style.backgroundColor) != null ? _b : void 0,
240
256
  fontSize: (_c = style == null ? void 0 : style.fontSize) != null ? _c : void 0,
241
257
  fontFamily: getFontFamily(style == null ? void 0 : style.fontFamily),
242
258
  fontWeight: (_d = style == null ? void 0 : style.fontWeight) != null ? _d : void 0,
243
- textAlign: (_e = style == null ? void 0 : style.textAlign) != null ? _e : void 0,
259
+ lineHeight: (_e = style == null ? void 0 : style.lineHeight) != null ? _e : void 0,
260
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
261
+ textAlign: (_f = style == null ? void 0 : style.textAlign) != null ? _f : void 0,
244
262
  padding: getPadding(style == null ? void 0 : style.padding)
245
263
  };
246
- const text = (_f = props == null ? void 0 : props.text) != null ? _f : TextPropsDefaults.text;
264
+ const text = (_g = props == null ? void 0 : props.text) != null ? _g : TextPropsDefaults.text;
247
265
  if (props == null ? void 0 : props.markdown) {
248
- return /* @__PURE__ */ React60__default.default.createElement(EmailMarkdown, { style: wStyle, markdown: text });
266
+ return /* @__PURE__ */ React58__default.default.createElement(EmailMarkdown, { style: wStyle, markdown: text });
249
267
  }
250
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wStyle }, text);
268
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wStyle }, text);
251
269
  }
252
270
  var PADDING_SCHEMA2 = zod.z.object({
253
271
  top: zod.z.number(),
@@ -296,7 +314,7 @@ function Avatar({ style, props }) {
296
314
  textAlign: (_e = style == null ? void 0 : style.textAlign) != null ? _e : void 0,
297
315
  padding: getPadding2(style == null ? void 0 : style.padding)
298
316
  };
299
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React60__default.default.createElement(
317
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React58__default.default.createElement(
300
318
  "img",
301
319
  {
302
320
  alt,
@@ -368,6 +386,8 @@ var ButtonPropsSchema = zod.z.object({
368
386
  fontSize: zod.z.number().min(0).optional().nullable(),
369
387
  fontFamily: FONT_FAMILY_SCHEMA2,
370
388
  fontWeight: zod.z.enum(["bold", "normal"]).optional().nullable(),
389
+ lineHeight: zod.z.number().gte(0).optional().nullable(),
390
+ letterSpacing: zod.z.number().optional().nullable(),
371
391
  textAlign: zod.z.enum(["left", "center", "right"]).optional().nullable(),
372
392
  padding: PADDING_SCHEMA3
373
393
  }).optional().nullable(),
@@ -420,7 +440,7 @@ var ButtonPropsDefaults = {
420
440
  buttonBackgroundColor: "#999999"
421
441
  };
422
442
  function Button({ style, props }) {
423
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
443
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
424
444
  const text = (_a = props == null ? void 0 : props.text) != null ? _a : ButtonPropsDefaults.text;
425
445
  const url = (_b = props == null ? void 0 : props.url) != null ? _b : ButtonPropsDefaults.url;
426
446
  const fullWidth = (_c = props == null ? void 0 : props.fullWidth) != null ? _c : ButtonPropsDefaults.fullWidth;
@@ -438,20 +458,22 @@ function Button({ style, props }) {
438
458
  fontSize: (_h = style == null ? void 0 : style.fontSize) != null ? _h : 16,
439
459
  fontFamily: getFontFamily2(style == null ? void 0 : style.fontFamily),
440
460
  fontWeight: (_i = style == null ? void 0 : style.fontWeight) != null ? _i : "bold",
461
+ lineHeight: (_j = style == null ? void 0 : style.lineHeight) != null ? _j : void 0,
462
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
441
463
  backgroundColor: buttonBackgroundColor,
442
464
  borderRadius: getRoundedCorners(props),
443
465
  display: fullWidth ? "block" : "inline-block",
444
466
  padding: `${padding[0]}px ${padding[1]}px`,
445
467
  textDecoration: "none"
446
468
  };
447
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React60__default.default.createElement("a", { href: url, style: linkStyle, target: "_blank" }, /* @__PURE__ */ React60__default.default.createElement(
469
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React58__default.default.createElement("a", { href: url, style: linkStyle, target: "_blank" }, /* @__PURE__ */ React58__default.default.createElement(
448
470
  "span",
449
471
  {
450
472
  dangerouslySetInnerHTML: {
451
473
  __html: `<!--[if mso]><i style="letter-spacing: ${padding[1]}px;mso-font-width:-100%;mso-text-raise:${textRaise}" hidden>&nbsp;</i><![endif]-->`
452
474
  }
453
475
  }
454
- ), /* @__PURE__ */ React60__default.default.createElement("span", null, text), /* @__PURE__ */ React60__default.default.createElement(
476
+ ), /* @__PURE__ */ React58__default.default.createElement("span", null, text), /* @__PURE__ */ React58__default.default.createElement(
455
477
  "span",
456
478
  {
457
479
  dangerouslySetInnerHTML: {
@@ -500,7 +522,7 @@ function ColumnsContainer({ style, columns, props }) {
500
522
  contentAlignment: (_d = props == null ? void 0 : props.contentAlignment) != null ? _d : ColumnsContainerPropsDefaults.contentAlignment,
501
523
  fixedWidths: props == null ? void 0 : props.fixedWidths
502
524
  };
503
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wStyle }, /* @__PURE__ */ React60__default.default.createElement(
525
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wStyle }, /* @__PURE__ */ React58__default.default.createElement(
504
526
  "table",
505
527
  {
506
528
  align: "center",
@@ -509,7 +531,7 @@ function ColumnsContainer({ style, columns, props }) {
509
531
  border: 0,
510
532
  style: { tableLayout: "fixed", borderCollapse: "collapse" }
511
533
  },
512
- /* @__PURE__ */ React60__default.default.createElement("tbody", { style: { width: "100%" } }, /* @__PURE__ */ React60__default.default.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React60__default.default.createElement(TableCell, { index: 0, props: blockProps, columns }), /* @__PURE__ */ React60__default.default.createElement(TableCell, { index: 1, props: blockProps, columns }), /* @__PURE__ */ React60__default.default.createElement(TableCell, { index: 2, props: blockProps, columns })))
534
+ /* @__PURE__ */ React58__default.default.createElement("tbody", { style: { width: "100%" } }, /* @__PURE__ */ React58__default.default.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React58__default.default.createElement(TableCell, { index: 0, props: blockProps, columns }), /* @__PURE__ */ React58__default.default.createElement(TableCell, { index: 1, props: blockProps, columns }), /* @__PURE__ */ React58__default.default.createElement(TableCell, { index: 2, props: blockProps, columns })))
513
535
  ));
514
536
  }
515
537
  function TableCell({ index, props, columns }) {
@@ -527,7 +549,7 @@ function TableCell({ index, props, columns }) {
527
549
  width: (_d = (_c = props.fixedWidths) == null ? void 0 : _c[index]) != null ? _d : void 0
528
550
  };
529
551
  const children = (_e = columns && columns[index]) != null ? _e : null;
530
- return /* @__PURE__ */ React60__default.default.createElement("td", { style }, children);
552
+ return /* @__PURE__ */ React58__default.default.createElement("td", { style }, children);
531
553
  }
532
554
  function getPaddingBefore(index, { columnsGap, columnsCount }) {
533
555
  if (index === 0) {
@@ -589,9 +611,9 @@ function Container({ style, children }) {
589
611
  padding: getPadding5(style == null ? void 0 : style.padding)
590
612
  };
591
613
  if (!children) {
592
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wStyle });
614
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wStyle });
593
615
  }
594
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wStyle }, children);
616
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wStyle }, children);
595
617
  }
596
618
  var container_default = Container;
597
619
  var COLOR_SCHEMA5 = zod.z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
@@ -625,7 +647,7 @@ function Divider({ style, props }) {
625
647
  };
626
648
  const borderTopWidth = (_b = props == null ? void 0 : props.lineHeight) != null ? _b : DividerPropsDefaults.lineHeight;
627
649
  const borderTopColor = (_c = props == null ? void 0 : props.lineColor) != null ? _c : DividerPropsDefaults.lineColor;
628
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: st }, /* @__PURE__ */ React60__default.default.createElement(
650
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: st }, /* @__PURE__ */ React58__default.default.createElement(
629
651
  "hr",
630
652
  {
631
653
  style: {
@@ -683,13 +705,16 @@ function getFontFamily3(fontFamily) {
683
705
  var HeadingPropsSchema = zod.z.object({
684
706
  props: zod.z.object({
685
707
  text: zod.z.string().optional().nullable(),
686
- level: zod.z.enum(["h1", "h2", "h3"]).optional().nullable()
708
+ level: zod.z.enum(["h1", "h2", "h3"]).optional().nullable(),
709
+ markdown: zod.z.boolean().optional().nullable()
687
710
  }).optional().nullable(),
688
711
  style: zod.z.object({
689
712
  color: COLOR_SCHEMA6,
690
713
  backgroundColor: COLOR_SCHEMA6,
691
714
  fontFamily: FONT_FAMILY_SCHEMA3,
692
715
  fontWeight: zod.z.enum(["bold", "normal"]).optional().nullable(),
716
+ lineHeight: zod.z.number().gte(0).optional().nullable(),
717
+ letterSpacing: zod.z.number().optional().nullable(),
693
718
  textAlign: zod.z.enum(["left", "center", "right"]).optional().nullable(),
694
719
  padding: PADDING_SCHEMA7
695
720
  }).optional().nullable()
@@ -700,26 +725,31 @@ var HeadingPropsDefaults = {
700
725
  text: ""
701
726
  };
702
727
  function Heading({ props, style }) {
703
- var _a, _b, _c, _d, _e, _f;
728
+ var _a, _b, _c, _d, _e, _f, _g, _h;
704
729
  const level = (_a = props == null ? void 0 : props.level) != null ? _a : HeadingPropsDefaults.level;
705
730
  const text = (_b = props == null ? void 0 : props.text) != null ? _b : HeadingPropsDefaults.text;
731
+ const isMarkdown = (_c = props == null ? void 0 : props.markdown) != null ? _c : false;
706
732
  const hStyle = {
707
- color: (_c = style == null ? void 0 : style.color) != null ? _c : void 0,
708
- backgroundColor: (_d = style == null ? void 0 : style.backgroundColor) != null ? _d : void 0,
709
- fontWeight: (_e = style == null ? void 0 : style.fontWeight) != null ? _e : "bold",
710
- textAlign: (_f = style == null ? void 0 : style.textAlign) != null ? _f : void 0,
733
+ color: (_d = style == null ? void 0 : style.color) != null ? _d : void 0,
734
+ backgroundColor: (_e = style == null ? void 0 : style.backgroundColor) != null ? _e : void 0,
735
+ fontWeight: (_f = style == null ? void 0 : style.fontWeight) != null ? _f : "bold",
736
+ lineHeight: (_g = style == null ? void 0 : style.lineHeight) != null ? _g : void 0,
737
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
738
+ textAlign: (_h = style == null ? void 0 : style.textAlign) != null ? _h : void 0,
711
739
  margin: 0,
712
740
  fontFamily: getFontFamily3(style == null ? void 0 : style.fontFamily),
713
741
  fontSize: getFontSize(level),
714
742
  padding: getPadding7(style == null ? void 0 : style.padding)
715
743
  };
744
+ const html2 = React58.useMemo(() => isMarkdown ? renderInlineMarkdownString(text) : null, [isMarkdown, text]);
745
+ const renderProps = isMarkdown ? { style: hStyle, dangerouslySetInnerHTML: { __html: html2 != null ? html2 : "" } } : { style: hStyle, children: text };
716
746
  switch (level) {
717
747
  case "h1":
718
- return /* @__PURE__ */ React60__default.default.createElement("h1", { style: hStyle }, text);
748
+ return /* @__PURE__ */ React58__default.default.createElement("h1", __spreadValues({}, renderProps));
719
749
  case "h2":
720
- return /* @__PURE__ */ React60__default.default.createElement("h2", { style: hStyle }, text);
750
+ return /* @__PURE__ */ React58__default.default.createElement("h2", __spreadValues({}, renderProps));
721
751
  case "h3":
722
- return /* @__PURE__ */ React60__default.default.createElement("h3", { style: hStyle }, text);
752
+ return /* @__PURE__ */ React58__default.default.createElement("h3", __spreadValues({}, renderProps));
723
753
  }
724
754
  }
725
755
  function getFontSize(level) {
@@ -801,9 +831,9 @@ function Html({ style, props }) {
801
831
  padding: getPadding8(style == null ? void 0 : style.padding)
802
832
  };
803
833
  if (!children) {
804
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: cssStyle });
834
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: cssStyle });
805
835
  }
806
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: children } });
836
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: children } });
807
837
  }
808
838
  var html_default = Html;
809
839
  var PADDING_SCHEMA9 = zod.z.object({
@@ -839,7 +869,7 @@ function Image({ style, props }) {
839
869
  const linkHref = (_c = props == null ? void 0 : props.linkHref) != null ? _c : null;
840
870
  const width = (_d = props == null ? void 0 : props.width) != null ? _d : void 0;
841
871
  const height = (_e = props == null ? void 0 : props.height) != null ? _e : void 0;
842
- const imageElement = /* @__PURE__ */ React60__default.default.createElement(
872
+ const imageElement = /* @__PURE__ */ React58__default.default.createElement(
843
873
  "img",
844
874
  {
845
875
  alt: (_f = props == null ? void 0 : props.alt) != null ? _f : "",
@@ -859,9 +889,9 @@ function Image({ style, props }) {
859
889
  }
860
890
  );
861
891
  if (!linkHref) {
862
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: sectionStyle }, imageElement);
892
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: sectionStyle }, imageElement);
863
893
  }
864
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React60__default.default.createElement("a", { href: linkHref, style: { textDecoration: "none" }, target: "_blank" }, imageElement));
894
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React58__default.default.createElement("a", { href: linkHref, style: { textDecoration: "none" }, target: "_blank" }, imageElement));
865
895
  }
866
896
  var image_default = Image;
867
897
  var FONT_FAMILY_SCHEMA5 = zod.z.enum([
@@ -1007,7 +1037,7 @@ function Signature({ style, props }) {
1007
1037
  color: linkColor,
1008
1038
  textDecoration: "none"
1009
1039
  };
1010
- const imageElement = imageUrl ? /* @__PURE__ */ React60__default.default.createElement(
1040
+ const imageElement = imageUrl ? /* @__PURE__ */ React58__default.default.createElement(
1011
1041
  "img",
1012
1042
  {
1013
1043
  src: imageUrl,
@@ -1026,18 +1056,18 @@ function Signature({ style, props }) {
1026
1056
  }
1027
1057
  ) : null;
1028
1058
  const contactParts = [];
1029
- if (email) contactParts.push(/* @__PURE__ */ React60__default.default.createElement("a", { key: "email", href: `mailto:${email}`, style: linkStyle }, email));
1030
- if (phone) contactParts.push(/* @__PURE__ */ React60__default.default.createElement("a", { key: "phone", href: `tel:${phone}`, style: linkStyle }, phone));
1059
+ if (email) contactParts.push(/* @__PURE__ */ React58__default.default.createElement("a", { key: "email", href: `mailto:${email}`, style: linkStyle }, email));
1060
+ if (phone) contactParts.push(/* @__PURE__ */ React58__default.default.createElement("a", { key: "phone", href: `tel:${phone}`, style: linkStyle }, phone));
1031
1061
  if (website) {
1032
1062
  const href = website.startsWith("http") ? website : `https://${website}`;
1033
- contactParts.push(/* @__PURE__ */ React60__default.default.createElement("a", { key: "website", href, style: linkStyle, target: "_blank" }, website));
1063
+ contactParts.push(/* @__PURE__ */ React58__default.default.createElement("a", { key: "website", href, style: linkStyle, target: "_blank" }, website));
1034
1064
  }
1035
- const textContent = /* @__PURE__ */ React60__default.default.createElement("div", null, name && /* @__PURE__ */ React60__default.default.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, address), contactParts.length > 0 && /* @__PURE__ */ React60__default.default.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, contactParts.map((part, i) => /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, { key: i }, i > 0 && /* @__PURE__ */ React60__default.default.createElement("span", { style: detailStyle }, " \xB7 "), part))));
1036
- const greetingElement = greeting ? /* @__PURE__ */ React60__default.default.createElement("p", { style: greetingStyle }, greeting) : null;
1065
+ const textContent = /* @__PURE__ */ React58__default.default.createElement("div", null, name && /* @__PURE__ */ React58__default.default.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, address), contactParts.length > 0 && /* @__PURE__ */ React58__default.default.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, contactParts.map((part, i) => /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, { key: i }, i > 0 && /* @__PURE__ */ React58__default.default.createElement("span", { style: detailStyle }, " \xB7 "), part))));
1066
+ const greetingElement = greeting ? /* @__PURE__ */ React58__default.default.createElement("p", { style: greetingStyle }, greeting) : null;
1037
1067
  if (layout === "vertical") {
1038
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React60__default.default.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
1068
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React58__default.default.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
1039
1069
  }
1040
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React60__default.default.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React60__default.default.createElement("tbody", null, /* @__PURE__ */ React60__default.default.createElement("tr", null, imageElement && /* @__PURE__ */ React60__default.default.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React60__default.default.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
1070
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React58__default.default.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React58__default.default.createElement("tbody", null, /* @__PURE__ */ React58__default.default.createElement("tr", null, imageElement && /* @__PURE__ */ React58__default.default.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React58__default.default.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
1041
1071
  }
1042
1072
  var signature_default = Signature;
1043
1073
  var SpacerPropsSchema = zod.z.object({
@@ -1054,13 +1084,13 @@ function Spacer({ props }) {
1054
1084
  const style = {
1055
1085
  height: (_a = props == null ? void 0 : props.height) != null ? _a : SpacerPropsDefaults.height
1056
1086
  };
1057
- return /* @__PURE__ */ React60__default.default.createElement("div", { style });
1087
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style });
1058
1088
  }
1059
1089
  var spacer_default = Spacer;
1060
1090
  function buildBlockComponent(blocks) {
1061
1091
  return function BlockComponent({ type, data }) {
1062
1092
  const Component = blocks[type].Component;
1063
- return /* @__PURE__ */ React60__default.default.createElement(Component, __spreadValues({}, data));
1093
+ return /* @__PURE__ */ React58__default.default.createElement(Component, __spreadValues({}, data));
1064
1094
  };
1065
1095
  }
1066
1096
  function buildBlockConfigurationSchema(blocks) {
@@ -1097,9 +1127,9 @@ function ColumnsContainerReader({ style, props }) {
1097
1127
  const _a = props != null ? props : {}, { columns } = _a, restProps = __objRest(_a, ["columns"]);
1098
1128
  let cols = void 0;
1099
1129
  if (columns) {
1100
- cols = columns.map((col) => col.childrenIds.map((childId) => /* @__PURE__ */ React60__default.default.createElement(ReaderBlock, { key: childId, id: childId })));
1130
+ cols = columns.map((col) => col.childrenIds.map((childId) => /* @__PURE__ */ React58__default.default.createElement(ReaderBlock, { key: childId, id: childId })));
1101
1131
  }
1102
- return /* @__PURE__ */ React60__default.default.createElement(columns_container_default, { props: restProps, columns: cols, style });
1132
+ return /* @__PURE__ */ React58__default.default.createElement(columns_container_default, { props: restProps, columns: cols, style });
1103
1133
  }
1104
1134
  var ContainerPropsSchema2 = zod.z.object({
1105
1135
  style: ContainerPropsSchema.shape.style,
@@ -1110,7 +1140,7 @@ var ContainerPropsSchema2 = zod.z.object({
1110
1140
  function ContainerReader({ style, props }) {
1111
1141
  var _a;
1112
1142
  const childrenIds = (_a = props == null ? void 0 : props.childrenIds) != null ? _a : [];
1113
- return /* @__PURE__ */ React60__default.default.createElement(container_default, { style }, childrenIds.map((childId) => /* @__PURE__ */ React60__default.default.createElement(ReaderBlock, { key: childId, id: childId })));
1143
+ return /* @__PURE__ */ React58__default.default.createElement(container_default, { style }, childrenIds.map((childId) => /* @__PURE__ */ React58__default.default.createElement(ReaderBlock, { key: childId, id: childId })));
1114
1144
  }
1115
1145
  var COLOR_SCHEMA9 = zod.z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
1116
1146
  var FONT_FAMILY_SCHEMA6 = zod.z.enum([
@@ -1126,7 +1156,8 @@ var FONT_FAMILY_SCHEMA6 = zod.z.enum([
1126
1156
  ]).nullable().optional();
1127
1157
  var TemplateVariableSchema = zod.z.object({
1128
1158
  name: zod.z.string(),
1129
- description: zod.z.string().optional().nullable()
1159
+ description: zod.z.string().optional().nullable(),
1160
+ sampleValue: zod.z.string().optional().nullable()
1130
1161
  });
1131
1162
  var EmailLayoutPropsSchema = zod.z.object({
1132
1163
  backdropColor: COLOR_SCHEMA9,
@@ -1182,9 +1213,9 @@ function EmailLayoutReader(props) {
1182
1213
  margin: "0"
1183
1214
  };
1184
1215
  if (props.backdropDisabled) {
1185
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: baseStyle }, childrenIds.map((childId) => /* @__PURE__ */ React60__default.default.createElement(ReaderBlock, { key: childId, id: childId })));
1216
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: baseStyle }, childrenIds.map((childId) => /* @__PURE__ */ React58__default.default.createElement(ReaderBlock, { key: childId, id: childId })));
1186
1217
  }
1187
- return /* @__PURE__ */ React60__default.default.createElement(
1218
+ return /* @__PURE__ */ React58__default.default.createElement(
1188
1219
  "div",
1189
1220
  {
1190
1221
  style: __spreadProps(__spreadValues({}, baseStyle), {
@@ -1194,7 +1225,7 @@ function EmailLayoutReader(props) {
1194
1225
  width: "100%"
1195
1226
  })
1196
1227
  },
1197
- /* @__PURE__ */ React60__default.default.createElement(
1228
+ /* @__PURE__ */ React58__default.default.createElement(
1198
1229
  "table",
1199
1230
  {
1200
1231
  align: "center",
@@ -1212,19 +1243,19 @@ function EmailLayoutReader(props) {
1212
1243
  cellPadding: "0",
1213
1244
  border: 0
1214
1245
  },
1215
- /* @__PURE__ */ React60__default.default.createElement("tbody", null, /* @__PURE__ */ React60__default.default.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React60__default.default.createElement("td", null, childrenIds.map((childId) => /* @__PURE__ */ React60__default.default.createElement(ReaderBlock, { key: childId, id: childId })))))
1246
+ /* @__PURE__ */ React58__default.default.createElement("tbody", null, /* @__PURE__ */ React58__default.default.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React58__default.default.createElement("td", null, childrenIds.map((childId) => /* @__PURE__ */ React58__default.default.createElement(ReaderBlock, { key: childId, id: childId })))))
1216
1247
  )
1217
1248
  );
1218
1249
  }
1219
1250
 
1220
1251
  // src/email-builder/reader/core.tsx
1221
- var ReaderContext = React60.createContext({});
1252
+ var ReaderContext = React58.createContext({});
1222
1253
  function useReaderDocument() {
1223
- return React60.useContext(ReaderContext);
1254
+ return React58.useContext(ReaderContext);
1224
1255
  }
1225
1256
  function ReaderBlock({ id }) {
1226
1257
  const document2 = useReaderDocument();
1227
- return document2[id] ? /* @__PURE__ */ React60__default.default.createElement(BaseReaderBlock, __spreadValues({}, document2[id])) : null;
1258
+ return document2[id] ? /* @__PURE__ */ React58__default.default.createElement(BaseReaderBlock, __spreadValues({}, document2[id])) : null;
1228
1259
  }
1229
1260
  var READER_DICTIONARY = buildBlockConfigurationDictionary({
1230
1261
  ColumnsContainer: {
@@ -1281,13 +1312,13 @@ var ReaderBlockSchema = buildBlockConfigurationSchema(READER_DICTIONARY);
1281
1312
  var ReaderDocumentSchema = zod.z.record(zod.z.string(), ReaderBlockSchema);
1282
1313
  var BaseReaderBlock = buildBlockComponent(READER_DICTIONARY);
1283
1314
  function Reader({ document: document2, rootBlockId }) {
1284
- return /* @__PURE__ */ React60__default.default.createElement(ReaderContext.Provider, { value: document2 }, /* @__PURE__ */ React60__default.default.createElement(ReaderBlock, { id: rootBlockId }));
1315
+ return /* @__PURE__ */ React58__default.default.createElement(ReaderContext.Provider, { value: document2 }, /* @__PURE__ */ React58__default.default.createElement(ReaderBlock, { id: rootBlockId }));
1285
1316
  }
1286
1317
 
1287
1318
  // src/email-builder/renderers/render-to-static-markup.tsx
1288
1319
  function renderToStaticMarkup(document2, { rootBlockId }) {
1289
1320
  return "<!DOCTYPE html>" + server.renderToStaticMarkup(
1290
- /* @__PURE__ */ React60__default.default.createElement("html", null, /* @__PURE__ */ React60__default.default.createElement("body", null, /* @__PURE__ */ React60__default.default.createElement(Reader, { document: document2, rootBlockId })))
1321
+ /* @__PURE__ */ React58__default.default.createElement("html", null, /* @__PURE__ */ React58__default.default.createElement("body", null, /* @__PURE__ */ React58__default.default.createElement(Reader, { document: document2, rootBlockId })))
1291
1322
  );
1292
1323
  }
1293
1324
 
@@ -1955,7 +1986,8 @@ var editorStateStore = zustand.create(() => ({
1955
1986
  selectedScreenSize: "desktop",
1956
1987
  inspectorDrawerOpen: true,
1957
1988
  samplesDrawerOpen: true,
1958
- persistenceEnabled: false
1989
+ persistenceEnabled: false,
1990
+ lastFocusedEditable: null
1959
1991
  }));
1960
1992
  function useDocument() {
1961
1993
  return editorStateStore((s) => s.document);
@@ -2028,6 +2060,15 @@ function setSelectedScreenSize(selectedScreenSize) {
2028
2060
  function setPersistenceEnabled(persistenceEnabled) {
2029
2061
  return editorStateStore.setState({ persistenceEnabled });
2030
2062
  }
2063
+ function useLastFocusedEditable() {
2064
+ return editorStateStore((s) => s.lastFocusedEditable);
2065
+ }
2066
+ function getLastFocusedEditable() {
2067
+ return editorStateStore.getState().lastFocusedEditable;
2068
+ }
2069
+ function setLastFocusedEditable(lastFocusedEditable) {
2070
+ return editorStateStore.setState({ lastFocusedEditable });
2071
+ }
2031
2072
 
2032
2073
  // src/app/save-payload.ts
2033
2074
  var ROOT_BLOCK_ID = "root";
@@ -2045,20 +2086,20 @@ function buildSavePayload(doc) {
2045
2086
  }
2046
2087
 
2047
2088
  // src/app/context.tsx
2048
- var EmailEditorContext = React60.createContext(null);
2089
+ var EmailEditorContext = React58.createContext(null);
2049
2090
  var EmailEditorProvider = ({
2050
2091
  children,
2051
2092
  initialTemplateId = null,
2052
2093
  initialTemplateName = null,
2053
2094
  onSave
2054
2095
  }) => {
2055
- const [currentTemplateId, setCurrentTemplateId] = React60.useState(initialTemplateId);
2056
- const [currentTemplateName, setCurrentTemplateName] = React60.useState(initialTemplateName);
2057
- const [currentTemplateKind, setCurrentTemplateKind] = React60.useState(null);
2058
- const saveListenersRef = React60.useRef([]);
2059
- const onSaveRef = React60.useRef(onSave);
2096
+ const [currentTemplateId, setCurrentTemplateId] = React58.useState(initialTemplateId);
2097
+ const [currentTemplateName, setCurrentTemplateName] = React58.useState(initialTemplateName);
2098
+ const [currentTemplateKind, setCurrentTemplateKind] = React58.useState(null);
2099
+ const saveListenersRef = React58.useRef([]);
2100
+ const onSaveRef = React58.useRef(onSave);
2060
2101
  onSaveRef.current = onSave;
2061
- const saveTemplate = React60.useCallback(() => {
2102
+ const saveTemplate = React58.useCallback(() => {
2062
2103
  const currentDoc = getDocument();
2063
2104
  saveListenersRef.current.forEach((listener) => listener(currentDoc));
2064
2105
  if (onSaveRef.current) {
@@ -2066,7 +2107,7 @@ var EmailEditorProvider = ({
2066
2107
  }
2067
2108
  return currentDoc;
2068
2109
  }, []);
2069
- const loadTemplate = React60.useCallback((newTemplate, templateId, templateName, kind) => {
2110
+ const loadTemplate = React58.useCallback((newTemplate, templateId, templateName, kind) => {
2070
2111
  if (templateId !== void 0) {
2071
2112
  setCurrentTemplateId(templateId);
2072
2113
  }
@@ -2077,20 +2118,20 @@ var EmailEditorProvider = ({
2077
2118
  setCurrentTemplateKind(kind);
2078
2119
  }
2079
2120
  }, []);
2080
- const setCurrentTemplate = React60.useCallback((templateId, templateName, kind) => {
2121
+ const setCurrentTemplate = React58.useCallback((templateId, templateName, kind) => {
2081
2122
  setCurrentTemplateId(templateId);
2082
2123
  setCurrentTemplateName(templateName);
2083
2124
  if (kind !== void 0) {
2084
2125
  setCurrentTemplateKind(kind);
2085
2126
  }
2086
2127
  }, []);
2087
- const registerSaveListener = React60.useCallback((callback) => {
2128
+ const registerSaveListener = React58.useCallback((callback) => {
2088
2129
  saveListenersRef.current = [...saveListenersRef.current, callback];
2089
2130
  return () => {
2090
2131
  saveListenersRef.current = saveListenersRef.current.filter((listener) => listener !== callback);
2091
2132
  };
2092
2133
  }, []);
2093
- const value = React60.useMemo(() => ({
2134
+ const value = React58.useMemo(() => ({
2094
2135
  currentTemplateId,
2095
2136
  currentTemplateName,
2096
2137
  currentTemplateKind,
@@ -2099,24 +2140,34 @@ var EmailEditorProvider = ({
2099
2140
  registerSaveListener,
2100
2141
  setCurrentTemplate
2101
2142
  }), [currentTemplateId, currentTemplateName, currentTemplateKind, saveTemplate, loadTemplate, registerSaveListener, setCurrentTemplate]);
2102
- return /* @__PURE__ */ React60__default.default.createElement(EmailEditorContext.Provider, { value }, children);
2143
+ return /* @__PURE__ */ React58__default.default.createElement(EmailEditorContext.Provider, { value }, children);
2103
2144
  };
2104
2145
  var useEmailEditor = () => {
2105
- const context = React60.useContext(EmailEditorContext);
2146
+ const context = React58.useContext(EmailEditorContext);
2106
2147
  if (!context) {
2107
2148
  throw new Error("useEmailEditor must be used within an EmailEditorProvider");
2108
2149
  }
2109
2150
  return context;
2110
2151
  };
2152
+ var ImageCallbacksContext = React58.createContext({});
2153
+ function ImageCallbacksProvider({
2154
+ callbacks,
2155
+ children
2156
+ }) {
2157
+ return /* @__PURE__ */ React58__default.default.createElement(ImageCallbacksContext.Provider, { value: callbacks }, children);
2158
+ }
2159
+ function useImageCallbacks() {
2160
+ return React58.useContext(ImageCallbacksContext);
2161
+ }
2111
2162
  function BaseSidebarPanel({ title, children }) {
2112
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { p: 2 }, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 } }, title), /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 5, mb: 3 }, children));
2163
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { p: 2 }, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 } }, title), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 5, mb: 3 }, children));
2113
2164
  }
2114
2165
  function RadioGroupInput({ label, children, defaultValue, onChange }) {
2115
- const [value, setValue] = React60.useState(defaultValue);
2116
- React60.useEffect(() => {
2166
+ const [value, setValue] = React58.useState(defaultValue);
2167
+ React58.useEffect(() => {
2117
2168
  setValue(defaultValue);
2118
2169
  }, [defaultValue]);
2119
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React60__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React60__default.default.createElement(
2170
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React58__default.default.createElement(
2120
2171
  material.ToggleButtonGroup,
2121
2172
  {
2122
2173
  exclusive: true,
@@ -2136,7 +2187,7 @@ function RadioGroupInput({ label, children, defaultValue, onChange }) {
2136
2187
  }
2137
2188
  function RawSliderInput(_a) {
2138
2189
  var _b = _a, { iconLabel, value, setValue, units } = _b, props = __objRest(_b, ["iconLabel", "value", "setValue", "units"]);
2139
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", spacing: 2, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { minWidth: 24, lineHeight: 1, flexShrink: 0 } }, iconLabel), /* @__PURE__ */ React60__default.default.createElement(
2190
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", spacing: 2, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { minWidth: 24, lineHeight: 1, flexShrink: 0 } }, iconLabel), /* @__PURE__ */ React58__default.default.createElement(
2140
2191
  material.Slider,
2141
2192
  __spreadProps(__spreadValues({}, props), {
2142
2193
  value,
@@ -2147,14 +2198,14 @@ function RawSliderInput(_a) {
2147
2198
  setValue(value2);
2148
2199
  }
2149
2200
  })
2150
- ), /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { minWidth: 32, textAlign: "right", flexShrink: 0 } }, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "body2", color: "text.secondary", sx: { lineHeight: 1 } }, value, units)));
2201
+ ), /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { minWidth: 32, textAlign: "right", flexShrink: 0 } }, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2", color: "text.secondary", sx: { lineHeight: 1 } }, value, units)));
2151
2202
  }
2152
2203
 
2153
2204
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/slider-input.tsx
2154
2205
  function SliderInput(_a) {
2155
2206
  var _b = _a, { label, defaultValue, onChange } = _b, props = __objRest(_b, ["label", "defaultValue", "onChange"]);
2156
- const [value, setValue] = React60.useState(defaultValue);
2157
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React60__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React60__default.default.createElement(
2207
+ const [value, setValue] = React58.useState(defaultValue);
2208
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React58__default.default.createElement(
2158
2209
  RawSliderInput,
2159
2210
  __spreadValues({
2160
2211
  value,
@@ -2166,12 +2217,12 @@ function SliderInput(_a) {
2166
2217
  ));
2167
2218
  }
2168
2219
  function TextInput({ helperText, label, placeholder, rows, InputProps: InputProps2, defaultValue, onChange }) {
2169
- const [value, setValue] = React60.useState(defaultValue);
2220
+ const [value, setValue] = React58.useState(defaultValue);
2170
2221
  const isMultiline = typeof rows === "number" && rows > 1;
2171
- React60.useEffect(() => {
2222
+ React58.useEffect(() => {
2172
2223
  setValue(defaultValue);
2173
2224
  }, [defaultValue]);
2174
- return /* @__PURE__ */ React60__default.default.createElement(
2225
+ return /* @__PURE__ */ React58__default.default.createElement(
2175
2226
  material.TextField,
2176
2227
  {
2177
2228
  fullWidth: true,
@@ -2197,7 +2248,7 @@ var TILE_BUTTON = {
2197
2248
  };
2198
2249
  function Swatch({ paletteColors, value, onChange }) {
2199
2250
  const renderButton2 = (colorValue) => {
2200
- return /* @__PURE__ */ React60__default.default.createElement(
2251
+ return /* @__PURE__ */ React58__default.default.createElement(
2201
2252
  material.Button,
2202
2253
  {
2203
2254
  key: colorValue,
@@ -2216,7 +2267,7 @@ function Swatch({ paletteColors, value, onChange }) {
2216
2267
  }
2217
2268
  );
2218
2269
  };
2219
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { width: "100%", sx: { display: "grid", gap: 1, gridTemplateColumns: "1fr 1fr 1fr 1fr 1fr 1fr" } }, paletteColors.map((c) => renderButton2(c)));
2270
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { width: "100%", sx: { display: "grid", gap: 1, gridTemplateColumns: "1fr 1fr 1fr 1fr 1fr 1fr" } }, paletteColors.map((c) => renderButton2(c)));
2220
2271
  }
2221
2272
 
2222
2273
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/color-input/picker.tsx
@@ -2283,7 +2334,7 @@ var SX = {
2283
2334
  }
2284
2335
  };
2285
2336
  function Picker({ value, onChange }) {
2286
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 1, sx: SX }, /* @__PURE__ */ React60__default.default.createElement(reactColorful.HexColorPicker, { color: value, onChange }), /* @__PURE__ */ React60__default.default.createElement(Swatch, { paletteColors: DEFAULT_PRESET_COLORS, value, onChange }), /* @__PURE__ */ React60__default.default.createElement(material.Box, { pt: 1 }, /* @__PURE__ */ React60__default.default.createElement(reactColorful.HexColorInput, { prefixed: true, color: value, onChange })));
2337
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 1, sx: SX }, /* @__PURE__ */ React58__default.default.createElement(reactColorful.HexColorPicker, { color: value, onChange }), /* @__PURE__ */ React58__default.default.createElement(Swatch, { paletteColors: DEFAULT_PRESET_COLORS, value, onChange }), /* @__PURE__ */ React58__default.default.createElement(material.Box, { pt: 1 }, /* @__PURE__ */ React58__default.default.createElement(reactColorful.HexColorInput, { prefixed: true, color: value, onChange })));
2287
2338
  }
2288
2339
 
2289
2340
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/color-input/base-color-input.tsx
@@ -2296,8 +2347,8 @@ var BUTTON_SX = {
2296
2347
  bgcolor: "#FFFFFF"
2297
2348
  };
2298
2349
  function ColorInput({ label, defaultValue, onChange, nullable }) {
2299
- const [anchorEl, setAnchorEl] = React60.useState(null);
2300
- const [value, setValue] = React60.useState(defaultValue);
2350
+ const [anchorEl, setAnchorEl] = React58.useState(null);
2351
+ const [value, setValue] = React58.useState(defaultValue);
2301
2352
  const handleClickOpen = (event) => {
2302
2353
  setAnchorEl(event.currentTarget);
2303
2354
  };
@@ -2308,7 +2359,7 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2308
2359
  if (typeof value !== "string" || value.trim().length === 0) {
2309
2360
  return null;
2310
2361
  }
2311
- return /* @__PURE__ */ React60__default.default.createElement(
2362
+ return /* @__PURE__ */ React58__default.default.createElement(
2312
2363
  material.ButtonBase,
2313
2364
  {
2314
2365
  onClick: () => {
@@ -2316,16 +2367,16 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2316
2367
  onChange(null);
2317
2368
  }
2318
2369
  },
2319
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.CloseOutlined, { fontSize: "small", sx: { color: "grey.600" } })
2370
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.CloseOutlined, { fontSize: "small", sx: { color: "grey.600" } })
2320
2371
  );
2321
2372
  };
2322
2373
  const renderOpenButton = () => {
2323
2374
  if (value) {
2324
- return /* @__PURE__ */ React60__default.default.createElement(material.ButtonBase, { onClick: handleClickOpen, sx: __spreadProps(__spreadValues({}, BUTTON_SX), { bgcolor: value }) });
2375
+ return /* @__PURE__ */ React58__default.default.createElement(material.ButtonBase, { onClick: handleClickOpen, sx: __spreadProps(__spreadValues({}, BUTTON_SX), { bgcolor: value }) });
2325
2376
  }
2326
- return /* @__PURE__ */ React60__default.default.createElement(material.ButtonBase, { onClick: handleClickOpen, sx: __spreadValues({}, BUTTON_SX) }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" }));
2377
+ return /* @__PURE__ */ React58__default.default.createElement(material.ButtonBase, { onClick: handleClickOpen, sx: __spreadValues({}, BUTTON_SX) }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" }));
2327
2378
  };
2328
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React60__default.default.createElement(material.InputLabel, { sx: { mb: 0.5 } }, label), /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 1 }, renderOpenButton(), renderResetButton()), /* @__PURE__ */ React60__default.default.createElement(
2379
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { sx: { mb: 0.5 } }, label), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 1 }, renderOpenButton(), renderResetButton()), /* @__PURE__ */ React58__default.default.createElement(
2329
2380
  material.Menu,
2330
2381
  {
2331
2382
  anchorEl,
@@ -2335,7 +2386,7 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2335
2386
  sx: { height: "auto", padding: 0 }
2336
2387
  }
2337
2388
  },
2338
- /* @__PURE__ */ React60__default.default.createElement(
2389
+ /* @__PURE__ */ React58__default.default.createElement(
2339
2390
  Picker,
2340
2391
  {
2341
2392
  value: value || "",
@@ -2350,10 +2401,10 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2350
2401
 
2351
2402
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/color-input/index.tsx
2352
2403
  function ColorInput2(props) {
2353
- return /* @__PURE__ */ React60__default.default.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: false }));
2404
+ return /* @__PURE__ */ React58__default.default.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: false }));
2354
2405
  }
2355
2406
  function NullableColorInput(props) {
2356
- return /* @__PURE__ */ React60__default.default.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: true }));
2407
+ return /* @__PURE__ */ React58__default.default.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: true }));
2357
2408
  }
2358
2409
 
2359
2410
  // src/editor/blocks/helpers/font-family.ts
@@ -2406,13 +2457,13 @@ var FONT_FAMILIES = [
2406
2457
  ];
2407
2458
 
2408
2459
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/font-family.tsx
2409
- var OPTIONS = FONT_FAMILIES.map((option) => /* @__PURE__ */ React60__default.default.createElement(material.MenuItem, { key: option.key, value: option.key, sx: { fontFamily: option.value } }, option.label));
2460
+ var OPTIONS = FONT_FAMILIES.map((option) => /* @__PURE__ */ React58__default.default.createElement(material.MenuItem, { key: option.key, value: option.key, sx: { fontFamily: option.value } }, option.label));
2410
2461
  function NullableFontFamily({ label, onChange, defaultValue }) {
2411
- const [value, setValue] = React60.useState(defaultValue != null ? defaultValue : "inherit");
2412
- React60.useEffect(() => {
2462
+ const [value, setValue] = React58.useState(defaultValue != null ? defaultValue : "inherit");
2463
+ React58.useEffect(() => {
2413
2464
  setValue(defaultValue != null ? defaultValue : "inherit");
2414
2465
  }, [defaultValue]);
2415
- return /* @__PURE__ */ React60__default.default.createElement(
2466
+ return /* @__PURE__ */ React58__default.default.createElement(
2416
2467
  material.TextField,
2417
2468
  {
2418
2469
  select: true,
@@ -2425,23 +2476,23 @@ function NullableFontFamily({ label, onChange, defaultValue }) {
2425
2476
  onChange(v === null ? null : v);
2426
2477
  }
2427
2478
  },
2428
- /* @__PURE__ */ React60__default.default.createElement(material.MenuItem, { value: "inherit" }, "Match email settings"),
2479
+ /* @__PURE__ */ React58__default.default.createElement(material.MenuItem, { value: "inherit" }, "Match email settings"),
2429
2480
  OPTIONS
2430
2481
  );
2431
2482
  }
2432
2483
  function FontSizeInput({ label, defaultValue, onChange }) {
2433
- const [value, setValue] = React60.useState(defaultValue);
2434
- React60.useEffect(() => {
2484
+ const [value, setValue] = React58.useState(defaultValue);
2485
+ React58.useEffect(() => {
2435
2486
  setValue(defaultValue);
2436
2487
  }, [defaultValue]);
2437
2488
  const handleChange = (value2) => {
2438
2489
  setValue(value2);
2439
2490
  onChange(value2);
2440
2491
  };
2441
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React60__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React60__default.default.createElement(
2492
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React58__default.default.createElement(
2442
2493
  RawSliderInput,
2443
2494
  {
2444
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.TextFieldsOutlined, { sx: { fontSize: 16 } }),
2495
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.TextFieldsOutlined, { sx: { fontSize: 16 } }),
2445
2496
  value,
2446
2497
  setValue: handleChange,
2447
2498
  units: "px",
@@ -2452,11 +2503,11 @@ function FontSizeInput({ label, defaultValue, onChange }) {
2452
2503
  ));
2453
2504
  }
2454
2505
  function FontWeightInput({ label, defaultValue, onChange }) {
2455
- const [value, setValue] = React60.useState(defaultValue);
2456
- React60.useEffect(() => {
2506
+ const [value, setValue] = React58.useState(defaultValue);
2507
+ React58.useEffect(() => {
2457
2508
  setValue(defaultValue);
2458
2509
  }, [defaultValue]);
2459
- return /* @__PURE__ */ React60__default.default.createElement(
2510
+ return /* @__PURE__ */ React58__default.default.createElement(
2460
2511
  RadioGroupInput,
2461
2512
  {
2462
2513
  label,
@@ -2466,12 +2517,56 @@ function FontWeightInput({ label, defaultValue, onChange }) {
2466
2517
  onChange(fontWeight);
2467
2518
  }
2468
2519
  },
2469
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "normal" }, "Regular"),
2470
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "bold" }, "Bold")
2520
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "normal" }, "Regular"),
2521
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "bold" }, "Bold")
2471
2522
  );
2472
2523
  }
2524
+ function LetterSpacingInput({ label, defaultValue, onChange }) {
2525
+ const [value, setValue] = React58.useState(defaultValue != null ? defaultValue : 0);
2526
+ React58.useEffect(() => {
2527
+ setValue(defaultValue != null ? defaultValue : 0);
2528
+ }, [defaultValue]);
2529
+ const handleChange = (v) => {
2530
+ setValue(v);
2531
+ onChange(v === 0 ? null : v);
2532
+ };
2533
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React58__default.default.createElement(
2534
+ RawSliderInput,
2535
+ {
2536
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SpaceBarOutlined, { sx: { fontSize: 16 } }),
2537
+ value,
2538
+ setValue: handleChange,
2539
+ units: "px",
2540
+ step: 0.1,
2541
+ min: 0,
2542
+ max: 2
2543
+ }
2544
+ ));
2545
+ }
2546
+ function LineHeightInput({ label, defaultValue, onChange }) {
2547
+ const [value, setValue] = React58.useState(defaultValue != null ? defaultValue : 0);
2548
+ React58.useEffect(() => {
2549
+ setValue(defaultValue != null ? defaultValue : 0);
2550
+ }, [defaultValue]);
2551
+ const handleChange = (v) => {
2552
+ setValue(v);
2553
+ onChange(v === 0 ? null : v);
2554
+ };
2555
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React58__default.default.createElement(
2556
+ RawSliderInput,
2557
+ {
2558
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FormatLineSpacingOutlined, { sx: { fontSize: 16 } }),
2559
+ value,
2560
+ setValue: handleChange,
2561
+ units: "",
2562
+ step: 0.1,
2563
+ min: 0,
2564
+ max: 2
2565
+ }
2566
+ ));
2567
+ }
2473
2568
  function PaddingInput({ label, defaultValue, onChange }) {
2474
- const [value, setValue] = React60.useState(() => {
2569
+ const [value, setValue] = React58.useState(() => {
2475
2570
  if (defaultValue) {
2476
2571
  return defaultValue;
2477
2572
  }
@@ -2489,10 +2584,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2489
2584
  setValue(v);
2490
2585
  onChange(v);
2491
2586
  }
2492
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 2, alignItems: "flex-start", pb: 1 }, /* @__PURE__ */ React60__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React60__default.default.createElement(
2587
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 2, alignItems: "flex-start", pb: 1 }, /* @__PURE__ */ React58__default.default.createElement(material.InputLabel, { shrink: true }, label), /* @__PURE__ */ React58__default.default.createElement(
2493
2588
  RawSliderInput,
2494
2589
  {
2495
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AlignVerticalTopOutlined, { sx: { fontSize: 16 } }),
2590
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AlignVerticalTopOutlined, { sx: { fontSize: 16 } }),
2496
2591
  value: value.top,
2497
2592
  setValue: (num) => handleChange("top", num),
2498
2593
  units: "px",
@@ -2501,10 +2596,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2501
2596
  max: 80,
2502
2597
  marks: true
2503
2598
  }
2504
- ), /* @__PURE__ */ React60__default.default.createElement(
2599
+ ), /* @__PURE__ */ React58__default.default.createElement(
2505
2600
  RawSliderInput,
2506
2601
  {
2507
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AlignVerticalBottomOutlined, { sx: { fontSize: 16 } }),
2602
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AlignVerticalBottomOutlined, { sx: { fontSize: 16 } }),
2508
2603
  value: value.bottom,
2509
2604
  setValue: (num) => handleChange("bottom", num),
2510
2605
  units: "px",
@@ -2513,10 +2608,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2513
2608
  max: 80,
2514
2609
  marks: true
2515
2610
  }
2516
- ), /* @__PURE__ */ React60__default.default.createElement(
2611
+ ), /* @__PURE__ */ React58__default.default.createElement(
2517
2612
  RawSliderInput,
2518
2613
  {
2519
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AlignHorizontalLeftOutlined, { sx: { fontSize: 16 } }),
2614
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AlignHorizontalLeftOutlined, { sx: { fontSize: 16 } }),
2520
2615
  value: value.left,
2521
2616
  setValue: (num) => handleChange("left", num),
2522
2617
  units: "px",
@@ -2525,10 +2620,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2525
2620
  max: 80,
2526
2621
  marks: true
2527
2622
  }
2528
- ), /* @__PURE__ */ React60__default.default.createElement(
2623
+ ), /* @__PURE__ */ React58__default.default.createElement(
2529
2624
  RawSliderInput,
2530
2625
  {
2531
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AlignHorizontalRightOutlined, { sx: { fontSize: 16 } }),
2626
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AlignHorizontalRightOutlined, { sx: { fontSize: 16 } }),
2532
2627
  value: value.right,
2533
2628
  setValue: (num) => handleChange("right", num),
2534
2629
  units: "px",
@@ -2540,11 +2635,11 @@ function PaddingInput({ label, defaultValue, onChange }) {
2540
2635
  ));
2541
2636
  }
2542
2637
  function TextAlignInput({ label, defaultValue, onChange }) {
2543
- const [value, setValue] = React60.useState(defaultValue != null ? defaultValue : "left");
2544
- React60.useEffect(() => {
2638
+ const [value, setValue] = React58.useState(defaultValue != null ? defaultValue : "left");
2639
+ React58.useEffect(() => {
2545
2640
  setValue(defaultValue != null ? defaultValue : "left");
2546
2641
  }, [defaultValue]);
2547
- return /* @__PURE__ */ React60__default.default.createElement(
2642
+ return /* @__PURE__ */ React58__default.default.createElement(
2548
2643
  RadioGroupInput,
2549
2644
  {
2550
2645
  label,
@@ -2554,9 +2649,9 @@ function TextAlignInput({ label, defaultValue, onChange }) {
2554
2649
  onChange(value2);
2555
2650
  }
2556
2651
  },
2557
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "left" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FormatAlignLeftOutlined, { fontSize: "small" })),
2558
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "center" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FormatAlignCenterOutlined, { fontSize: "small" })),
2559
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "right" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FormatAlignRightOutlined, { fontSize: "small" }))
2652
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "left" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FormatAlignLeftOutlined, { fontSize: "small" })),
2653
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "center" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FormatAlignCenterOutlined, { fontSize: "small" })),
2654
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "right" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FormatAlignRightOutlined, { fontSize: "small" }))
2560
2655
  );
2561
2656
  }
2562
2657
 
@@ -2569,14 +2664,14 @@ function SingleStylePropertyPanel({ name, value, onChange }) {
2569
2664
  };
2570
2665
  switch (name) {
2571
2666
  case "backgroundColor":
2572
- return /* @__PURE__ */ React60__default.default.createElement(NullableColorInput, { label: "Background color", defaultValue, onChange: handleChange });
2667
+ return /* @__PURE__ */ React58__default.default.createElement(NullableColorInput, { label: "Background color", defaultValue, onChange: handleChange });
2573
2668
  case "borderColor":
2574
- return /* @__PURE__ */ React60__default.default.createElement(NullableColorInput, { label: "Border color", defaultValue, onChange: handleChange });
2669
+ return /* @__PURE__ */ React58__default.default.createElement(NullableColorInput, { label: "Border color", defaultValue, onChange: handleChange });
2575
2670
  case "borderRadius":
2576
- return /* @__PURE__ */ React60__default.default.createElement(
2671
+ return /* @__PURE__ */ React58__default.default.createElement(
2577
2672
  SliderInput,
2578
2673
  {
2579
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.RoundedCornerOutlined, null),
2674
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.RoundedCornerOutlined, null),
2580
2675
  units: "px",
2581
2676
  step: 4,
2582
2677
  marks: true,
@@ -2588,29 +2683,33 @@ function SingleStylePropertyPanel({ name, value, onChange }) {
2588
2683
  }
2589
2684
  );
2590
2685
  case "color":
2591
- return /* @__PURE__ */ React60__default.default.createElement(NullableColorInput, { label: "Text color", defaultValue, onChange: handleChange });
2686
+ return /* @__PURE__ */ React58__default.default.createElement(NullableColorInput, { label: "Text color", defaultValue, onChange: handleChange });
2592
2687
  case "fontFamily":
2593
- return /* @__PURE__ */ React60__default.default.createElement(NullableFontFamily, { label: "Font family", defaultValue, onChange: handleChange });
2688
+ return /* @__PURE__ */ React58__default.default.createElement(NullableFontFamily, { label: "Font family", defaultValue, onChange: handleChange });
2594
2689
  case "fontSize":
2595
- return /* @__PURE__ */ React60__default.default.createElement(FontSizeInput, { label: "Font size", defaultValue, onChange: handleChange });
2690
+ return /* @__PURE__ */ React58__default.default.createElement(FontSizeInput, { label: "Font size", defaultValue, onChange: handleChange });
2596
2691
  case "fontWeight":
2597
- return /* @__PURE__ */ React60__default.default.createElement(FontWeightInput, { label: "Font weight", defaultValue, onChange: handleChange });
2692
+ return /* @__PURE__ */ React58__default.default.createElement(FontWeightInput, { label: "Font weight", defaultValue, onChange: handleChange });
2693
+ case "lineHeight":
2694
+ return /* @__PURE__ */ React58__default.default.createElement(LineHeightInput, { label: "Line height", defaultValue, onChange: handleChange });
2695
+ case "letterSpacing":
2696
+ return /* @__PURE__ */ React58__default.default.createElement(LetterSpacingInput, { label: "Letter spacing", defaultValue, onChange: handleChange });
2598
2697
  case "textAlign":
2599
- return /* @__PURE__ */ React60__default.default.createElement(TextAlignInput, { label: "Alignment", defaultValue, onChange: handleChange });
2698
+ return /* @__PURE__ */ React58__default.default.createElement(TextAlignInput, { label: "Alignment", defaultValue, onChange: handleChange });
2600
2699
  case "padding":
2601
- return /* @__PURE__ */ React60__default.default.createElement(PaddingInput, { label: "Padding", defaultValue, onChange: handleChange });
2700
+ return /* @__PURE__ */ React58__default.default.createElement(PaddingInput, { label: "Padding", defaultValue, onChange: handleChange });
2602
2701
  }
2603
2702
  }
2604
2703
 
2605
2704
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/style-inputs/multi-style-property-panel.tsx
2606
2705
  function MultiStylePropertyPanel({ names, value, onChange }) {
2607
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, names.map((name) => /* @__PURE__ */ React60__default.default.createElement(SingleStylePropertyPanel, { key: name, name, value: value || {}, onChange })));
2706
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, names.map((name) => /* @__PURE__ */ React58__default.default.createElement(SingleStylePropertyPanel, { key: name, name, value: value || {}, onChange })));
2608
2707
  }
2609
2708
 
2610
2709
  // src/app/inspector-drawer/configuration-panel/input-panels/avatar-sidebar-panel.tsx
2611
2710
  function AvatarSidebarPanel({ data, setData }) {
2612
2711
  var _a, _b, _c, _d, _e, _f, _g, _h;
2613
- const [, setErrors] = React60.useState(null);
2712
+ const [, setErrors] = React58.useState(null);
2614
2713
  const updateData = (d) => {
2615
2714
  const res = AvatarPropsSchema.safeParse(d);
2616
2715
  if (res.success) {
@@ -2624,11 +2723,11 @@ function AvatarSidebarPanel({ data, setData }) {
2624
2723
  const imageUrl = (_d = (_c = data.props) == null ? void 0 : _c.imageUrl) != null ? _d : AvatarPropsDefaults.imageUrl;
2625
2724
  const alt = (_f = (_e = data.props) == null ? void 0 : _e.alt) != null ? _f : AvatarPropsDefaults.alt;
2626
2725
  const shape = (_h = (_g = data.props) == null ? void 0 : _g.shape) != null ? _h : AvatarPropsDefaults.shape;
2627
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Avatar block" }, /* @__PURE__ */ React60__default.default.createElement(
2726
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Avatar block" }, /* @__PURE__ */ React58__default.default.createElement(
2628
2727
  SliderInput,
2629
2728
  {
2630
2729
  label: "Size",
2631
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AspectRatioOutlined, { sx: { color: "text.secondary" } }),
2730
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AspectRatioOutlined, { sx: { color: "text.secondary" } }),
2632
2731
  units: "px",
2633
2732
  step: 3,
2634
2733
  min: 32,
@@ -2638,7 +2737,7 @@ function AvatarSidebarPanel({ data, setData }) {
2638
2737
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { size: size2 }) }));
2639
2738
  }
2640
2739
  }
2641
- ), /* @__PURE__ */ React60__default.default.createElement(
2740
+ ), /* @__PURE__ */ React58__default.default.createElement(
2642
2741
  RadioGroupInput,
2643
2742
  {
2644
2743
  label: "Shape",
@@ -2647,10 +2746,10 @@ function AvatarSidebarPanel({ data, setData }) {
2647
2746
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { shape: shape2 }) }));
2648
2747
  }
2649
2748
  },
2650
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "circle" }, "Circle"),
2651
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "square" }, "Square"),
2652
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded")
2653
- ), /* @__PURE__ */ React60__default.default.createElement(
2749
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "circle" }, "Circle"),
2750
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "square" }, "Square"),
2751
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded")
2752
+ ), /* @__PURE__ */ React58__default.default.createElement(
2654
2753
  TextInput,
2655
2754
  {
2656
2755
  label: "Image URL",
@@ -2659,7 +2758,7 @@ function AvatarSidebarPanel({ data, setData }) {
2659
2758
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }));
2660
2759
  }
2661
2760
  }
2662
- ), /* @__PURE__ */ React60__default.default.createElement(
2761
+ ), /* @__PURE__ */ React58__default.default.createElement(
2663
2762
  TextInput,
2664
2763
  {
2665
2764
  label: "Alt text",
@@ -2668,7 +2767,7 @@ function AvatarSidebarPanel({ data, setData }) {
2668
2767
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt: alt2 }) }));
2669
2768
  }
2670
2769
  }
2671
- ), /* @__PURE__ */ React60__default.default.createElement(
2770
+ ), /* @__PURE__ */ React58__default.default.createElement(
2672
2771
  MultiStylePropertyPanel,
2673
2772
  {
2674
2773
  names: ["textAlign", "padding"],
@@ -2679,7 +2778,7 @@ function AvatarSidebarPanel({ data, setData }) {
2679
2778
  }
2680
2779
  function ButtonSidebarPanel({ data, setData }) {
2681
2780
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
2682
- const [, setErrors] = React60.useState(null);
2781
+ const [, setErrors] = React58.useState(null);
2683
2782
  const updateData = (d) => {
2684
2783
  const res = ButtonPropsSchema.safeParse(d);
2685
2784
  if (res.success) {
@@ -2696,68 +2795,77 @@ function ButtonSidebarPanel({ data, setData }) {
2696
2795
  const buttonStyle = (_j = (_i = data.props) == null ? void 0 : _i.buttonStyle) != null ? _j : ButtonPropsDefaults.buttonStyle;
2697
2796
  const buttonTextColor = (_l = (_k = data.props) == null ? void 0 : _k.buttonTextColor) != null ? _l : ButtonPropsDefaults.buttonTextColor;
2698
2797
  const buttonBackgroundColor = (_n = (_m = data.props) == null ? void 0 : _m.buttonBackgroundColor) != null ? _n : ButtonPropsDefaults.buttonBackgroundColor;
2699
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Button block" }, /* @__PURE__ */ React60__default.default.createElement(
2798
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Button block" }, /* @__PURE__ */ React58__default.default.createElement(
2700
2799
  TextInput,
2701
2800
  {
2702
2801
  label: "Text",
2703
2802
  defaultValue: text,
2704
2803
  onChange: (text2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text: text2 }) }))
2705
2804
  }
2706
- ), /* @__PURE__ */ React60__default.default.createElement(
2805
+ ), /* @__PURE__ */ React58__default.default.createElement(
2707
2806
  TextInput,
2708
2807
  {
2709
2808
  label: "Url",
2710
2809
  defaultValue: url,
2711
2810
  onChange: (url2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: url2 }) }))
2712
2811
  }
2713
- ), /* @__PURE__ */ React60__default.default.createElement(
2812
+ ), /* @__PURE__ */ React58__default.default.createElement(
2714
2813
  RadioGroupInput,
2715
2814
  {
2716
2815
  label: "Width",
2717
2816
  defaultValue: fullWidth ? "FULL_WIDTH" : "AUTO",
2718
2817
  onChange: (v) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { fullWidth: v === "FULL_WIDTH" }) }))
2719
2818
  },
2720
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "FULL_WIDTH" }, "Full"),
2721
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "AUTO" }, "Auto")
2722
- ), /* @__PURE__ */ React60__default.default.createElement(
2819
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "FULL_WIDTH" }, "Full"),
2820
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "AUTO" }, "Auto")
2821
+ ), /* @__PURE__ */ React58__default.default.createElement(
2723
2822
  RadioGroupInput,
2724
2823
  {
2725
2824
  label: "Size",
2726
2825
  defaultValue: size,
2727
2826
  onChange: (size2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { size: size2 }) }))
2728
2827
  },
2729
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "x-small" }, "Xs"),
2730
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "small" }, "Sm"),
2731
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "medium" }, "Md"),
2732
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "large" }, "Lg")
2733
- ), /* @__PURE__ */ React60__default.default.createElement(
2828
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "x-small" }, "Xs"),
2829
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "small" }, "Sm"),
2830
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "medium" }, "Md"),
2831
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "large" }, "Lg")
2832
+ ), /* @__PURE__ */ React58__default.default.createElement(
2734
2833
  RadioGroupInput,
2735
2834
  {
2736
2835
  label: "Style",
2737
2836
  defaultValue: buttonStyle,
2738
2837
  onChange: (buttonStyle2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonStyle: buttonStyle2 }) }))
2739
2838
  },
2740
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "rectangle" }, "Rectangle"),
2741
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded"),
2742
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "pill" }, "Pill")
2743
- ), /* @__PURE__ */ React60__default.default.createElement(
2839
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "rectangle" }, "Rectangle"),
2840
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded"),
2841
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "pill" }, "Pill")
2842
+ ), /* @__PURE__ */ React58__default.default.createElement(
2744
2843
  ColorInput2,
2745
2844
  {
2746
2845
  label: "Text color",
2747
2846
  defaultValue: buttonTextColor,
2748
2847
  onChange: (buttonTextColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonTextColor: buttonTextColor2 }) }))
2749
2848
  }
2750
- ), /* @__PURE__ */ React60__default.default.createElement(
2849
+ ), /* @__PURE__ */ React58__default.default.createElement(
2751
2850
  ColorInput2,
2752
2851
  {
2753
2852
  label: "Button color",
2754
2853
  defaultValue: buttonBackgroundColor,
2755
2854
  onChange: (buttonBackgroundColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonBackgroundColor: buttonBackgroundColor2 }) }))
2756
2855
  }
2757
- ), /* @__PURE__ */ React60__default.default.createElement(
2856
+ ), /* @__PURE__ */ React58__default.default.createElement(
2758
2857
  MultiStylePropertyPanel,
2759
2858
  {
2760
- names: ["backgroundColor", "fontFamily", "fontSize", "fontWeight", "textAlign", "padding"],
2859
+ names: [
2860
+ "backgroundColor",
2861
+ "fontFamily",
2862
+ "fontSize",
2863
+ "fontWeight",
2864
+ "lineHeight",
2865
+ "letterSpacing",
2866
+ "textAlign",
2867
+ "padding"
2868
+ ],
2761
2869
  value: data.style,
2762
2870
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
2763
2871
  }
@@ -2780,7 +2888,7 @@ function TextDimensionInput({ label, defaultValue, onChange }) {
2780
2888
  const value = parseInt(ev.target.value);
2781
2889
  onChange(isNaN(value) ? null : value);
2782
2890
  };
2783
- return /* @__PURE__ */ React60__default.default.createElement(
2891
+ return /* @__PURE__ */ React58__default.default.createElement(
2784
2892
  material.TextField,
2785
2893
  {
2786
2894
  fullWidth: true,
@@ -2791,7 +2899,7 @@ function TextDimensionInput({ label, defaultValue, onChange }) {
2791
2899
  placeholder: "auto",
2792
2900
  size: "small",
2793
2901
  InputProps: {
2794
- endAdornment: /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "body2", color: "text.secondary" }, "px")
2902
+ endAdornment: /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2", color: "text.secondary" }, "px")
2795
2903
  }
2796
2904
  }
2797
2905
  );
@@ -2799,7 +2907,7 @@ function TextDimensionInput({ label, defaultValue, onChange }) {
2799
2907
 
2800
2908
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/column-widths-input.tsx
2801
2909
  function ColumnWidthsInput({ defaultValue, onChange }) {
2802
- const [currentValue, setCurrentValue] = React60.useState(() => {
2910
+ const [currentValue, setCurrentValue] = React58.useState(() => {
2803
2911
  if (defaultValue) {
2804
2912
  return defaultValue;
2805
2913
  }
@@ -2813,7 +2921,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2813
2921
  };
2814
2922
  let column3 = null;
2815
2923
  {
2816
- column3 = /* @__PURE__ */ React60__default.default.createElement(
2924
+ column3 = /* @__PURE__ */ React58__default.default.createElement(
2817
2925
  TextDimensionInput,
2818
2926
  {
2819
2927
  label: "Column 3",
@@ -2824,7 +2932,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2824
2932
  }
2825
2933
  );
2826
2934
  }
2827
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 1 }, /* @__PURE__ */ React60__default.default.createElement(
2935
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 1 }, /* @__PURE__ */ React58__default.default.createElement(
2828
2936
  TextDimensionInput,
2829
2937
  {
2830
2938
  label: "Column 1",
@@ -2833,7 +2941,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2833
2941
  setIndexValue(0, v);
2834
2942
  }
2835
2943
  }
2836
- ), /* @__PURE__ */ React60__default.default.createElement(
2944
+ ), /* @__PURE__ */ React58__default.default.createElement(
2837
2945
  TextDimensionInput,
2838
2946
  {
2839
2947
  label: "Column 2",
@@ -2848,7 +2956,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2848
2956
  // src/app/inspector-drawer/configuration-panel/input-panels/columns-container-sidebar-panel.tsx
2849
2957
  function ColumnsContainerPanel({ data, setData }) {
2850
2958
  var _a, _b, _c, _d, _e, _f;
2851
- const [, setErrors] = React60.useState(null);
2959
+ const [, setErrors] = React58.useState(null);
2852
2960
  const updateData = (d) => {
2853
2961
  const res = columns_container_props_schema_default2.safeParse(d);
2854
2962
  if (res.success) {
@@ -2858,7 +2966,7 @@ function ColumnsContainerPanel({ data, setData }) {
2858
2966
  setErrors(res.error);
2859
2967
  }
2860
2968
  };
2861
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Columns block" }, /* @__PURE__ */ React60__default.default.createElement(
2969
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Columns block" }, /* @__PURE__ */ React58__default.default.createElement(
2862
2970
  RadioGroupInput,
2863
2971
  {
2864
2972
  label: "Number of columns",
@@ -2867,9 +2975,9 @@ function ColumnsContainerPanel({ data, setData }) {
2867
2975
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { columnsCount: v === "2" ? 2 : 3 }) }));
2868
2976
  }
2869
2977
  },
2870
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "2" }, "2"),
2871
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "3" }, "3")
2872
- ), /* @__PURE__ */ React60__default.default.createElement(
2978
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "2" }, "2"),
2979
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "3" }, "3")
2980
+ ), /* @__PURE__ */ React58__default.default.createElement(
2873
2981
  ColumnWidthsInput,
2874
2982
  {
2875
2983
  defaultValue: (_b = data.props) == null ? void 0 : _b.fixedWidths,
@@ -2877,11 +2985,11 @@ function ColumnsContainerPanel({ data, setData }) {
2877
2985
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { fixedWidths }) }));
2878
2986
  }
2879
2987
  }
2880
- ), /* @__PURE__ */ React60__default.default.createElement(
2988
+ ), /* @__PURE__ */ React58__default.default.createElement(
2881
2989
  SliderInput,
2882
2990
  {
2883
2991
  label: "Columns gap",
2884
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.SpaceBarOutlined, { sx: { color: "text.secondary" } }),
2992
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SpaceBarOutlined, { sx: { color: "text.secondary" } }),
2885
2993
  units: "px",
2886
2994
  step: 4,
2887
2995
  marks: true,
@@ -2890,7 +2998,7 @@ function ColumnsContainerPanel({ data, setData }) {
2890
2998
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.columnsGap) != null ? _d : 0,
2891
2999
  onChange: (columnsGap) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { columnsGap }) }))
2892
3000
  }
2893
- ), /* @__PURE__ */ React60__default.default.createElement(
3001
+ ), /* @__PURE__ */ React58__default.default.createElement(
2894
3002
  RadioGroupInput,
2895
3003
  {
2896
3004
  label: "Alignment",
@@ -2899,10 +3007,10 @@ function ColumnsContainerPanel({ data, setData }) {
2899
3007
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }));
2900
3008
  }
2901
3009
  },
2902
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "top" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.VerticalAlignTopOutlined, { fontSize: "small" })),
2903
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "middle" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.VerticalAlignCenterOutlined, { fontSize: "small" })),
2904
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "bottom" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.VerticalAlignBottomOutlined, { fontSize: "small" }))
2905
- ), /* @__PURE__ */ React60__default.default.createElement(
3010
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "top" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.VerticalAlignTopOutlined, { fontSize: "small" })),
3011
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "middle" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.VerticalAlignCenterOutlined, { fontSize: "small" })),
3012
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "bottom" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.VerticalAlignBottomOutlined, { fontSize: "small" }))
3013
+ ), /* @__PURE__ */ React58__default.default.createElement(
2906
3014
  MultiStylePropertyPanel,
2907
3015
  {
2908
3016
  names: ["backgroundColor", "padding"],
@@ -2921,7 +3029,7 @@ var container_props_schema_default = ContainerPropsSchema3;
2921
3029
 
2922
3030
  // src/app/inspector-drawer/configuration-panel/input-panels/container-sidebar-panel.tsx
2923
3031
  function ContainerSidebarPanel({ data, setData }) {
2924
- const [, setErrors] = React60.useState(null);
3032
+ const [, setErrors] = React58.useState(null);
2925
3033
  const updateData = (d) => {
2926
3034
  const res = container_props_schema_default.safeParse(d);
2927
3035
  if (res.success) {
@@ -2931,7 +3039,7 @@ function ContainerSidebarPanel({ data, setData }) {
2931
3039
  setErrors(res.error);
2932
3040
  }
2933
3041
  };
2934
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Container block" }, /* @__PURE__ */ React60__default.default.createElement(
3042
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Container block" }, /* @__PURE__ */ React58__default.default.createElement(
2935
3043
  MultiStylePropertyPanel,
2936
3044
  {
2937
3045
  names: ["backgroundColor", "borderColor", "borderRadius", "padding"],
@@ -2942,7 +3050,7 @@ function ContainerSidebarPanel({ data, setData }) {
2942
3050
  }
2943
3051
  function DividerSidebarPanel({ data, setData }) {
2944
3052
  var _a, _b, _c, _d;
2945
- const [, setErrors] = React60.useState(null);
3053
+ const [, setErrors] = React58.useState(null);
2946
3054
  const updateData = (d) => {
2947
3055
  const res = DividerPropsSchema.safeParse(d);
2948
3056
  if (res.success) {
@@ -2954,18 +3062,18 @@ function DividerSidebarPanel({ data, setData }) {
2954
3062
  };
2955
3063
  const lineColor = (_b = (_a = data.props) == null ? void 0 : _a.lineColor) != null ? _b : DividerPropsDefaults.lineColor;
2956
3064
  const lineHeight = (_d = (_c = data.props) == null ? void 0 : _c.lineHeight) != null ? _d : DividerPropsDefaults.lineHeight;
2957
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Divider block" }, /* @__PURE__ */ React60__default.default.createElement(
3065
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Divider block" }, /* @__PURE__ */ React58__default.default.createElement(
2958
3066
  ColorInput2,
2959
3067
  {
2960
3068
  label: "Color",
2961
3069
  defaultValue: lineColor,
2962
3070
  onChange: (lineColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { lineColor: lineColor2 }) }))
2963
3071
  }
2964
- ), /* @__PURE__ */ React60__default.default.createElement(
3072
+ ), /* @__PURE__ */ React58__default.default.createElement(
2965
3073
  SliderInput,
2966
3074
  {
2967
3075
  label: "Height",
2968
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.HeightOutlined, { sx: { color: "text.secondary" } }),
3076
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.HeightOutlined, { sx: { color: "text.secondary" } }),
2969
3077
  units: "px",
2970
3078
  step: 1,
2971
3079
  min: 1,
@@ -2973,7 +3081,7 @@ function DividerSidebarPanel({ data, setData }) {
2973
3081
  defaultValue: lineHeight,
2974
3082
  onChange: (lineHeight2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { lineHeight: lineHeight2 }) }))
2975
3083
  }
2976
- ), /* @__PURE__ */ React60__default.default.createElement(
3084
+ ), /* @__PURE__ */ React58__default.default.createElement(
2977
3085
  MultiStylePropertyPanel,
2978
3086
  {
2979
3087
  names: ["backgroundColor", "padding"],
@@ -2996,7 +3104,8 @@ var FONT_FAMILY_SCHEMA7 = zod.z.enum([
2996
3104
  ]).nullable().optional();
2997
3105
  var TemplateVariableSchema2 = zod.z.object({
2998
3106
  name: zod.z.string(),
2999
- description: zod.z.string().optional().nullable()
3107
+ description: zod.z.string().optional().nullable(),
3108
+ sampleValue: zod.z.string().optional().nullable()
3000
3109
  });
3001
3110
  var EmailLayoutPropsSchema2 = zod.z.object({
3002
3111
  backdropColor: COLOR_SCHEMA10,
@@ -3012,15 +3121,15 @@ var EmailLayoutPropsSchema2 = zod.z.object({
3012
3121
  });
3013
3122
  var email_layout_props_schema_default = EmailLayoutPropsSchema2;
3014
3123
  function BooleanInput({ label, defaultValue, onChange }) {
3015
- const [value, setValue] = React60.useState(defaultValue);
3016
- React60.useEffect(() => {
3124
+ const [value, setValue] = React58.useState(defaultValue);
3125
+ React58.useEffect(() => {
3017
3126
  setValue(defaultValue);
3018
3127
  }, [defaultValue]);
3019
- return /* @__PURE__ */ React60__default.default.createElement(
3128
+ return /* @__PURE__ */ React58__default.default.createElement(
3020
3129
  material.FormControlLabel,
3021
3130
  {
3022
3131
  label,
3023
- control: /* @__PURE__ */ React60__default.default.createElement(
3132
+ control: /* @__PURE__ */ React58__default.default.createElement(
3024
3133
  material.Switch,
3025
3134
  {
3026
3135
  checked: value,
@@ -3037,7 +3146,7 @@ function BooleanInput({ label, defaultValue, onChange }) {
3037
3146
  // src/app/inspector-drawer/configuration-panel/input-panels/email-layout-sidebar-panel.tsx
3038
3147
  function EmailLayoutSidebarFields({ data, setData }) {
3039
3148
  var _a, _b, _c, _d, _e, _f;
3040
- const [, setErrors] = React60.useState(null);
3149
+ const [, setErrors] = React58.useState(null);
3041
3150
  const updateData = (d) => {
3042
3151
  const res = email_layout_props_schema_default.safeParse(d);
3043
3152
  if (res.success) {
@@ -3048,38 +3157,38 @@ function EmailLayoutSidebarFields({ data, setData }) {
3048
3157
  }
3049
3158
  };
3050
3159
  const backdropDisabled = (_a = data.backdropDisabled) != null ? _a : false;
3051
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Global" }, /* @__PURE__ */ React60__default.default.createElement(
3160
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Global" }, /* @__PURE__ */ React58__default.default.createElement(
3052
3161
  BooleanInput,
3053
3162
  {
3054
3163
  label: "Disable backdrop",
3055
3164
  defaultValue: backdropDisabled,
3056
3165
  onChange: (backdropDisabled2) => updateData(__spreadProps(__spreadValues({}, data), { backdropDisabled: backdropDisabled2 }))
3057
3166
  }
3058
- ), !backdropDisabled && /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
3167
+ ), !backdropDisabled && /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
3059
3168
  ColorInput2,
3060
3169
  {
3061
3170
  label: "Backdrop color",
3062
3171
  defaultValue: (_b = data.backdropColor) != null ? _b : "#F5F5F5",
3063
3172
  onChange: (backdropColor) => updateData(__spreadProps(__spreadValues({}, data), { backdropColor }))
3064
3173
  }
3065
- ), /* @__PURE__ */ React60__default.default.createElement(
3174
+ ), /* @__PURE__ */ React58__default.default.createElement(
3066
3175
  ColorInput2,
3067
3176
  {
3068
3177
  label: "Canvas color",
3069
3178
  defaultValue: (_c = data.canvasColor) != null ? _c : "#FFFFFF",
3070
3179
  onChange: (canvasColor) => updateData(__spreadProps(__spreadValues({}, data), { canvasColor }))
3071
3180
  }
3072
- ), /* @__PURE__ */ React60__default.default.createElement(
3181
+ ), /* @__PURE__ */ React58__default.default.createElement(
3073
3182
  NullableColorInput,
3074
3183
  {
3075
3184
  label: "Canvas border color",
3076
3185
  defaultValue: (_d = data.borderColor) != null ? _d : null,
3077
3186
  onChange: (borderColor) => updateData(__spreadProps(__spreadValues({}, data), { borderColor }))
3078
3187
  }
3079
- ), /* @__PURE__ */ React60__default.default.createElement(
3188
+ ), /* @__PURE__ */ React58__default.default.createElement(
3080
3189
  SliderInput,
3081
3190
  {
3082
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.RoundedCornerOutlined, null),
3191
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.RoundedCornerOutlined, null),
3083
3192
  units: "px",
3084
3193
  step: 4,
3085
3194
  marks: true,
@@ -3089,14 +3198,14 @@ function EmailLayoutSidebarFields({ data, setData }) {
3089
3198
  defaultValue: (_e = data.borderRadius) != null ? _e : 0,
3090
3199
  onChange: (borderRadius) => updateData(__spreadProps(__spreadValues({}, data), { borderRadius }))
3091
3200
  }
3092
- )), /* @__PURE__ */ React60__default.default.createElement(
3201
+ )), /* @__PURE__ */ React58__default.default.createElement(
3093
3202
  NullableFontFamily,
3094
3203
  {
3095
3204
  label: "Font family",
3096
3205
  defaultValue: "MODERN_SANS",
3097
3206
  onChange: (fontFamily) => updateData(__spreadProps(__spreadValues({}, data), { fontFamily }))
3098
3207
  }
3099
- ), /* @__PURE__ */ React60__default.default.createElement(
3208
+ ), /* @__PURE__ */ React58__default.default.createElement(
3100
3209
  ColorInput2,
3101
3210
  {
3102
3211
  label: "Text color",
@@ -3107,7 +3216,7 @@ function EmailLayoutSidebarFields({ data, setData }) {
3107
3216
  }
3108
3217
  function HeadingSidebarPanel({ data, setData }) {
3109
3218
  var _a, _b, _c, _d;
3110
- const [, setErrors] = React60.useState(null);
3219
+ const [, setErrors] = React58.useState(null);
3111
3220
  const updateData = (d) => {
3112
3221
  const res = HeadingPropsSchema.safeParse(d);
3113
3222
  if (res.success) {
@@ -3117,7 +3226,7 @@ function HeadingSidebarPanel({ data, setData }) {
3117
3226
  setErrors(res.error);
3118
3227
  }
3119
3228
  };
3120
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Heading block" }, /* @__PURE__ */ React60__default.default.createElement(
3229
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Heading block" }, /* @__PURE__ */ React58__default.default.createElement(
3121
3230
  TextInput,
3122
3231
  {
3123
3232
  label: "Content",
@@ -3127,7 +3236,7 @@ function HeadingSidebarPanel({ data, setData }) {
3127
3236
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text }) }));
3128
3237
  }
3129
3238
  }
3130
- ), /* @__PURE__ */ React60__default.default.createElement(
3239
+ ), /* @__PURE__ */ React58__default.default.createElement(
3131
3240
  RadioGroupInput,
3132
3241
  {
3133
3242
  label: "Level",
@@ -3136,13 +3245,22 @@ function HeadingSidebarPanel({ data, setData }) {
3136
3245
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { level }) }));
3137
3246
  }
3138
3247
  },
3139
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "h1" }, "H1"),
3140
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "h2" }, "H2"),
3141
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "h3" }, "H3")
3142
- ), /* @__PURE__ */ React60__default.default.createElement(
3248
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "h1" }, "H1"),
3249
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "h2" }, "H2"),
3250
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "h3" }, "H3")
3251
+ ), /* @__PURE__ */ React58__default.default.createElement(
3143
3252
  MultiStylePropertyPanel,
3144
3253
  {
3145
- names: ["color", "backgroundColor", "fontFamily", "fontWeight", "textAlign", "padding"],
3254
+ names: [
3255
+ "color",
3256
+ "backgroundColor",
3257
+ "fontFamily",
3258
+ "fontWeight",
3259
+ "lineHeight",
3260
+ "letterSpacing",
3261
+ "textAlign",
3262
+ "padding"
3263
+ ],
3146
3264
  value: data.style,
3147
3265
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
3148
3266
  }
@@ -3150,7 +3268,7 @@ function HeadingSidebarPanel({ data, setData }) {
3150
3268
  }
3151
3269
  function HtmlSidebarPanel({ data, setData }) {
3152
3270
  var _a, _b;
3153
- const [, setErrors] = React60.useState(null);
3271
+ const [, setErrors] = React58.useState(null);
3154
3272
  const updateData = (d) => {
3155
3273
  const res = HtmlPropsSchema.safeParse(d);
3156
3274
  if (res.success) {
@@ -3160,7 +3278,7 @@ function HtmlSidebarPanel({ data, setData }) {
3160
3278
  setErrors(res.error);
3161
3279
  }
3162
3280
  };
3163
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Html block" }, /* @__PURE__ */ React60__default.default.createElement(
3281
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Html block" }, /* @__PURE__ */ React58__default.default.createElement(
3164
3282
  TextInput,
3165
3283
  {
3166
3284
  label: "Content",
@@ -3168,7 +3286,7 @@ function HtmlSidebarPanel({ data, setData }) {
3168
3286
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.contents) != null ? _b : "",
3169
3287
  onChange: (contents) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contents }) }))
3170
3288
  }
3171
- ), /* @__PURE__ */ React60__default.default.createElement(
3289
+ ), /* @__PURE__ */ React58__default.default.createElement(
3172
3290
  MultiStylePropertyPanel,
3173
3291
  {
3174
3292
  names: ["color", "backgroundColor", "fontFamily", "fontSize", "textAlign", "padding"],
@@ -3177,9 +3295,160 @@ function HtmlSidebarPanel({ data, setData }) {
3177
3295
  }
3178
3296
  ));
3179
3297
  }
3298
+ function ImageLibraryDialog({ open, onClose, onPick }) {
3299
+ const { loadImages, deleteImage } = useImageCallbacks();
3300
+ const [images, setImages] = React58.useState(null);
3301
+ const [error, setError] = React58.useState(null);
3302
+ const [query, setQuery] = React58.useState("");
3303
+ const [busy, setBusy] = React58.useState(false);
3304
+ const refresh = () => __async(null, null, function* () {
3305
+ if (!loadImages) return;
3306
+ setBusy(true);
3307
+ setError(null);
3308
+ try {
3309
+ const list = yield loadImages();
3310
+ setImages(list);
3311
+ } catch (e) {
3312
+ setError(e instanceof Error ? e.message : "Failed to load images");
3313
+ } finally {
3314
+ setBusy(false);
3315
+ }
3316
+ });
3317
+ React58.useEffect(() => {
3318
+ if (open) {
3319
+ setQuery("");
3320
+ void refresh();
3321
+ }
3322
+ }, [open]);
3323
+ const filtered = React58.useMemo(() => {
3324
+ if (!images) return null;
3325
+ const q = query.trim().toLowerCase();
3326
+ if (!q) return images;
3327
+ return images.filter((img) => {
3328
+ var _a;
3329
+ const haystack = `${(_a = img.alt) != null ? _a : ""} ${img.url}`.toLowerCase();
3330
+ return haystack.includes(q);
3331
+ });
3332
+ }, [images, query]);
3333
+ const handleDelete = (url) => __async(null, null, function* () {
3334
+ if (!deleteImage) return;
3335
+ const ok = window.confirm("Delete this image from the library?");
3336
+ if (!ok) return;
3337
+ setBusy(true);
3338
+ try {
3339
+ yield deleteImage(url);
3340
+ yield refresh();
3341
+ } catch (e) {
3342
+ setError(e instanceof Error ? e.message : "Failed to delete image");
3343
+ setBusy(false);
3344
+ }
3345
+ });
3346
+ return /* @__PURE__ */ React58__default.default.createElement(material.Dialog, { open, onClose, maxWidth: "md", fullWidth: true }, /* @__PURE__ */ React58__default.default.createElement(material.DialogTitle, null, "Image library"), /* @__PURE__ */ React58__default.default.createElement(material.DialogContent, { dividers: true }, /* @__PURE__ */ React58__default.default.createElement(
3347
+ material.TextField,
3348
+ {
3349
+ fullWidth: true,
3350
+ size: "small",
3351
+ placeholder: "Search by alt text or URL",
3352
+ value: query,
3353
+ onChange: (e) => setQuery(e.target.value),
3354
+ autoFocus: true,
3355
+ InputProps: {
3356
+ startAdornment: /* @__PURE__ */ React58__default.default.createElement(material.InputAdornment, { position: "start" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SearchOutlined, { fontSize: "small" }))
3357
+ },
3358
+ sx: { mb: 2 }
3359
+ }
3360
+ ), error && /* @__PURE__ */ React58__default.default.createElement(material.Alert, { severity: "error", sx: { mb: 2 } }, error), busy && !images && /* @__PURE__ */ React58__default.default.createElement(material.Stack, { alignItems: "center", sx: { py: 4 } }, /* @__PURE__ */ React58__default.default.createElement(material.CircularProgress, { size: 28 })), filtered && filtered.length === 0 && /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary", textAlign: "center", py: 4 } }, query ? "No images match your search." : "No images in the library yet."), filtered && filtered.length > 0 && /* @__PURE__ */ React58__default.default.createElement(
3361
+ material.Box,
3362
+ {
3363
+ sx: {
3364
+ display: "grid",
3365
+ gridTemplateColumns: "repeat(auto-fill, minmax(140px, 1fr))",
3366
+ gap: 1.5
3367
+ }
3368
+ },
3369
+ filtered.map((img) => /* @__PURE__ */ React58__default.default.createElement(
3370
+ ImageTile,
3371
+ {
3372
+ key: img.url,
3373
+ image: img,
3374
+ onPick: () => onPick(img),
3375
+ onDelete: deleteImage ? () => handleDelete(img.url) : void 0
3376
+ }
3377
+ ))
3378
+ )), /* @__PURE__ */ React58__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React58__default.default.createElement(material.Button, { onClick: onClose }, "Close")));
3379
+ }
3380
+ function ImageTile({
3381
+ image,
3382
+ onPick,
3383
+ onDelete
3384
+ }) {
3385
+ var _a, _b;
3386
+ const src = (_a = image.thumbnailUrl) != null ? _a : image.url;
3387
+ const label = image.alt || image.url.split("/").pop() || "image";
3388
+ return /* @__PURE__ */ React58__default.default.createElement(
3389
+ material.Box,
3390
+ {
3391
+ sx: {
3392
+ position: "relative",
3393
+ borderRadius: 1,
3394
+ border: 1,
3395
+ borderColor: "divider",
3396
+ overflow: "hidden",
3397
+ cursor: "pointer",
3398
+ transition: "border-color 120ms",
3399
+ "&:hover": { borderColor: "primary.main" },
3400
+ "&:hover .delete-btn": { opacity: 1 }
3401
+ },
3402
+ onClick: onPick
3403
+ },
3404
+ /* @__PURE__ */ React58__default.default.createElement(
3405
+ material.Box,
3406
+ {
3407
+ component: "img",
3408
+ src,
3409
+ alt: (_b = image.alt) != null ? _b : "",
3410
+ sx: { display: "block", width: "100%", aspectRatio: "1 / 1", objectFit: "cover", backgroundColor: "#f5f5f5" }
3411
+ }
3412
+ ),
3413
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { p: 0.75, fontSize: 11, color: "text.secondary", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, label),
3414
+ onDelete && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Delete from library" }, /* @__PURE__ */ React58__default.default.createElement(
3415
+ material.IconButton,
3416
+ {
3417
+ size: "small",
3418
+ className: "delete-btn",
3419
+ onClick: (e) => {
3420
+ e.stopPropagation();
3421
+ onDelete();
3422
+ },
3423
+ sx: {
3424
+ position: "absolute",
3425
+ top: 4,
3426
+ right: 4,
3427
+ opacity: 0,
3428
+ backgroundColor: "rgba(255,255,255,0.85)",
3429
+ transition: "opacity 120ms",
3430
+ "&:hover": { backgroundColor: "rgba(255,255,255,0.95)" }
3431
+ },
3432
+ "aria-label": "Delete image"
3433
+ },
3434
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DeleteOutline, { fontSize: "small" })
3435
+ ))
3436
+ );
3437
+ }
3438
+
3439
+ // src/app/inspector-drawer/configuration-panel/input-panels/image-sidebar-panel.tsx
3440
+ function isHttpUrl(value) {
3441
+ if (!value) return false;
3442
+ return /^http:\/\//i.test(value.trim());
3443
+ }
3180
3444
  function ImageSidebarPanel({ data, setData }) {
3181
3445
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
3182
- const [, setErrors] = React60.useState(null);
3446
+ const [, setErrors] = React58.useState(null);
3447
+ const { uploadImage, loadImages } = useImageCallbacks();
3448
+ const fileInputRef = React58.useRef(null);
3449
+ const [uploading, setUploading] = React58.useState(false);
3450
+ const [uploadError, setUploadError] = React58.useState(null);
3451
+ const [libraryOpen, setLibraryOpen] = React58.useState(false);
3183
3452
  const updateData = (d) => {
3184
3453
  const res = ImagePropsSchema.safeParse(d);
3185
3454
  if (res.success) {
@@ -3189,24 +3458,88 @@ function ImageSidebarPanel({ data, setData }) {
3189
3458
  setErrors(res.error);
3190
3459
  }
3191
3460
  };
3192
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Image block" }, /* @__PURE__ */ React60__default.default.createElement(
3461
+ const applyUploadedImage = (uploaded) => {
3462
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2;
3463
+ updateData(__spreadProps(__spreadValues({}, data), {
3464
+ props: __spreadProps(__spreadValues({}, data.props), {
3465
+ url: uploaded.url,
3466
+ width: (_c2 = (_b2 = uploaded.width) != null ? _b2 : (_a2 = data.props) == null ? void 0 : _a2.width) != null ? _c2 : null,
3467
+ height: (_f2 = (_e2 = uploaded.height) != null ? _e2 : (_d2 = data.props) == null ? void 0 : _d2.height) != null ? _f2 : null,
3468
+ alt: (_i2 = (_h2 = uploaded.alt) != null ? _h2 : (_g2 = data.props) == null ? void 0 : _g2.alt) != null ? _i2 : ""
3469
+ })
3470
+ }));
3471
+ };
3472
+ const handleFile = (file) => __async(null, null, function* () {
3473
+ if (!uploadImage) return;
3474
+ setUploading(true);
3475
+ setUploadError(null);
3476
+ try {
3477
+ const uploaded = yield uploadImage(file);
3478
+ applyUploadedImage(uploaded);
3479
+ } catch (e) {
3480
+ setUploadError(e instanceof Error ? e.message : "Upload failed");
3481
+ } finally {
3482
+ setUploading(false);
3483
+ }
3484
+ });
3485
+ const url = (_b = (_a = data.props) == null ? void 0 : _a.url) != null ? _b : "";
3486
+ const showHttpWarning = isHttpUrl(url);
3487
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Image block" }, (uploadImage || loadImages) && /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 1 }, uploadImage && /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
3488
+ material.Button,
3489
+ {
3490
+ fullWidth: true,
3491
+ variant: "outlined",
3492
+ size: "small",
3493
+ startIcon: uploading ? /* @__PURE__ */ React58__default.default.createElement(material.CircularProgress, { size: 14 }) : /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.CloudUploadOutlined, { fontSize: "small" }),
3494
+ disabled: uploading,
3495
+ onClick: () => {
3496
+ var _a2;
3497
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
3498
+ }
3499
+ },
3500
+ uploading ? "Uploading\u2026" : "Upload"
3501
+ ), /* @__PURE__ */ React58__default.default.createElement(
3502
+ "input",
3503
+ {
3504
+ ref: fileInputRef,
3505
+ type: "file",
3506
+ accept: "image/*",
3507
+ hidden: true,
3508
+ onChange: (e) => __async(null, null, function* () {
3509
+ var _a2;
3510
+ const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
3511
+ e.target.value = "";
3512
+ if (file) yield handleFile(file);
3513
+ })
3514
+ }
3515
+ )), loadImages && /* @__PURE__ */ React58__default.default.createElement(
3516
+ material.Button,
3517
+ {
3518
+ fullWidth: true,
3519
+ variant: "outlined",
3520
+ size: "small",
3521
+ startIcon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.CollectionsOutlined, { fontSize: "small" }),
3522
+ onClick: () => setLibraryOpen(true)
3523
+ },
3524
+ "Library"
3525
+ )), uploadError && /* @__PURE__ */ React58__default.default.createElement(material.Alert, { severity: "error", onClose: () => setUploadError(null), sx: { mt: 1 } }, uploadError), /* @__PURE__ */ React58__default.default.createElement(
3193
3526
  TextInput,
3194
3527
  {
3195
3528
  label: "Source URL",
3196
- defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.url) != null ? _b : "",
3529
+ defaultValue: url,
3197
3530
  onChange: (v) => {
3198
- const url = v.trim().length === 0 ? null : v.trim();
3199
- updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url }) }));
3531
+ const next = v.trim().length === 0 ? null : v.trim();
3532
+ updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: next }) }));
3200
3533
  }
3201
3534
  }
3202
- ), /* @__PURE__ */ React60__default.default.createElement(
3535
+ ), showHttpWarning && /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { mt: -1, mb: 1, display: "flex", alignItems: "flex-start", gap: 0.75 } }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ErrorOutlineOutlined, { fontSize: "small", sx: { color: "warning.main", mt: "2px" } }), /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { fontSize: 12, color: "warning.dark" } }, "Non-HTTPS URL: Gmail and other clients strip mixed content. Use https:// for reliable delivery.")), /* @__PURE__ */ React58__default.default.createElement(
3203
3536
  TextInput,
3204
3537
  {
3205
3538
  label: "Alt text",
3206
3539
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.alt) != null ? _d : "",
3207
3540
  onChange: (alt) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt }) }))
3208
3541
  }
3209
- ), /* @__PURE__ */ React60__default.default.createElement(
3542
+ ), /* @__PURE__ */ React58__default.default.createElement(
3210
3543
  TextInput,
3211
3544
  {
3212
3545
  label: "Click through URL",
@@ -3216,42 +3549,52 @@ function ImageSidebarPanel({ data, setData }) {
3216
3549
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { linkHref }) }));
3217
3550
  }
3218
3551
  }
3219
- ), /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React60__default.default.createElement(
3552
+ ), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React58__default.default.createElement(
3220
3553
  TextDimensionInput,
3221
3554
  {
3222
3555
  label: "Width",
3223
3556
  defaultValue: (_g = data.props) == null ? void 0 : _g.width,
3224
3557
  onChange: (width) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { width }) }))
3225
3558
  }
3226
- ), /* @__PURE__ */ React60__default.default.createElement(
3559
+ ), /* @__PURE__ */ React58__default.default.createElement(
3227
3560
  TextDimensionInput,
3228
3561
  {
3229
3562
  label: "Height",
3230
3563
  defaultValue: (_h = data.props) == null ? void 0 : _h.height,
3231
3564
  onChange: (height) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { height }) }))
3232
3565
  }
3233
- )), /* @__PURE__ */ React60__default.default.createElement(
3566
+ )), /* @__PURE__ */ React58__default.default.createElement(
3234
3567
  RadioGroupInput,
3235
3568
  {
3236
3569
  label: "Alignment",
3237
3570
  defaultValue: (_j = (_i = data.props) == null ? void 0 : _i.contentAlignment) != null ? _j : "middle",
3238
3571
  onChange: (contentAlignment) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }))
3239
3572
  },
3240
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "top" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.VerticalAlignTopOutlined, { fontSize: "small" })),
3241
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "middle" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.VerticalAlignCenterOutlined, { fontSize: "small" })),
3242
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "bottom" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.VerticalAlignBottomOutlined, { fontSize: "small" }))
3243
- ), /* @__PURE__ */ React60__default.default.createElement(
3573
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "top" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.VerticalAlignTopOutlined, { fontSize: "small" })),
3574
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "middle" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.VerticalAlignCenterOutlined, { fontSize: "small" })),
3575
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "bottom" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.VerticalAlignBottomOutlined, { fontSize: "small" }))
3576
+ ), /* @__PURE__ */ React58__default.default.createElement(
3244
3577
  MultiStylePropertyPanel,
3245
3578
  {
3246
3579
  names: ["backgroundColor", "textAlign", "padding"],
3247
3580
  value: data.style,
3248
3581
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
3249
3582
  }
3583
+ ), loadImages && /* @__PURE__ */ React58__default.default.createElement(
3584
+ ImageLibraryDialog,
3585
+ {
3586
+ open: libraryOpen,
3587
+ onClose: () => setLibraryOpen(false),
3588
+ onPick: (image) => {
3589
+ applyUploadedImage(image);
3590
+ setLibraryOpen(false);
3591
+ }
3592
+ }
3250
3593
  ));
3251
3594
  }
3252
3595
  function SignatureSidebarPanel({ data, setData }) {
3253
3596
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D;
3254
- const [, setErrors] = React60.useState(null);
3597
+ const [, setErrors] = React58.useState(null);
3255
3598
  const updateData = (d) => {
3256
3599
  const res = SignaturePropsSchema.safeParse(d);
3257
3600
  if (res.success) {
@@ -3276,74 +3619,74 @@ function SignatureSidebarPanel({ data, setData }) {
3276
3619
  const nameColor = (_z = (_y = data.props) == null ? void 0 : _y.nameColor) != null ? _z : SignaturePropsDefaults.nameColor;
3277
3620
  const textColor = (_B = (_A = data.props) == null ? void 0 : _A.textColor) != null ? _B : SignaturePropsDefaults.textColor;
3278
3621
  const linkColor = (_D = (_C = data.props) == null ? void 0 : _C.linkColor) != null ? _D : SignaturePropsDefaults.linkColor;
3279
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Signature block" }, /* @__PURE__ */ React60__default.default.createElement(
3622
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Signature block" }, /* @__PURE__ */ React58__default.default.createElement(
3280
3623
  TextInput,
3281
3624
  {
3282
3625
  label: "Greeting",
3283
3626
  defaultValue: greeting,
3284
3627
  onChange: (greeting2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { greeting: greeting2 }) }))
3285
3628
  }
3286
- ), /* @__PURE__ */ React60__default.default.createElement(
3629
+ ), /* @__PURE__ */ React58__default.default.createElement(
3287
3630
  TextInput,
3288
3631
  {
3289
3632
  label: "Name",
3290
3633
  defaultValue: name,
3291
3634
  onChange: (name2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { name: name2 }) }))
3292
3635
  }
3293
- ), /* @__PURE__ */ React60__default.default.createElement(
3636
+ ), /* @__PURE__ */ React58__default.default.createElement(
3294
3637
  TextInput,
3295
3638
  {
3296
3639
  label: "Title",
3297
3640
  defaultValue: title,
3298
3641
  onChange: (title2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { title: title2 }) }))
3299
3642
  }
3300
- ), /* @__PURE__ */ React60__default.default.createElement(
3643
+ ), /* @__PURE__ */ React58__default.default.createElement(
3301
3644
  TextInput,
3302
3645
  {
3303
3646
  label: "Company",
3304
3647
  defaultValue: company,
3305
3648
  onChange: (company2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { company: company2 }) }))
3306
3649
  }
3307
- ), /* @__PURE__ */ React60__default.default.createElement(
3650
+ ), /* @__PURE__ */ React58__default.default.createElement(
3308
3651
  TextInput,
3309
3652
  {
3310
3653
  label: "Address",
3311
3654
  defaultValue: address,
3312
3655
  onChange: (address2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { address: address2 }) }))
3313
3656
  }
3314
- ), /* @__PURE__ */ React60__default.default.createElement(
3657
+ ), /* @__PURE__ */ React58__default.default.createElement(
3315
3658
  TextInput,
3316
3659
  {
3317
3660
  label: "Email",
3318
3661
  defaultValue: email,
3319
3662
  onChange: (email2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { email: email2 }) }))
3320
3663
  }
3321
- ), /* @__PURE__ */ React60__default.default.createElement(
3664
+ ), /* @__PURE__ */ React58__default.default.createElement(
3322
3665
  TextInput,
3323
3666
  {
3324
3667
  label: "Phone",
3325
3668
  defaultValue: phone,
3326
3669
  onChange: (phone2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { phone: phone2 }) }))
3327
3670
  }
3328
- ), /* @__PURE__ */ React60__default.default.createElement(
3671
+ ), /* @__PURE__ */ React58__default.default.createElement(
3329
3672
  TextInput,
3330
3673
  {
3331
3674
  label: "Website",
3332
3675
  defaultValue: website,
3333
3676
  onChange: (website2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { website: website2 }) }))
3334
3677
  }
3335
- ), /* @__PURE__ */ React60__default.default.createElement(
3678
+ ), /* @__PURE__ */ React58__default.default.createElement(
3336
3679
  TextInput,
3337
3680
  {
3338
3681
  label: "Image URL",
3339
3682
  defaultValue: imageUrl,
3340
3683
  onChange: (imageUrl2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }))
3341
3684
  }
3342
- ), /* @__PURE__ */ React60__default.default.createElement(
3685
+ ), /* @__PURE__ */ React58__default.default.createElement(
3343
3686
  SliderInput,
3344
3687
  {
3345
3688
  label: "Image size",
3346
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AspectRatioOutlined, { sx: { color: "text.secondary" } }),
3689
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AspectRatioOutlined, { sx: { color: "text.secondary" } }),
3347
3690
  units: "px",
3348
3691
  step: 4,
3349
3692
  min: 32,
@@ -3351,47 +3694,47 @@ function SignatureSidebarPanel({ data, setData }) {
3351
3694
  defaultValue: imageSize,
3352
3695
  onChange: (imageSize2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageSize: imageSize2 }) }))
3353
3696
  }
3354
- ), /* @__PURE__ */ React60__default.default.createElement(
3697
+ ), /* @__PURE__ */ React58__default.default.createElement(
3355
3698
  RadioGroupInput,
3356
3699
  {
3357
3700
  label: "Image shape",
3358
3701
  defaultValue: imageShape,
3359
3702
  onChange: (imageShape2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageShape: imageShape2 }) }))
3360
3703
  },
3361
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "circle" }, "Circle"),
3362
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "square" }, "Square"),
3363
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded")
3364
- ), /* @__PURE__ */ React60__default.default.createElement(
3704
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "circle" }, "Circle"),
3705
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "square" }, "Square"),
3706
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded")
3707
+ ), /* @__PURE__ */ React58__default.default.createElement(
3365
3708
  RadioGroupInput,
3366
3709
  {
3367
3710
  label: "Layout",
3368
3711
  defaultValue: layout,
3369
3712
  onChange: (layout2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { layout: layout2 }) }))
3370
3713
  },
3371
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "horizontal" }, "Horizontal"),
3372
- /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "vertical" }, "Vertical")
3373
- ), /* @__PURE__ */ React60__default.default.createElement(
3714
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "horizontal" }, "Horizontal"),
3715
+ /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "vertical" }, "Vertical")
3716
+ ), /* @__PURE__ */ React58__default.default.createElement(
3374
3717
  ColorInput2,
3375
3718
  {
3376
3719
  label: "Name color",
3377
3720
  defaultValue: nameColor,
3378
3721
  onChange: (nameColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { nameColor: nameColor2 }) }))
3379
3722
  }
3380
- ), /* @__PURE__ */ React60__default.default.createElement(
3723
+ ), /* @__PURE__ */ React58__default.default.createElement(
3381
3724
  ColorInput2,
3382
3725
  {
3383
3726
  label: "Text color",
3384
3727
  defaultValue: textColor,
3385
3728
  onChange: (textColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { textColor: textColor2 }) }))
3386
3729
  }
3387
- ), /* @__PURE__ */ React60__default.default.createElement(
3730
+ ), /* @__PURE__ */ React58__default.default.createElement(
3388
3731
  ColorInput2,
3389
3732
  {
3390
3733
  label: "Link color",
3391
3734
  defaultValue: linkColor,
3392
3735
  onChange: (linkColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { linkColor: linkColor2 }) }))
3393
3736
  }
3394
- ), /* @__PURE__ */ React60__default.default.createElement(
3737
+ ), /* @__PURE__ */ React58__default.default.createElement(
3395
3738
  MultiStylePropertyPanel,
3396
3739
  {
3397
3740
  names: ["backgroundColor", "fontFamily", "padding"],
@@ -3402,7 +3745,7 @@ function SignatureSidebarPanel({ data, setData }) {
3402
3745
  }
3403
3746
  function SpacerSidebarPanel({ data, setData }) {
3404
3747
  var _a, _b;
3405
- const [, setErrors] = React60.useState(null);
3748
+ const [, setErrors] = React58.useState(null);
3406
3749
  const updateData = (d) => {
3407
3750
  const res = SpacerPropsSchema.safeParse(d);
3408
3751
  if (res.success) {
@@ -3412,11 +3755,11 @@ function SpacerSidebarPanel({ data, setData }) {
3412
3755
  setErrors(res.error);
3413
3756
  }
3414
3757
  };
3415
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Spacer block" }, /* @__PURE__ */ React60__default.default.createElement(
3758
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Spacer block" }, /* @__PURE__ */ React58__default.default.createElement(
3416
3759
  SliderInput,
3417
3760
  {
3418
3761
  label: "Height",
3419
- iconLabel: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.HeightOutlined, { sx: { color: "text.secondary" } }),
3762
+ iconLabel: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.HeightOutlined, { sx: { color: "text.secondary" } }),
3420
3763
  units: "px",
3421
3764
  step: 4,
3422
3765
  min: 4,
@@ -3428,7 +3771,7 @@ function SpacerSidebarPanel({ data, setData }) {
3428
3771
  }
3429
3772
  function TextSidebarPanel({ data, setData }) {
3430
3773
  var _a, _b, _c, _d;
3431
- const [, setErrors] = React60.useState(null);
3774
+ const [, setErrors] = React58.useState(null);
3432
3775
  const updateData = (d) => {
3433
3776
  const res = TextPropsSchema.safeParse(d);
3434
3777
  if (res.success) {
@@ -3438,7 +3781,7 @@ function TextSidebarPanel({ data, setData }) {
3438
3781
  setErrors(res.error);
3439
3782
  }
3440
3783
  };
3441
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Text block" }, /* @__PURE__ */ React60__default.default.createElement(
3784
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Text block" }, /* @__PURE__ */ React58__default.default.createElement(
3442
3785
  TextInput,
3443
3786
  {
3444
3787
  label: "Content",
@@ -3446,17 +3789,27 @@ function TextSidebarPanel({ data, setData }) {
3446
3789
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.text) != null ? _b : "",
3447
3790
  onChange: (text) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text }) }))
3448
3791
  }
3449
- ), /* @__PURE__ */ React60__default.default.createElement(
3792
+ ), /* @__PURE__ */ React58__default.default.createElement(
3450
3793
  BooleanInput,
3451
3794
  {
3452
3795
  label: "Markdown",
3453
3796
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.markdown) != null ? _d : false,
3454
3797
  onChange: (markdown) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { markdown }) }))
3455
3798
  }
3456
- ), /* @__PURE__ */ React60__default.default.createElement(
3799
+ ), /* @__PURE__ */ React58__default.default.createElement(
3457
3800
  MultiStylePropertyPanel,
3458
3801
  {
3459
- names: ["color", "backgroundColor", "fontFamily", "fontSize", "fontWeight", "textAlign", "padding"],
3802
+ names: [
3803
+ "color",
3804
+ "backgroundColor",
3805
+ "fontFamily",
3806
+ "fontSize",
3807
+ "fontWeight",
3808
+ "lineHeight",
3809
+ "letterSpacing",
3810
+ "textAlign",
3811
+ "padding"
3812
+ ],
3460
3813
  value: data.style,
3461
3814
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
3462
3815
  }
@@ -3465,7 +3818,7 @@ function TextSidebarPanel({ data, setData }) {
3465
3818
 
3466
3819
  // src/app/inspector-drawer/configuration-panel/index.tsx
3467
3820
  function renderMessage(val) {
3468
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { m: 3, p: 1, border: "1px dashed", borderColor: "divider" } }, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { color: "text.secondary" }, val));
3821
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { m: 3, p: 1, border: "1px dashed", borderColor: "divider" } }, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { color: "text.secondary" }, val));
3469
3822
  }
3470
3823
  function ConfigurationPanel() {
3471
3824
  const document2 = useDocument();
@@ -3481,55 +3834,55 @@ function ConfigurationPanel() {
3481
3834
  const { data, type } = block;
3482
3835
  switch (type) {
3483
3836
  case "Avatar":
3484
- return /* @__PURE__ */ React60__default.default.createElement(AvatarSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3837
+ return /* @__PURE__ */ React58__default.default.createElement(AvatarSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3485
3838
  case "Button":
3486
- return /* @__PURE__ */ React60__default.default.createElement(ButtonSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3839
+ return /* @__PURE__ */ React58__default.default.createElement(ButtonSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3487
3840
  case "ColumnsContainer":
3488
- return /* @__PURE__ */ React60__default.default.createElement(ColumnsContainerPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3841
+ return /* @__PURE__ */ React58__default.default.createElement(ColumnsContainerPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3489
3842
  case "Container":
3490
- return /* @__PURE__ */ React60__default.default.createElement(ContainerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3843
+ return /* @__PURE__ */ React58__default.default.createElement(ContainerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3491
3844
  case "Divider":
3492
- return /* @__PURE__ */ React60__default.default.createElement(DividerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3845
+ return /* @__PURE__ */ React58__default.default.createElement(DividerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3493
3846
  case "Heading":
3494
- return /* @__PURE__ */ React60__default.default.createElement(HeadingSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3847
+ return /* @__PURE__ */ React58__default.default.createElement(HeadingSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3495
3848
  case "Html":
3496
- return /* @__PURE__ */ React60__default.default.createElement(HtmlSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3849
+ return /* @__PURE__ */ React58__default.default.createElement(HtmlSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3497
3850
  case "Image":
3498
- return /* @__PURE__ */ React60__default.default.createElement(ImageSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3851
+ return /* @__PURE__ */ React58__default.default.createElement(ImageSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3499
3852
  case "EmailLayout":
3500
- return /* @__PURE__ */ React60__default.default.createElement(EmailLayoutSidebarFields, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3853
+ return /* @__PURE__ */ React58__default.default.createElement(EmailLayoutSidebarFields, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3501
3854
  case "Spacer":
3502
- return /* @__PURE__ */ React60__default.default.createElement(SpacerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3855
+ return /* @__PURE__ */ React58__default.default.createElement(SpacerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3503
3856
  case "Signature":
3504
- return /* @__PURE__ */ React60__default.default.createElement(SignatureSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3857
+ return /* @__PURE__ */ React58__default.default.createElement(SignatureSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3505
3858
  case "Text":
3506
- return /* @__PURE__ */ React60__default.default.createElement(TextSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3859
+ return /* @__PURE__ */ React58__default.default.createElement(TextSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3507
3860
  default:
3508
- return /* @__PURE__ */ React60__default.default.createElement("pre", null, JSON.stringify(block, null, " "));
3861
+ return /* @__PURE__ */ React58__default.default.createElement("pre", null, JSON.stringify(block, null, " "));
3509
3862
  }
3510
3863
  }
3511
3864
  function StylesPanel() {
3512
3865
  const block = useDocument().root;
3513
3866
  if (!block) {
3514
- return /* @__PURE__ */ React60__default.default.createElement("p", null, "Block not found");
3867
+ return /* @__PURE__ */ React58__default.default.createElement("p", null, "Block not found");
3515
3868
  }
3516
3869
  const { data, type } = block;
3517
3870
  if (type !== "EmailLayout") {
3518
3871
  throw new Error('Expected "root" element to be of type EmailLayout');
3519
3872
  }
3520
- return /* @__PURE__ */ React60__default.default.createElement(EmailLayoutSidebarFields, { key: "root", data, setData: (data2) => setDocument({ root: { type, data: data2 } }) });
3873
+ return /* @__PURE__ */ React58__default.default.createElement(EmailLayoutSidebarFields, { key: "root", data, setData: (data2) => setDocument({ root: { type, data: data2 } }) });
3521
3874
  }
3522
3875
  function TemplateDownloadButton() {
3523
3876
  const doc = useDocument();
3524
- const href = React60.useMemo(() => {
3877
+ const href = React58.useMemo(() => {
3525
3878
  return `data:text/plain,${encodeURIComponent(JSON.stringify(doc, null, " "))}`;
3526
3879
  }, [doc]);
3527
- return /* @__PURE__ */ React60__default.default.createElement(
3880
+ return /* @__PURE__ */ React58__default.default.createElement(
3528
3881
  material.Button,
3529
3882
  {
3530
3883
  variant: "outlined",
3531
3884
  color: "primary",
3532
- startIcon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FileDownloadOutlined, null),
3885
+ startIcon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FileDownloadOutlined, null),
3533
3886
  href,
3534
3887
  download: "emailTemplate.json",
3535
3888
  fullWidth: true
@@ -3561,9 +3914,9 @@ function TemplatePanel({ deleteTemplate, copyTemplate }) {
3561
3914
  }
3562
3915
  };
3563
3916
  if (!currentTemplateId) {
3564
- return /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Template" }, "No template selected");
3917
+ return /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Template" }, "No template selected");
3565
3918
  }
3566
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Template" }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 2 }, !persistenceEnabled && /* @__PURE__ */ React60__default.default.createElement(
3919
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Template" }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 2 }, !persistenceEnabled && /* @__PURE__ */ React58__default.default.createElement(
3567
3920
  material.Typography,
3568
3921
  {
3569
3922
  variant: "body2",
@@ -3576,110 +3929,449 @@ function TemplatePanel({ deleteTemplate, copyTemplate }) {
3576
3929
  }
3577
3930
  },
3578
3931
  "Save functionality is disabled. To enable saving, provide the necessary callback functions."
3579
- ), persistenceEnabled && /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
3932
+ ), persistenceEnabled && /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
3580
3933
  material.Button,
3581
3934
  {
3582
3935
  variant: "outlined",
3583
3936
  color: "primary",
3584
- startIcon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ContentCopyOutlined, null),
3937
+ startIcon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ContentCopyOutlined, null),
3585
3938
  onClick: handleCopyToSamples,
3586
3939
  fullWidth: true,
3587
3940
  disabled: !copyTemplate
3588
3941
  },
3589
3942
  "Save as Sample Template"
3590
- ), /* @__PURE__ */ React60__default.default.createElement(
3943
+ ), /* @__PURE__ */ React58__default.default.createElement(
3591
3944
  material.Button,
3592
3945
  {
3593
3946
  variant: "outlined",
3594
3947
  color: "error",
3595
- startIcon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.DeleteOutlined, null),
3948
+ startIcon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DeleteOutlined, null),
3596
3949
  onClick: handleDelete,
3597
3950
  fullWidth: true,
3598
3951
  disabled: !deleteTemplate
3599
3952
  },
3600
3953
  "Delete Template"
3601
- )))), persistenceEnabled && /* @__PURE__ */ React60__default.default.createElement(BaseSidebarPanel, { title: "Export" }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 2 }, /* @__PURE__ */ React60__default.default.createElement(TemplateDownloadButton, null))));
3954
+ )))), persistenceEnabled && /* @__PURE__ */ React58__default.default.createElement(BaseSidebarPanel, { title: "Export" }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 2 }, /* @__PURE__ */ React58__default.default.createElement(TemplateDownloadButton, null))));
3602
3955
  }
3956
+
3957
+ // src/app/variables/variable-utils.ts
3603
3958
  var VARIABLE_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
3604
- function validateName(name, index, all) {
3605
- if (!name.trim()) return "Name is required";
3606
- if (!VARIABLE_NAME_RE.test(name)) return "Use letters, digits, underscore; start with a letter or underscore";
3607
- const duplicate = all.some((v, i) => i !== index && v.name === name);
3959
+ var MAX_VARIABLE_NAME_LENGTH = 64;
3960
+ var RESERVED_VARIABLE_NAMES = /* @__PURE__ */ new Set(["this", "true", "false", "null", "undefined"]);
3961
+ var HANDLEBARS_KEYWORDS = /* @__PURE__ */ new Set(["if", "each", "unless", "else", "with"]);
3962
+ function validateVariableName(name, siblings, indexBeingEdited) {
3963
+ const trimmed = name.trim();
3964
+ if (!trimmed) return "Name is required";
3965
+ if (trimmed.length > MAX_VARIABLE_NAME_LENGTH) return `Max ${MAX_VARIABLE_NAME_LENGTH} characters`;
3966
+ if (!VARIABLE_NAME_RE.test(trimmed)) return "Use letters, digits, underscore; start with a letter or underscore";
3967
+ if (RESERVED_VARIABLE_NAMES.has(trimmed)) return "Reserved word; pick another name";
3968
+ const duplicate = siblings.some((v, i) => i !== indexBeingEdited && v.name === trimmed);
3608
3969
  if (duplicate) return "Already declared";
3609
3970
  return null;
3610
3971
  }
3972
+ var TOKEN_ROOT_RE = /\{\{\s*(?:#(?:if|each|unless|with)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)(?:\.[\w.]+)?\s*\}\}/g;
3973
+ function extractTokenRoots(text) {
3974
+ if (!text) return [];
3975
+ const roots = /* @__PURE__ */ new Set();
3976
+ for (const m of text.matchAll(TOKEN_ROOT_RE)) {
3977
+ const name = m[1];
3978
+ if (RESERVED_VARIABLE_NAMES.has(name) || HANDLEBARS_KEYWORDS.has(name)) continue;
3979
+ roots.add(name);
3980
+ }
3981
+ return [...roots];
3982
+ }
3983
+ function forEachTextFieldInDocument(doc, visit) {
3984
+ var _a, _b;
3985
+ const root = doc.root;
3986
+ if (root && root.type === "EmailLayout" && typeof ((_a = root.data) == null ? void 0 : _a.subject) === "string") {
3987
+ visit(root.data.subject);
3988
+ }
3989
+ for (const [id, block] of Object.entries(doc)) {
3990
+ if (id === "root" || !block || typeof block !== "object") continue;
3991
+ const type = block.type;
3992
+ const props = (_b = block.data) == null ? void 0 : _b.props;
3993
+ if (!props) continue;
3994
+ if ((type === "Text" || type === "Heading" || type === "Button") && typeof props.text === "string") {
3995
+ visit(props.text);
3996
+ } else if (type === "Html" && typeof props.contents === "string") {
3997
+ visit(props.contents);
3998
+ }
3999
+ }
4000
+ }
4001
+ function collectTokenUsage(doc) {
4002
+ const usage = /* @__PURE__ */ new Map();
4003
+ forEachTextFieldInDocument(doc, (value) => {
4004
+ var _a;
4005
+ for (const root of extractTokenRoots(value)) {
4006
+ usage.set(root, ((_a = usage.get(root)) != null ? _a : 0) + 1);
4007
+ }
4008
+ });
4009
+ return usage;
4010
+ }
4011
+ function escapeRegex(name) {
4012
+ return name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4013
+ }
4014
+ function buildRenameReplacers(oldName, newName) {
4015
+ const esc = escapeRegex(oldName);
4016
+ const simple = new RegExp(`\\{\\{\\s*${esc}(\\.[\\w.]+)?\\s*\\}\\}`, "g");
4017
+ const helper = new RegExp(`(\\{\\{\\s*#(?:if|each|unless|with)\\s+)${esc}(\\.[\\w.]+)?(\\s*\\}\\})`, "g");
4018
+ return (text) => text.replace(helper, `$1${newName}$2$3`).replace(simple, `{{${newName}$1}}`);
4019
+ }
4020
+ function buildRenamePatch(doc, oldName, newName) {
4021
+ var _a;
4022
+ if (oldName === newName) return {};
4023
+ const rewrite = buildRenameReplacers(oldName, newName);
4024
+ const patch = {};
4025
+ const root = doc.root;
4026
+ if (root && root.type === "EmailLayout") {
4027
+ const layoutData = root.data;
4028
+ const oldSubject = (_a = layoutData.subject) != null ? _a : "";
4029
+ const newSubject = rewrite(oldSubject);
4030
+ if (newSubject !== oldSubject) {
4031
+ patch.root = __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, layoutData), { subject: newSubject }) });
4032
+ }
4033
+ }
4034
+ for (const [id, block] of Object.entries(doc)) {
4035
+ if (id === "root" || !block || typeof block !== "object") continue;
4036
+ const type = block.type;
4037
+ const data = block.data;
4038
+ const props = data == null ? void 0 : data.props;
4039
+ if (!props) continue;
4040
+ if ((type === "Text" || type === "Heading" || type === "Button") && typeof props.text === "string") {
4041
+ const nextText = rewrite(props.text);
4042
+ if (nextText !== props.text) {
4043
+ patch[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { text: nextText }) }) });
4044
+ }
4045
+ } else if (type === "Html" && typeof props.contents === "string") {
4046
+ const nextContents = rewrite(props.contents);
4047
+ if (nextContents !== props.contents) {
4048
+ patch[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { contents: nextContents }) }) });
4049
+ }
4050
+ }
4051
+ }
4052
+ return patch;
4053
+ }
4054
+ function substituteSampleValues(text, samples) {
4055
+ if (!text) return text;
4056
+ let out = text;
4057
+ out = out.replace(
4058
+ /\{\{\s*#(?:if|each|unless|with)\s+[^}]*\}\}/g,
4059
+ ""
4060
+ );
4061
+ out = out.replace(/\{\{\s*\/(?:if|each|unless|with)\s*\}\}/g, "");
4062
+ out = out.replace(/\{\{\s*else\s*\}\}/g, "");
4063
+ out = out.replace(TOKEN_ROOT_RE, (match, root) => {
4064
+ var _a;
4065
+ if (!samples.has(root)) return match;
4066
+ return (_a = samples.get(root)) != null ? _a : "";
4067
+ });
4068
+ return out;
4069
+ }
4070
+ function buildSampleValueMap(variables) {
4071
+ const m = /* @__PURE__ */ new Map();
4072
+ if (!variables) return m;
4073
+ for (const v of variables) {
4074
+ if (v.name && typeof v.sampleValue === "string" && v.sampleValue.length > 0) {
4075
+ m.set(v.name, v.sampleValue);
4076
+ }
4077
+ }
4078
+ return m;
4079
+ }
4080
+ function applySampleValuesToDocument(doc, samples) {
4081
+ if (samples.size === 0) return doc;
4082
+ const next = __spreadValues({}, doc);
4083
+ const root = doc.root;
4084
+ if (root && root.type === "EmailLayout") {
4085
+ const layoutData = root.data;
4086
+ if (typeof layoutData.subject === "string") {
4087
+ const newSubject = substituteSampleValues(layoutData.subject, samples);
4088
+ if (newSubject !== layoutData.subject) {
4089
+ next.root = __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, layoutData), { subject: newSubject }) });
4090
+ }
4091
+ }
4092
+ }
4093
+ for (const [id, block] of Object.entries(doc)) {
4094
+ if (id === "root" || !block || typeof block !== "object") continue;
4095
+ const type = block.type;
4096
+ const data = block.data;
4097
+ const props = data == null ? void 0 : data.props;
4098
+ if (!props) continue;
4099
+ if ((type === "Text" || type === "Heading" || type === "Button") && typeof props.text === "string") {
4100
+ const newText = substituteSampleValues(props.text, samples);
4101
+ if (newText !== props.text) {
4102
+ next[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { text: newText }) }) });
4103
+ }
4104
+ } else if (type === "Html" && typeof props.contents === "string") {
4105
+ const newContents = substituteSampleValues(props.contents, samples);
4106
+ if (newContents !== props.contents) {
4107
+ next[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { contents: newContents }) }) });
4108
+ }
4109
+ }
4110
+ }
4111
+ return next;
4112
+ }
4113
+
4114
+ // src/app/inspector-drawer/variables-panel.tsx
4115
+ function toPersistShape(v) {
4116
+ return {
4117
+ name: v.name,
4118
+ description: v.description ? v.description : void 0,
4119
+ sampleValue: v.sampleValue ? v.sampleValue : void 0
4120
+ };
4121
+ }
3611
4122
  function VariablesPanel() {
3612
4123
  var _a;
3613
4124
  const document2 = useDocument();
4125
+ const lastFocused = useLastFocusedEditable();
3614
4126
  const root = document2.root;
3615
4127
  if (!root || root.type !== "EmailLayout") {
3616
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { p: 2 }, /* @__PURE__ */ React60__default.default.createElement(material.Alert, { severity: "info" }, "Open a template to manage variables."));
4128
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { p: 2 }, /* @__PURE__ */ React58__default.default.createElement(material.Alert, { severity: "info" }, "Open a template to manage variables."));
3617
4129
  }
3618
4130
  const data = root.data;
3619
4131
  const variables = ((_a = data.variables) != null ? _a : []).map((v) => {
3620
- var _a2;
4132
+ var _a2, _b;
3621
4133
  return {
3622
4134
  name: v.name,
3623
- description: (_a2 = v.description) != null ? _a2 : ""
4135
+ description: (_a2 = v.description) != null ? _a2 : "",
4136
+ sampleValue: (_b = v.sampleValue) != null ? _b : ""
3624
4137
  };
3625
4138
  });
3626
- const commit = (next) => {
3627
- setDocument({
3628
- root: __spreadProps(__spreadValues({}, root), {
3629
- data: __spreadProps(__spreadValues({}, data), {
3630
- variables: next.map((v) => ({
3631
- name: v.name,
3632
- description: v.description ? v.description : void 0
3633
- }))
3634
- })
4139
+ const usage = React58.useMemo(() => collectTokenUsage(document2), [document2]);
4140
+ const declaredNames = React58.useMemo(() => new Set(variables.map((v) => v.name)), [variables]);
4141
+ const undeclared = React58.useMemo(
4142
+ () => [...usage.keys()].filter((n) => n && !declaredNames.has(n)),
4143
+ [usage, declaredNames]
4144
+ );
4145
+ const writeVariables = (next, extraPatch = {}) => {
4146
+ var _a2;
4147
+ const baseRoot = (_a2 = extraPatch.root) != null ? _a2 : root;
4148
+ const newRoot = __spreadProps(__spreadValues({}, baseRoot), {
4149
+ data: __spreadProps(__spreadValues({}, baseRoot.data), {
4150
+ variables: next.map(toPersistShape)
3635
4151
  })
3636
4152
  });
4153
+ setDocument(__spreadProps(__spreadValues({}, extraPatch), { root: newRoot }));
3637
4154
  };
3638
4155
  const updateAt = (index, patch) => {
3639
4156
  const next = variables.map((v, i) => i === index ? __spreadValues(__spreadValues({}, v), patch) : v);
3640
- commit(next);
4157
+ writeVariables(next);
3641
4158
  };
3642
4159
  const add = () => {
3643
- commit([...variables, { name: "", description: "" }]);
4160
+ writeVariables([...variables, { name: "", description: "", sampleValue: "" }]);
4161
+ };
4162
+ const addFromToken = (name) => {
4163
+ writeVariables([...variables, { name, description: "", sampleValue: "" }]);
3644
4164
  };
3645
4165
  const removeAt = (index) => {
3646
- commit(variables.filter((_, i) => i !== index));
4166
+ var _a2;
4167
+ const v = variables[index];
4168
+ const usageCount = v.name ? (_a2 = usage.get(v.name)) != null ? _a2 : 0 : 0;
4169
+ if (usageCount > 0) {
4170
+ const ok = window.confirm(
4171
+ `"${v.name}" is still referenced in the body (${usageCount} occurrence${usageCount === 1 ? "" : "s"}). Delete anyway?`
4172
+ );
4173
+ if (!ok) return;
4174
+ }
4175
+ writeVariables(variables.filter((_, i) => i !== index));
4176
+ };
4177
+ const commitRename = (index, newName) => {
4178
+ const oldName = variables[index].name;
4179
+ const trimmed = newName.trim();
4180
+ if (trimmed === oldName) return;
4181
+ const error = validateVariableName(trimmed, variables, index);
4182
+ if (error) return;
4183
+ const patch = oldName ? buildRenamePatch(document2, oldName, trimmed) : {};
4184
+ const next = variables.map((v, i) => i === index ? __spreadProps(__spreadValues({}, v), { name: trimmed }) : v);
4185
+ writeVariables(next, patch);
3647
4186
  };
3648
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { p: 2 }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { mb: 1 } }, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "subtitle1", sx: { fontWeight: 600 } }, "Variables"), /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Add variable" }, /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { size: "small", onClick: add, "aria-label": "Add variable" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" })))), /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mb: 2 } }, "Declared variables travel with the template. Reference them in subject and body as", " ", /* @__PURE__ */ React60__default.default.createElement(material.Box, { component: "code", sx: { fontFamily: "monospace" } }, "{{name}}"), "."), variables.length === 0 ? /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary" } }, "No variables declared. Click + to add one.") : /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 2 }, variables.map((v, i) => {
4187
+ const canInsert = Boolean(
4188
+ lastFocused && (lastFocused.field === "subject" || lastFocused.blockId && document2[lastFocused.blockId])
4189
+ );
4190
+ const insertIntoFocused = (name) => {
4191
+ var _a2, _b, _c;
4192
+ const focused = getLastFocusedEditable();
4193
+ if (!focused) return;
4194
+ const token = `{{${name}}}`;
4195
+ if (focused.field === "subject") {
4196
+ const layoutData = root.data;
4197
+ const current2 = (_a2 = layoutData.subject) != null ? _a2 : "";
4198
+ const next2 = current2.slice(0, focused.selectionStart) + token + current2.slice(focused.selectionEnd);
4199
+ setDocument({
4200
+ root: __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, layoutData), { subject: next2 }) })
4201
+ });
4202
+ return;
4203
+ }
4204
+ const block = document2[focused.blockId];
4205
+ if (!block) return;
4206
+ const blockData = block.data;
4207
+ const props = (_b = blockData == null ? void 0 : blockData.props) != null ? _b : {};
4208
+ const field = focused.field;
4209
+ const current = (_c = props[field]) != null ? _c : "";
4210
+ const next = current.slice(0, focused.selectionStart) + token + current.slice(focused.selectionEnd);
4211
+ setDocument({
4212
+ [focused.blockId]: __spreadProps(__spreadValues({}, block), {
4213
+ data: __spreadProps(__spreadValues({}, blockData), { props: __spreadProps(__spreadValues({}, props), { [field]: next }) })
4214
+ })
4215
+ });
4216
+ };
4217
+ const copy = (name) => __async(null, null, function* () {
4218
+ try {
4219
+ yield navigator.clipboard.writeText(`{{${name}}}`);
4220
+ } catch (e) {
4221
+ }
4222
+ });
4223
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { p: 2 }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { mb: 1 } }, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "subtitle1", sx: { fontWeight: 600 } }, "Variables"), /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Add variable" }, /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { size: "small", onClick: add, "aria-label": "Add variable" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" })))), /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mb: 2 } }, "Declared variables travel with the template. Reference them in subject and body as", " ", /* @__PURE__ */ React58__default.default.createElement(material.Box, { component: "code", sx: { fontFamily: "monospace" } }, "{{name}}"), ". In Preview mode, tokens render with the sample values below."), undeclared.length > 0 && /* @__PURE__ */ React58__default.default.createElement(material.Alert, { severity: "warning", sx: { mb: 2 } }, /* @__PURE__ */ React58__default.default.createElement(material.AlertTitle, { sx: { fontSize: 13 } }, "Undeclared in body"), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, useFlexGap: true, flexWrap: "wrap" }, undeclared.map((name) => /* @__PURE__ */ React58__default.default.createElement(
4224
+ material.Chip,
4225
+ {
4226
+ key: name,
4227
+ size: "small",
4228
+ label: name,
4229
+ onClick: () => addFromToken(name),
4230
+ onDelete: () => addFromToken(name),
4231
+ deleteIcon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AddOutlined, null),
4232
+ sx: { fontFamily: "monospace" }
4233
+ }
4234
+ ))), /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 0.5 } }, "Click a token to declare it.")), variables.length === 0 ? /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary" } }, "No variables declared. Click + to add one.") : /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 2 }, variables.map((v, i) => {
3649
4235
  var _a2;
3650
- const nameError = validateName(v.name, i, variables);
3651
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { key: i, spacing: 0.75, sx: { pb: 1, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React60__default.default.createElement(
3652
- material.TextField,
4236
+ return /* @__PURE__ */ React58__default.default.createElement(
4237
+ VariableRow,
3653
4238
  {
3654
- label: "Name",
3655
- size: "small",
3656
- fullWidth: true,
3657
- value: v.name,
3658
- onChange: (e) => updateAt(i, { name: e.target.value }),
3659
- error: Boolean(nameError),
3660
- helperText: nameError != null ? nameError : " "
4239
+ key: i,
4240
+ index: i,
4241
+ variable: v,
4242
+ siblings: variables,
4243
+ usageCount: v.name ? (_a2 = usage.get(v.name)) != null ? _a2 : 0 : 0,
4244
+ canInsert,
4245
+ onCommitRename: (name) => commitRename(i, name),
4246
+ onChangeDescription: (description) => updateAt(i, { description }),
4247
+ onChangeSampleValue: (sampleValue) => updateAt(i, { sampleValue }),
4248
+ onRemove: () => removeAt(i),
4249
+ onInsert: () => v.name && insertIntoFocused(v.name),
4250
+ onCopy: () => v.name && copy(v.name)
3661
4251
  }
3662
- ), /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Remove" }, /* @__PURE__ */ React60__default.default.createElement(
3663
- material.IconButton,
3664
- {
3665
- size: "small",
3666
- onClick: () => removeAt(i),
3667
- "aria-label": `Remove ${v.name || "variable"}`,
3668
- sx: { mt: 0.5 }
4252
+ );
4253
+ })));
4254
+ }
4255
+ function VariableRow({
4256
+ index,
4257
+ variable,
4258
+ siblings,
4259
+ usageCount,
4260
+ canInsert,
4261
+ onCommitRename,
4262
+ onChangeDescription,
4263
+ onChangeSampleValue,
4264
+ onRemove,
4265
+ onInsert,
4266
+ onCopy
4267
+ }) {
4268
+ var _a, _b;
4269
+ const [draftName, setDraftName] = React58.useState(variable.name);
4270
+ const [isEditing, setIsEditing] = React58.useState(false);
4271
+ React58.useEffect(() => {
4272
+ if (!isEditing) setDraftName(variable.name);
4273
+ }, [variable.name, isEditing]);
4274
+ const nameError = validateVariableName(draftName, siblings, index);
4275
+ const unused = Boolean(variable.name) && usageCount === 0;
4276
+ const hasName = Boolean(variable.name);
4277
+ const commit = () => {
4278
+ setIsEditing(false);
4279
+ if (nameError) {
4280
+ setDraftName(variable.name);
4281
+ return;
4282
+ }
4283
+ if (draftName.trim() !== variable.name) {
4284
+ onCommitRename(draftName.trim());
4285
+ }
4286
+ };
4287
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 0.75, sx: { pb: 1, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58__default.default.createElement(
4288
+ material.TextField,
4289
+ {
4290
+ label: "Name",
4291
+ size: "small",
4292
+ fullWidth: true,
4293
+ value: draftName,
4294
+ onChange: (e) => {
4295
+ setDraftName(e.target.value);
4296
+ setIsEditing(true);
3669
4297
  },
3670
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.DeleteOutline, { fontSize: "small" })
3671
- ))), /* @__PURE__ */ React60__default.default.createElement(
3672
- material.TextField,
3673
- {
3674
- label: "Description",
3675
- size: "small",
3676
- fullWidth: true,
3677
- value: (_a2 = v.description) != null ? _a2 : "",
3678
- onChange: (e) => updateAt(i, { description: e.target.value }),
3679
- placeholder: "Optional"
4298
+ onFocus: () => setIsEditing(true),
4299
+ onBlur: commit,
4300
+ onKeyDown: (e) => {
4301
+ if (e.key === "Enter") {
4302
+ e.target.blur();
4303
+ } else if (e.key === "Escape") {
4304
+ setDraftName(variable.name);
4305
+ setIsEditing(false);
4306
+ e.target.blur();
4307
+ }
4308
+ },
4309
+ error: Boolean(nameError),
4310
+ helperText: nameError != null ? nameError : " "
4311
+ }
4312
+ ), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 0.25, sx: { mt: 0.5 } }, /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Copy {{name}}" }, /* @__PURE__ */ React58__default.default.createElement("span", null, /* @__PURE__ */ React58__default.default.createElement(
4313
+ material.IconButton,
4314
+ {
4315
+ size: "small",
4316
+ onClick: onCopy,
4317
+ disabled: !hasName,
4318
+ "aria-label": `Copy ${variable.name || "variable"} token`
4319
+ },
4320
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" })
4321
+ ))), /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: canInsert ? "Insert at cursor" : "Focus a text field first" }, /* @__PURE__ */ React58__default.default.createElement("span", null, /* @__PURE__ */ React58__default.default.createElement(
4322
+ material.IconButton,
4323
+ {
4324
+ size: "small",
4325
+ onClick: onInsert,
4326
+ disabled: !hasName || !canInsert,
4327
+ "aria-label": `Insert ${variable.name || "variable"} at cursor`
4328
+ },
4329
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.InputOutlined, { fontSize: "small" })
4330
+ ))), /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Remove" }, /* @__PURE__ */ React58__default.default.createElement(
4331
+ material.IconButton,
4332
+ {
4333
+ size: "small",
4334
+ onClick: onRemove,
4335
+ "aria-label": `Remove ${variable.name || "variable"}`
4336
+ },
4337
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DeleteOutline, { fontSize: "small" })
4338
+ )))), /* @__PURE__ */ React58__default.default.createElement(
4339
+ material.TextField,
4340
+ {
4341
+ label: "Description",
4342
+ size: "small",
4343
+ fullWidth: true,
4344
+ value: (_a = variable.description) != null ? _a : "",
4345
+ onChange: (e) => onChangeDescription(e.target.value),
4346
+ placeholder: "Optional"
4347
+ }
4348
+ ), /* @__PURE__ */ React58__default.default.createElement(
4349
+ material.TextField,
4350
+ {
4351
+ label: "Sample value",
4352
+ size: "small",
4353
+ fullWidth: true,
4354
+ value: (_b = variable.sampleValue) != null ? _b : "",
4355
+ onChange: (e) => onChangeSampleValue(e.target.value),
4356
+ placeholder: "Shown in Preview mode",
4357
+ InputProps: {
4358
+ startAdornment: /* @__PURE__ */ React58__default.default.createElement(
4359
+ iconsMaterial.DataObjectOutlined,
4360
+ {
4361
+ fontSize: "small",
4362
+ sx: { color: "text.secondary", mr: 0.75 }
4363
+ }
4364
+ )
3680
4365
  }
3681
- ));
3682
- })));
4366
+ }
4367
+ ), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, sx: { pt: 0.25 } }, hasName && (unused ? /* @__PURE__ */ React58__default.default.createElement(material.Chip, { size: "small", color: "warning", variant: "outlined", label: "Unused in body" }) : /* @__PURE__ */ React58__default.default.createElement(
4368
+ material.Chip,
4369
+ {
4370
+ size: "small",
4371
+ variant: "outlined",
4372
+ label: `${usageCount} ref${usageCount === 1 ? "" : "s"}`
4373
+ }
4374
+ ))));
3683
4375
  }
3684
4376
 
3685
4377
  // src/app/inspector-drawer/index.tsx
@@ -3696,13 +4388,13 @@ function InspectorDrawer({
3696
4388
  const renderCurrentSidebarPanel = () => {
3697
4389
  switch (selectedSidebarTab) {
3698
4390
  case "block-configuration":
3699
- return /* @__PURE__ */ React60__default.default.createElement(ConfigurationPanel, null);
4391
+ return /* @__PURE__ */ React58__default.default.createElement(ConfigurationPanel, null);
3700
4392
  case "styles":
3701
- return /* @__PURE__ */ React60__default.default.createElement(StylesPanel, null);
4393
+ return /* @__PURE__ */ React58__default.default.createElement(StylesPanel, null);
3702
4394
  case "variables":
3703
- return /* @__PURE__ */ React60__default.default.createElement(VariablesPanel, null);
4395
+ return /* @__PURE__ */ React58__default.default.createElement(VariablesPanel, null);
3704
4396
  case "template-settings":
3705
- return /* @__PURE__ */ React60__default.default.createElement(
4397
+ return /* @__PURE__ */ React58__default.default.createElement(
3706
4398
  TemplatePanel,
3707
4399
  {
3708
4400
  deleteTemplate,
@@ -3711,7 +4403,7 @@ function InspectorDrawer({
3711
4403
  );
3712
4404
  }
3713
4405
  };
3714
- return /* @__PURE__ */ React60__default.default.createElement(
4406
+ return /* @__PURE__ */ React58__default.default.createElement(
3715
4407
  material.Drawer,
3716
4408
  {
3717
4409
  variant: "persistent",
@@ -3733,7 +4425,7 @@ function InspectorDrawer({
3733
4425
  width: inspectorDrawerOpen ? INSPECTOR_DRAWER_WIDTH : 0
3734
4426
  }
3735
4427
  },
3736
- /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: 49, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React60__default.default.createElement(material.Box, { px: 1 }, /* @__PURE__ */ React60__default.default.createElement(
4428
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: 49, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React58__default.default.createElement(material.Box, { px: 1 }, /* @__PURE__ */ React58__default.default.createElement(
3737
4429
  material.Tabs,
3738
4430
  {
3739
4431
  value: selectedSidebarTab,
@@ -3741,25 +4433,25 @@ function InspectorDrawer({
3741
4433
  variant: "fullWidth",
3742
4434
  sx: { "& .MuiTab-root": { minWidth: 0, px: 1, fontSize: 13 } }
3743
4435
  },
3744
- /* @__PURE__ */ React60__default.default.createElement(material.Tab, { value: "styles", label: "Styles" }),
3745
- /* @__PURE__ */ React60__default.default.createElement(material.Tab, { value: "block-configuration", label: "Inspect" }),
3746
- /* @__PURE__ */ React60__default.default.createElement(material.Tab, { value: "variables", label: "Variables" }),
3747
- /* @__PURE__ */ React60__default.default.createElement(material.Tab, { value: "template-settings", label: "Settings" })
4436
+ /* @__PURE__ */ React58__default.default.createElement(material.Tab, { value: "styles", label: "Styles" }),
4437
+ /* @__PURE__ */ React58__default.default.createElement(material.Tab, { value: "block-configuration", label: "Inspect" }),
4438
+ /* @__PURE__ */ React58__default.default.createElement(material.Tab, { value: "variables", label: "Variables" }),
4439
+ /* @__PURE__ */ React58__default.default.createElement(material.Tab, { value: "template-settings", label: "Settings" })
3748
4440
  ))),
3749
- /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" } }, renderCurrentSidebarPanel())
4441
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" } }, renderCurrentSidebarPanel())
3750
4442
  );
3751
4443
  }
3752
- var SnackbarContext = React60.createContext(null);
4444
+ var SnackbarContext = React58.createContext(null);
3753
4445
  function useSnackbar() {
3754
- const context = React60.useContext(SnackbarContext);
4446
+ const context = React58.useContext(SnackbarContext);
3755
4447
  if (!context) {
3756
4448
  throw new Error("useSnackbar must be used within a SnackbarProvider");
3757
4449
  }
3758
4450
  return context;
3759
4451
  }
3760
4452
  function SnackbarProvider({ children }) {
3761
- const [message, setMessage] = React60.useState(null);
3762
- const [duration, setDuration] = React60.useState(3e3);
4453
+ const [message, setMessage] = React58.useState(null);
4454
+ const [duration, setDuration] = React58.useState(3e3);
3763
4455
  const showMessage = (text, customDuration = 3e3) => {
3764
4456
  setMessage(text);
3765
4457
  setDuration(customDuration);
@@ -3767,7 +4459,7 @@ function SnackbarProvider({ children }) {
3767
4459
  const handleClose = () => {
3768
4460
  setMessage(null);
3769
4461
  };
3770
- return /* @__PURE__ */ React60__default.default.createElement(SnackbarContext.Provider, { value: { showMessage } }, children, /* @__PURE__ */ React60__default.default.createElement(
4462
+ return /* @__PURE__ */ React58__default.default.createElement(SnackbarContext.Provider, { value: { showMessage } }, children, /* @__PURE__ */ React58__default.default.createElement(
3771
4463
  material.Snackbar,
3772
4464
  {
3773
4465
  anchorOrigin: { vertical: "top", horizontal: "center" },
@@ -3814,7 +4506,7 @@ function TemplateRow({
3814
4506
  onDuplicateAsTemplate
3815
4507
  }) {
3816
4508
  const { setCurrentTemplate } = useEmailEditor();
3817
- const [hover, setHover] = React60.useState(false);
4509
+ const [hover, setHover] = React58.useState(false);
3818
4510
  const handleClick = () => __async(null, null, function* () {
3819
4511
  try {
3820
4512
  const content = yield templateLoader();
@@ -3833,7 +4525,7 @@ function TemplateRow({
3833
4525
  const hasActions = Boolean(
3834
4526
  onDuplicate || onRename || onDelete || onPromote || onDemote || onDuplicateAsTemplate
3835
4527
  );
3836
- return /* @__PURE__ */ React60__default.default.createElement(
4528
+ return /* @__PURE__ */ React58__default.default.createElement(
3837
4529
  material.Box,
3838
4530
  {
3839
4531
  role: "button",
@@ -3859,7 +4551,7 @@ function TemplateRow({
3859
4551
  "&:focus-visible": { outline: "2px solid", outlineColor: "primary.main" }
3860
4552
  }
3861
4553
  },
3862
- /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", alignItems: "flex-start", spacing: 1 }, /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { flexGrow: 1, minWidth: 0 } }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", alignItems: "baseline", spacing: 1, sx: { minWidth: 0 } }, /* @__PURE__ */ React60__default.default.createElement(
4554
+ /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", alignItems: "flex-start", spacing: 1 }, /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { flexGrow: 1, minWidth: 0 } }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", alignItems: "baseline", spacing: 1, sx: { minWidth: 0 } }, /* @__PURE__ */ React58__default.default.createElement(
3863
4555
  material.Typography,
3864
4556
  {
3865
4557
  variant: "body2",
@@ -3873,14 +4565,14 @@ function TemplateRow({
3873
4565
  title: template.slug
3874
4566
  },
3875
4567
  template.slug
3876
- ), updated && /* @__PURE__ */ React60__default.default.createElement(
4568
+ ), updated && /* @__PURE__ */ React58__default.default.createElement(
3877
4569
  material.Typography,
3878
4570
  {
3879
4571
  variant: "caption",
3880
4572
  sx: { color: "text.secondary", flexShrink: 0, fontSize: "0.7rem" }
3881
4573
  },
3882
4574
  updated
3883
- )), template.description && /* @__PURE__ */ React60__default.default.createElement(
4575
+ )), template.description && /* @__PURE__ */ React58__default.default.createElement(
3884
4576
  material.Typography,
3885
4577
  {
3886
4578
  variant: "caption",
@@ -3894,7 +4586,7 @@ function TemplateRow({
3894
4586
  }
3895
4587
  },
3896
4588
  template.description
3897
- ), template.tags && template.tags.length > 0 && /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, sx: { mt: 0.5, flexWrap: "wrap", gap: 0.5 } }, template.tags.map((tag) => /* @__PURE__ */ React60__default.default.createElement(
4589
+ ), template.tags && template.tags.length > 0 && /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, sx: { mt: 0.5, flexWrap: "wrap", gap: 0.5 } }, template.tags.map((tag) => /* @__PURE__ */ React58__default.default.createElement(
3898
4590
  material.Chip,
3899
4591
  {
3900
4592
  key: tag,
@@ -3903,7 +4595,7 @@ function TemplateRow({
3903
4595
  sx: { height: 18, fontSize: "0.65rem", "& .MuiChip-label": { px: 0.75 } }
3904
4596
  }
3905
4597
  ))))),
3906
- hasActions && hover && /* @__PURE__ */ React60__default.default.createElement(
4598
+ hasActions && hover && /* @__PURE__ */ React58__default.default.createElement(
3907
4599
  material.Stack,
3908
4600
  {
3909
4601
  direction: "row",
@@ -3919,7 +4611,7 @@ function TemplateRow({
3919
4611
  p: 0.25
3920
4612
  }
3921
4613
  },
3922
- onDuplicateAsTemplate && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Duplicate as template" }, /* @__PURE__ */ React60__default.default.createElement(
4614
+ onDuplicateAsTemplate && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Duplicate as template" }, /* @__PURE__ */ React58__default.default.createElement(
3923
4615
  material.IconButton,
3924
4616
  {
3925
4617
  size: "small",
@@ -3928,9 +4620,9 @@ function TemplateRow({
3928
4620
  onDuplicateAsTemplate();
3929
4621
  }
3930
4622
  },
3931
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.LibraryAddOutlined, { fontSize: "small" })
4623
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.LibraryAddOutlined, { fontSize: "small" })
3932
4624
  )),
3933
- onDuplicate && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Duplicate" }, /* @__PURE__ */ React60__default.default.createElement(
4625
+ onDuplicate && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Duplicate" }, /* @__PURE__ */ React58__default.default.createElement(
3934
4626
  material.IconButton,
3935
4627
  {
3936
4628
  size: "small",
@@ -3939,9 +4631,9 @@ function TemplateRow({
3939
4631
  onDuplicate();
3940
4632
  }
3941
4633
  },
3942
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" })
4634
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" })
3943
4635
  )),
3944
- onRename && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Rename" }, /* @__PURE__ */ React60__default.default.createElement(
4636
+ onRename && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Rename" }, /* @__PURE__ */ React58__default.default.createElement(
3945
4637
  material.IconButton,
3946
4638
  {
3947
4639
  size: "small",
@@ -3950,9 +4642,9 @@ function TemplateRow({
3950
4642
  onRename();
3951
4643
  }
3952
4644
  },
3953
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.DriveFileRenameOutlineOutlined, { fontSize: "small" })
4645
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DriveFileRenameOutlineOutlined, { fontSize: "small" })
3954
4646
  )),
3955
- onPromote && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Promote to sample" }, /* @__PURE__ */ React60__default.default.createElement(
4647
+ onPromote && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Promote to sample" }, /* @__PURE__ */ React58__default.default.createElement(
3956
4648
  material.IconButton,
3957
4649
  {
3958
4650
  size: "small",
@@ -3961,9 +4653,9 @@ function TemplateRow({
3961
4653
  onPromote();
3962
4654
  }
3963
4655
  },
3964
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FileUploadOutlined, { fontSize: "small" })
4656
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FileUploadOutlined, { fontSize: "small" })
3965
4657
  )),
3966
- onDemote && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Demote to template" }, /* @__PURE__ */ React60__default.default.createElement(
4658
+ onDemote && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Demote to template" }, /* @__PURE__ */ React58__default.default.createElement(
3967
4659
  material.IconButton,
3968
4660
  {
3969
4661
  size: "small",
@@ -3972,9 +4664,9 @@ function TemplateRow({
3972
4664
  onDemote();
3973
4665
  }
3974
4666
  },
3975
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FileDownloadOutlined, { fontSize: "small" })
4667
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FileDownloadOutlined, { fontSize: "small" })
3976
4668
  )),
3977
- onDelete && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Delete" }, /* @__PURE__ */ React60__default.default.createElement(
4669
+ onDelete && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Delete" }, /* @__PURE__ */ React58__default.default.createElement(
3978
4670
  material.IconButton,
3979
4671
  {
3980
4672
  size: "small",
@@ -3983,7 +4675,7 @@ function TemplateRow({
3983
4675
  onDelete();
3984
4676
  }
3985
4677
  },
3986
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.DeleteOutlined, { fontSize: "small" })
4678
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DeleteOutlined, { fontSize: "small" })
3987
4679
  ))
3988
4680
  )
3989
4681
  );
@@ -3995,10 +4687,10 @@ function RenameDialog({
3995
4687
  onClose,
3996
4688
  onSubmit
3997
4689
  }) {
3998
- const [value, setValue] = React60.useState(currentSlug);
3999
- const [error, setError] = React60.useState(null);
4000
- const [submitting, setSubmitting] = React60.useState(false);
4001
- React60.useEffect(() => {
4690
+ const [value, setValue] = React58.useState(currentSlug);
4691
+ const [error, setError] = React58.useState(null);
4692
+ const [submitting, setSubmitting] = React58.useState(false);
4693
+ React58.useEffect(() => {
4002
4694
  if (open) {
4003
4695
  setValue(currentSlug);
4004
4696
  setError(null);
@@ -4034,7 +4726,7 @@ function RenameDialog({
4034
4726
  setSubmitting(false);
4035
4727
  }
4036
4728
  });
4037
- return /* @__PURE__ */ React60__default.default.createElement(material.Dialog, { open, onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React60__default.default.createElement(material.DialogTitle, null, "Rename template"), /* @__PURE__ */ React60__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React60__default.default.createElement(
4729
+ return /* @__PURE__ */ React58__default.default.createElement(material.Dialog, { open, onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React58__default.default.createElement(material.DialogTitle, null, "Rename template"), /* @__PURE__ */ React58__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React58__default.default.createElement(
4038
4730
  material.TextField,
4039
4731
  {
4040
4732
  autoFocus: true,
@@ -4053,7 +4745,7 @@ function RenameDialog({
4053
4745
  }
4054
4746
  }
4055
4747
  }
4056
- )), /* @__PURE__ */ React60__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React60__default.default.createElement(material.Button, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ React60__default.default.createElement(
4748
+ )), /* @__PURE__ */ React58__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React58__default.default.createElement(material.Button, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ React58__default.default.createElement(
4057
4749
  material.Button,
4058
4750
  {
4059
4751
  onClick: handleSubmit,
@@ -4071,10 +4763,10 @@ function SaveTemplateDialog({
4071
4763
  defaultName = "",
4072
4764
  error: externalError = null
4073
4765
  }) {
4074
- const [templateName, setTemplateName] = React60.useState(defaultName);
4075
- const [internalError, setInternalError] = React60.useState("");
4076
- const [isSubmitting, setIsSubmitting] = React60.useState(false);
4077
- React60.useEffect(() => {
4766
+ const [templateName, setTemplateName] = React58.useState(defaultName);
4767
+ const [internalError, setInternalError] = React58.useState("");
4768
+ const [isSubmitting, setIsSubmitting] = React58.useState(false);
4769
+ React58.useEffect(() => {
4078
4770
  if (open) {
4079
4771
  setTemplateName(defaultName);
4080
4772
  setInternalError("");
@@ -4122,7 +4814,7 @@ function SaveTemplateDialog({
4122
4814
  setInternalError("");
4123
4815
  onClose();
4124
4816
  };
4125
- return /* @__PURE__ */ React60__default.default.createElement(
4817
+ return /* @__PURE__ */ React58__default.default.createElement(
4126
4818
  material.Dialog,
4127
4819
  {
4128
4820
  open,
@@ -4130,8 +4822,8 @@ function SaveTemplateDialog({
4130
4822
  maxWidth: "sm",
4131
4823
  fullWidth: true
4132
4824
  },
4133
- /* @__PURE__ */ React60__default.default.createElement(material.DialogTitle, null, "Save Email Template"),
4134
- /* @__PURE__ */ React60__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { pt: 1 } }, /* @__PURE__ */ React60__default.default.createElement(
4825
+ /* @__PURE__ */ React58__default.default.createElement(material.DialogTitle, null, "Save Email Template"),
4826
+ /* @__PURE__ */ React58__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { pt: 1 } }, /* @__PURE__ */ React58__default.default.createElement(
4135
4827
  material.TextField,
4136
4828
  {
4137
4829
  autoFocus: true,
@@ -4153,7 +4845,7 @@ function SaveTemplateDialog({
4153
4845
  disabled: isSubmitting
4154
4846
  }
4155
4847
  ))),
4156
- /* @__PURE__ */ React60__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React60__default.default.createElement(material.Button, { onClick: handleCancel, disabled: isSubmitting }, "Cancel"), /* @__PURE__ */ React60__default.default.createElement(
4848
+ /* @__PURE__ */ React58__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React58__default.default.createElement(material.Button, { onClick: handleCancel, disabled: isSubmitting }, "Cancel"), /* @__PURE__ */ React58__default.default.createElement(
4157
4849
  material.Button,
4158
4850
  {
4159
4851
  onClick: handleSave,
@@ -4223,17 +4915,17 @@ function SamplesDrawer({
4223
4915
  const samplesDrawerOpen = useSamplesDrawerOpen();
4224
4916
  const { setCurrentTemplate, loadTemplate: ctxLoadTemplate } = useEmailEditor();
4225
4917
  const { showMessage } = useSnackbar();
4226
- const [samples, setSamples] = React60.useState([EMPTY_TEMPLATE]);
4227
- const [templates, setTemplates] = React60.useState([]);
4228
- const [loadingSamples, setLoadingSamples] = React60.useState(false);
4229
- const [loadingTemplates, setLoadingTemplates] = React60.useState(false);
4230
- const [templatesError, setTemplatesError] = React60.useState(null);
4231
- const [search, setSearch] = React60.useState("");
4232
- const [sortKey, setSortKey] = React60.useState("updatedAt");
4233
- const [activeTags, setActiveTags] = React60.useState([]);
4234
- const [renameTarget, setRenameTarget] = React60.useState(null);
4235
- const [pendingSaveAs, setPendingSaveAs] = React60.useState(null);
4236
- const [newError, setNewError] = React60.useState(null);
4918
+ const [samples, setSamples] = React58.useState([EMPTY_TEMPLATE]);
4919
+ const [templates, setTemplates] = React58.useState([]);
4920
+ const [loadingSamples, setLoadingSamples] = React58.useState(false);
4921
+ const [loadingTemplates, setLoadingTemplates] = React58.useState(false);
4922
+ const [templatesError, setTemplatesError] = React58.useState(null);
4923
+ const [search, setSearch] = React58.useState("");
4924
+ const [sortKey, setSortKey] = React58.useState("updatedAt");
4925
+ const [activeTags, setActiveTags] = React58.useState([]);
4926
+ const [renameTarget, setRenameTarget] = React58.useState(null);
4927
+ const [pendingSaveAs, setPendingSaveAs] = React58.useState(null);
4928
+ const [newError, setNewError] = React58.useState(null);
4237
4929
  const handleLoadTemplate = (templateId) => __async(null, null, function* () {
4238
4930
  if (templateId === "empty-email") {
4239
4931
  return empty_email_message_default;
@@ -4244,7 +4936,7 @@ function SamplesDrawer({
4244
4936
  return null;
4245
4937
  });
4246
4938
  const withKind = (items, fallback) => items.map((item) => item.kind ? item : __spreadProps(__spreadValues({}, item), { kind: fallback }));
4247
- React60.useEffect(() => {
4939
+ React58.useEffect(() => {
4248
4940
  if (!enabled || !samplesDrawerOpen || !loadSamples) return;
4249
4941
  setLoadingSamples(true);
4250
4942
  loadSamples().then((results) => {
@@ -4270,11 +4962,11 @@ function SamplesDrawer({
4270
4962
  setLoadingTemplates(false);
4271
4963
  }
4272
4964
  });
4273
- React60.useEffect(() => {
4965
+ React58.useEffect(() => {
4274
4966
  if (!enabled || !loadTemplates) return;
4275
4967
  refreshTemplates();
4276
4968
  }, [enabled, loadTemplates]);
4277
- React60.useEffect(() => {
4969
+ React58.useEffect(() => {
4278
4970
  const handler = (e) => {
4279
4971
  const detail = e.detail;
4280
4972
  if (Array.isArray(detail)) setTemplates(withKind(detail, "template"));
@@ -4282,7 +4974,7 @@ function SamplesDrawer({
4282
4974
  window.addEventListener("templateListUpdated", handler);
4283
4975
  return () => window.removeEventListener("templateListUpdated", handler);
4284
4976
  }, []);
4285
- const { templateRows, sampleRows } = React60.useMemo(() => {
4977
+ const { templateRows, sampleRows } = React58.useMemo(() => {
4286
4978
  const byId = /* @__PURE__ */ new Map();
4287
4979
  for (const s of samples) byId.set(s.id, s);
4288
4980
  for (const t of templates) byId.set(t.id, t);
@@ -4292,7 +4984,7 @@ function SamplesDrawer({
4292
4984
  sampleRows: all.filter((t) => t.kind === "sample")
4293
4985
  };
4294
4986
  }, [samples, templates]);
4295
- const allTags = React60.useMemo(() => {
4987
+ const allTags = React58.useMemo(() => {
4296
4988
  var _a2;
4297
4989
  const set = /* @__PURE__ */ new Set();
4298
4990
  for (const t of templateRows) {
@@ -4300,7 +4992,7 @@ function SamplesDrawer({
4300
4992
  }
4301
4993
  return Array.from(set).sort();
4302
4994
  }, [templateRows]);
4303
- const filteredTemplates = React60.useMemo(() => {
4995
+ const filteredTemplates = React58.useMemo(() => {
4304
4996
  const term = search.trim().toLowerCase();
4305
4997
  const matchSearch = (t) => {
4306
4998
  if (!term) return true;
@@ -4419,7 +5111,7 @@ function SamplesDrawer({
4419
5111
  return null;
4420
5112
  }
4421
5113
  const existingSlugs = templates.map((t) => t.slug);
4422
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
5114
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
4423
5115
  material.Drawer,
4424
5116
  {
4425
5117
  variant: "persistent",
@@ -4434,7 +5126,7 @@ function SamplesDrawer({
4434
5126
  transitionDuration: { enter: enterDuration, exit: exitDuration },
4435
5127
  sx: { width: samplesDrawerOpen ? SAMPLES_DRAWER_WIDTH : 0 }
4436
5128
  },
4437
- /* @__PURE__ */ React60__default.default.createElement(
5129
+ /* @__PURE__ */ React58__default.default.createElement(
4438
5130
  material.Stack,
4439
5131
  {
4440
5132
  py: 1,
@@ -4444,16 +5136,16 @@ function SamplesDrawer({
4444
5136
  spacing: 1.5,
4445
5137
  sx: { overflowY: "auto" }
4446
5138
  },
4447
- /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { pt: 1 } }, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "h6", component: "h1" }, "Templates"), saveAs && /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "New template" }, /* @__PURE__ */ React60__default.default.createElement(
5139
+ /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { pt: 1 } }, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "h6", component: "h1" }, "Templates"), saveAs && /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "New template" }, /* @__PURE__ */ React58__default.default.createElement(
4448
5140
  material.IconButton,
4449
5141
  {
4450
5142
  size: "small",
4451
5143
  onClick: openNewTemplateDialog,
4452
5144
  "aria-label": "New template"
4453
5145
  },
4454
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" })
5146
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" })
4455
5147
  ))),
4456
- loadTemplates && /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
5148
+ loadTemplates && /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
4457
5149
  material.TextField,
4458
5150
  {
4459
5151
  size: "small",
@@ -4461,10 +5153,10 @@ function SamplesDrawer({
4461
5153
  value: search,
4462
5154
  onChange: (e) => setSearch(e.target.value),
4463
5155
  InputProps: {
4464
- startAdornment: /* @__PURE__ */ React60__default.default.createElement(material.InputAdornment, { position: "start" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.SearchOutlined, { fontSize: "small" }))
5156
+ startAdornment: /* @__PURE__ */ React58__default.default.createElement(material.InputAdornment, { position: "start" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SearchOutlined, { fontSize: "small" }))
4465
5157
  }
4466
5158
  }
4467
- ), /* @__PURE__ */ React60__default.default.createElement(
5159
+ ), /* @__PURE__ */ React58__default.default.createElement(
4468
5160
  material.TextField,
4469
5161
  {
4470
5162
  select: true,
@@ -4473,8 +5165,8 @@ function SamplesDrawer({
4473
5165
  value: sortKey,
4474
5166
  onChange: (e) => setSortKey(e.target.value)
4475
5167
  },
4476
- SORT_OPTIONS.map((opt) => /* @__PURE__ */ React60__default.default.createElement(material.MenuItem, { key: opt.value, value: opt.value }, opt.label))
4477
- ), allTags.length > 0 && /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", sx: { flexWrap: "wrap", gap: 0.5 } }, allTags.map((tag) => /* @__PURE__ */ React60__default.default.createElement(
5168
+ SORT_OPTIONS.map((opt) => /* @__PURE__ */ React58__default.default.createElement(material.MenuItem, { key: opt.value, value: opt.value }, opt.label))
5169
+ ), allTags.length > 0 && /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", sx: { flexWrap: "wrap", gap: 0.5 } }, allTags.map((tag) => /* @__PURE__ */ React58__default.default.createElement(
4478
5170
  material.Chip,
4479
5171
  {
4480
5172
  key: tag,
@@ -4485,7 +5177,7 @@ function SamplesDrawer({
4485
5177
  variant: activeTags.includes(tag) ? "filled" : "outlined",
4486
5178
  onClick: () => toggleTag(tag)
4487
5179
  }
4488
- ))), /* @__PURE__ */ React60__default.default.createElement(material.Box, null, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Your Templates"), loadingTemplates ? /* @__PURE__ */ React60__default.default.createElement(material.Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React60__default.default.createElement(material.CircularProgress, { size: 24 })) : templatesError ? /* @__PURE__ */ React60__default.default.createElement(material.Alert, { severity: "error", sx: { my: 1 } }, templatesError) : filteredTemplates.length > 0 ? /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 0.25, sx: { width: "100%" } }, filteredTemplates.map((template) => /* @__PURE__ */ React60__default.default.createElement(
5180
+ ))), /* @__PURE__ */ React58__default.default.createElement(material.Box, null, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Your Templates"), loadingTemplates ? /* @__PURE__ */ React58__default.default.createElement(material.Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React58__default.default.createElement(material.CircularProgress, { size: 24 })) : templatesError ? /* @__PURE__ */ React58__default.default.createElement(material.Alert, { severity: "error", sx: { my: 1 } }, templatesError) : filteredTemplates.length > 0 ? /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 0.25, sx: { width: "100%" } }, filteredTemplates.map((template) => /* @__PURE__ */ React58__default.default.createElement(
4489
5181
  TemplateRow,
4490
5182
  {
4491
5183
  key: template.id,
@@ -4497,8 +5189,8 @@ function SamplesDrawer({
4497
5189
  onDelete: deleteTemplate ? () => handleDelete(template) : void 0,
4498
5190
  onPromote: setTemplateKind ? () => handleSetKind(template, "sample") : void 0
4499
5191
  }
4500
- ))) : /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, templateRows.length === 0 ? "No saved templates yet" : "No templates match your filters")), /* @__PURE__ */ React60__default.default.createElement(material.Divider, null)),
4501
- /* @__PURE__ */ React60__default.default.createElement(material.Box, null, /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Sample Templates"), loadingSamples ? /* @__PURE__ */ React60__default.default.createElement(material.Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React60__default.default.createElement(material.CircularProgress, { size: 24 })) : sampleRows.length > 0 ? /* @__PURE__ */ React60__default.default.createElement(material.Stack, { spacing: 0.25, sx: { width: "100%" } }, sampleRows.map((sample) => /* @__PURE__ */ React60__default.default.createElement(
5192
+ ))) : /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, templateRows.length === 0 ? "No saved templates yet" : "No templates match your filters")), /* @__PURE__ */ React58__default.default.createElement(material.Divider, null)),
5193
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, null, /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Sample Templates"), loadingSamples ? /* @__PURE__ */ React58__default.default.createElement(material.Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React58__default.default.createElement(material.CircularProgress, { size: 24 })) : sampleRows.length > 0 ? /* @__PURE__ */ React58__default.default.createElement(material.Stack, { spacing: 0.25, sx: { width: "100%" } }, sampleRows.map((sample) => /* @__PURE__ */ React58__default.default.createElement(
4502
5194
  TemplateRow,
4503
5195
  {
4504
5196
  key: sample.id,
@@ -4508,9 +5200,9 @@ function SamplesDrawer({
4508
5200
  onDuplicateAsTemplate: saveAs ? () => handleDuplicateAsTemplate(sample) : void 0,
4509
5201
  onDemote: setTemplateKind && sample.id !== "empty-email" ? () => handleSetKind(sample, "template") : void 0
4510
5202
  }
4511
- ))) : /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, "No samples available"))
5203
+ ))) : /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, "No samples available"))
4512
5204
  )
4513
- ), renameTarget && /* @__PURE__ */ React60__default.default.createElement(
5205
+ ), renameTarget && /* @__PURE__ */ React58__default.default.createElement(
4514
5206
  RenameDialog,
4515
5207
  {
4516
5208
  open: !!renameTarget,
@@ -4519,7 +5211,7 @@ function SamplesDrawer({
4519
5211
  onClose: () => setRenameTarget(null),
4520
5212
  onSubmit: handleRenameSubmit
4521
5213
  }
4522
- ), /* @__PURE__ */ React60__default.default.createElement(
5214
+ ), /* @__PURE__ */ React58__default.default.createElement(
4523
5215
  SaveTemplateDialog,
4524
5216
  {
4525
5217
  open: !!pendingSaveAs,
@@ -4546,7 +5238,7 @@ var ICON_SX = {
4546
5238
  borderColor: "cadet.300"
4547
5239
  };
4548
5240
  function BlockTypeButton({ label, icon, onClick }) {
4549
- return /* @__PURE__ */ React60__default.default.createElement(
5241
+ return /* @__PURE__ */ React58__default.default.createElement(
4550
5242
  material.Button,
4551
5243
  {
4552
5244
  sx: BUTTON_SX2,
@@ -4555,14 +5247,14 @@ function BlockTypeButton({ label, icon, onClick }) {
4555
5247
  onClick();
4556
5248
  }
4557
5249
  },
4558
- /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: ICON_SX }, icon),
4559
- /* @__PURE__ */ React60__default.default.createElement(material.Typography, { variant: "body2" }, label)
5250
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: ICON_SX }, icon),
5251
+ /* @__PURE__ */ React58__default.default.createElement(material.Typography, { variant: "body2" }, label)
4560
5252
  );
4561
5253
  }
4562
5254
  var BUTTONS = [
4563
5255
  {
4564
5256
  label: "Heading",
4565
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.HMobiledataOutlined, null),
5257
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.HMobiledataOutlined, null),
4566
5258
  block: () => ({
4567
5259
  type: "Heading",
4568
5260
  data: {
@@ -4575,7 +5267,7 @@ var BUTTONS = [
4575
5267
  },
4576
5268
  {
4577
5269
  label: "Text",
4578
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.NotesOutlined, null),
5270
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.NotesOutlined, null),
4579
5271
  block: () => ({
4580
5272
  type: "Text",
4581
5273
  data: {
@@ -4589,7 +5281,7 @@ var BUTTONS = [
4589
5281
  },
4590
5282
  {
4591
5283
  label: "Button",
4592
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.SmartButtonOutlined, null),
5284
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SmartButtonOutlined, null),
4593
5285
  block: () => ({
4594
5286
  type: "Button",
4595
5287
  data: {
@@ -4603,7 +5295,7 @@ var BUTTONS = [
4603
5295
  },
4604
5296
  {
4605
5297
  label: "Image",
4606
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ImageOutlined, null),
5298
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ImageOutlined, null),
4607
5299
  block: () => ({
4608
5300
  type: "Image",
4609
5301
  data: {
@@ -4619,7 +5311,7 @@ var BUTTONS = [
4619
5311
  },
4620
5312
  {
4621
5313
  label: "Avatar",
4622
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AccountCircleOutlined, null),
5314
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AccountCircleOutlined, null),
4623
5315
  block: () => ({
4624
5316
  type: "Avatar",
4625
5317
  data: {
@@ -4633,7 +5325,7 @@ var BUTTONS = [
4633
5325
  },
4634
5326
  {
4635
5327
  label: "Personal Signature",
4636
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ContactMailOutlined, null),
5328
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ContactMailOutlined, null),
4637
5329
  block: () => ({
4638
5330
  type: "Signature",
4639
5331
  data: {
@@ -4655,7 +5347,7 @@ var BUTTONS = [
4655
5347
  },
4656
5348
  {
4657
5349
  label: "Company Signature",
4658
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.BusinessOutlined, null),
5350
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.BusinessOutlined, null),
4659
5351
  block: () => ({
4660
5352
  type: "Signature",
4661
5353
  data: {
@@ -4675,7 +5367,7 @@ var BUTTONS = [
4675
5367
  },
4676
5368
  {
4677
5369
  label: "Divider",
4678
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.HorizontalRuleOutlined, null),
5370
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.HorizontalRuleOutlined, null),
4679
5371
  block: () => ({
4680
5372
  type: "Divider",
4681
5373
  data: {
@@ -4688,7 +5380,7 @@ var BUTTONS = [
4688
5380
  },
4689
5381
  {
4690
5382
  label: "Spacer",
4691
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.Crop32Outlined, null),
5383
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.Crop32Outlined, null),
4692
5384
  block: () => ({
4693
5385
  type: "Spacer",
4694
5386
  data: {}
@@ -4696,7 +5388,7 @@ var BUTTONS = [
4696
5388
  },
4697
5389
  {
4698
5390
  label: "Html",
4699
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.HtmlOutlined, null),
5391
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.HtmlOutlined, null),
4700
5392
  block: () => ({
4701
5393
  type: "Html",
4702
5394
  data: {
@@ -4711,7 +5403,7 @@ var BUTTONS = [
4711
5403
  },
4712
5404
  {
4713
5405
  label: "Columns",
4714
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ViewColumnOutlined, null),
5406
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ViewColumnOutlined, null),
4715
5407
  block: () => ({
4716
5408
  type: "ColumnsContainer",
4717
5409
  data: {
@@ -4726,7 +5418,7 @@ var BUTTONS = [
4726
5418
  },
4727
5419
  {
4728
5420
  label: "Container",
4729
- icon: /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.LibraryAddOutlined, null),
5421
+ icon: /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.LibraryAddOutlined, null),
4730
5422
  block: () => ({
4731
5423
  type: "Container",
4732
5424
  data: {
@@ -4750,7 +5442,7 @@ function BlocksMenu({ anchorEl, setAnchorEl, onSelect }) {
4750
5442
  if (anchorEl === null) {
4751
5443
  return null;
4752
5444
  }
4753
- return /* @__PURE__ */ React60__default.default.createElement(
5445
+ return /* @__PURE__ */ React58__default.default.createElement(
4754
5446
  material.Menu,
4755
5447
  {
4756
5448
  open: true,
@@ -4759,12 +5451,12 @@ function BlocksMenu({ anchorEl, setAnchorEl, onSelect }) {
4759
5451
  anchorOrigin: { vertical: "bottom", horizontal: "center" },
4760
5452
  transformOrigin: { vertical: "top", horizontal: "center" }
4761
5453
  },
4762
- /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { p: 1, display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr" } }, BUTTONS.map((k, i) => /* @__PURE__ */ React60__default.default.createElement(BlockTypeButton, { key: i, label: k.label, icon: k.icon, onClick: () => onClick(k.block()) })))
5454
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { p: 1, display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr" } }, BUTTONS.map((k, i) => /* @__PURE__ */ React58__default.default.createElement(BlockTypeButton, { key: i, label: k.label, icon: k.icon, onClick: () => onClick(k.block()) })))
4763
5455
  );
4764
5456
  }
4765
5457
  function DividerButton({ buttonElement, onClick }) {
4766
- const [visible, setVisible] = React60.useState(false);
4767
- React60.useEffect(() => {
5458
+ const [visible, setVisible] = React58.useState(false);
5459
+ React58.useEffect(() => {
4768
5460
  function listener({ clientX, clientY }) {
4769
5461
  if (!buttonElement) {
4770
5462
  return;
@@ -4786,7 +5478,7 @@ function DividerButton({ buttonElement, onClick }) {
4786
5478
  window.removeEventListener("mousemove", listener);
4787
5479
  };
4788
5480
  }, [buttonElement, setVisible]);
4789
- return /* @__PURE__ */ React60__default.default.createElement(material.Fade, { in: visible }, /* @__PURE__ */ React60__default.default.createElement(
5481
+ return /* @__PURE__ */ React58__default.default.createElement(material.Fade, { in: visible }, /* @__PURE__ */ React58__default.default.createElement(
4790
5482
  material.IconButton,
4791
5483
  {
4792
5484
  size: "small",
@@ -4809,11 +5501,11 @@ function DividerButton({ buttonElement, onClick }) {
4809
5501
  onClick();
4810
5502
  }
4811
5503
  },
4812
- /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" })
5504
+ /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" })
4813
5505
  ));
4814
5506
  }
4815
5507
  function PlaceholderButton({ onClick }) {
4816
- return /* @__PURE__ */ React60__default.default.createElement(
5508
+ return /* @__PURE__ */ React58__default.default.createElement(
4817
5509
  material.ButtonBase,
4818
5510
  {
4819
5511
  onClick: (ev) => {
@@ -4829,7 +5521,7 @@ function PlaceholderButton({ onClick }) {
4829
5521
  bgcolor: "rgba(0,0,0, 0.05)"
4830
5522
  }
4831
5523
  },
4832
- /* @__PURE__ */ React60__default.default.createElement(
5524
+ /* @__PURE__ */ React58__default.default.createElement(
4833
5525
  iconsMaterial.AddOutlined,
4834
5526
  {
4835
5527
  sx: {
@@ -4846,19 +5538,19 @@ function PlaceholderButton({ onClick }) {
4846
5538
 
4847
5539
  // src/editor/blocks/helpers/editor-children-ids/add-block-menu/index.tsx
4848
5540
  function AddBlockButton({ onSelect, placeholder }) {
4849
- const [menuAnchorEl, setMenuAnchorEl] = React60.useState(null);
4850
- const [buttonElement, setButtonElement] = React60.useState(null);
5541
+ const [menuAnchorEl, setMenuAnchorEl] = React58.useState(null);
5542
+ const [buttonElement, setButtonElement] = React58.useState(null);
4851
5543
  const handleButtonClick = () => {
4852
5544
  setMenuAnchorEl(buttonElement);
4853
5545
  };
4854
5546
  const renderButton2 = () => {
4855
5547
  if (placeholder) {
4856
- return /* @__PURE__ */ React60__default.default.createElement(PlaceholderButton, { onClick: handleButtonClick });
5548
+ return /* @__PURE__ */ React58__default.default.createElement(PlaceholderButton, { onClick: handleButtonClick });
4857
5549
  } else {
4858
- return /* @__PURE__ */ React60__default.default.createElement(DividerButton, { buttonElement, onClick: handleButtonClick });
5550
+ return /* @__PURE__ */ React58__default.default.createElement(DividerButton, { buttonElement, onClick: handleButtonClick });
4859
5551
  }
4860
5552
  };
4861
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement("div", { ref: setButtonElement, style: { position: "relative" } }, renderButton2()), /* @__PURE__ */ React60__default.default.createElement(BlocksMenu, { anchorEl: menuAnchorEl, setAnchorEl: setMenuAnchorEl, onSelect }));
5553
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement("div", { ref: setButtonElement, style: { position: "relative" } }, renderButton2()), /* @__PURE__ */ React58__default.default.createElement(BlocksMenu, { anchorEl: menuAnchorEl, setAnchorEl: setMenuAnchorEl, onSelect }));
4862
5554
  }
4863
5555
 
4864
5556
  // src/editor/blocks/helpers/editor-children-ids/index.tsx
@@ -4885,9 +5577,9 @@ function EditorChildrenIds({ childrenIds, onChange }) {
4885
5577
  });
4886
5578
  };
4887
5579
  if (!childrenIds || childrenIds.length === 0) {
4888
- return /* @__PURE__ */ React60__default.default.createElement(AddBlockButton, { placeholder: true, onSelect: appendBlock });
5580
+ return /* @__PURE__ */ React58__default.default.createElement(AddBlockButton, { placeholder: true, onSelect: appendBlock });
4889
5581
  }
4890
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, childrenIds.map((childId, i) => /* @__PURE__ */ React60__default.default.createElement(React60.Fragment, { key: childId }, /* @__PURE__ */ React60__default.default.createElement(AddBlockButton, { onSelect: (block) => insertBlock(block, i) }), /* @__PURE__ */ React60__default.default.createElement(EditorBlock, { id: childId }))), /* @__PURE__ */ React60__default.default.createElement(AddBlockButton, { onSelect: appendBlock }));
5582
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, childrenIds.map((childId, i) => /* @__PURE__ */ React58__default.default.createElement(React58.Fragment, { key: childId }, /* @__PURE__ */ React58__default.default.createElement(AddBlockButton, { onSelect: (block) => insertBlock(block, i) }), /* @__PURE__ */ React58__default.default.createElement(EditorBlock, { id: childId }))), /* @__PURE__ */ React58__default.default.createElement(AddBlockButton, { onSelect: appendBlock }));
4891
5583
  }
4892
5584
 
4893
5585
  // src/editor/blocks/columns-container/columns-container-editor.tsx
@@ -4914,15 +5606,15 @@ function ColumnsContainerEditor({ style, props }) {
4914
5606
  });
4915
5607
  setSelectedBlockId(blockId);
4916
5608
  };
4917
- return /* @__PURE__ */ React60__default.default.createElement(
5609
+ return /* @__PURE__ */ React58__default.default.createElement(
4918
5610
  columns_container_default,
4919
5611
  {
4920
5612
  props: restProps,
4921
5613
  style,
4922
5614
  columns: [
4923
- /* @__PURE__ */ React60__default.default.createElement(EditorChildrenIds, { childrenIds: (_b = columns == null ? void 0 : columns[0]) == null ? void 0 : _b.childrenIds, onChange: (change) => updateColumn(0, change) }),
4924
- /* @__PURE__ */ React60__default.default.createElement(EditorChildrenIds, { childrenIds: (_c = columns == null ? void 0 : columns[1]) == null ? void 0 : _c.childrenIds, onChange: (change) => updateColumn(1, change) }),
4925
- /* @__PURE__ */ React60__default.default.createElement(EditorChildrenIds, { childrenIds: (_d = columns == null ? void 0 : columns[2]) == null ? void 0 : _d.childrenIds, onChange: (change) => updateColumn(2, change) })
5615
+ /* @__PURE__ */ React58__default.default.createElement(EditorChildrenIds, { childrenIds: (_b = columns == null ? void 0 : columns[0]) == null ? void 0 : _b.childrenIds, onChange: (change) => updateColumn(0, change) }),
5616
+ /* @__PURE__ */ React58__default.default.createElement(EditorChildrenIds, { childrenIds: (_c = columns == null ? void 0 : columns[1]) == null ? void 0 : _c.childrenIds, onChange: (change) => updateColumn(1, change) }),
5617
+ /* @__PURE__ */ React58__default.default.createElement(EditorChildrenIds, { childrenIds: (_d = columns == null ? void 0 : columns[2]) == null ? void 0 : _d.childrenIds, onChange: (change) => updateColumn(2, change) })
4926
5618
  ]
4927
5619
  }
4928
5620
  );
@@ -4932,7 +5624,7 @@ function ContainerEditor({ style, props }) {
4932
5624
  const childrenIds = (_a = props == null ? void 0 : props.childrenIds) != null ? _a : [];
4933
5625
  const document2 = useDocument();
4934
5626
  const currentBlockId = useCurrentBlockId();
4935
- return /* @__PURE__ */ React60__default.default.createElement(container_default, { style }, /* @__PURE__ */ React60__default.default.createElement(
5627
+ return /* @__PURE__ */ React58__default.default.createElement(container_default, { style }, /* @__PURE__ */ React58__default.default.createElement(
4936
5628
  EditorChildrenIds,
4937
5629
  {
4938
5630
  childrenIds,
@@ -5038,7 +5730,7 @@ function EmailLayoutEditor(props) {
5038
5730
  const document2 = useDocument();
5039
5731
  const currentBlockId = useCurrentBlockId();
5040
5732
  const selectedBlockId = useSelectedBlockId();
5041
- const handleDelete = React60.useCallback((e) => {
5733
+ const handleDelete = React58.useCallback((e) => {
5042
5734
  var _a2, _b2, _c2;
5043
5735
  if (e.key !== "Delete" && e.key !== "Backspace") return;
5044
5736
  if (!selectedBlockId) return;
@@ -5069,7 +5761,7 @@ function EmailLayoutEditor(props) {
5069
5761
  delete nDocument[selectedBlockId];
5070
5762
  resetDocument(nDocument);
5071
5763
  }, [selectedBlockId, document2]);
5072
- const handleCopy = React60.useCallback((e) => {
5764
+ const handleCopy = React58.useCallback((e) => {
5073
5765
  if (!(e.metaKey || e.ctrlKey) || e.key !== "c") return;
5074
5766
  if (!selectedBlockId) return;
5075
5767
  const target = e.target;
@@ -5082,7 +5774,7 @@ function EmailLayoutEditor(props) {
5082
5774
  const payload = JSON.stringify({ __emailEditorBlocks: true, rootBlockId: selectedBlockId, blocks });
5083
5775
  navigator.clipboard.writeText(payload);
5084
5776
  }, [selectedBlockId, document2]);
5085
- const handlePaste = React60.useCallback((e) => __async(null, null, function* () {
5777
+ const handlePaste = React58.useCallback((e) => __async(null, null, function* () {
5086
5778
  var _a2;
5087
5779
  const target = e.target;
5088
5780
  if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable) {
@@ -5113,7 +5805,7 @@ function EmailLayoutEditor(props) {
5113
5805
  resetDocument(doc);
5114
5806
  setSelectedBlockId(newRootId);
5115
5807
  }), [document2, childrenIds, selectedBlockId, currentBlockId]);
5116
- React60.useEffect(() => {
5808
+ React58.useEffect(() => {
5117
5809
  window.addEventListener("keydown", handleDelete);
5118
5810
  window.addEventListener("keydown", handleCopy);
5119
5811
  window.addEventListener("paste", handlePaste);
@@ -5132,7 +5824,7 @@ function EmailLayoutEditor(props) {
5132
5824
  lineHeight: "1.5",
5133
5825
  margin: "0"
5134
5826
  };
5135
- const editorChildren = /* @__PURE__ */ React60__default.default.createElement(
5827
+ const editorChildren = /* @__PURE__ */ React58__default.default.createElement(
5136
5828
  EditorChildrenIds,
5137
5829
  {
5138
5830
  childrenIds,
@@ -5151,7 +5843,7 @@ function EmailLayoutEditor(props) {
5151
5843
  }
5152
5844
  );
5153
5845
  if (props.backdropDisabled) {
5154
- return /* @__PURE__ */ React60__default.default.createElement(
5846
+ return /* @__PURE__ */ React58__default.default.createElement(
5155
5847
  "div",
5156
5848
  {
5157
5849
  onClick: () => {
@@ -5164,10 +5856,10 @@ function EmailLayoutEditor(props) {
5164
5856
  minHeight: "100%"
5165
5857
  })
5166
5858
  },
5167
- /* @__PURE__ */ React60__default.default.createElement("div", { style: { maxWidth: "600px" } }, editorChildren)
5859
+ /* @__PURE__ */ React58__default.default.createElement("div", { style: { maxWidth: "600px" } }, editorChildren)
5168
5860
  );
5169
5861
  }
5170
- return /* @__PURE__ */ React60__default.default.createElement(
5862
+ return /* @__PURE__ */ React58__default.default.createElement(
5171
5863
  "div",
5172
5864
  {
5173
5865
  onClick: () => {
@@ -5180,7 +5872,7 @@ function EmailLayoutEditor(props) {
5180
5872
  minHeight: "100%"
5181
5873
  })
5182
5874
  },
5183
- /* @__PURE__ */ React60__default.default.createElement(
5875
+ /* @__PURE__ */ React58__default.default.createElement(
5184
5876
  "table",
5185
5877
  {
5186
5878
  align: "center",
@@ -5204,7 +5896,7 @@ function EmailLayoutEditor(props) {
5204
5896
  cellPadding: "0",
5205
5897
  border: 0
5206
5898
  },
5207
- /* @__PURE__ */ React60__default.default.createElement("tbody", null, /* @__PURE__ */ React60__default.default.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React60__default.default.createElement("td", null, editorChildren)))
5899
+ /* @__PURE__ */ React58__default.default.createElement("tbody", null, /* @__PURE__ */ React58__default.default.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React58__default.default.createElement("td", null, editorChildren)))
5208
5900
  )
5209
5901
  );
5210
5902
  }
@@ -5363,13 +6055,13 @@ function TuneMenu({ blockId }) {
5363
6055
  resetDocument(nDocument);
5364
6056
  setSelectedBlockId(blockId);
5365
6057
  };
5366
- return /* @__PURE__ */ React60__default.default.createElement(material.Paper, { sx, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, null, /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Move up", placement: "left-start" }, /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: () => handleMoveClick("up"), sx: { color: "text.primary" } }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ArrowUpwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Move down", placement: "left-start" }, /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: () => handleMoveClick("down"), sx: { color: "text.primary" } }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ArrowDownwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Copy block", placement: "left-start" }, /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: handleCopyClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Delete", placement: "left-start" }, /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: handleDeleteClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.DeleteOutlined, { fontSize: "small" })))));
6058
+ return /* @__PURE__ */ React58__default.default.createElement(material.Paper, { sx, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, null, /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Move up", placement: "left-start" }, /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: () => handleMoveClick("up"), sx: { color: "text.primary" } }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ArrowUpwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Move down", placement: "left-start" }, /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: () => handleMoveClick("down"), sx: { color: "text.primary" } }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ArrowDownwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Copy block", placement: "left-start" }, /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: handleCopyClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Delete", placement: "left-start" }, /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: handleDeleteClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DeleteOutlined, { fontSize: "small" })))));
5367
6059
  }
5368
6060
 
5369
6061
  // src/editor/blocks/helpers/block-wrappers/editor-block-wrapper.tsx
5370
6062
  function EditorBlockWrapper({ children }) {
5371
6063
  const selectedBlockId = useSelectedBlockId();
5372
- const [mouseInside, setMouseInside] = React60.useState(false);
6064
+ const [mouseInside, setMouseInside] = React58.useState(false);
5373
6065
  const blockId = useCurrentBlockId();
5374
6066
  let outline;
5375
6067
  if (selectedBlockId === blockId) {
@@ -5381,9 +6073,9 @@ function EditorBlockWrapper({ children }) {
5381
6073
  if (selectedBlockId !== blockId) {
5382
6074
  return null;
5383
6075
  }
5384
- return /* @__PURE__ */ React60__default.default.createElement(TuneMenu, { blockId });
6076
+ return /* @__PURE__ */ React58__default.default.createElement(TuneMenu, { blockId });
5385
6077
  };
5386
- return /* @__PURE__ */ React60__default.default.createElement(
6078
+ return /* @__PURE__ */ React58__default.default.createElement(
5387
6079
  material.Box,
5388
6080
  {
5389
6081
  sx: {
@@ -5469,8 +6161,8 @@ function ButtonEditor({ style, props }) {
5469
6161
  const fullWidth = (_b = props == null ? void 0 : props.fullWidth) != null ? _b : ButtonPropsDefaults.fullWidth;
5470
6162
  const buttonTextColor = (_c = props == null ? void 0 : props.buttonTextColor) != null ? _c : ButtonPropsDefaults.buttonTextColor;
5471
6163
  const buttonBackgroundColor = (_d = props == null ? void 0 : props.buttonBackgroundColor) != null ? _d : ButtonPropsDefaults.buttonBackgroundColor;
5472
- const [localText, setLocalText] = React60.useState(text);
5473
- React60.useEffect(() => {
6164
+ const [localText, setLocalText] = React58.useState(text);
6165
+ React58.useEffect(() => {
5474
6166
  setLocalText(text);
5475
6167
  }, [text]);
5476
6168
  const padding = getButtonSizePadding2(props);
@@ -5513,19 +6205,203 @@ function ButtonEditor({ style, props }) {
5513
6205
  width: fullWidth ? "100%" : void 0,
5514
6206
  textAlign: "center"
5515
6207
  });
5516
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React60__default.default.createElement(
6208
+ const trackFocus = (e) => {
6209
+ var _a2, _b2;
6210
+ const el = e.currentTarget;
6211
+ setLastFocusedEditable({
6212
+ blockId,
6213
+ field: "text",
6214
+ selectionStart: (_a2 = el.selectionStart) != null ? _a2 : el.value.length,
6215
+ selectionEnd: (_b2 = el.selectionEnd) != null ? _b2 : el.value.length
6216
+ });
6217
+ };
6218
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React58__default.default.createElement(
5517
6219
  "input",
5518
6220
  {
5519
6221
  type: "text",
5520
6222
  value: localText,
5521
6223
  onChange: handleTextChange,
5522
- style: inputStyle,
5523
- onClick: (e) => e.stopPropagation()
6224
+ onFocus: trackFocus,
6225
+ onSelect: trackFocus,
6226
+ onKeyUp: trackFocus,
6227
+ onClick: (e) => {
6228
+ e.stopPropagation();
6229
+ trackFocus(e);
6230
+ },
6231
+ style: inputStyle
5524
6232
  }
5525
6233
  ));
5526
6234
  }
5527
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React60__default.default.createElement("span", { style: linkStyle }, /* @__PURE__ */ React60__default.default.createElement("span", null, text)));
6235
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React58__default.default.createElement("span", { style: linkStyle }, /* @__PURE__ */ React58__default.default.createElement("span", null, text)));
6236
+ }
6237
+ function useMarkdownToolbar({ text, isSelected, commitText, trackSelection }) {
6238
+ const textareaRef = React58.useRef(null);
6239
+ const [selection, setSelection] = React58.useState({ start: 0, end: 0 });
6240
+ const [linkPrompt, setLinkPrompt] = React58.useState(false);
6241
+ const pendingSelectionRef = React58.useRef(null);
6242
+ const textRef = React58.useRef(text);
6243
+ React58.useEffect(() => {
6244
+ textRef.current = text;
6245
+ }, [text]);
6246
+ const syncSelection = React58.useCallback(
6247
+ (start, end) => {
6248
+ const next = { start, end };
6249
+ setSelection(next);
6250
+ trackSelection == null ? void 0 : trackSelection(next);
6251
+ },
6252
+ [trackSelection]
6253
+ );
6254
+ const trackFocus = React58.useCallback(
6255
+ (e) => {
6256
+ var _a, _b;
6257
+ const el = e.currentTarget;
6258
+ const start = (_a = el.selectionStart) != null ? _a : el.value.length;
6259
+ const end = (_b = el.selectionEnd) != null ? _b : el.value.length;
6260
+ syncSelection(start, end);
6261
+ },
6262
+ [syncSelection]
6263
+ );
6264
+ React58.useEffect(() => {
6265
+ const target = pendingSelectionRef.current;
6266
+ if (!target) return;
6267
+ const ta = textareaRef.current;
6268
+ if (!ta) return;
6269
+ ta.focus();
6270
+ ta.setSelectionRange(target.start, target.end);
6271
+ syncSelection(target.start, target.end);
6272
+ pendingSelectionRef.current = null;
6273
+ }, [text, syncSelection]);
6274
+ React58.useEffect(() => {
6275
+ if (!isSelected || selection.start === selection.end) {
6276
+ setLinkPrompt(false);
6277
+ }
6278
+ }, [isSelected, selection.start, selection.end]);
6279
+ const wrapSelection = (prefix, suffix) => {
6280
+ var _a, _b;
6281
+ const ta = textareaRef.current;
6282
+ if (!ta) return;
6283
+ const start = (_a = ta.selectionStart) != null ? _a : selection.start;
6284
+ const end = (_b = ta.selectionEnd) != null ? _b : selection.end;
6285
+ if (start === end) return;
6286
+ const current = textRef.current;
6287
+ const selected = current.slice(start, end);
6288
+ const before = current.slice(0, start);
6289
+ const after = current.slice(end);
6290
+ const wrapped = `${prefix}${selected}${suffix}`;
6291
+ const newText = `${before}${wrapped}${after}`;
6292
+ const newStart = start + prefix.length;
6293
+ const newEnd = newStart + selected.length;
6294
+ pendingSelectionRef.current = { start: newStart, end: newEnd };
6295
+ commitText(newText);
6296
+ };
6297
+ const handleBold = () => wrapSelection("**", "**");
6298
+ const handleItalic = () => wrapSelection("*", "*");
6299
+ const handleLinkRequest = () => {
6300
+ if (selection.start === selection.end) return;
6301
+ setLinkPrompt(true);
6302
+ };
6303
+ const handleLinkSubmit = (url) => {
6304
+ const start = selection.start;
6305
+ const end = selection.end;
6306
+ if (start === end) {
6307
+ setLinkPrompt(false);
6308
+ return;
6309
+ }
6310
+ const current = textRef.current;
6311
+ const selected = current.slice(start, end);
6312
+ const before = current.slice(0, start);
6313
+ const after = current.slice(end);
6314
+ const wrapped = `[${selected}](${url})`;
6315
+ const newText = `${before}${wrapped}${after}`;
6316
+ const newStart = start + wrapped.length;
6317
+ pendingSelectionRef.current = { start: newStart, end: newStart };
6318
+ commitText(newText);
6319
+ setLinkPrompt(false);
6320
+ };
6321
+ const handleLinkCancel = () => {
6322
+ var _a;
6323
+ setLinkPrompt(false);
6324
+ (_a = textareaRef.current) == null ? void 0 : _a.focus();
6325
+ };
6326
+ const handleKeyDown = (e) => {
6327
+ if (!(e.metaKey || e.ctrlKey)) return;
6328
+ const key = e.key.toLowerCase();
6329
+ if (key === "b") {
6330
+ e.preventDefault();
6331
+ handleBold();
6332
+ } else if (key === "i") {
6333
+ e.preventDefault();
6334
+ handleItalic();
6335
+ } else if (key === "k") {
6336
+ e.preventDefault();
6337
+ handleLinkRequest();
6338
+ }
6339
+ };
6340
+ const toolbarVisible = isSelected && (selection.start !== selection.end || linkPrompt);
6341
+ return {
6342
+ textareaRef,
6343
+ selection,
6344
+ trackFocus,
6345
+ handleKeyDown,
6346
+ toolbarProps: {
6347
+ visible: toolbarVisible,
6348
+ linkPrompt,
6349
+ onBold: handleBold,
6350
+ onItalic: handleItalic,
6351
+ onLinkRequest: handleLinkRequest,
6352
+ onLinkSubmit: handleLinkSubmit,
6353
+ onLinkCancel: handleLinkCancel
6354
+ }
6355
+ };
6356
+ }
6357
+ function InlineFormattingToolbar({
6358
+ anchorEl,
6359
+ visible,
6360
+ linkPrompt,
6361
+ onBold,
6362
+ onItalic,
6363
+ onLinkRequest,
6364
+ onLinkSubmit,
6365
+ onLinkCancel
6366
+ }) {
6367
+ const [url, setUrl] = React58.useState("");
6368
+ const inputRef = React58.useRef(null);
6369
+ React58.useEffect(() => {
6370
+ if (linkPrompt) {
6371
+ setUrl("");
6372
+ setTimeout(() => {
6373
+ var _a;
6374
+ return (_a = inputRef.current) == null ? void 0 : _a.focus();
6375
+ }, 0);
6376
+ }
6377
+ }, [linkPrompt]);
6378
+ const preventBlur = (e) => e.preventDefault();
6379
+ return /* @__PURE__ */ React58__default.default.createElement(material.Popper, { open: visible, anchorEl, placement: "top-start", style: { zIndex: 1300 } }, /* @__PURE__ */ React58__default.default.createElement(material.Paper, { elevation: 4, sx: { px: 0.5, py: 0.25, mb: 0.5 }, onMouseDown: preventBlur }, linkPrompt ? /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", alignItems: "center", spacing: 0.5, sx: { px: 0.5 } }, /* @__PURE__ */ React58__default.default.createElement(
6380
+ material.TextField,
6381
+ {
6382
+ inputRef,
6383
+ value: url,
6384
+ onChange: (e) => setUrl(e.target.value),
6385
+ placeholder: "https://example.com",
6386
+ variant: "standard",
6387
+ size: "small",
6388
+ onKeyDown: (e) => {
6389
+ if (e.key === "Enter") {
6390
+ e.preventDefault();
6391
+ const trimmed = url.trim();
6392
+ if (trimmed) onLinkSubmit(trimmed);
6393
+ else onLinkCancel();
6394
+ } else if (e.key === "Escape") {
6395
+ e.preventDefault();
6396
+ onLinkCancel();
6397
+ }
6398
+ },
6399
+ sx: { width: 220 }
6400
+ }
6401
+ )) : /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 0.25 }, /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { size: "small", onClick: onBold, title: "Bold (Cmd+B)", "aria-label": "Bold" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FormatBoldOutlined, { fontSize: "small" })), /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { size: "small", onClick: onItalic, title: "Italic (Cmd+I)", "aria-label": "Italic" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FormatItalicOutlined, { fontSize: "small" })), /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { size: "small", onClick: onLinkRequest, title: "Link (Cmd+K)", "aria-label": "Link" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.LinkOutlined, { fontSize: "small" })))));
5528
6402
  }
6403
+
6404
+ // src/editor/blocks/heading/heading-editor.tsx
5529
6405
  function getFontFamily9(fontFamily) {
5530
6406
  switch (fontFamily) {
5531
6407
  case "MODERN_SANS":
@@ -5588,25 +6464,28 @@ function getFontSize2(level) {
5588
6464
  }
5589
6465
  }
5590
6466
  function HeadingEditor({ style, props }) {
5591
- var _a, _b, _c, _d, _e, _f;
6467
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
5592
6468
  const blockId = useCurrentBlockId();
5593
6469
  const selectedBlockId = useSelectedBlockId();
5594
6470
  const document2 = useDocument();
5595
6471
  const isSelected = selectedBlockId === blockId;
5596
6472
  const level = (_a = props == null ? void 0 : props.level) != null ? _a : HeadingPropsDefaults.level;
5597
6473
  const textContent = (_b = props == null ? void 0 : props.text) != null ? _b : HeadingPropsDefaults.text;
5598
- const [localText, setLocalText] = React60.useState(textContent);
6474
+ const [localText, setLocalText] = React58.useState(textContent);
6475
+ const isMarkdown = (_c = props == null ? void 0 : props.markdown) != null ? _c : false;
5599
6476
  const rootBlock = document2.root;
5600
6477
  const rootFontFamily = rootBlock && rootBlock.type === "EmailLayout" ? getFontFamily9(rootBlock.data.fontFamily) : '"Helvetica Neue", Arial, sans-serif';
5601
- React60.useEffect(() => {
6478
+ React58.useEffect(() => {
5602
6479
  setLocalText(textContent);
5603
6480
  }, [textContent]);
5604
6481
  const fontFamily = getFontFamily9(style == null ? void 0 : style.fontFamily) || rootFontFamily;
5605
6482
  const hStyle = {
5606
- color: (_c = style == null ? void 0 : style.color) != null ? _c : void 0,
5607
- backgroundColor: (_d = style == null ? void 0 : style.backgroundColor) != null ? _d : void 0,
5608
- fontWeight: (_e = style == null ? void 0 : style.fontWeight) != null ? _e : "bold",
5609
- textAlign: (_f = style == null ? void 0 : style.textAlign) != null ? _f : void 0,
6483
+ color: (_d = style == null ? void 0 : style.color) != null ? _d : void 0,
6484
+ backgroundColor: (_e = style == null ? void 0 : style.backgroundColor) != null ? _e : void 0,
6485
+ fontWeight: (_f = style == null ? void 0 : style.fontWeight) != null ? _f : "bold",
6486
+ lineHeight: (_g = style == null ? void 0 : style.lineHeight) != null ? _g : void 0,
6487
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
6488
+ textAlign: (_h = style == null ? void 0 : style.textAlign) != null ? _h : void 0,
5610
6489
  margin: 0,
5611
6490
  fontFamily,
5612
6491
  fontSize: getFontSize2(level),
@@ -5620,53 +6499,79 @@ function HeadingEditor({ style, props }) {
5620
6499
  resize: "none",
5621
6500
  backgroundColor: "transparent",
5622
6501
  overflow: "hidden",
5623
- lineHeight: "inherit",
6502
+ lineHeight: (_i = hStyle.lineHeight) != null ? _i : "inherit",
5624
6503
  margin: 0,
5625
6504
  display: "block",
5626
6505
  width: "100%"
5627
6506
  });
5628
- const handleTextChange = (e) => {
5629
- const newText = e.target.value;
6507
+ const commitText = (newText, opts) => {
5630
6508
  setLocalText(newText);
5631
6509
  setDocument({
5632
6510
  [blockId]: {
5633
6511
  type: "Heading",
5634
6512
  data: {
5635
6513
  style,
5636
- props: __spreadProps(__spreadValues({}, props), {
6514
+ props: __spreadValues(__spreadProps(__spreadValues({}, props), {
5637
6515
  text: newText
5638
- })
6516
+ }), (opts == null ? void 0 : opts.enableMarkdown) ? { markdown: true } : {})
5639
6517
  }
5640
6518
  }
5641
6519
  });
5642
6520
  };
6521
+ const handleTextChange = (e) => {
6522
+ commitText(e.target.value);
6523
+ };
5643
6524
  const adjustTextareaHeight = (element) => {
5644
6525
  if (element) {
5645
6526
  element.style.height = "auto";
5646
6527
  element.style.height = `${element.scrollHeight}px`;
5647
6528
  }
5648
6529
  };
6530
+ const { textareaRef, trackFocus, handleKeyDown, toolbarProps } = useMarkdownToolbar({
6531
+ text: localText,
6532
+ isSelected,
6533
+ commitText: (newText) => commitText(newText, { enableMarkdown: true }),
6534
+ trackSelection: (sel) => {
6535
+ setLastFocusedEditable({
6536
+ blockId,
6537
+ field: "text",
6538
+ selectionStart: sel.start,
6539
+ selectionEnd: sel.end
6540
+ });
6541
+ }
6542
+ });
6543
+ React58.useEffect(() => {
6544
+ if (textareaRef.current) adjustTextareaHeight(textareaRef.current);
6545
+ }, [localText, textareaRef]);
5649
6546
  if (isSelected) {
5650
- return /* @__PURE__ */ React60__default.default.createElement(
6547
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
5651
6548
  "textarea",
5652
6549
  {
6550
+ ref: textareaRef,
5653
6551
  value: localText,
5654
6552
  onChange: handleTextChange,
6553
+ onFocus: trackFocus,
6554
+ onSelect: trackFocus,
6555
+ onKeyUp: trackFocus,
6556
+ onKeyDown: handleKeyDown,
6557
+ onClick: (e) => {
6558
+ e.stopPropagation();
6559
+ trackFocus(e);
6560
+ },
5655
6561
  style: textareaStyle,
5656
6562
  rows: 1,
5657
- onInput: (e) => adjustTextareaHeight(e.target),
5658
- ref: (el) => el && adjustTextareaHeight(el),
5659
- onClick: (e) => e.stopPropagation()
6563
+ onInput: (e) => adjustTextareaHeight(e.target)
5660
6564
  }
5661
- );
6565
+ ), /* @__PURE__ */ React58__default.default.createElement(InlineFormattingToolbar, __spreadValues({ anchorEl: textareaRef.current }, toolbarProps)));
5662
6566
  }
6567
+ const headingProps = isMarkdown ? { style: hStyle, dangerouslySetInnerHTML: { __html: renderInlineMarkdownString(textContent) } } : { style: hStyle, children: textContent };
5663
6568
  switch (level) {
5664
6569
  case "h1":
5665
- return /* @__PURE__ */ React60__default.default.createElement("h1", { style: hStyle }, textContent);
6570
+ return /* @__PURE__ */ React58__default.default.createElement("h1", __spreadValues({}, headingProps));
5666
6571
  case "h2":
5667
- return /* @__PURE__ */ React60__default.default.createElement("h2", { style: hStyle }, textContent);
6572
+ return /* @__PURE__ */ React58__default.default.createElement("h2", __spreadValues({}, headingProps));
5668
6573
  case "h3":
5669
- return /* @__PURE__ */ React60__default.default.createElement("h3", { style: hStyle }, textContent);
6574
+ return /* @__PURE__ */ React58__default.default.createElement("h3", __spreadValues({}, headingProps));
5670
6575
  }
5671
6576
  }
5672
6577
  function HtmlEditor({ style, props }) {
@@ -5675,8 +6580,8 @@ function HtmlEditor({ style, props }) {
5675
6580
  const selectedBlockId = useSelectedBlockId();
5676
6581
  const isSelected = selectedBlockId === blockId;
5677
6582
  const contents = (_a = props == null ? void 0 : props.contents) != null ? _a : "";
5678
- const [localContents, setLocalContents] = React60.useState(contents);
5679
- React60.useEffect(() => {
6583
+ const [localContents, setLocalContents] = React58.useState(contents);
6584
+ React58.useEffect(() => {
5680
6585
  setLocalContents(contents);
5681
6586
  }, [contents]);
5682
6587
  const cssStyle = {
@@ -5721,23 +6626,39 @@ function HtmlEditor({ style, props }) {
5721
6626
  margin: 0,
5722
6627
  backgroundColor: "transparent"
5723
6628
  });
5724
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: cssStyle }, /* @__PURE__ */ React60__default.default.createElement(
6629
+ const trackFocus = (e) => {
6630
+ var _a2, _b2;
6631
+ const el = e.currentTarget;
6632
+ setLastFocusedEditable({
6633
+ blockId,
6634
+ field: "contents",
6635
+ selectionStart: (_a2 = el.selectionStart) != null ? _a2 : el.value.length,
6636
+ selectionEnd: (_b2 = el.selectionEnd) != null ? _b2 : el.value.length
6637
+ });
6638
+ };
6639
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: cssStyle }, /* @__PURE__ */ React58__default.default.createElement(
5725
6640
  "textarea",
5726
6641
  {
5727
6642
  value: localContents,
5728
6643
  onChange: handleChange,
6644
+ onFocus: trackFocus,
6645
+ onSelect: trackFocus,
6646
+ onKeyUp: trackFocus,
6647
+ onClick: (e) => {
6648
+ e.stopPropagation();
6649
+ trackFocus(e);
6650
+ },
5729
6651
  style: textareaStyle,
5730
6652
  rows: 3,
5731
6653
  onInput: (e) => adjustTextareaHeight(e.target),
5732
- ref: (el) => el && adjustTextareaHeight(el),
5733
- onClick: (e) => e.stopPropagation()
6654
+ ref: (el) => el && adjustTextareaHeight(el)
5734
6655
  }
5735
6656
  ));
5736
6657
  }
5737
6658
  if (!contents) {
5738
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: cssStyle });
6659
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: cssStyle });
5739
6660
  }
5740
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: contents } });
6661
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: contents } });
5741
6662
  }
5742
6663
  function getImageBorderRadius2(shape, size) {
5743
6664
  switch (shape) {
@@ -5770,36 +6691,36 @@ function SignatureEditor({ style, props }) {
5770
6691
  const nameColor = (_m = props == null ? void 0 : props.nameColor) != null ? _m : SignaturePropsDefaults.nameColor;
5771
6692
  const textColor = (_n = props == null ? void 0 : props.textColor) != null ? _n : SignaturePropsDefaults.textColor;
5772
6693
  const linkColor = (_o = props == null ? void 0 : props.linkColor) != null ? _o : SignaturePropsDefaults.linkColor;
5773
- const [localGreeting, setLocalGreeting] = React60.useState(greeting);
5774
- const [localName, setLocalName] = React60.useState(name);
5775
- const [localTitle, setLocalTitle] = React60.useState(title);
5776
- const [localCompany, setLocalCompany] = React60.useState(company);
5777
- const [localAddress, setLocalAddress] = React60.useState(address);
5778
- const [localEmail, setLocalEmail] = React60.useState(email);
5779
- const [localPhone, setLocalPhone] = React60.useState(phone);
5780
- const [localWebsite, setLocalWebsite] = React60.useState(website);
5781
- React60.useEffect(() => {
6694
+ const [localGreeting, setLocalGreeting] = React58.useState(greeting);
6695
+ const [localName, setLocalName] = React58.useState(name);
6696
+ const [localTitle, setLocalTitle] = React58.useState(title);
6697
+ const [localCompany, setLocalCompany] = React58.useState(company);
6698
+ const [localAddress, setLocalAddress] = React58.useState(address);
6699
+ const [localEmail, setLocalEmail] = React58.useState(email);
6700
+ const [localPhone, setLocalPhone] = React58.useState(phone);
6701
+ const [localWebsite, setLocalWebsite] = React58.useState(website);
6702
+ React58.useEffect(() => {
5782
6703
  setLocalGreeting(greeting);
5783
6704
  }, [greeting]);
5784
- React60.useEffect(() => {
6705
+ React58.useEffect(() => {
5785
6706
  setLocalName(name);
5786
6707
  }, [name]);
5787
- React60.useEffect(() => {
6708
+ React58.useEffect(() => {
5788
6709
  setLocalTitle(title);
5789
6710
  }, [title]);
5790
- React60.useEffect(() => {
6711
+ React58.useEffect(() => {
5791
6712
  setLocalCompany(company);
5792
6713
  }, [company]);
5793
- React60.useEffect(() => {
6714
+ React58.useEffect(() => {
5794
6715
  setLocalAddress(address);
5795
6716
  }, [address]);
5796
- React60.useEffect(() => {
6717
+ React58.useEffect(() => {
5797
6718
  setLocalEmail(email);
5798
6719
  }, [email]);
5799
- React60.useEffect(() => {
6720
+ React58.useEffect(() => {
5800
6721
  setLocalPhone(phone);
5801
6722
  }, [phone]);
5802
- React60.useEffect(() => {
6723
+ React58.useEffect(() => {
5803
6724
  setLocalWebsite(website);
5804
6725
  }, [website]);
5805
6726
  const updateProps = (updates) => {
@@ -5852,7 +6773,7 @@ function SignatureEditor({ style, props }) {
5852
6773
  backgroundColor: (_p = style == null ? void 0 : style.backgroundColor) != null ? _p : void 0,
5853
6774
  padding: (style == null ? void 0 : style.padding) ? `${style.padding.top}px ${style.padding.right}px ${style.padding.bottom}px ${style.padding.left}px` : void 0
5854
6775
  };
5855
- const imageElement = imageUrl ? /* @__PURE__ */ React60__default.default.createElement(
6776
+ const imageElement = imageUrl ? /* @__PURE__ */ React58__default.default.createElement(
5856
6777
  "img",
5857
6778
  {
5858
6779
  src: imageUrl,
@@ -5870,7 +6791,7 @@ function SignatureEditor({ style, props }) {
5870
6791
  }
5871
6792
  }
5872
6793
  ) : null;
5873
- const greetingElement = isSelected ? /* @__PURE__ */ React60__default.default.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React60__default.default.createElement(
6794
+ const greetingElement = isSelected ? /* @__PURE__ */ React58__default.default.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React58__default.default.createElement(
5874
6795
  "input",
5875
6796
  {
5876
6797
  value: localGreeting,
@@ -5881,8 +6802,8 @@ function SignatureEditor({ style, props }) {
5881
6802
  placeholder: "Greeting (e.g. Best regards,)",
5882
6803
  style: __spreadValues(__spreadValues({}, inputBase), greetingStyle)
5883
6804
  }
5884
- )) : greeting ? /* @__PURE__ */ React60__default.default.createElement("p", { style: greetingStyle }, greeting) : null;
5885
- const textContent = isSelected ? /* @__PURE__ */ React60__default.default.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React60__default.default.createElement(
6805
+ )) : greeting ? /* @__PURE__ */ React58__default.default.createElement("p", { style: greetingStyle }, greeting) : null;
6806
+ const textContent = isSelected ? /* @__PURE__ */ React58__default.default.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React58__default.default.createElement(
5886
6807
  "input",
5887
6808
  {
5888
6809
  value: localName,
@@ -5893,7 +6814,7 @@ function SignatureEditor({ style, props }) {
5893
6814
  placeholder: "Name",
5894
6815
  style: __spreadValues(__spreadValues({}, inputBase), nameStyle)
5895
6816
  }
5896
- ), /* @__PURE__ */ React60__default.default.createElement(
6817
+ ), /* @__PURE__ */ React58__default.default.createElement(
5897
6818
  "input",
5898
6819
  {
5899
6820
  value: localTitle,
@@ -5904,7 +6825,7 @@ function SignatureEditor({ style, props }) {
5904
6825
  placeholder: "Title",
5905
6826
  style: __spreadValues(__spreadValues({}, inputBase), detailStyle)
5906
6827
  }
5907
- ), /* @__PURE__ */ React60__default.default.createElement(
6828
+ ), /* @__PURE__ */ React58__default.default.createElement(
5908
6829
  "input",
5909
6830
  {
5910
6831
  value: localCompany,
@@ -5915,7 +6836,7 @@ function SignatureEditor({ style, props }) {
5915
6836
  placeholder: "Company",
5916
6837
  style: __spreadValues(__spreadValues({}, inputBase), detailStyle)
5917
6838
  }
5918
- ), /* @__PURE__ */ React60__default.default.createElement(
6839
+ ), /* @__PURE__ */ React58__default.default.createElement(
5919
6840
  "input",
5920
6841
  {
5921
6842
  value: localAddress,
@@ -5926,7 +6847,7 @@ function SignatureEditor({ style, props }) {
5926
6847
  placeholder: "Address",
5927
6848
  style: __spreadValues(__spreadValues({}, inputBase), detailStyle)
5928
6849
  }
5929
- ), /* @__PURE__ */ React60__default.default.createElement(
6850
+ ), /* @__PURE__ */ React58__default.default.createElement(
5930
6851
  "input",
5931
6852
  {
5932
6853
  value: localEmail,
@@ -5937,7 +6858,7 @@ function SignatureEditor({ style, props }) {
5937
6858
  placeholder: "Email",
5938
6859
  style: __spreadProps(__spreadValues(__spreadValues({}, inputBase), linkStyle), { marginTop: 4, display: "block" })
5939
6860
  }
5940
- ), /* @__PURE__ */ React60__default.default.createElement(
6861
+ ), /* @__PURE__ */ React58__default.default.createElement(
5941
6862
  "input",
5942
6863
  {
5943
6864
  value: localPhone,
@@ -5948,7 +6869,7 @@ function SignatureEditor({ style, props }) {
5948
6869
  placeholder: "Phone",
5949
6870
  style: __spreadProps(__spreadValues(__spreadValues({}, inputBase), linkStyle), { display: "block" })
5950
6871
  }
5951
- ), /* @__PURE__ */ React60__default.default.createElement(
6872
+ ), /* @__PURE__ */ React58__default.default.createElement(
5952
6873
  "input",
5953
6874
  {
5954
6875
  value: localWebsite,
@@ -5959,11 +6880,11 @@ function SignatureEditor({ style, props }) {
5959
6880
  placeholder: "Website",
5960
6881
  style: __spreadProps(__spreadValues(__spreadValues({}, inputBase), linkStyle), { display: "block" })
5961
6882
  }
5962
- )) : /* @__PURE__ */ React60__default.default.createElement("div", null, name && /* @__PURE__ */ React60__default.default.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, address), (email || phone || website) && /* @__PURE__ */ React60__default.default.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, email && /* @__PURE__ */ React60__default.default.createElement("span", { style: linkStyle }, email), email && (phone || website) && /* @__PURE__ */ React60__default.default.createElement("span", { style: detailStyle }, " \xB7 "), phone && /* @__PURE__ */ React60__default.default.createElement("span", { style: linkStyle }, phone), phone && website && /* @__PURE__ */ React60__default.default.createElement("span", { style: detailStyle }, " \xB7 "), website && /* @__PURE__ */ React60__default.default.createElement("span", { style: linkStyle }, website)), !name && !title && !company && !email && !phone && !website && /* @__PURE__ */ React60__default.default.createElement("p", { style: detailStyle }, "Click to edit signature"));
6883
+ )) : /* @__PURE__ */ React58__default.default.createElement("div", null, name && /* @__PURE__ */ React58__default.default.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, address), (email || phone || website) && /* @__PURE__ */ React58__default.default.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, email && /* @__PURE__ */ React58__default.default.createElement("span", { style: linkStyle }, email), email && (phone || website) && /* @__PURE__ */ React58__default.default.createElement("span", { style: detailStyle }, " \xB7 "), phone && /* @__PURE__ */ React58__default.default.createElement("span", { style: linkStyle }, phone), phone && website && /* @__PURE__ */ React58__default.default.createElement("span", { style: detailStyle }, " \xB7 "), website && /* @__PURE__ */ React58__default.default.createElement("span", { style: linkStyle }, website)), !name && !title && !company && !email && !phone && !website && /* @__PURE__ */ React58__default.default.createElement("p", { style: detailStyle }, "Click to edit signature"));
5963
6884
  if (layout === "vertical") {
5964
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React60__default.default.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
6885
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React58__default.default.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
5965
6886
  }
5966
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React60__default.default.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React60__default.default.createElement("tbody", null, /* @__PURE__ */ React60__default.default.createElement("tr", null, imageElement && /* @__PURE__ */ React60__default.default.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React60__default.default.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
6887
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React58__default.default.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React58__default.default.createElement("tbody", null, /* @__PURE__ */ React58__default.default.createElement("tr", null, imageElement && /* @__PURE__ */ React58__default.default.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React58__default.default.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
5967
6888
  }
5968
6889
  function getFontFamily10(fontFamily) {
5969
6890
  switch (fontFamily) {
@@ -6017,17 +6938,17 @@ function getPadding13(padding) {
6017
6938
  return void 0;
6018
6939
  }
6019
6940
  function TextEditor({ style, props }) {
6020
- var _a, _b, _c, _d, _e, _f, _g;
6941
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
6021
6942
  const blockId = useCurrentBlockId();
6022
6943
  const selectedBlockId = useSelectedBlockId();
6023
6944
  const document2 = useDocument();
6024
6945
  const isSelected = selectedBlockId === blockId;
6025
6946
  const textContent = (_a = props == null ? void 0 : props.text) != null ? _a : TextPropsDefaults.text;
6026
- const [localText, setLocalText] = React60.useState(textContent);
6947
+ const [localText, setLocalText] = React58.useState(textContent);
6027
6948
  const isMarkdown = (_b = props == null ? void 0 : props.markdown) != null ? _b : false;
6028
6949
  const rootBlock = document2.root;
6029
6950
  const rootFontFamily = rootBlock && rootBlock.type === "EmailLayout" ? getFontFamily10(rootBlock.data.fontFamily) : '"Helvetica Neue", Arial, sans-serif';
6030
- React60.useEffect(() => {
6951
+ React58.useEffect(() => {
6031
6952
  setLocalText(textContent);
6032
6953
  }, [textContent]);
6033
6954
  const fontFamily = getFontFamily10(style == null ? void 0 : style.fontFamily) || rootFontFamily;
@@ -6037,7 +6958,9 @@ function TextEditor({ style, props }) {
6037
6958
  fontSize: (_e = style == null ? void 0 : style.fontSize) != null ? _e : void 0,
6038
6959
  fontFamily,
6039
6960
  fontWeight: (_f = style == null ? void 0 : style.fontWeight) != null ? _f : void 0,
6040
- textAlign: (_g = style == null ? void 0 : style.textAlign) != null ? _g : void 0,
6961
+ lineHeight: (_g = style == null ? void 0 : style.lineHeight) != null ? _g : void 0,
6962
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
6963
+ textAlign: (_h = style == null ? void 0 : style.textAlign) != null ? _h : void 0,
6041
6964
  padding: getPadding13(style == null ? void 0 : style.padding),
6042
6965
  width: "100%",
6043
6966
  minHeight: "1em"
@@ -6048,7 +6971,7 @@ function TextEditor({ style, props }) {
6048
6971
  resize: "none",
6049
6972
  backgroundColor: "transparent",
6050
6973
  overflow: "hidden",
6051
- lineHeight: "inherit",
6974
+ lineHeight: (_i = wStyle.lineHeight) != null ? _i : "inherit",
6052
6975
  margin: 0,
6053
6976
  display: "block",
6054
6977
  width: "100%",
@@ -6056,72 +6979,97 @@ function TextEditor({ style, props }) {
6056
6979
  fontWeight: wStyle.fontWeight,
6057
6980
  textAlign: wStyle.textAlign
6058
6981
  });
6059
- const handleTextChange = (e) => {
6060
- const newText = e.target.value;
6982
+ const commitText = (newText, opts) => {
6061
6983
  setLocalText(newText);
6062
6984
  setDocument({
6063
6985
  [blockId]: {
6064
6986
  type: "Text",
6065
6987
  data: {
6066
6988
  style,
6067
- props: __spreadProps(__spreadValues({}, props), {
6989
+ props: __spreadValues(__spreadProps(__spreadValues({}, props), {
6068
6990
  text: newText
6069
- })
6991
+ }), (opts == null ? void 0 : opts.enableMarkdown) ? { markdown: true } : {})
6070
6992
  }
6071
6993
  }
6072
6994
  });
6073
6995
  };
6996
+ const handleTextChange = (e) => {
6997
+ commitText(e.target.value);
6998
+ };
6074
6999
  const adjustTextareaHeight = (element) => {
6075
7000
  if (element) {
6076
7001
  element.style.height = "auto";
6077
7002
  element.style.height = `${element.scrollHeight}px`;
6078
7003
  }
6079
7004
  };
7005
+ const { textareaRef, trackFocus, handleKeyDown, toolbarProps } = useMarkdownToolbar({
7006
+ text: localText,
7007
+ isSelected,
7008
+ commitText: (newText) => commitText(newText, { enableMarkdown: true }),
7009
+ trackSelection: (sel) => {
7010
+ setLastFocusedEditable({
7011
+ blockId,
7012
+ field: "text",
7013
+ selectionStart: sel.start,
7014
+ selectionEnd: sel.end
7015
+ });
7016
+ }
7017
+ });
7018
+ React58.useEffect(() => {
7019
+ if (textareaRef.current) adjustTextareaHeight(textareaRef.current);
7020
+ }, [localText, textareaRef]);
6080
7021
  if (isSelected) {
6081
- return /* @__PURE__ */ React60__default.default.createElement(
7022
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
6082
7023
  "textarea",
6083
7024
  {
7025
+ ref: textareaRef,
6084
7026
  value: localText,
6085
7027
  onChange: handleTextChange,
7028
+ onFocus: trackFocus,
7029
+ onSelect: trackFocus,
7030
+ onKeyUp: trackFocus,
7031
+ onKeyDown: handleKeyDown,
7032
+ onClick: (e) => {
7033
+ e.stopPropagation();
7034
+ trackFocus(e);
7035
+ },
6086
7036
  style: textareaStyle,
6087
7037
  rows: 1,
6088
- onInput: (e) => adjustTextareaHeight(e.target),
6089
- ref: (el) => el && adjustTextareaHeight(el),
6090
- onClick: (e) => e.stopPropagation()
7038
+ onInput: (e) => adjustTextareaHeight(e.target)
6091
7039
  }
6092
- );
7040
+ ), /* @__PURE__ */ React58__default.default.createElement(InlineFormattingToolbar, __spreadValues({ anchorEl: textareaRef.current }, toolbarProps)));
6093
7041
  }
6094
7042
  if (isMarkdown) {
6095
- return /* @__PURE__ */ React60__default.default.createElement(EmailMarkdown, { style: wStyle, markdown: textContent });
7043
+ return /* @__PURE__ */ React58__default.default.createElement(EmailMarkdown, { style: wStyle, markdown: textContent });
6096
7044
  }
6097
- return /* @__PURE__ */ React60__default.default.createElement("div", { style: wStyle }, textContent);
7045
+ return /* @__PURE__ */ React58__default.default.createElement("div", { style: wStyle }, textContent);
6098
7046
  }
6099
7047
 
6100
7048
  // src/editor/core.tsx
6101
7049
  var EDITOR_DICTIONARY = buildBlockConfigurationDictionary({
6102
7050
  Avatar: {
6103
7051
  schema: AvatarPropsSchema,
6104
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(avatar_default, __spreadValues({}, props)))
7052
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(avatar_default, __spreadValues({}, props)))
6105
7053
  },
6106
7054
  Button: {
6107
7055
  schema: ButtonPropsSchema,
6108
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(ButtonEditor, __spreadValues({}, props)))
7056
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(ButtonEditor, __spreadValues({}, props)))
6109
7057
  },
6110
7058
  Container: {
6111
7059
  schema: container_props_schema_default,
6112
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(ContainerEditor, __spreadValues({}, props)))
7060
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(ContainerEditor, __spreadValues({}, props)))
6113
7061
  },
6114
7062
  ColumnsContainer: {
6115
7063
  schema: columns_container_props_schema_default2,
6116
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(ColumnsContainerEditor, __spreadValues({}, props)))
7064
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(ColumnsContainerEditor, __spreadValues({}, props)))
6117
7065
  },
6118
7066
  Heading: {
6119
7067
  schema: HeadingPropsSchema,
6120
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(HeadingEditor, __spreadValues({}, props)))
7068
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(HeadingEditor, __spreadValues({}, props)))
6121
7069
  },
6122
7070
  Html: {
6123
7071
  schema: HtmlPropsSchema,
6124
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(HtmlEditor, __spreadValues({}, props)))
7072
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(HtmlEditor, __spreadValues({}, props)))
6125
7073
  },
6126
7074
  Image: {
6127
7075
  schema: ImagePropsSchema,
@@ -6133,28 +7081,28 @@ var EDITOR_DICTIONARY = buildBlockConfigurationDictionary({
6133
7081
  linkHref: null
6134
7082
  })
6135
7083
  });
6136
- return /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(image_default, __spreadValues({}, props)));
7084
+ return /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(image_default, __spreadValues({}, props)));
6137
7085
  }
6138
7086
  },
6139
7087
  Text: {
6140
7088
  schema: TextPropsSchema,
6141
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(TextEditor, __spreadValues({}, props)))
7089
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(TextEditor, __spreadValues({}, props)))
6142
7090
  },
6143
7091
  EmailLayout: {
6144
7092
  schema: email_layout_props_schema_default,
6145
- Component: (p) => /* @__PURE__ */ React60__default.default.createElement(EmailLayoutEditor, __spreadValues({}, p))
7093
+ Component: (p) => /* @__PURE__ */ React58__default.default.createElement(EmailLayoutEditor, __spreadValues({}, p))
6146
7094
  },
6147
7095
  Spacer: {
6148
7096
  schema: SpacerPropsSchema,
6149
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(spacer_default, __spreadValues({}, props)))
7097
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(spacer_default, __spreadValues({}, props)))
6150
7098
  },
6151
7099
  Divider: {
6152
7100
  schema: DividerPropsSchema,
6153
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(divider_default, __spreadValues({}, props)))
7101
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(divider_default, __spreadValues({}, props)))
6154
7102
  },
6155
7103
  Signature: {
6156
7104
  schema: SignaturePropsSchema,
6157
- Component: (props) => /* @__PURE__ */ React60__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60__default.default.createElement(SignatureEditor, __spreadValues({}, props)))
7105
+ Component: (props) => /* @__PURE__ */ React58__default.default.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58__default.default.createElement(SignatureEditor, __spreadValues({}, props)))
6158
7106
  }
6159
7107
  });
6160
7108
  var EditorBlock2 = buildBlockComponent(EDITOR_DICTIONARY);
@@ -6162,15 +7110,15 @@ var EditorBlockSchema = buildBlockConfigurationSchema(EDITOR_DICTIONARY);
6162
7110
  zod.z.record(zod.z.string(), EditorBlockSchema);
6163
7111
 
6164
7112
  // src/editor/editor-block.tsx
6165
- var EditorBlockContext = React60.createContext(null);
6166
- var useCurrentBlockId = () => React60.useContext(EditorBlockContext);
7113
+ var EditorBlockContext = React58.createContext(null);
7114
+ var useCurrentBlockId = () => React58.useContext(EditorBlockContext);
6167
7115
  function EditorBlock({ id }) {
6168
7116
  const document2 = useDocument();
6169
7117
  const block = document2[id];
6170
7118
  if (!block) {
6171
7119
  throw new Error("Could not find block");
6172
7120
  }
6173
- return /* @__PURE__ */ React60__default.default.createElement(EditorBlockContext.Provider, { value: id }, /* @__PURE__ */ React60__default.default.createElement(EditorBlock2, __spreadValues({}, block)));
7121
+ return /* @__PURE__ */ React58__default.default.createElement(EditorBlockContext.Provider, { value: id }, /* @__PURE__ */ React58__default.default.createElement(EditorBlock2, __spreadValues({}, block)));
6174
7122
  }
6175
7123
  function ToggleInspectorPanelButton() {
6176
7124
  const inspectorDrawerOpen = useInspectorDrawerOpen();
@@ -6178,20 +7126,20 @@ function ToggleInspectorPanelButton() {
6178
7126
  toggleInspectorDrawerOpen();
6179
7127
  };
6180
7128
  if (inspectorDrawerOpen) {
6181
- return /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: handleClick }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.LastPageOutlined, { fontSize: "small" }));
7129
+ return /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: handleClick }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.LastPageOutlined, { fontSize: "small" }));
6182
7130
  }
6183
- return /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: handleClick }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.AppRegistrationOutlined, { fontSize: "small" }));
7131
+ return /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: handleClick }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.AppRegistrationOutlined, { fontSize: "small" }));
6184
7132
  }
6185
7133
  function useIcon() {
6186
7134
  const samplesDrawerOpen = useSamplesDrawerOpen();
6187
7135
  if (samplesDrawerOpen) {
6188
- return /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.FirstPageOutlined, { fontSize: "small" });
7136
+ return /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.FirstPageOutlined, { fontSize: "small" });
6189
7137
  }
6190
- return /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.MenuOutlined, { fontSize: "small" });
7138
+ return /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.MenuOutlined, { fontSize: "small" });
6191
7139
  }
6192
7140
  function ToggleSamplesPanelButton() {
6193
7141
  const icon = useIcon();
6194
- return /* @__PURE__ */ React60__default.default.createElement(material.IconButton, { onClick: toggleSamplesDrawerOpen }, icon);
7142
+ return /* @__PURE__ */ React58__default.default.createElement(material.IconButton, { onClick: toggleSamplesDrawerOpen }, icon);
6195
7143
  }
6196
7144
  function formatHtml(html2, spaces = 2) {
6197
7145
  try {
@@ -6239,8 +7187,8 @@ function json(value) {
6239
7187
 
6240
7188
  // src/app/email-canvas/helper/highlighted-code-panel.tsx
6241
7189
  function HighlightedCodePanel({ type, value }) {
6242
- const [code, setCode] = React60.useState(null);
6243
- React60.useEffect(() => {
7190
+ const [code, setCode] = React58.useState(null);
7191
+ React58.useEffect(() => {
6244
7192
  switch (type) {
6245
7193
  case "html":
6246
7194
  html(value).then(setCode);
@@ -6253,7 +7201,7 @@ function HighlightedCodePanel({ type, value }) {
6253
7201
  if (code === null) {
6254
7202
  return null;
6255
7203
  }
6256
- return /* @__PURE__ */ React60__default.default.createElement(
7204
+ return /* @__PURE__ */ React58__default.default.createElement(
6257
7205
  "pre",
6258
7206
  {
6259
7207
  style: {
@@ -6278,18 +7226,18 @@ function HighlightedCodePanel({ type, value }) {
6278
7226
  // src/app/email-canvas/html-panel.tsx
6279
7227
  function HtmlPanel() {
6280
7228
  const document2 = useDocument();
6281
- const code = React60.useMemo(() => renderToStaticMarkup(document2, { rootBlockId: "root" }), [document2]);
6282
- return /* @__PURE__ */ React60__default.default.createElement(HighlightedCodePanel, { type: "html", value: code });
7229
+ const code = React58.useMemo(() => renderToStaticMarkup(document2, { rootBlockId: "root" }), [document2]);
7230
+ return /* @__PURE__ */ React58__default.default.createElement(HighlightedCodePanel, { type: "html", value: code });
6283
7231
  }
6284
7232
  function JsonPanel() {
6285
7233
  const document2 = useDocument();
6286
- const code = React60.useMemo(() => JSON.stringify(document2, null, " "), [document2]);
6287
- return /* @__PURE__ */ React60__default.default.createElement(HighlightedCodePanel, { type: "json", value: code });
7234
+ const code = React58.useMemo(() => JSON.stringify(document2, null, " "), [document2]);
7235
+ return /* @__PURE__ */ React58__default.default.createElement(HighlightedCodePanel, { type: "json", value: code });
6288
7236
  }
6289
7237
  function TextPanel() {
6290
7238
  const document2 = useDocument();
6291
- const text = React60.useMemo(() => renderToText(document2, { rootBlockId: "root" }), [document2]);
6292
- return /* @__PURE__ */ React60__default.default.createElement(
7239
+ const text = React58.useMemo(() => renderToText(document2, { rootBlockId: "root" }), [document2]);
7240
+ return /* @__PURE__ */ React58__default.default.createElement(
6293
7241
  "pre",
6294
7242
  {
6295
7243
  style: {
@@ -6325,42 +7273,42 @@ function MainTabsGroup() {
6325
7273
  setSelectedMainTab("editor");
6326
7274
  }
6327
7275
  };
6328
- return /* @__PURE__ */ React60__default.default.createElement(material.Tabs, { value: selectedMainTab, onChange: handleChange }, /* @__PURE__ */ React60__default.default.createElement(
7276
+ return /* @__PURE__ */ React58__default.default.createElement(material.Tabs, { value: selectedMainTab, onChange: handleChange }, /* @__PURE__ */ React58__default.default.createElement(
6329
7277
  material.Tab,
6330
7278
  {
6331
7279
  value: "editor",
6332
- label: /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Edit" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.EditOutlined, { fontSize: "small" }))
7280
+ label: /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Edit" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.EditOutlined, { fontSize: "small" }))
6333
7281
  }
6334
- ), /* @__PURE__ */ React60__default.default.createElement(
7282
+ ), /* @__PURE__ */ React58__default.default.createElement(
6335
7283
  material.Tab,
6336
7284
  {
6337
7285
  value: "preview",
6338
- label: /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Preview" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.PreviewOutlined, { fontSize: "small" }))
7286
+ label: /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Preview" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.PreviewOutlined, { fontSize: "small" }))
6339
7287
  }
6340
- ), /* @__PURE__ */ React60__default.default.createElement(
7288
+ ), /* @__PURE__ */ React58__default.default.createElement(
6341
7289
  material.Tab,
6342
7290
  {
6343
7291
  value: "html",
6344
- label: /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "HTML output" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.CodeOutlined, { fontSize: "small" }))
7292
+ label: /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "HTML output" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.CodeOutlined, { fontSize: "small" }))
6345
7293
  }
6346
- ), /* @__PURE__ */ React60__default.default.createElement(
7294
+ ), /* @__PURE__ */ React58__default.default.createElement(
6347
7295
  material.Tab,
6348
7296
  {
6349
7297
  value: "text",
6350
- label: /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Plain text output" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.SubjectOutlined, { fontSize: "small" }))
7298
+ label: /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Plain text output" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SubjectOutlined, { fontSize: "small" }))
6351
7299
  }
6352
- ), /* @__PURE__ */ React60__default.default.createElement(
7300
+ ), /* @__PURE__ */ React58__default.default.createElement(
6353
7301
  material.Tab,
6354
7302
  {
6355
7303
  value: "json",
6356
- label: /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "JSON output" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.DataObjectOutlined, { fontSize: "small" }))
7304
+ label: /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "JSON output" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.DataObjectOutlined, { fontSize: "small" }))
6357
7305
  }
6358
7306
  ));
6359
7307
  }
6360
7308
  function SaveButton({ loadTemplates, saveAs }) {
6361
7309
  const { saveTemplate, currentTemplateId, currentTemplateKind, setCurrentTemplate } = useEmailEditor();
6362
7310
  const { showMessage } = useSnackbar();
6363
- const [saveDialogOpen, setSaveDialogOpen] = React60.useState(false);
7311
+ const [saveDialogOpen, setSaveDialogOpen] = React58.useState(false);
6364
7312
  const document2 = useDocument();
6365
7313
  const isSample = currentTemplateKind === "sample";
6366
7314
  const handleSave = () => __async(null, null, function* () {
@@ -6399,7 +7347,7 @@ function SaveButton({ loadTemplates, saveAs }) {
6399
7347
  return false;
6400
7348
  }
6401
7349
  });
6402
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
7350
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
6403
7351
  material.IconButton,
6404
7352
  {
6405
7353
  onClick: handleSave,
@@ -6410,8 +7358,8 @@ function SaveButton({ loadTemplates, saveAs }) {
6410
7358
  }
6411
7359
  }
6412
7360
  },
6413
- /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: isSample ? "Save as new template" : "Save template" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.SaveOutlined, { fontSize: "small" }))
6414
- ), /* @__PURE__ */ React60__default.default.createElement(
7361
+ /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: isSample ? "Save as new template" : "Save template" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.SaveOutlined, { fontSize: "small" }))
7362
+ ), /* @__PURE__ */ React58__default.default.createElement(
6415
7363
  SaveTemplateDialog,
6416
7364
  {
6417
7365
  open: saveDialogOpen,
@@ -6424,9 +7372,9 @@ function SaveButton({ loadTemplates, saveAs }) {
6424
7372
  function NewTemplateButton({ loadTemplates, saveAs }) {
6425
7373
  const { setCurrentTemplate, loadTemplate } = useEmailEditor();
6426
7374
  const { showMessage } = useSnackbar();
6427
- const [saveDialogOpen, setSaveDialogOpen] = React60.useState(false);
6428
- const [templates, setTemplates] = React60.useState([]);
6429
- const [nameError, setNameError] = React60.useState(null);
7375
+ const [saveDialogOpen, setSaveDialogOpen] = React58.useState(false);
7376
+ const [templates, setTemplates] = React58.useState([]);
7377
+ const [nameError, setNameError] = React58.useState(null);
6430
7378
  const fetchTemplates = () => __async(null, null, function* () {
6431
7379
  if (loadTemplates) {
6432
7380
  try {
@@ -6481,7 +7429,7 @@ function NewTemplateButton({ loadTemplates, saveAs }) {
6481
7429
  }
6482
7430
  return false;
6483
7431
  });
6484
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
7432
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
6485
7433
  material.IconButton,
6486
7434
  {
6487
7435
  onClick: handleNewTemplate,
@@ -6492,8 +7440,8 @@ function NewTemplateButton({ loadTemplates, saveAs }) {
6492
7440
  }
6493
7441
  }
6494
7442
  },
6495
- /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "New template" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.Add, { fontSize: "small" }))
6496
- ), /* @__PURE__ */ React60__default.default.createElement(
7443
+ /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "New template" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.Add, { fontSize: "small" }))
7444
+ ), /* @__PURE__ */ React58__default.default.createElement(
6497
7445
  SaveTemplateDialog,
6498
7446
  {
6499
7447
  open: saveDialogOpen,
@@ -6520,7 +7468,18 @@ function SubjectInput() {
6520
7468
  root: __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, data), { subject: value }) })
6521
7469
  });
6522
7470
  };
6523
- return /* @__PURE__ */ React60__default.default.createElement(
7471
+ const trackFocus = (e) => {
7472
+ var _a2, _b;
7473
+ const target = e.target;
7474
+ if (!target || typeof target.value !== "string") return;
7475
+ setLastFocusedEditable({
7476
+ blockId: "subject",
7477
+ field: "subject",
7478
+ selectionStart: (_a2 = target.selectionStart) != null ? _a2 : target.value.length,
7479
+ selectionEnd: (_b = target.selectionEnd) != null ? _b : target.value.length
7480
+ });
7481
+ };
7482
+ return /* @__PURE__ */ React58__default.default.createElement(
6524
7483
  material.Box,
6525
7484
  {
6526
7485
  sx: {
@@ -6537,19 +7496,191 @@ function SubjectInput() {
6537
7496
  gap: 1.5
6538
7497
  }
6539
7498
  },
6540
- /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: { color: "text.secondary", fontSize: 13, fontWeight: 600, minWidth: 56 } }, "Subject"),
6541
- /* @__PURE__ */ React60__default.default.createElement(
7499
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { color: "text.secondary", fontSize: 13, fontWeight: 600, minWidth: 56 } }, "Subject"),
7500
+ /* @__PURE__ */ React58__default.default.createElement(
6542
7501
  material.InputBase,
6543
7502
  {
6544
7503
  fullWidth: true,
6545
7504
  placeholder: "Email subject \u2014 supports {{variables}}",
6546
7505
  value: subject,
6547
7506
  onChange: (e) => handleChange(e.target.value),
7507
+ onFocus: trackFocus,
7508
+ onSelect: trackFocus,
7509
+ onKeyUp: trackFocus,
7510
+ onClick: trackFocus,
6548
7511
  sx: { fontSize: 14 }
6549
7512
  }
6550
7513
  )
6551
7514
  );
6552
7515
  }
7516
+ function SubjectPreview() {
7517
+ var _a, _b;
7518
+ const document2 = useDocument();
7519
+ const root = document2.root;
7520
+ if (!root || root.type !== "EmailLayout") return null;
7521
+ const data = root.data;
7522
+ const subject = (_a = data.subject) != null ? _a : "";
7523
+ if (!subject) return null;
7524
+ const samples = buildSampleValueMap((_b = data.variables) != null ? _b : []);
7525
+ const rendered = substituteSampleValues(subject, samples);
7526
+ return /* @__PURE__ */ React58__default.default.createElement(
7527
+ material.Box,
7528
+ {
7529
+ sx: {
7530
+ px: 3,
7531
+ py: 1.25,
7532
+ borderBottom: 1,
7533
+ borderColor: "divider",
7534
+ backgroundColor: "white",
7535
+ position: "sticky",
7536
+ top: 49,
7537
+ zIndex: "appBar",
7538
+ display: "flex",
7539
+ alignItems: "center",
7540
+ gap: 1.5
7541
+ }
7542
+ },
7543
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { color: "text.secondary", fontSize: 13, fontWeight: 600, minWidth: 56 } }, "Subject"),
7544
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { fontSize: 14 } }, rendered)
7545
+ );
7546
+ }
7547
+ function generateId3() {
7548
+ return `block-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
7549
+ }
7550
+ function buildImageBlock(uploaded) {
7551
+ var _a, _b, _c;
7552
+ return {
7553
+ type: "Image",
7554
+ data: {
7555
+ props: {
7556
+ url: uploaded.url,
7557
+ width: (_a = uploaded.width) != null ? _a : null,
7558
+ height: (_b = uploaded.height) != null ? _b : null,
7559
+ alt: (_c = uploaded.alt) != null ? _c : "",
7560
+ contentAlignment: "middle"
7561
+ },
7562
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
7563
+ }
7564
+ };
7565
+ }
7566
+ function appendImageBlock(uploaded) {
7567
+ var _a;
7568
+ const doc = getDocument();
7569
+ const root = doc.root;
7570
+ if (!root || root.type !== "EmailLayout") return;
7571
+ const id = generateId3();
7572
+ const childrenIds = [...(_a = root.data.childrenIds) != null ? _a : [], id];
7573
+ setDocument({
7574
+ [id]: buildImageBlock(uploaded),
7575
+ root: __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, root.data), { childrenIds }) })
7576
+ });
7577
+ setSelectedBlockId(id);
7578
+ }
7579
+ function findImageFile(items) {
7580
+ var _a;
7581
+ if (!items) return null;
7582
+ const fileList = items instanceof FileList ? Array.from(items) : Array.from(items);
7583
+ for (const item of fileList) {
7584
+ const file = item instanceof File ? item : (_a = item.getAsFile) == null ? void 0 : _a.call(item);
7585
+ if (file && file.type.startsWith("image/")) return file;
7586
+ }
7587
+ return null;
7588
+ }
7589
+ function ImageDropPasteHandler({ enabled, children }) {
7590
+ const { uploadImage } = useImageCallbacks();
7591
+ const wrapperRef = React58.useRef(null);
7592
+ const dragDepth = React58.useRef(0);
7593
+ const [dragging, setDragging] = React58.useState(false);
7594
+ const [uploading, setUploading] = React58.useState(false);
7595
+ const active = enabled && Boolean(uploadImage);
7596
+ React58.useEffect(() => {
7597
+ if (!active || !uploadImage) return;
7598
+ const handlePaste = (e) => __async(null, null, function* () {
7599
+ var _a;
7600
+ const target = e.target;
7601
+ if ((target == null ? void 0 : target.tagName) === "INPUT" || (target == null ? void 0 : target.tagName) === "TEXTAREA" || (target == null ? void 0 : target.isContentEditable)) return;
7602
+ const file = findImageFile((_a = e.clipboardData) == null ? void 0 : _a.files);
7603
+ if (!file) return;
7604
+ e.preventDefault();
7605
+ setUploading(true);
7606
+ try {
7607
+ const uploaded = yield uploadImage(file);
7608
+ appendImageBlock(uploaded);
7609
+ } catch (e2) {
7610
+ } finally {
7611
+ setUploading(false);
7612
+ }
7613
+ });
7614
+ window.addEventListener("paste", handlePaste);
7615
+ return () => window.removeEventListener("paste", handlePaste);
7616
+ }, [active, uploadImage]);
7617
+ if (!active) return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, children);
7618
+ const onDragEnter = (e) => {
7619
+ var _a, _b;
7620
+ if (!Array.from((_b = (_a = e.dataTransfer) == null ? void 0 : _a.items) != null ? _b : []).some((i) => i.kind === "file")) return;
7621
+ dragDepth.current += 1;
7622
+ setDragging(true);
7623
+ };
7624
+ const onDragLeave = () => {
7625
+ dragDepth.current = Math.max(0, dragDepth.current - 1);
7626
+ if (dragDepth.current === 0) setDragging(false);
7627
+ };
7628
+ const onDragOver = (e) => {
7629
+ var _a, _b;
7630
+ if (!Array.from((_b = (_a = e.dataTransfer) == null ? void 0 : _a.items) != null ? _b : []).some((i) => i.kind === "file")) return;
7631
+ e.preventDefault();
7632
+ e.dataTransfer.dropEffect = "copy";
7633
+ };
7634
+ const onDrop = (e) => __async(null, null, function* () {
7635
+ var _a;
7636
+ dragDepth.current = 0;
7637
+ setDragging(false);
7638
+ const file = findImageFile((_a = e.dataTransfer) == null ? void 0 : _a.files);
7639
+ if (!file || !uploadImage) return;
7640
+ e.preventDefault();
7641
+ setUploading(true);
7642
+ try {
7643
+ const uploaded = yield uploadImage(file);
7644
+ appendImageBlock(uploaded);
7645
+ } catch (e2) {
7646
+ } finally {
7647
+ setUploading(false);
7648
+ }
7649
+ });
7650
+ return /* @__PURE__ */ React58__default.default.createElement(
7651
+ material.Box,
7652
+ {
7653
+ ref: wrapperRef,
7654
+ onDragEnter,
7655
+ onDragLeave,
7656
+ onDragOver,
7657
+ onDrop,
7658
+ sx: { position: "relative" }
7659
+ },
7660
+ children,
7661
+ (dragging || uploading) && /* @__PURE__ */ React58__default.default.createElement(
7662
+ material.Box,
7663
+ {
7664
+ sx: {
7665
+ position: "absolute",
7666
+ inset: 0,
7667
+ backgroundColor: "rgba(33, 150, 243, 0.06)",
7668
+ border: "2px dashed",
7669
+ borderColor: "primary.main",
7670
+ borderRadius: 1,
7671
+ display: "flex",
7672
+ alignItems: "flex-start",
7673
+ justifyContent: "center",
7674
+ paddingTop: 12,
7675
+ color: "primary.dark",
7676
+ pointerEvents: "none",
7677
+ zIndex: 10
7678
+ }
7679
+ },
7680
+ /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: { display: "flex", alignItems: "center", gap: 1, fontWeight: 600, fontSize: 14 } }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.CloudUploadOutlined, null), uploading ? "Uploading\u2026" : "Drop image to insert")
7681
+ )
7682
+ );
7683
+ }
6553
7684
 
6554
7685
  // src/app/email-canvas/index.tsx
6555
7686
  function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true }) {
@@ -6580,21 +7711,29 @@ function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true })
6580
7711
  }
6581
7712
  };
6582
7713
  const renderMainPanel = () => {
7714
+ var _a;
6583
7715
  switch (selectedMainTab) {
6584
7716
  case "editor":
6585
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: mainBoxSx }, /* @__PURE__ */ React60__default.default.createElement(EditorBlock, { id: "root" }));
6586
- case "preview":
6587
- return /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: mainBoxSx }, /* @__PURE__ */ React60__default.default.createElement(Reader, { document: document2, rootBlockId: "root" }));
7717
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: mainBoxSx }, /* @__PURE__ */ React58__default.default.createElement(EditorBlock, { id: "root" }));
7718
+ case "preview": {
7719
+ const rootBlock = document2.root;
7720
+ const layoutData = rootBlock && rootBlock.type === "EmailLayout" ? rootBlock.data : void 0;
7721
+ const samples = buildSampleValueMap(
7722
+ (_a = layoutData == null ? void 0 : layoutData.variables) != null ? _a : []
7723
+ );
7724
+ const previewDoc = applySampleValuesToDocument(document2, samples);
7725
+ return /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: mainBoxSx }, /* @__PURE__ */ React58__default.default.createElement(Reader, { document: previewDoc, rootBlockId: "root" }));
7726
+ }
6588
7727
  case "html":
6589
- return /* @__PURE__ */ React60__default.default.createElement(HtmlPanel, null);
7728
+ return /* @__PURE__ */ React58__default.default.createElement(HtmlPanel, null);
6590
7729
  case "text":
6591
- return /* @__PURE__ */ React60__default.default.createElement(TextPanel, null);
7730
+ return /* @__PURE__ */ React58__default.default.createElement(TextPanel, null);
6592
7731
  case "json":
6593
- return /* @__PURE__ */ React60__default.default.createElement(JsonPanel, null);
7732
+ return /* @__PURE__ */ React58__default.default.createElement(JsonPanel, null);
6594
7733
  }
6595
7734
  };
6596
7735
  const showSaveButtons = persistenceEnabled;
6597
- return /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(
7736
+ return /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(
6598
7737
  material.Stack,
6599
7738
  {
6600
7739
  sx: {
@@ -6611,13 +7750,13 @@ function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true })
6611
7750
  justifyContent: "space-between",
6612
7751
  alignItems: "center"
6613
7752
  },
6614
- samplesDrawerEnabled && /* @__PURE__ */ React60__default.default.createElement(ToggleSamplesPanelButton, null),
6615
- /* @__PURE__ */ React60__default.default.createElement(material.Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React60__default.default.createElement(MainTabsGroup, null)), /* @__PURE__ */ React60__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React60__default.default.createElement(material.ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "desktop" }, /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Desktop view" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60__default.default.createElement(material.ToggleButton, { value: "mobile" }, /* @__PURE__ */ React60__default.default.createElement(material.Tooltip, { title: "Mobile view" }, /* @__PURE__ */ React60__default.default.createElement(iconsMaterial.PhoneIphoneOutlined, { fontSize: "small" })))), showSaveButtons && /* @__PURE__ */ React60__default.default.createElement(React60__default.default.Fragment, null, /* @__PURE__ */ React60__default.default.createElement(NewTemplateButton, { loadTemplates, saveAs }), /* @__PURE__ */ React60__default.default.createElement(SaveButton, { loadTemplates, saveAs })))),
6616
- /* @__PURE__ */ React60__default.default.createElement(ToggleInspectorPanelButton, null)
6617
- ), selectedMainTab === "editor" && /* @__PURE__ */ React60__default.default.createElement(SubjectInput, null), /* @__PURE__ */ React60__default.default.createElement(material.Box, { sx: {
7753
+ samplesDrawerEnabled && /* @__PURE__ */ React58__default.default.createElement(ToggleSamplesPanelButton, null),
7754
+ /* @__PURE__ */ React58__default.default.createElement(material.Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React58__default.default.createElement(MainTabsGroup, null)), /* @__PURE__ */ React58__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React58__default.default.createElement(material.ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "desktop" }, /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Desktop view" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58__default.default.createElement(material.ToggleButton, { value: "mobile" }, /* @__PURE__ */ React58__default.default.createElement(material.Tooltip, { title: "Mobile view" }, /* @__PURE__ */ React58__default.default.createElement(iconsMaterial.PhoneIphoneOutlined, { fontSize: "small" })))), showSaveButtons && /* @__PURE__ */ React58__default.default.createElement(React58__default.default.Fragment, null, /* @__PURE__ */ React58__default.default.createElement(NewTemplateButton, { loadTemplates, saveAs }), /* @__PURE__ */ React58__default.default.createElement(SaveButton, { loadTemplates, saveAs })))),
7755
+ /* @__PURE__ */ React58__default.default.createElement(ToggleInspectorPanelButton, null)
7756
+ ), selectedMainTab === "editor" && /* @__PURE__ */ React58__default.default.createElement(SubjectInput, null), selectedMainTab === "preview" && /* @__PURE__ */ React58__default.default.createElement(SubjectPreview, null), /* @__PURE__ */ React58__default.default.createElement(ImageDropPasteHandler, { enabled: selectedMainTab === "editor" }, /* @__PURE__ */ React58__default.default.createElement(material.Box, { sx: {
6618
7757
  paddingBottom: "50px",
6619
7758
  minWidth: 370
6620
- } }, renderMainPanel()));
7759
+ } }, renderMainPanel())));
6621
7760
  }
6622
7761
 
6623
7762
  // src/app/index.tsx
@@ -6653,7 +7792,7 @@ function useDrawerTransition(cssProperty, open) {
6653
7792
  duration: !open ? transitions.duration.leavingScreen : transitions.duration.enteringScreen
6654
7793
  });
6655
7794
  }
6656
- var EmailEditorInternal = React60.forwardRef((props, ref) => {
7795
+ var EmailEditorInternal = React58.forwardRef((props, ref) => {
6657
7796
  const {
6658
7797
  drawerEnterDuration = 225,
6659
7798
  drawerExitDuration = 225,
@@ -6675,10 +7814,10 @@ var EmailEditorInternal = React60.forwardRef((props, ref) => {
6675
7814
  const samplesDrawerOpen = useSamplesDrawerOpen();
6676
7815
  const marginLeftTransition = useDrawerTransition("margin-left", samplesDrawerOpen);
6677
7816
  const marginRightTransition = useDrawerTransition("margin-right", inspectorDrawerOpen);
6678
- const onChangeRef = React60.useRef(onChange);
7817
+ const onChangeRef = React58.useRef(onChange);
6679
7818
  onChangeRef.current = onChange;
6680
- const prevDocJsonRef = React60.useRef("");
6681
- React60.useEffect(() => {
7819
+ const prevDocJsonRef = React58.useRef("");
7820
+ React58.useEffect(() => {
6682
7821
  var _a;
6683
7822
  const docJson = JSON.stringify(currentDocument);
6684
7823
  if (docJson !== prevDocJsonRef.current) {
@@ -6686,7 +7825,7 @@ var EmailEditorInternal = React60.forwardRef((props, ref) => {
6686
7825
  (_a = onChangeRef.current) == null ? void 0 : _a.call(onChangeRef, currentDocument);
6687
7826
  }
6688
7827
  }, [currentDocument]);
6689
- React60.useImperativeHandle(ref, () => ({
7828
+ React58.useImperativeHandle(ref, () => ({
6690
7829
  saveTemplate: () => {
6691
7830
  return saveTemplate();
6692
7831
  },
@@ -6698,7 +7837,7 @@ var EmailEditorInternal = React60.forwardRef((props, ref) => {
6698
7837
  return getDocument();
6699
7838
  }
6700
7839
  }));
6701
- return /* @__PURE__ */ React60__default.default.createElement(material.Stack, { position: "relative", id: "drawer-container", sx: { minHeight } }, /* @__PURE__ */ React60__default.default.createElement(
7840
+ return /* @__PURE__ */ React58__default.default.createElement(material.Stack, { position: "relative", id: "drawer-container", sx: { minHeight } }, /* @__PURE__ */ React58__default.default.createElement(
6702
7841
  InspectorDrawer,
6703
7842
  {
6704
7843
  enterDuration: drawerEnterDuration,
@@ -6706,7 +7845,7 @@ var EmailEditorInternal = React60.forwardRef((props, ref) => {
6706
7845
  deleteTemplate,
6707
7846
  copyTemplate
6708
7847
  }
6709
- ), /* @__PURE__ */ React60__default.default.createElement(
7848
+ ), /* @__PURE__ */ React58__default.default.createElement(
6710
7849
  SamplesDrawer,
6711
7850
  {
6712
7851
  enterDuration: drawerEnterDuration,
@@ -6722,7 +7861,7 @@ var EmailEditorInternal = React60.forwardRef((props, ref) => {
6722
7861
  setTemplateKind,
6723
7862
  saveAs
6724
7863
  }
6725
- ), /* @__PURE__ */ React60__default.default.createElement(
7864
+ ), /* @__PURE__ */ React58__default.default.createElement(
6726
7865
  material.Stack,
6727
7866
  {
6728
7867
  sx: {
@@ -6731,10 +7870,10 @@ var EmailEditorInternal = React60.forwardRef((props, ref) => {
6731
7870
  transition: [marginLeftTransition, marginRightTransition].join(", ")
6732
7871
  }
6733
7872
  },
6734
- /* @__PURE__ */ React60__default.default.createElement(TemplatePanel2, { loadTemplates, saveAs, samplesDrawerEnabled })
7873
+ /* @__PURE__ */ React58__default.default.createElement(TemplatePanel2, { loadTemplates, saveAs, samplesDrawerEnabled })
6735
7874
  ));
6736
7875
  });
6737
- var EmailEditor = React60.forwardRef((props, ref) => {
7876
+ var EmailEditor = React58.forwardRef((props, ref) => {
6738
7877
  const {
6739
7878
  initialTemplate: initialTemplateProp,
6740
7879
  initialTemplateId,
@@ -6754,21 +7893,28 @@ var EmailEditor = React60.forwardRef((props, ref) => {
6754
7893
  renameTemplate,
6755
7894
  setTemplateKind,
6756
7895
  saveAs,
7896
+ uploadImage,
7897
+ loadImages,
7898
+ deleteImage,
6757
7899
  theme
6758
7900
  } = props;
6759
- const resolvedTemplate = React60.useMemo(
7901
+ const resolvedTemplate = React58.useMemo(
6760
7902
  () => typeof initialTemplateProp === "string" ? htmlToEditorConfig(initialTemplateProp) : initialTemplateProp,
6761
7903
  [initialTemplateProp]
6762
7904
  );
6763
- const prevTemplateRef = React60.useRef(void 0);
7905
+ const prevTemplateRef = React58.useRef(void 0);
6764
7906
  if (resolvedTemplate && resolvedTemplate !== prevTemplateRef.current) {
6765
7907
  prevTemplateRef.current = resolvedTemplate;
6766
7908
  resetDocument(resolvedTemplate);
6767
7909
  }
6768
- React60.useEffect(() => {
7910
+ React58.useEffect(() => {
6769
7911
  setPersistenceEnabled(persistenceEnabled);
6770
7912
  }, [persistenceEnabled]);
6771
- return /* @__PURE__ */ React60__default.default.createElement(material.ThemeProvider, { theme: theme || theme_default }, /* @__PURE__ */ React60__default.default.createElement(material.CssBaseline, null), /* @__PURE__ */ React60__default.default.createElement("div", { style: { height: "100%", overflow: "auto" } }, /* @__PURE__ */ React60__default.default.createElement(SnackbarProvider, null, /* @__PURE__ */ React60__default.default.createElement(
7913
+ const imageCallbacks = React58.useMemo(
7914
+ () => ({ uploadImage, loadImages, deleteImage }),
7915
+ [uploadImage, loadImages, deleteImage]
7916
+ );
7917
+ return /* @__PURE__ */ React58__default.default.createElement(material.ThemeProvider, { theme: theme || theme_default }, /* @__PURE__ */ React58__default.default.createElement(material.CssBaseline, null), /* @__PURE__ */ React58__default.default.createElement("div", { style: { height: "100%", overflow: "auto" } }, /* @__PURE__ */ React58__default.default.createElement(SnackbarProvider, null, /* @__PURE__ */ React58__default.default.createElement(ImageCallbacksProvider, { callbacks: imageCallbacks }, /* @__PURE__ */ React58__default.default.createElement(
6772
7918
  EmailEditorProvider,
6773
7919
  {
6774
7920
  initialTemplate: resolvedTemplate,
@@ -6777,7 +7923,7 @@ var EmailEditor = React60.forwardRef((props, ref) => {
6777
7923
  onSave,
6778
7924
  onChange
6779
7925
  },
6780
- /* @__PURE__ */ React60__default.default.createElement(
7926
+ /* @__PURE__ */ React58__default.default.createElement(
6781
7927
  EmailEditorInternal,
6782
7928
  {
6783
7929
  ref,
@@ -6796,7 +7942,7 @@ var EmailEditor = React60.forwardRef((props, ref) => {
6796
7942
  onChange
6797
7943
  }
6798
7944
  )
6799
- ))));
7945
+ )))));
6800
7946
  });
6801
7947
  EmailEditor.displayName = "EmailEditor";
6802
7948
  EmailEditorInternal.displayName = "EmailEditorInternal";