@kontakto/email-template-editor 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import DOMPurify from 'dompurify';
2
2
  import { marked, Renderer } from 'marked';
3
- import React60, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo, useContext, useState, useCallback, Fragment } from 'react';
3
+ import React58, { createContext, forwardRef, useRef, useEffect, useImperativeHandle, useMemo, useContext, useState, useCallback, Fragment } from 'react';
4
4
  import { z } from 'zod';
5
5
  import { renderToStaticMarkup as renderToStaticMarkup$1 } from 'react-dom/server';
6
6
  import { createTheme, alpha, lighten, darken } from '@mui/material/styles';
7
- import { MenuItem, Stack, ThemeProvider, CssBaseline, useTheme, Drawer, Box, Tabs, Tab, Typography, Tooltip, IconButton, TextField, InputAdornment, Chip, CircularProgress, Alert, Divider as Divider$1, ToggleButtonGroup, ToggleButton, Snackbar, Dialog, DialogTitle, DialogContent, DialogActions, Button as Button$1, InputBase, FormControlLabel, Switch, InputLabel, Menu, Slider, ButtonBase, Paper, Fade } from '@mui/material';
7
+ import { MenuItem, Stack, ThemeProvider, CssBaseline, useTheme, Drawer, Box, Tabs, Tab, Typography, Tooltip, IconButton, TextField, InputAdornment, Chip, CircularProgress, Alert, Divider as Divider$1, ToggleButtonGroup, ToggleButton, Snackbar, Dialog, DialogTitle, DialogContent, DialogActions, Button as Button$1, InputBase, AlertTitle, FormControlLabel, Switch, InputLabel, Menu, Slider, ButtonBase, Paper, Fade } from '@mui/material';
8
8
  import { create } from 'zustand';
9
- import { AddOutlined, SearchOutlined, MonitorOutlined, PhoneIphoneOutlined, LibraryAddOutlined, ContentCopyOutlined, DriveFileRenameOutlineOutlined, FileUploadOutlined, FileDownloadOutlined, DeleteOutlined, EditOutlined, PreviewOutlined, CodeOutlined, SubjectOutlined, DataObjectOutlined, Add, SaveOutlined, LastPageOutlined, AppRegistrationOutlined, DeleteOutline, FirstPageOutlined, MenuOutlined, RoundedCornerOutlined, AspectRatioOutlined, HeightOutlined, VerticalAlignTopOutlined, VerticalAlignCenterOutlined, VerticalAlignBottomOutlined, SpaceBarOutlined, CloseOutlined, AlignVerticalTopOutlined, AlignVerticalBottomOutlined, AlignHorizontalLeftOutlined, AlignHorizontalRightOutlined, FormatAlignLeftOutlined, FormatAlignCenterOutlined, FormatAlignRightOutlined, TextFieldsOutlined, ArrowUpwardOutlined, ArrowDownwardOutlined, HMobiledataOutlined, NotesOutlined, SmartButtonOutlined, ImageOutlined, AccountCircleOutlined, ContactMailOutlined, BusinessOutlined, HorizontalRuleOutlined, Crop32Outlined, HtmlOutlined, ViewColumnOutlined } from '@mui/icons-material';
9
+ import { AddOutlined, SearchOutlined, MonitorOutlined, PhoneIphoneOutlined, LibraryAddOutlined, ContentCopyOutlined, DriveFileRenameOutlineOutlined, FileUploadOutlined, FileDownloadOutlined, DeleteOutlined, EditOutlined, PreviewOutlined, CodeOutlined, SubjectOutlined, DataObjectOutlined, Add, SaveOutlined, LastPageOutlined, AppRegistrationOutlined, CloudUploadOutlined, FirstPageOutlined, MenuOutlined, InputOutlined, DeleteOutline, RoundedCornerOutlined, AspectRatioOutlined, HeightOutlined, CollectionsOutlined, ErrorOutlineOutlined, VerticalAlignTopOutlined, VerticalAlignCenterOutlined, VerticalAlignBottomOutlined, SpaceBarOutlined, CloseOutlined, AlignVerticalTopOutlined, AlignVerticalBottomOutlined, AlignHorizontalLeftOutlined, AlignHorizontalRightOutlined, FormatAlignLeftOutlined, FormatAlignCenterOutlined, FormatAlignRightOutlined, FormatLineSpacingOutlined, TextFieldsOutlined, ArrowUpwardOutlined, ArrowDownwardOutlined, HMobiledataOutlined, NotesOutlined, SmartButtonOutlined, ImageOutlined, AccountCircleOutlined, ContactMailOutlined, BusinessOutlined, HorizontalRuleOutlined, Crop32Outlined, HtmlOutlined, ViewColumnOutlined } from '@mui/icons-material';
10
10
  import { HexColorPicker, HexColorInput } from 'react-colorful';
11
11
  import hljs from 'highlight.js';
12
12
  import jsonHighlighter from 'highlight.js/lib/languages/json';
@@ -159,7 +159,7 @@ function renderMarkdownString(str) {
159
159
  function EmailMarkdown(_a) {
160
160
  var _b = _a, { markdown } = _b, props = __objRest(_b, ["markdown"]);
161
161
  const data = useMemo(() => renderMarkdownString(markdown), [markdown]);
162
- return /* @__PURE__ */ React60.createElement("div", __spreadProps(__spreadValues({}, props), { dangerouslySetInnerHTML: { __html: data } }));
162
+ return /* @__PURE__ */ React58.createElement("div", __spreadProps(__spreadValues({}, props), { dangerouslySetInnerHTML: { __html: data } }));
163
163
  }
164
164
  var FONT_FAMILY_SCHEMA = z.enum([
165
165
  "MODERN_SANS",
@@ -210,6 +210,8 @@ var TextPropsSchema = z.object({
210
210
  fontSize: z.number().gte(0).optional().nullable(),
211
211
  fontFamily: FONT_FAMILY_SCHEMA,
212
212
  fontWeight: z.enum(["bold", "normal"]).optional().nullable(),
213
+ lineHeight: z.number().gte(0).optional().nullable(),
214
+ letterSpacing: z.number().optional().nullable(),
213
215
  textAlign: z.enum(["left", "center", "right"]).optional().nullable(),
214
216
  padding: PADDING_SCHEMA
215
217
  }).optional().nullable(),
@@ -223,21 +225,23 @@ var TextPropsDefaults = {
223
225
  text: ""
224
226
  };
225
227
  function Text({ style, props }) {
226
- var _a, _b, _c, _d, _e, _f;
228
+ var _a, _b, _c, _d, _e, _f, _g;
227
229
  const wStyle = {
228
230
  color: (_a = style == null ? void 0 : style.color) != null ? _a : void 0,
229
231
  backgroundColor: (_b = style == null ? void 0 : style.backgroundColor) != null ? _b : void 0,
230
232
  fontSize: (_c = style == null ? void 0 : style.fontSize) != null ? _c : void 0,
231
233
  fontFamily: getFontFamily(style == null ? void 0 : style.fontFamily),
232
234
  fontWeight: (_d = style == null ? void 0 : style.fontWeight) != null ? _d : void 0,
233
- textAlign: (_e = style == null ? void 0 : style.textAlign) != null ? _e : void 0,
235
+ lineHeight: (_e = style == null ? void 0 : style.lineHeight) != null ? _e : void 0,
236
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
237
+ textAlign: (_f = style == null ? void 0 : style.textAlign) != null ? _f : void 0,
234
238
  padding: getPadding(style == null ? void 0 : style.padding)
235
239
  };
236
- const text = (_f = props == null ? void 0 : props.text) != null ? _f : TextPropsDefaults.text;
240
+ const text = (_g = props == null ? void 0 : props.text) != null ? _g : TextPropsDefaults.text;
237
241
  if (props == null ? void 0 : props.markdown) {
238
- return /* @__PURE__ */ React60.createElement(EmailMarkdown, { style: wStyle, markdown: text });
242
+ return /* @__PURE__ */ React58.createElement(EmailMarkdown, { style: wStyle, markdown: text });
239
243
  }
240
- return /* @__PURE__ */ React60.createElement("div", { style: wStyle }, text);
244
+ return /* @__PURE__ */ React58.createElement("div", { style: wStyle }, text);
241
245
  }
242
246
  var PADDING_SCHEMA2 = z.object({
243
247
  top: z.number(),
@@ -286,7 +290,7 @@ function Avatar({ style, props }) {
286
290
  textAlign: (_e = style == null ? void 0 : style.textAlign) != null ? _e : void 0,
287
291
  padding: getPadding2(style == null ? void 0 : style.padding)
288
292
  };
289
- return /* @__PURE__ */ React60.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React60.createElement(
293
+ return /* @__PURE__ */ React58.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React58.createElement(
290
294
  "img",
291
295
  {
292
296
  alt,
@@ -358,6 +362,8 @@ var ButtonPropsSchema = z.object({
358
362
  fontSize: z.number().min(0).optional().nullable(),
359
363
  fontFamily: FONT_FAMILY_SCHEMA2,
360
364
  fontWeight: z.enum(["bold", "normal"]).optional().nullable(),
365
+ lineHeight: z.number().gte(0).optional().nullable(),
366
+ letterSpacing: z.number().optional().nullable(),
361
367
  textAlign: z.enum(["left", "center", "right"]).optional().nullable(),
362
368
  padding: PADDING_SCHEMA3
363
369
  }).optional().nullable(),
@@ -410,7 +416,7 @@ var ButtonPropsDefaults = {
410
416
  buttonBackgroundColor: "#999999"
411
417
  };
412
418
  function Button({ style, props }) {
413
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
419
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
414
420
  const text = (_a = props == null ? void 0 : props.text) != null ? _a : ButtonPropsDefaults.text;
415
421
  const url = (_b = props == null ? void 0 : props.url) != null ? _b : ButtonPropsDefaults.url;
416
422
  const fullWidth = (_c = props == null ? void 0 : props.fullWidth) != null ? _c : ButtonPropsDefaults.fullWidth;
@@ -428,20 +434,22 @@ function Button({ style, props }) {
428
434
  fontSize: (_h = style == null ? void 0 : style.fontSize) != null ? _h : 16,
429
435
  fontFamily: getFontFamily2(style == null ? void 0 : style.fontFamily),
430
436
  fontWeight: (_i = style == null ? void 0 : style.fontWeight) != null ? _i : "bold",
437
+ lineHeight: (_j = style == null ? void 0 : style.lineHeight) != null ? _j : void 0,
438
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
431
439
  backgroundColor: buttonBackgroundColor,
432
440
  borderRadius: getRoundedCorners(props),
433
441
  display: fullWidth ? "block" : "inline-block",
434
442
  padding: `${padding[0]}px ${padding[1]}px`,
435
443
  textDecoration: "none"
436
444
  };
437
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React60.createElement("a", { href: url, style: linkStyle, target: "_blank" }, /* @__PURE__ */ React60.createElement(
445
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React58.createElement("a", { href: url, style: linkStyle, target: "_blank" }, /* @__PURE__ */ React58.createElement(
438
446
  "span",
439
447
  {
440
448
  dangerouslySetInnerHTML: {
441
449
  __html: `<!--[if mso]><i style="letter-spacing: ${padding[1]}px;mso-font-width:-100%;mso-text-raise:${textRaise}" hidden>&nbsp;</i><![endif]-->`
442
450
  }
443
451
  }
444
- ), /* @__PURE__ */ React60.createElement("span", null, text), /* @__PURE__ */ React60.createElement(
452
+ ), /* @__PURE__ */ React58.createElement("span", null, text), /* @__PURE__ */ React58.createElement(
445
453
  "span",
446
454
  {
447
455
  dangerouslySetInnerHTML: {
@@ -490,7 +498,7 @@ function ColumnsContainer({ style, columns, props }) {
490
498
  contentAlignment: (_d = props == null ? void 0 : props.contentAlignment) != null ? _d : ColumnsContainerPropsDefaults.contentAlignment,
491
499
  fixedWidths: props == null ? void 0 : props.fixedWidths
492
500
  };
493
- return /* @__PURE__ */ React60.createElement("div", { style: wStyle }, /* @__PURE__ */ React60.createElement(
501
+ return /* @__PURE__ */ React58.createElement("div", { style: wStyle }, /* @__PURE__ */ React58.createElement(
494
502
  "table",
495
503
  {
496
504
  align: "center",
@@ -499,7 +507,7 @@ function ColumnsContainer({ style, columns, props }) {
499
507
  border: 0,
500
508
  style: { tableLayout: "fixed", borderCollapse: "collapse" }
501
509
  },
502
- /* @__PURE__ */ React60.createElement("tbody", { style: { width: "100%" } }, /* @__PURE__ */ React60.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React60.createElement(TableCell, { index: 0, props: blockProps, columns }), /* @__PURE__ */ React60.createElement(TableCell, { index: 1, props: blockProps, columns }), /* @__PURE__ */ React60.createElement(TableCell, { index: 2, props: blockProps, columns })))
510
+ /* @__PURE__ */ React58.createElement("tbody", { style: { width: "100%" } }, /* @__PURE__ */ React58.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React58.createElement(TableCell, { index: 0, props: blockProps, columns }), /* @__PURE__ */ React58.createElement(TableCell, { index: 1, props: blockProps, columns }), /* @__PURE__ */ React58.createElement(TableCell, { index: 2, props: blockProps, columns })))
503
511
  ));
504
512
  }
505
513
  function TableCell({ index, props, columns }) {
@@ -517,7 +525,7 @@ function TableCell({ index, props, columns }) {
517
525
  width: (_d = (_c = props.fixedWidths) == null ? void 0 : _c[index]) != null ? _d : void 0
518
526
  };
519
527
  const children = (_e = columns && columns[index]) != null ? _e : null;
520
- return /* @__PURE__ */ React60.createElement("td", { style }, children);
528
+ return /* @__PURE__ */ React58.createElement("td", { style }, children);
521
529
  }
522
530
  function getPaddingBefore(index, { columnsGap, columnsCount }) {
523
531
  if (index === 0) {
@@ -579,9 +587,9 @@ function Container({ style, children }) {
579
587
  padding: getPadding5(style == null ? void 0 : style.padding)
580
588
  };
581
589
  if (!children) {
582
- return /* @__PURE__ */ React60.createElement("div", { style: wStyle });
590
+ return /* @__PURE__ */ React58.createElement("div", { style: wStyle });
583
591
  }
584
- return /* @__PURE__ */ React60.createElement("div", { style: wStyle }, children);
592
+ return /* @__PURE__ */ React58.createElement("div", { style: wStyle }, children);
585
593
  }
586
594
  var container_default = Container;
587
595
  var COLOR_SCHEMA5 = z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
@@ -615,7 +623,7 @@ function Divider({ style, props }) {
615
623
  };
616
624
  const borderTopWidth = (_b = props == null ? void 0 : props.lineHeight) != null ? _b : DividerPropsDefaults.lineHeight;
617
625
  const borderTopColor = (_c = props == null ? void 0 : props.lineColor) != null ? _c : DividerPropsDefaults.lineColor;
618
- return /* @__PURE__ */ React60.createElement("div", { style: st }, /* @__PURE__ */ React60.createElement(
626
+ return /* @__PURE__ */ React58.createElement("div", { style: st }, /* @__PURE__ */ React58.createElement(
619
627
  "hr",
620
628
  {
621
629
  style: {
@@ -680,6 +688,8 @@ var HeadingPropsSchema = z.object({
680
688
  backgroundColor: COLOR_SCHEMA6,
681
689
  fontFamily: FONT_FAMILY_SCHEMA3,
682
690
  fontWeight: z.enum(["bold", "normal"]).optional().nullable(),
691
+ lineHeight: z.number().gte(0).optional().nullable(),
692
+ letterSpacing: z.number().optional().nullable(),
683
693
  textAlign: z.enum(["left", "center", "right"]).optional().nullable(),
684
694
  padding: PADDING_SCHEMA7
685
695
  }).optional().nullable()
@@ -690,14 +700,16 @@ var HeadingPropsDefaults = {
690
700
  text: ""
691
701
  };
692
702
  function Heading({ props, style }) {
693
- var _a, _b, _c, _d, _e, _f;
703
+ var _a, _b, _c, _d, _e, _f, _g;
694
704
  const level = (_a = props == null ? void 0 : props.level) != null ? _a : HeadingPropsDefaults.level;
695
705
  const text = (_b = props == null ? void 0 : props.text) != null ? _b : HeadingPropsDefaults.text;
696
706
  const hStyle = {
697
707
  color: (_c = style == null ? void 0 : style.color) != null ? _c : void 0,
698
708
  backgroundColor: (_d = style == null ? void 0 : style.backgroundColor) != null ? _d : void 0,
699
709
  fontWeight: (_e = style == null ? void 0 : style.fontWeight) != null ? _e : "bold",
700
- textAlign: (_f = style == null ? void 0 : style.textAlign) != null ? _f : void 0,
710
+ lineHeight: (_f = style == null ? void 0 : style.lineHeight) != null ? _f : void 0,
711
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
712
+ textAlign: (_g = style == null ? void 0 : style.textAlign) != null ? _g : void 0,
701
713
  margin: 0,
702
714
  fontFamily: getFontFamily3(style == null ? void 0 : style.fontFamily),
703
715
  fontSize: getFontSize(level),
@@ -705,11 +717,11 @@ function Heading({ props, style }) {
705
717
  };
706
718
  switch (level) {
707
719
  case "h1":
708
- return /* @__PURE__ */ React60.createElement("h1", { style: hStyle }, text);
720
+ return /* @__PURE__ */ React58.createElement("h1", { style: hStyle }, text);
709
721
  case "h2":
710
- return /* @__PURE__ */ React60.createElement("h2", { style: hStyle }, text);
722
+ return /* @__PURE__ */ React58.createElement("h2", { style: hStyle }, text);
711
723
  case "h3":
712
- return /* @__PURE__ */ React60.createElement("h3", { style: hStyle }, text);
724
+ return /* @__PURE__ */ React58.createElement("h3", { style: hStyle }, text);
713
725
  }
714
726
  }
715
727
  function getFontSize(level) {
@@ -791,9 +803,9 @@ function Html({ style, props }) {
791
803
  padding: getPadding8(style == null ? void 0 : style.padding)
792
804
  };
793
805
  if (!children) {
794
- return /* @__PURE__ */ React60.createElement("div", { style: cssStyle });
806
+ return /* @__PURE__ */ React58.createElement("div", { style: cssStyle });
795
807
  }
796
- return /* @__PURE__ */ React60.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: children } });
808
+ return /* @__PURE__ */ React58.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: children } });
797
809
  }
798
810
  var html_default = Html;
799
811
  var PADDING_SCHEMA9 = z.object({
@@ -829,7 +841,7 @@ function Image({ style, props }) {
829
841
  const linkHref = (_c = props == null ? void 0 : props.linkHref) != null ? _c : null;
830
842
  const width = (_d = props == null ? void 0 : props.width) != null ? _d : void 0;
831
843
  const height = (_e = props == null ? void 0 : props.height) != null ? _e : void 0;
832
- const imageElement = /* @__PURE__ */ React60.createElement(
844
+ const imageElement = /* @__PURE__ */ React58.createElement(
833
845
  "img",
834
846
  {
835
847
  alt: (_f = props == null ? void 0 : props.alt) != null ? _f : "",
@@ -849,9 +861,9 @@ function Image({ style, props }) {
849
861
  }
850
862
  );
851
863
  if (!linkHref) {
852
- return /* @__PURE__ */ React60.createElement("div", { style: sectionStyle }, imageElement);
864
+ return /* @__PURE__ */ React58.createElement("div", { style: sectionStyle }, imageElement);
853
865
  }
854
- return /* @__PURE__ */ React60.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React60.createElement("a", { href: linkHref, style: { textDecoration: "none" }, target: "_blank" }, imageElement));
866
+ return /* @__PURE__ */ React58.createElement("div", { style: sectionStyle }, /* @__PURE__ */ React58.createElement("a", { href: linkHref, style: { textDecoration: "none" }, target: "_blank" }, imageElement));
855
867
  }
856
868
  var image_default = Image;
857
869
  var FONT_FAMILY_SCHEMA5 = z.enum([
@@ -997,7 +1009,7 @@ function Signature({ style, props }) {
997
1009
  color: linkColor,
998
1010
  textDecoration: "none"
999
1011
  };
1000
- const imageElement = imageUrl ? /* @__PURE__ */ React60.createElement(
1012
+ const imageElement = imageUrl ? /* @__PURE__ */ React58.createElement(
1001
1013
  "img",
1002
1014
  {
1003
1015
  src: imageUrl,
@@ -1016,18 +1028,18 @@ function Signature({ style, props }) {
1016
1028
  }
1017
1029
  ) : null;
1018
1030
  const contactParts = [];
1019
- if (email) contactParts.push(/* @__PURE__ */ React60.createElement("a", { key: "email", href: `mailto:${email}`, style: linkStyle }, email));
1020
- if (phone) contactParts.push(/* @__PURE__ */ React60.createElement("a", { key: "phone", href: `tel:${phone}`, style: linkStyle }, phone));
1031
+ if (email) contactParts.push(/* @__PURE__ */ React58.createElement("a", { key: "email", href: `mailto:${email}`, style: linkStyle }, email));
1032
+ if (phone) contactParts.push(/* @__PURE__ */ React58.createElement("a", { key: "phone", href: `tel:${phone}`, style: linkStyle }, phone));
1021
1033
  if (website) {
1022
1034
  const href = website.startsWith("http") ? website : `https://${website}`;
1023
- contactParts.push(/* @__PURE__ */ React60.createElement("a", { key: "website", href, style: linkStyle, target: "_blank" }, website));
1035
+ contactParts.push(/* @__PURE__ */ React58.createElement("a", { key: "website", href, style: linkStyle, target: "_blank" }, website));
1024
1036
  }
1025
- const textContent = /* @__PURE__ */ React60.createElement("div", null, name && /* @__PURE__ */ React60.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, address), contactParts.length > 0 && /* @__PURE__ */ React60.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, contactParts.map((part, i) => /* @__PURE__ */ React60.createElement(React60.Fragment, { key: i }, i > 0 && /* @__PURE__ */ React60.createElement("span", { style: detailStyle }, " \xB7 "), part))));
1026
- const greetingElement = greeting ? /* @__PURE__ */ React60.createElement("p", { style: greetingStyle }, greeting) : null;
1037
+ const textContent = /* @__PURE__ */ React58.createElement("div", null, name && /* @__PURE__ */ React58.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, address), contactParts.length > 0 && /* @__PURE__ */ React58.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, contactParts.map((part, i) => /* @__PURE__ */ React58.createElement(React58.Fragment, { key: i }, i > 0 && /* @__PURE__ */ React58.createElement("span", { style: detailStyle }, " \xB7 "), part))));
1038
+ const greetingElement = greeting ? /* @__PURE__ */ React58.createElement("p", { style: greetingStyle }, greeting) : null;
1027
1039
  if (layout === "vertical") {
1028
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React60.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
1040
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React58.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
1029
1041
  }
1030
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React60.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React60.createElement("tbody", null, /* @__PURE__ */ React60.createElement("tr", null, imageElement && /* @__PURE__ */ React60.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React60.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
1042
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React58.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React58.createElement("tbody", null, /* @__PURE__ */ React58.createElement("tr", null, imageElement && /* @__PURE__ */ React58.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React58.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
1031
1043
  }
1032
1044
  var signature_default = Signature;
1033
1045
  var SpacerPropsSchema = z.object({
@@ -1044,13 +1056,13 @@ function Spacer({ props }) {
1044
1056
  const style = {
1045
1057
  height: (_a = props == null ? void 0 : props.height) != null ? _a : SpacerPropsDefaults.height
1046
1058
  };
1047
- return /* @__PURE__ */ React60.createElement("div", { style });
1059
+ return /* @__PURE__ */ React58.createElement("div", { style });
1048
1060
  }
1049
1061
  var spacer_default = Spacer;
1050
1062
  function buildBlockComponent(blocks) {
1051
1063
  return function BlockComponent({ type, data }) {
1052
1064
  const Component = blocks[type].Component;
1053
- return /* @__PURE__ */ React60.createElement(Component, __spreadValues({}, data));
1065
+ return /* @__PURE__ */ React58.createElement(Component, __spreadValues({}, data));
1054
1066
  };
1055
1067
  }
1056
1068
  function buildBlockConfigurationSchema(blocks) {
@@ -1087,9 +1099,9 @@ function ColumnsContainerReader({ style, props }) {
1087
1099
  const _a = props != null ? props : {}, { columns } = _a, restProps = __objRest(_a, ["columns"]);
1088
1100
  let cols = void 0;
1089
1101
  if (columns) {
1090
- cols = columns.map((col) => col.childrenIds.map((childId) => /* @__PURE__ */ React60.createElement(ReaderBlock, { key: childId, id: childId })));
1102
+ cols = columns.map((col) => col.childrenIds.map((childId) => /* @__PURE__ */ React58.createElement(ReaderBlock, { key: childId, id: childId })));
1091
1103
  }
1092
- return /* @__PURE__ */ React60.createElement(columns_container_default, { props: restProps, columns: cols, style });
1104
+ return /* @__PURE__ */ React58.createElement(columns_container_default, { props: restProps, columns: cols, style });
1093
1105
  }
1094
1106
  var ContainerPropsSchema2 = z.object({
1095
1107
  style: ContainerPropsSchema.shape.style,
@@ -1100,7 +1112,7 @@ var ContainerPropsSchema2 = z.object({
1100
1112
  function ContainerReader({ style, props }) {
1101
1113
  var _a;
1102
1114
  const childrenIds = (_a = props == null ? void 0 : props.childrenIds) != null ? _a : [];
1103
- return /* @__PURE__ */ React60.createElement(container_default, { style }, childrenIds.map((childId) => /* @__PURE__ */ React60.createElement(ReaderBlock, { key: childId, id: childId })));
1115
+ return /* @__PURE__ */ React58.createElement(container_default, { style }, childrenIds.map((childId) => /* @__PURE__ */ React58.createElement(ReaderBlock, { key: childId, id: childId })));
1104
1116
  }
1105
1117
  var COLOR_SCHEMA9 = z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
1106
1118
  var FONT_FAMILY_SCHEMA6 = z.enum([
@@ -1116,7 +1128,8 @@ var FONT_FAMILY_SCHEMA6 = z.enum([
1116
1128
  ]).nullable().optional();
1117
1129
  var TemplateVariableSchema = z.object({
1118
1130
  name: z.string(),
1119
- description: z.string().optional().nullable()
1131
+ description: z.string().optional().nullable(),
1132
+ sampleValue: z.string().optional().nullable()
1120
1133
  });
1121
1134
  var EmailLayoutPropsSchema = z.object({
1122
1135
  backdropColor: COLOR_SCHEMA9,
@@ -1172,9 +1185,9 @@ function EmailLayoutReader(props) {
1172
1185
  margin: "0"
1173
1186
  };
1174
1187
  if (props.backdropDisabled) {
1175
- return /* @__PURE__ */ React60.createElement("div", { style: baseStyle }, childrenIds.map((childId) => /* @__PURE__ */ React60.createElement(ReaderBlock, { key: childId, id: childId })));
1188
+ return /* @__PURE__ */ React58.createElement("div", { style: baseStyle }, childrenIds.map((childId) => /* @__PURE__ */ React58.createElement(ReaderBlock, { key: childId, id: childId })));
1176
1189
  }
1177
- return /* @__PURE__ */ React60.createElement(
1190
+ return /* @__PURE__ */ React58.createElement(
1178
1191
  "div",
1179
1192
  {
1180
1193
  style: __spreadProps(__spreadValues({}, baseStyle), {
@@ -1184,7 +1197,7 @@ function EmailLayoutReader(props) {
1184
1197
  width: "100%"
1185
1198
  })
1186
1199
  },
1187
- /* @__PURE__ */ React60.createElement(
1200
+ /* @__PURE__ */ React58.createElement(
1188
1201
  "table",
1189
1202
  {
1190
1203
  align: "center",
@@ -1202,7 +1215,7 @@ function EmailLayoutReader(props) {
1202
1215
  cellPadding: "0",
1203
1216
  border: 0
1204
1217
  },
1205
- /* @__PURE__ */ React60.createElement("tbody", null, /* @__PURE__ */ React60.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React60.createElement("td", null, childrenIds.map((childId) => /* @__PURE__ */ React60.createElement(ReaderBlock, { key: childId, id: childId })))))
1218
+ /* @__PURE__ */ React58.createElement("tbody", null, /* @__PURE__ */ React58.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React58.createElement("td", null, childrenIds.map((childId) => /* @__PURE__ */ React58.createElement(ReaderBlock, { key: childId, id: childId })))))
1206
1219
  )
1207
1220
  );
1208
1221
  }
@@ -1214,7 +1227,7 @@ function useReaderDocument() {
1214
1227
  }
1215
1228
  function ReaderBlock({ id }) {
1216
1229
  const document2 = useReaderDocument();
1217
- return document2[id] ? /* @__PURE__ */ React60.createElement(BaseReaderBlock, __spreadValues({}, document2[id])) : null;
1230
+ return document2[id] ? /* @__PURE__ */ React58.createElement(BaseReaderBlock, __spreadValues({}, document2[id])) : null;
1218
1231
  }
1219
1232
  var READER_DICTIONARY = buildBlockConfigurationDictionary({
1220
1233
  ColumnsContainer: {
@@ -1271,13 +1284,13 @@ var ReaderBlockSchema = buildBlockConfigurationSchema(READER_DICTIONARY);
1271
1284
  var ReaderDocumentSchema = z.record(z.string(), ReaderBlockSchema);
1272
1285
  var BaseReaderBlock = buildBlockComponent(READER_DICTIONARY);
1273
1286
  function Reader({ document: document2, rootBlockId }) {
1274
- return /* @__PURE__ */ React60.createElement(ReaderContext.Provider, { value: document2 }, /* @__PURE__ */ React60.createElement(ReaderBlock, { id: rootBlockId }));
1287
+ return /* @__PURE__ */ React58.createElement(ReaderContext.Provider, { value: document2 }, /* @__PURE__ */ React58.createElement(ReaderBlock, { id: rootBlockId }));
1275
1288
  }
1276
1289
 
1277
1290
  // src/email-builder/renderers/render-to-static-markup.tsx
1278
1291
  function renderToStaticMarkup(document2, { rootBlockId }) {
1279
1292
  return "<!DOCTYPE html>" + renderToStaticMarkup$1(
1280
- /* @__PURE__ */ React60.createElement("html", null, /* @__PURE__ */ React60.createElement("body", null, /* @__PURE__ */ React60.createElement(Reader, { document: document2, rootBlockId })))
1293
+ /* @__PURE__ */ React58.createElement("html", null, /* @__PURE__ */ React58.createElement("body", null, /* @__PURE__ */ React58.createElement(Reader, { document: document2, rootBlockId })))
1281
1294
  );
1282
1295
  }
1283
1296
 
@@ -1945,7 +1958,8 @@ var editorStateStore = create(() => ({
1945
1958
  selectedScreenSize: "desktop",
1946
1959
  inspectorDrawerOpen: true,
1947
1960
  samplesDrawerOpen: true,
1948
- persistenceEnabled: false
1961
+ persistenceEnabled: false,
1962
+ lastFocusedEditable: null
1949
1963
  }));
1950
1964
  function useDocument() {
1951
1965
  return editorStateStore((s) => s.document);
@@ -2018,6 +2032,15 @@ function setSelectedScreenSize(selectedScreenSize) {
2018
2032
  function setPersistenceEnabled(persistenceEnabled) {
2019
2033
  return editorStateStore.setState({ persistenceEnabled });
2020
2034
  }
2035
+ function useLastFocusedEditable() {
2036
+ return editorStateStore((s) => s.lastFocusedEditable);
2037
+ }
2038
+ function getLastFocusedEditable() {
2039
+ return editorStateStore.getState().lastFocusedEditable;
2040
+ }
2041
+ function setLastFocusedEditable(lastFocusedEditable) {
2042
+ return editorStateStore.setState({ lastFocusedEditable });
2043
+ }
2021
2044
 
2022
2045
  // src/app/save-payload.ts
2023
2046
  var ROOT_BLOCK_ID = "root";
@@ -2089,7 +2112,7 @@ var EmailEditorProvider = ({
2089
2112
  registerSaveListener,
2090
2113
  setCurrentTemplate
2091
2114
  }), [currentTemplateId, currentTemplateName, currentTemplateKind, saveTemplate, loadTemplate, registerSaveListener, setCurrentTemplate]);
2092
- return /* @__PURE__ */ React60.createElement(EmailEditorContext.Provider, { value }, children);
2115
+ return /* @__PURE__ */ React58.createElement(EmailEditorContext.Provider, { value }, children);
2093
2116
  };
2094
2117
  var useEmailEditor = () => {
2095
2118
  const context = useContext(EmailEditorContext);
@@ -2098,15 +2121,25 @@ var useEmailEditor = () => {
2098
2121
  }
2099
2122
  return context;
2100
2123
  };
2124
+ var ImageCallbacksContext = createContext({});
2125
+ function ImageCallbacksProvider({
2126
+ callbacks,
2127
+ children
2128
+ }) {
2129
+ return /* @__PURE__ */ React58.createElement(ImageCallbacksContext.Provider, { value: callbacks }, children);
2130
+ }
2131
+ function useImageCallbacks() {
2132
+ return useContext(ImageCallbacksContext);
2133
+ }
2101
2134
  function BaseSidebarPanel({ title, children }) {
2102
- return /* @__PURE__ */ React60.createElement(Box, { p: 2 }, /* @__PURE__ */ React60.createElement(Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 } }, title), /* @__PURE__ */ React60.createElement(Stack, { spacing: 5, mb: 3 }, children));
2135
+ return /* @__PURE__ */ React58.createElement(Box, { p: 2 }, /* @__PURE__ */ React58.createElement(Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 } }, title), /* @__PURE__ */ React58.createElement(Stack, { spacing: 5, mb: 3 }, children));
2103
2136
  }
2104
2137
  function RadioGroupInput({ label, children, defaultValue, onChange }) {
2105
2138
  const [value, setValue] = useState(defaultValue);
2106
2139
  useEffect(() => {
2107
2140
  setValue(defaultValue);
2108
2141
  }, [defaultValue]);
2109
- return /* @__PURE__ */ React60.createElement(Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React60.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React60.createElement(
2142
+ return /* @__PURE__ */ React58.createElement(Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React58.createElement(
2110
2143
  ToggleButtonGroup,
2111
2144
  {
2112
2145
  exclusive: true,
@@ -2126,7 +2159,7 @@ function RadioGroupInput({ label, children, defaultValue, onChange }) {
2126
2159
  }
2127
2160
  function RawSliderInput(_a) {
2128
2161
  var _b = _a, { iconLabel, value, setValue, units } = _b, props = __objRest(_b, ["iconLabel", "value", "setValue", "units"]);
2129
- return /* @__PURE__ */ React60.createElement(Stack, { direction: "row", alignItems: "center", spacing: 2, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React60.createElement(Box, { sx: { minWidth: 24, lineHeight: 1, flexShrink: 0 } }, iconLabel), /* @__PURE__ */ React60.createElement(
2162
+ return /* @__PURE__ */ React58.createElement(Stack, { direction: "row", alignItems: "center", spacing: 2, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React58.createElement(Box, { sx: { minWidth: 24, lineHeight: 1, flexShrink: 0 } }, iconLabel), /* @__PURE__ */ React58.createElement(
2130
2163
  Slider,
2131
2164
  __spreadProps(__spreadValues({}, props), {
2132
2165
  value,
@@ -2137,14 +2170,14 @@ function RawSliderInput(_a) {
2137
2170
  setValue(value2);
2138
2171
  }
2139
2172
  })
2140
- ), /* @__PURE__ */ React60.createElement(Box, { sx: { minWidth: 32, textAlign: "right", flexShrink: 0 } }, /* @__PURE__ */ React60.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { lineHeight: 1 } }, value, units)));
2173
+ ), /* @__PURE__ */ React58.createElement(Box, { sx: { minWidth: 32, textAlign: "right", flexShrink: 0 } }, /* @__PURE__ */ React58.createElement(Typography, { variant: "body2", color: "text.secondary", sx: { lineHeight: 1 } }, value, units)));
2141
2174
  }
2142
2175
 
2143
2176
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/slider-input.tsx
2144
2177
  function SliderInput(_a) {
2145
2178
  var _b = _a, { label, defaultValue, onChange } = _b, props = __objRest(_b, ["label", "defaultValue", "onChange"]);
2146
2179
  const [value, setValue] = useState(defaultValue);
2147
- return /* @__PURE__ */ React60.createElement(Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React60.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React60.createElement(
2180
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React58.createElement(
2148
2181
  RawSliderInput,
2149
2182
  __spreadValues({
2150
2183
  value,
@@ -2161,7 +2194,7 @@ function TextInput({ helperText, label, placeholder, rows, InputProps: InputProp
2161
2194
  useEffect(() => {
2162
2195
  setValue(defaultValue);
2163
2196
  }, [defaultValue]);
2164
- return /* @__PURE__ */ React60.createElement(
2197
+ return /* @__PURE__ */ React58.createElement(
2165
2198
  TextField,
2166
2199
  {
2167
2200
  fullWidth: true,
@@ -2187,7 +2220,7 @@ var TILE_BUTTON = {
2187
2220
  };
2188
2221
  function Swatch({ paletteColors, value, onChange }) {
2189
2222
  const renderButton2 = (colorValue) => {
2190
- return /* @__PURE__ */ React60.createElement(
2223
+ return /* @__PURE__ */ React58.createElement(
2191
2224
  Button$1,
2192
2225
  {
2193
2226
  key: colorValue,
@@ -2206,7 +2239,7 @@ function Swatch({ paletteColors, value, onChange }) {
2206
2239
  }
2207
2240
  );
2208
2241
  };
2209
- return /* @__PURE__ */ React60.createElement(Box, { width: "100%", sx: { display: "grid", gap: 1, gridTemplateColumns: "1fr 1fr 1fr 1fr 1fr 1fr" } }, paletteColors.map((c) => renderButton2(c)));
2242
+ return /* @__PURE__ */ React58.createElement(Box, { width: "100%", sx: { display: "grid", gap: 1, gridTemplateColumns: "1fr 1fr 1fr 1fr 1fr 1fr" } }, paletteColors.map((c) => renderButton2(c)));
2210
2243
  }
2211
2244
 
2212
2245
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/color-input/picker.tsx
@@ -2273,7 +2306,7 @@ var SX = {
2273
2306
  }
2274
2307
  };
2275
2308
  function Picker({ value, onChange }) {
2276
- return /* @__PURE__ */ React60.createElement(Stack, { spacing: 1, sx: SX }, /* @__PURE__ */ React60.createElement(HexColorPicker, { color: value, onChange }), /* @__PURE__ */ React60.createElement(Swatch, { paletteColors: DEFAULT_PRESET_COLORS, value, onChange }), /* @__PURE__ */ React60.createElement(Box, { pt: 1 }, /* @__PURE__ */ React60.createElement(HexColorInput, { prefixed: true, color: value, onChange })));
2309
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 1, sx: SX }, /* @__PURE__ */ React58.createElement(HexColorPicker, { color: value, onChange }), /* @__PURE__ */ React58.createElement(Swatch, { paletteColors: DEFAULT_PRESET_COLORS, value, onChange }), /* @__PURE__ */ React58.createElement(Box, { pt: 1 }, /* @__PURE__ */ React58.createElement(HexColorInput, { prefixed: true, color: value, onChange })));
2277
2310
  }
2278
2311
 
2279
2312
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/color-input/base-color-input.tsx
@@ -2298,7 +2331,7 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2298
2331
  if (typeof value !== "string" || value.trim().length === 0) {
2299
2332
  return null;
2300
2333
  }
2301
- return /* @__PURE__ */ React60.createElement(
2334
+ return /* @__PURE__ */ React58.createElement(
2302
2335
  ButtonBase,
2303
2336
  {
2304
2337
  onClick: () => {
@@ -2306,16 +2339,16 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2306
2339
  onChange(null);
2307
2340
  }
2308
2341
  },
2309
- /* @__PURE__ */ React60.createElement(CloseOutlined, { fontSize: "small", sx: { color: "grey.600" } })
2342
+ /* @__PURE__ */ React58.createElement(CloseOutlined, { fontSize: "small", sx: { color: "grey.600" } })
2310
2343
  );
2311
2344
  };
2312
2345
  const renderOpenButton = () => {
2313
2346
  if (value) {
2314
- return /* @__PURE__ */ React60.createElement(ButtonBase, { onClick: handleClickOpen, sx: __spreadProps(__spreadValues({}, BUTTON_SX), { bgcolor: value }) });
2347
+ return /* @__PURE__ */ React58.createElement(ButtonBase, { onClick: handleClickOpen, sx: __spreadProps(__spreadValues({}, BUTTON_SX), { bgcolor: value }) });
2315
2348
  }
2316
- return /* @__PURE__ */ React60.createElement(ButtonBase, { onClick: handleClickOpen, sx: __spreadValues({}, BUTTON_SX) }, /* @__PURE__ */ React60.createElement(AddOutlined, { fontSize: "small" }));
2349
+ return /* @__PURE__ */ React58.createElement(ButtonBase, { onClick: handleClickOpen, sx: __spreadValues({}, BUTTON_SX) }, /* @__PURE__ */ React58.createElement(AddOutlined, { fontSize: "small" }));
2317
2350
  };
2318
- return /* @__PURE__ */ React60.createElement(Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React60.createElement(InputLabel, { sx: { mb: 0.5 } }, label), /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 1 }, renderOpenButton(), renderResetButton()), /* @__PURE__ */ React60.createElement(
2351
+ return /* @__PURE__ */ React58.createElement(Stack, { alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(InputLabel, { sx: { mb: 0.5 } }, label), /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 1 }, renderOpenButton(), renderResetButton()), /* @__PURE__ */ React58.createElement(
2319
2352
  Menu,
2320
2353
  {
2321
2354
  anchorEl,
@@ -2325,7 +2358,7 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2325
2358
  sx: { height: "auto", padding: 0 }
2326
2359
  }
2327
2360
  },
2328
- /* @__PURE__ */ React60.createElement(
2361
+ /* @__PURE__ */ React58.createElement(
2329
2362
  Picker,
2330
2363
  {
2331
2364
  value: value || "",
@@ -2340,10 +2373,10 @@ function ColorInput({ label, defaultValue, onChange, nullable }) {
2340
2373
 
2341
2374
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/color-input/index.tsx
2342
2375
  function ColorInput2(props) {
2343
- return /* @__PURE__ */ React60.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: false }));
2376
+ return /* @__PURE__ */ React58.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: false }));
2344
2377
  }
2345
2378
  function NullableColorInput(props) {
2346
- return /* @__PURE__ */ React60.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: true }));
2379
+ return /* @__PURE__ */ React58.createElement(ColorInput, __spreadProps(__spreadValues({}, props), { nullable: true }));
2347
2380
  }
2348
2381
 
2349
2382
  // src/editor/blocks/helpers/font-family.ts
@@ -2396,13 +2429,13 @@ var FONT_FAMILIES = [
2396
2429
  ];
2397
2430
 
2398
2431
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/inputs/font-family.tsx
2399
- var OPTIONS = FONT_FAMILIES.map((option) => /* @__PURE__ */ React60.createElement(MenuItem, { key: option.key, value: option.key, sx: { fontFamily: option.value } }, option.label));
2432
+ var OPTIONS = FONT_FAMILIES.map((option) => /* @__PURE__ */ React58.createElement(MenuItem, { key: option.key, value: option.key, sx: { fontFamily: option.value } }, option.label));
2400
2433
  function NullableFontFamily({ label, onChange, defaultValue }) {
2401
2434
  const [value, setValue] = useState(defaultValue != null ? defaultValue : "inherit");
2402
2435
  useEffect(() => {
2403
2436
  setValue(defaultValue != null ? defaultValue : "inherit");
2404
2437
  }, [defaultValue]);
2405
- return /* @__PURE__ */ React60.createElement(
2438
+ return /* @__PURE__ */ React58.createElement(
2406
2439
  TextField,
2407
2440
  {
2408
2441
  select: true,
@@ -2415,7 +2448,7 @@ function NullableFontFamily({ label, onChange, defaultValue }) {
2415
2448
  onChange(v === null ? null : v);
2416
2449
  }
2417
2450
  },
2418
- /* @__PURE__ */ React60.createElement(MenuItem, { value: "inherit" }, "Match email settings"),
2451
+ /* @__PURE__ */ React58.createElement(MenuItem, { value: "inherit" }, "Match email settings"),
2419
2452
  OPTIONS
2420
2453
  );
2421
2454
  }
@@ -2428,10 +2461,10 @@ function FontSizeInput({ label, defaultValue, onChange }) {
2428
2461
  setValue(value2);
2429
2462
  onChange(value2);
2430
2463
  };
2431
- return /* @__PURE__ */ React60.createElement(Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React60.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React60.createElement(
2464
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React58.createElement(
2432
2465
  RawSliderInput,
2433
2466
  {
2434
- iconLabel: /* @__PURE__ */ React60.createElement(TextFieldsOutlined, { sx: { fontSize: 16 } }),
2467
+ iconLabel: /* @__PURE__ */ React58.createElement(TextFieldsOutlined, { sx: { fontSize: 16 } }),
2435
2468
  value,
2436
2469
  setValue: handleChange,
2437
2470
  units: "px",
@@ -2446,7 +2479,7 @@ function FontWeightInput({ label, defaultValue, onChange }) {
2446
2479
  useEffect(() => {
2447
2480
  setValue(defaultValue);
2448
2481
  }, [defaultValue]);
2449
- return /* @__PURE__ */ React60.createElement(
2482
+ return /* @__PURE__ */ React58.createElement(
2450
2483
  RadioGroupInput,
2451
2484
  {
2452
2485
  label,
@@ -2456,10 +2489,67 @@ function FontWeightInput({ label, defaultValue, onChange }) {
2456
2489
  onChange(fontWeight);
2457
2490
  }
2458
2491
  },
2459
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "normal" }, "Regular"),
2460
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "bold" }, "Bold")
2492
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "normal" }, "Regular"),
2493
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "bold" }, "Bold")
2461
2494
  );
2462
2495
  }
2496
+ function LetterSpacingInput({ label, defaultValue, onChange }) {
2497
+ const handleChange = (ev) => {
2498
+ const raw = ev.target.value.trim();
2499
+ if (raw === "") {
2500
+ onChange(null);
2501
+ return;
2502
+ }
2503
+ const value = parseFloat(raw);
2504
+ onChange(isNaN(value) ? null : value);
2505
+ };
2506
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(
2507
+ TextField,
2508
+ {
2509
+ fullWidth: true,
2510
+ onChange: handleChange,
2511
+ defaultValue: defaultValue != null ? defaultValue : "",
2512
+ label,
2513
+ variant: "standard",
2514
+ placeholder: "normal",
2515
+ size: "small",
2516
+ type: "number",
2517
+ inputProps: { step: 0.5 },
2518
+ InputProps: {
2519
+ startAdornment: /* @__PURE__ */ React58.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React58.createElement(SpaceBarOutlined, { sx: { fontSize: 16 } })),
2520
+ endAdornment: /* @__PURE__ */ React58.createElement(Typography, { variant: "body2", color: "text.secondary" }, "px")
2521
+ }
2522
+ }
2523
+ ));
2524
+ }
2525
+ function LineHeightInput({ label, defaultValue, onChange }) {
2526
+ const handleChange = (ev) => {
2527
+ const raw = ev.target.value.trim();
2528
+ if (raw === "") {
2529
+ onChange(null);
2530
+ return;
2531
+ }
2532
+ const value = parseFloat(raw);
2533
+ onChange(isNaN(value) ? null : value);
2534
+ };
2535
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(
2536
+ TextField,
2537
+ {
2538
+ fullWidth: true,
2539
+ onChange: handleChange,
2540
+ defaultValue: defaultValue != null ? defaultValue : "",
2541
+ label,
2542
+ variant: "standard",
2543
+ placeholder: "default",
2544
+ size: "small",
2545
+ type: "number",
2546
+ inputProps: { step: 0.1 },
2547
+ InputProps: {
2548
+ startAdornment: /* @__PURE__ */ React58.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React58.createElement(FormatLineSpacingOutlined, { sx: { fontSize: 16 } }))
2549
+ }
2550
+ }
2551
+ ));
2552
+ }
2463
2553
  function PaddingInput({ label, defaultValue, onChange }) {
2464
2554
  const [value, setValue] = useState(() => {
2465
2555
  if (defaultValue) {
@@ -2479,10 +2569,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2479
2569
  setValue(v);
2480
2570
  onChange(v);
2481
2571
  }
2482
- return /* @__PURE__ */ React60.createElement(Stack, { spacing: 2, alignItems: "flex-start", pb: 1 }, /* @__PURE__ */ React60.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React60.createElement(
2572
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 2, alignItems: "flex-start", pb: 1 }, /* @__PURE__ */ React58.createElement(InputLabel, { shrink: true }, label), /* @__PURE__ */ React58.createElement(
2483
2573
  RawSliderInput,
2484
2574
  {
2485
- iconLabel: /* @__PURE__ */ React60.createElement(AlignVerticalTopOutlined, { sx: { fontSize: 16 } }),
2575
+ iconLabel: /* @__PURE__ */ React58.createElement(AlignVerticalTopOutlined, { sx: { fontSize: 16 } }),
2486
2576
  value: value.top,
2487
2577
  setValue: (num) => handleChange("top", num),
2488
2578
  units: "px",
@@ -2491,10 +2581,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2491
2581
  max: 80,
2492
2582
  marks: true
2493
2583
  }
2494
- ), /* @__PURE__ */ React60.createElement(
2584
+ ), /* @__PURE__ */ React58.createElement(
2495
2585
  RawSliderInput,
2496
2586
  {
2497
- iconLabel: /* @__PURE__ */ React60.createElement(AlignVerticalBottomOutlined, { sx: { fontSize: 16 } }),
2587
+ iconLabel: /* @__PURE__ */ React58.createElement(AlignVerticalBottomOutlined, { sx: { fontSize: 16 } }),
2498
2588
  value: value.bottom,
2499
2589
  setValue: (num) => handleChange("bottom", num),
2500
2590
  units: "px",
@@ -2503,10 +2593,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2503
2593
  max: 80,
2504
2594
  marks: true
2505
2595
  }
2506
- ), /* @__PURE__ */ React60.createElement(
2596
+ ), /* @__PURE__ */ React58.createElement(
2507
2597
  RawSliderInput,
2508
2598
  {
2509
- iconLabel: /* @__PURE__ */ React60.createElement(AlignHorizontalLeftOutlined, { sx: { fontSize: 16 } }),
2599
+ iconLabel: /* @__PURE__ */ React58.createElement(AlignHorizontalLeftOutlined, { sx: { fontSize: 16 } }),
2510
2600
  value: value.left,
2511
2601
  setValue: (num) => handleChange("left", num),
2512
2602
  units: "px",
@@ -2515,10 +2605,10 @@ function PaddingInput({ label, defaultValue, onChange }) {
2515
2605
  max: 80,
2516
2606
  marks: true
2517
2607
  }
2518
- ), /* @__PURE__ */ React60.createElement(
2608
+ ), /* @__PURE__ */ React58.createElement(
2519
2609
  RawSliderInput,
2520
2610
  {
2521
- iconLabel: /* @__PURE__ */ React60.createElement(AlignHorizontalRightOutlined, { sx: { fontSize: 16 } }),
2611
+ iconLabel: /* @__PURE__ */ React58.createElement(AlignHorizontalRightOutlined, { sx: { fontSize: 16 } }),
2522
2612
  value: value.right,
2523
2613
  setValue: (num) => handleChange("right", num),
2524
2614
  units: "px",
@@ -2534,7 +2624,7 @@ function TextAlignInput({ label, defaultValue, onChange }) {
2534
2624
  useEffect(() => {
2535
2625
  setValue(defaultValue != null ? defaultValue : "left");
2536
2626
  }, [defaultValue]);
2537
- return /* @__PURE__ */ React60.createElement(
2627
+ return /* @__PURE__ */ React58.createElement(
2538
2628
  RadioGroupInput,
2539
2629
  {
2540
2630
  label,
@@ -2544,9 +2634,9 @@ function TextAlignInput({ label, defaultValue, onChange }) {
2544
2634
  onChange(value2);
2545
2635
  }
2546
2636
  },
2547
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "left" }, /* @__PURE__ */ React60.createElement(FormatAlignLeftOutlined, { fontSize: "small" })),
2548
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "center" }, /* @__PURE__ */ React60.createElement(FormatAlignCenterOutlined, { fontSize: "small" })),
2549
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "right" }, /* @__PURE__ */ React60.createElement(FormatAlignRightOutlined, { fontSize: "small" }))
2637
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "left" }, /* @__PURE__ */ React58.createElement(FormatAlignLeftOutlined, { fontSize: "small" })),
2638
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "center" }, /* @__PURE__ */ React58.createElement(FormatAlignCenterOutlined, { fontSize: "small" })),
2639
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "right" }, /* @__PURE__ */ React58.createElement(FormatAlignRightOutlined, { fontSize: "small" }))
2550
2640
  );
2551
2641
  }
2552
2642
 
@@ -2559,14 +2649,14 @@ function SingleStylePropertyPanel({ name, value, onChange }) {
2559
2649
  };
2560
2650
  switch (name) {
2561
2651
  case "backgroundColor":
2562
- return /* @__PURE__ */ React60.createElement(NullableColorInput, { label: "Background color", defaultValue, onChange: handleChange });
2652
+ return /* @__PURE__ */ React58.createElement(NullableColorInput, { label: "Background color", defaultValue, onChange: handleChange });
2563
2653
  case "borderColor":
2564
- return /* @__PURE__ */ React60.createElement(NullableColorInput, { label: "Border color", defaultValue, onChange: handleChange });
2654
+ return /* @__PURE__ */ React58.createElement(NullableColorInput, { label: "Border color", defaultValue, onChange: handleChange });
2565
2655
  case "borderRadius":
2566
- return /* @__PURE__ */ React60.createElement(
2656
+ return /* @__PURE__ */ React58.createElement(
2567
2657
  SliderInput,
2568
2658
  {
2569
- iconLabel: /* @__PURE__ */ React60.createElement(RoundedCornerOutlined, null),
2659
+ iconLabel: /* @__PURE__ */ React58.createElement(RoundedCornerOutlined, null),
2570
2660
  units: "px",
2571
2661
  step: 4,
2572
2662
  marks: true,
@@ -2578,23 +2668,27 @@ function SingleStylePropertyPanel({ name, value, onChange }) {
2578
2668
  }
2579
2669
  );
2580
2670
  case "color":
2581
- return /* @__PURE__ */ React60.createElement(NullableColorInput, { label: "Text color", defaultValue, onChange: handleChange });
2671
+ return /* @__PURE__ */ React58.createElement(NullableColorInput, { label: "Text color", defaultValue, onChange: handleChange });
2582
2672
  case "fontFamily":
2583
- return /* @__PURE__ */ React60.createElement(NullableFontFamily, { label: "Font family", defaultValue, onChange: handleChange });
2673
+ return /* @__PURE__ */ React58.createElement(NullableFontFamily, { label: "Font family", defaultValue, onChange: handleChange });
2584
2674
  case "fontSize":
2585
- return /* @__PURE__ */ React60.createElement(FontSizeInput, { label: "Font size", defaultValue, onChange: handleChange });
2675
+ return /* @__PURE__ */ React58.createElement(FontSizeInput, { label: "Font size", defaultValue, onChange: handleChange });
2586
2676
  case "fontWeight":
2587
- return /* @__PURE__ */ React60.createElement(FontWeightInput, { label: "Font weight", defaultValue, onChange: handleChange });
2677
+ return /* @__PURE__ */ React58.createElement(FontWeightInput, { label: "Font weight", defaultValue, onChange: handleChange });
2678
+ case "lineHeight":
2679
+ return /* @__PURE__ */ React58.createElement(LineHeightInput, { label: "Line height", defaultValue, onChange: handleChange });
2680
+ case "letterSpacing":
2681
+ return /* @__PURE__ */ React58.createElement(LetterSpacingInput, { label: "Letter spacing", defaultValue, onChange: handleChange });
2588
2682
  case "textAlign":
2589
- return /* @__PURE__ */ React60.createElement(TextAlignInput, { label: "Alignment", defaultValue, onChange: handleChange });
2683
+ return /* @__PURE__ */ React58.createElement(TextAlignInput, { label: "Alignment", defaultValue, onChange: handleChange });
2590
2684
  case "padding":
2591
- return /* @__PURE__ */ React60.createElement(PaddingInput, { label: "Padding", defaultValue, onChange: handleChange });
2685
+ return /* @__PURE__ */ React58.createElement(PaddingInput, { label: "Padding", defaultValue, onChange: handleChange });
2592
2686
  }
2593
2687
  }
2594
2688
 
2595
2689
  // src/app/inspector-drawer/configuration-panel/input-panels/helpers/style-inputs/multi-style-property-panel.tsx
2596
2690
  function MultiStylePropertyPanel({ names, value, onChange }) {
2597
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, names.map((name) => /* @__PURE__ */ React60.createElement(SingleStylePropertyPanel, { key: name, name, value: value || {}, onChange })));
2691
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, names.map((name) => /* @__PURE__ */ React58.createElement(SingleStylePropertyPanel, { key: name, name, value: value || {}, onChange })));
2598
2692
  }
2599
2693
 
2600
2694
  // src/app/inspector-drawer/configuration-panel/input-panels/avatar-sidebar-panel.tsx
@@ -2614,11 +2708,11 @@ function AvatarSidebarPanel({ data, setData }) {
2614
2708
  const imageUrl = (_d = (_c = data.props) == null ? void 0 : _c.imageUrl) != null ? _d : AvatarPropsDefaults.imageUrl;
2615
2709
  const alt = (_f = (_e = data.props) == null ? void 0 : _e.alt) != null ? _f : AvatarPropsDefaults.alt;
2616
2710
  const shape = (_h = (_g = data.props) == null ? void 0 : _g.shape) != null ? _h : AvatarPropsDefaults.shape;
2617
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Avatar block" }, /* @__PURE__ */ React60.createElement(
2711
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Avatar block" }, /* @__PURE__ */ React58.createElement(
2618
2712
  SliderInput,
2619
2713
  {
2620
2714
  label: "Size",
2621
- iconLabel: /* @__PURE__ */ React60.createElement(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
2715
+ iconLabel: /* @__PURE__ */ React58.createElement(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
2622
2716
  units: "px",
2623
2717
  step: 3,
2624
2718
  min: 32,
@@ -2628,7 +2722,7 @@ function AvatarSidebarPanel({ data, setData }) {
2628
2722
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { size: size2 }) }));
2629
2723
  }
2630
2724
  }
2631
- ), /* @__PURE__ */ React60.createElement(
2725
+ ), /* @__PURE__ */ React58.createElement(
2632
2726
  RadioGroupInput,
2633
2727
  {
2634
2728
  label: "Shape",
@@ -2637,10 +2731,10 @@ function AvatarSidebarPanel({ data, setData }) {
2637
2731
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { shape: shape2 }) }));
2638
2732
  }
2639
2733
  },
2640
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "circle" }, "Circle"),
2641
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "square" }, "Square"),
2642
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "rounded" }, "Rounded")
2643
- ), /* @__PURE__ */ React60.createElement(
2734
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "circle" }, "Circle"),
2735
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "square" }, "Square"),
2736
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "rounded" }, "Rounded")
2737
+ ), /* @__PURE__ */ React58.createElement(
2644
2738
  TextInput,
2645
2739
  {
2646
2740
  label: "Image URL",
@@ -2649,7 +2743,7 @@ function AvatarSidebarPanel({ data, setData }) {
2649
2743
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }));
2650
2744
  }
2651
2745
  }
2652
- ), /* @__PURE__ */ React60.createElement(
2746
+ ), /* @__PURE__ */ React58.createElement(
2653
2747
  TextInput,
2654
2748
  {
2655
2749
  label: "Alt text",
@@ -2658,7 +2752,7 @@ function AvatarSidebarPanel({ data, setData }) {
2658
2752
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt: alt2 }) }));
2659
2753
  }
2660
2754
  }
2661
- ), /* @__PURE__ */ React60.createElement(
2755
+ ), /* @__PURE__ */ React58.createElement(
2662
2756
  MultiStylePropertyPanel,
2663
2757
  {
2664
2758
  names: ["textAlign", "padding"],
@@ -2686,68 +2780,77 @@ function ButtonSidebarPanel({ data, setData }) {
2686
2780
  const buttonStyle = (_j = (_i = data.props) == null ? void 0 : _i.buttonStyle) != null ? _j : ButtonPropsDefaults.buttonStyle;
2687
2781
  const buttonTextColor = (_l = (_k = data.props) == null ? void 0 : _k.buttonTextColor) != null ? _l : ButtonPropsDefaults.buttonTextColor;
2688
2782
  const buttonBackgroundColor = (_n = (_m = data.props) == null ? void 0 : _m.buttonBackgroundColor) != null ? _n : ButtonPropsDefaults.buttonBackgroundColor;
2689
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Button block" }, /* @__PURE__ */ React60.createElement(
2783
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Button block" }, /* @__PURE__ */ React58.createElement(
2690
2784
  TextInput,
2691
2785
  {
2692
2786
  label: "Text",
2693
2787
  defaultValue: text,
2694
2788
  onChange: (text2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text: text2 }) }))
2695
2789
  }
2696
- ), /* @__PURE__ */ React60.createElement(
2790
+ ), /* @__PURE__ */ React58.createElement(
2697
2791
  TextInput,
2698
2792
  {
2699
2793
  label: "Url",
2700
2794
  defaultValue: url,
2701
2795
  onChange: (url2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: url2 }) }))
2702
2796
  }
2703
- ), /* @__PURE__ */ React60.createElement(
2797
+ ), /* @__PURE__ */ React58.createElement(
2704
2798
  RadioGroupInput,
2705
2799
  {
2706
2800
  label: "Width",
2707
2801
  defaultValue: fullWidth ? "FULL_WIDTH" : "AUTO",
2708
2802
  onChange: (v) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { fullWidth: v === "FULL_WIDTH" }) }))
2709
2803
  },
2710
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "FULL_WIDTH" }, "Full"),
2711
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "AUTO" }, "Auto")
2712
- ), /* @__PURE__ */ React60.createElement(
2804
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "FULL_WIDTH" }, "Full"),
2805
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "AUTO" }, "Auto")
2806
+ ), /* @__PURE__ */ React58.createElement(
2713
2807
  RadioGroupInput,
2714
2808
  {
2715
2809
  label: "Size",
2716
2810
  defaultValue: size,
2717
2811
  onChange: (size2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { size: size2 }) }))
2718
2812
  },
2719
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "x-small" }, "Xs"),
2720
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "small" }, "Sm"),
2721
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "medium" }, "Md"),
2722
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "large" }, "Lg")
2723
- ), /* @__PURE__ */ React60.createElement(
2813
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "x-small" }, "Xs"),
2814
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "small" }, "Sm"),
2815
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "medium" }, "Md"),
2816
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "large" }, "Lg")
2817
+ ), /* @__PURE__ */ React58.createElement(
2724
2818
  RadioGroupInput,
2725
2819
  {
2726
2820
  label: "Style",
2727
2821
  defaultValue: buttonStyle,
2728
2822
  onChange: (buttonStyle2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonStyle: buttonStyle2 }) }))
2729
2823
  },
2730
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "rectangle" }, "Rectangle"),
2731
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "rounded" }, "Rounded"),
2732
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "pill" }, "Pill")
2733
- ), /* @__PURE__ */ React60.createElement(
2824
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "rectangle" }, "Rectangle"),
2825
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "rounded" }, "Rounded"),
2826
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "pill" }, "Pill")
2827
+ ), /* @__PURE__ */ React58.createElement(
2734
2828
  ColorInput2,
2735
2829
  {
2736
2830
  label: "Text color",
2737
2831
  defaultValue: buttonTextColor,
2738
2832
  onChange: (buttonTextColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonTextColor: buttonTextColor2 }) }))
2739
2833
  }
2740
- ), /* @__PURE__ */ React60.createElement(
2834
+ ), /* @__PURE__ */ React58.createElement(
2741
2835
  ColorInput2,
2742
2836
  {
2743
2837
  label: "Button color",
2744
2838
  defaultValue: buttonBackgroundColor,
2745
2839
  onChange: (buttonBackgroundColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonBackgroundColor: buttonBackgroundColor2 }) }))
2746
2840
  }
2747
- ), /* @__PURE__ */ React60.createElement(
2841
+ ), /* @__PURE__ */ React58.createElement(
2748
2842
  MultiStylePropertyPanel,
2749
2843
  {
2750
- names: ["backgroundColor", "fontFamily", "fontSize", "fontWeight", "textAlign", "padding"],
2844
+ names: [
2845
+ "backgroundColor",
2846
+ "fontFamily",
2847
+ "fontSize",
2848
+ "fontWeight",
2849
+ "lineHeight",
2850
+ "letterSpacing",
2851
+ "textAlign",
2852
+ "padding"
2853
+ ],
2751
2854
  value: data.style,
2752
2855
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
2753
2856
  }
@@ -2770,7 +2873,7 @@ function TextDimensionInput({ label, defaultValue, onChange }) {
2770
2873
  const value = parseInt(ev.target.value);
2771
2874
  onChange(isNaN(value) ? null : value);
2772
2875
  };
2773
- return /* @__PURE__ */ React60.createElement(
2876
+ return /* @__PURE__ */ React58.createElement(
2774
2877
  TextField,
2775
2878
  {
2776
2879
  fullWidth: true,
@@ -2781,7 +2884,7 @@ function TextDimensionInput({ label, defaultValue, onChange }) {
2781
2884
  placeholder: "auto",
2782
2885
  size: "small",
2783
2886
  InputProps: {
2784
- endAdornment: /* @__PURE__ */ React60.createElement(Typography, { variant: "body2", color: "text.secondary" }, "px")
2887
+ endAdornment: /* @__PURE__ */ React58.createElement(Typography, { variant: "body2", color: "text.secondary" }, "px")
2785
2888
  }
2786
2889
  }
2787
2890
  );
@@ -2803,7 +2906,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2803
2906
  };
2804
2907
  let column3 = null;
2805
2908
  {
2806
- column3 = /* @__PURE__ */ React60.createElement(
2909
+ column3 = /* @__PURE__ */ React58.createElement(
2807
2910
  TextDimensionInput,
2808
2911
  {
2809
2912
  label: "Column 3",
@@ -2814,7 +2917,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2814
2917
  }
2815
2918
  );
2816
2919
  }
2817
- return /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 1 }, /* @__PURE__ */ React60.createElement(
2920
+ return /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 1 }, /* @__PURE__ */ React58.createElement(
2818
2921
  TextDimensionInput,
2819
2922
  {
2820
2923
  label: "Column 1",
@@ -2823,7 +2926,7 @@ function ColumnWidthsInput({ defaultValue, onChange }) {
2823
2926
  setIndexValue(0, v);
2824
2927
  }
2825
2928
  }
2826
- ), /* @__PURE__ */ React60.createElement(
2929
+ ), /* @__PURE__ */ React58.createElement(
2827
2930
  TextDimensionInput,
2828
2931
  {
2829
2932
  label: "Column 2",
@@ -2848,7 +2951,7 @@ function ColumnsContainerPanel({ data, setData }) {
2848
2951
  setErrors(res.error);
2849
2952
  }
2850
2953
  };
2851
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Columns block" }, /* @__PURE__ */ React60.createElement(
2954
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Columns block" }, /* @__PURE__ */ React58.createElement(
2852
2955
  RadioGroupInput,
2853
2956
  {
2854
2957
  label: "Number of columns",
@@ -2857,9 +2960,9 @@ function ColumnsContainerPanel({ data, setData }) {
2857
2960
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { columnsCount: v === "2" ? 2 : 3 }) }));
2858
2961
  }
2859
2962
  },
2860
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "2" }, "2"),
2861
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "3" }, "3")
2862
- ), /* @__PURE__ */ React60.createElement(
2963
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "2" }, "2"),
2964
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "3" }, "3")
2965
+ ), /* @__PURE__ */ React58.createElement(
2863
2966
  ColumnWidthsInput,
2864
2967
  {
2865
2968
  defaultValue: (_b = data.props) == null ? void 0 : _b.fixedWidths,
@@ -2867,11 +2970,11 @@ function ColumnsContainerPanel({ data, setData }) {
2867
2970
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { fixedWidths }) }));
2868
2971
  }
2869
2972
  }
2870
- ), /* @__PURE__ */ React60.createElement(
2973
+ ), /* @__PURE__ */ React58.createElement(
2871
2974
  SliderInput,
2872
2975
  {
2873
2976
  label: "Columns gap",
2874
- iconLabel: /* @__PURE__ */ React60.createElement(SpaceBarOutlined, { sx: { color: "text.secondary" } }),
2977
+ iconLabel: /* @__PURE__ */ React58.createElement(SpaceBarOutlined, { sx: { color: "text.secondary" } }),
2875
2978
  units: "px",
2876
2979
  step: 4,
2877
2980
  marks: true,
@@ -2880,7 +2983,7 @@ function ColumnsContainerPanel({ data, setData }) {
2880
2983
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.columnsGap) != null ? _d : 0,
2881
2984
  onChange: (columnsGap) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { columnsGap }) }))
2882
2985
  }
2883
- ), /* @__PURE__ */ React60.createElement(
2986
+ ), /* @__PURE__ */ React58.createElement(
2884
2987
  RadioGroupInput,
2885
2988
  {
2886
2989
  label: "Alignment",
@@ -2889,10 +2992,10 @@ function ColumnsContainerPanel({ data, setData }) {
2889
2992
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }));
2890
2993
  }
2891
2994
  },
2892
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "top" }, /* @__PURE__ */ React60.createElement(VerticalAlignTopOutlined, { fontSize: "small" })),
2893
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "middle" }, /* @__PURE__ */ React60.createElement(VerticalAlignCenterOutlined, { fontSize: "small" })),
2894
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "bottom" }, /* @__PURE__ */ React60.createElement(VerticalAlignBottomOutlined, { fontSize: "small" }))
2895
- ), /* @__PURE__ */ React60.createElement(
2995
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "top" }, /* @__PURE__ */ React58.createElement(VerticalAlignTopOutlined, { fontSize: "small" })),
2996
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "middle" }, /* @__PURE__ */ React58.createElement(VerticalAlignCenterOutlined, { fontSize: "small" })),
2997
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "bottom" }, /* @__PURE__ */ React58.createElement(VerticalAlignBottomOutlined, { fontSize: "small" }))
2998
+ ), /* @__PURE__ */ React58.createElement(
2896
2999
  MultiStylePropertyPanel,
2897
3000
  {
2898
3001
  names: ["backgroundColor", "padding"],
@@ -2921,7 +3024,7 @@ function ContainerSidebarPanel({ data, setData }) {
2921
3024
  setErrors(res.error);
2922
3025
  }
2923
3026
  };
2924
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Container block" }, /* @__PURE__ */ React60.createElement(
3027
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Container block" }, /* @__PURE__ */ React58.createElement(
2925
3028
  MultiStylePropertyPanel,
2926
3029
  {
2927
3030
  names: ["backgroundColor", "borderColor", "borderRadius", "padding"],
@@ -2944,18 +3047,18 @@ function DividerSidebarPanel({ data, setData }) {
2944
3047
  };
2945
3048
  const lineColor = (_b = (_a = data.props) == null ? void 0 : _a.lineColor) != null ? _b : DividerPropsDefaults.lineColor;
2946
3049
  const lineHeight = (_d = (_c = data.props) == null ? void 0 : _c.lineHeight) != null ? _d : DividerPropsDefaults.lineHeight;
2947
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Divider block" }, /* @__PURE__ */ React60.createElement(
3050
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Divider block" }, /* @__PURE__ */ React58.createElement(
2948
3051
  ColorInput2,
2949
3052
  {
2950
3053
  label: "Color",
2951
3054
  defaultValue: lineColor,
2952
3055
  onChange: (lineColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { lineColor: lineColor2 }) }))
2953
3056
  }
2954
- ), /* @__PURE__ */ React60.createElement(
3057
+ ), /* @__PURE__ */ React58.createElement(
2955
3058
  SliderInput,
2956
3059
  {
2957
3060
  label: "Height",
2958
- iconLabel: /* @__PURE__ */ React60.createElement(HeightOutlined, { sx: { color: "text.secondary" } }),
3061
+ iconLabel: /* @__PURE__ */ React58.createElement(HeightOutlined, { sx: { color: "text.secondary" } }),
2959
3062
  units: "px",
2960
3063
  step: 1,
2961
3064
  min: 1,
@@ -2963,7 +3066,7 @@ function DividerSidebarPanel({ data, setData }) {
2963
3066
  defaultValue: lineHeight,
2964
3067
  onChange: (lineHeight2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { lineHeight: lineHeight2 }) }))
2965
3068
  }
2966
- ), /* @__PURE__ */ React60.createElement(
3069
+ ), /* @__PURE__ */ React58.createElement(
2967
3070
  MultiStylePropertyPanel,
2968
3071
  {
2969
3072
  names: ["backgroundColor", "padding"],
@@ -2986,7 +3089,8 @@ var FONT_FAMILY_SCHEMA7 = z.enum([
2986
3089
  ]).nullable().optional();
2987
3090
  var TemplateVariableSchema2 = z.object({
2988
3091
  name: z.string(),
2989
- description: z.string().optional().nullable()
3092
+ description: z.string().optional().nullable(),
3093
+ sampleValue: z.string().optional().nullable()
2990
3094
  });
2991
3095
  var EmailLayoutPropsSchema2 = z.object({
2992
3096
  backdropColor: COLOR_SCHEMA10,
@@ -3006,11 +3110,11 @@ function BooleanInput({ label, defaultValue, onChange }) {
3006
3110
  useEffect(() => {
3007
3111
  setValue(defaultValue);
3008
3112
  }, [defaultValue]);
3009
- return /* @__PURE__ */ React60.createElement(
3113
+ return /* @__PURE__ */ React58.createElement(
3010
3114
  FormControlLabel,
3011
3115
  {
3012
3116
  label,
3013
- control: /* @__PURE__ */ React60.createElement(
3117
+ control: /* @__PURE__ */ React58.createElement(
3014
3118
  Switch,
3015
3119
  {
3016
3120
  checked: value,
@@ -3038,38 +3142,38 @@ function EmailLayoutSidebarFields({ data, setData }) {
3038
3142
  }
3039
3143
  };
3040
3144
  const backdropDisabled = (_a = data.backdropDisabled) != null ? _a : false;
3041
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Global" }, /* @__PURE__ */ React60.createElement(
3145
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Global" }, /* @__PURE__ */ React58.createElement(
3042
3146
  BooleanInput,
3043
3147
  {
3044
3148
  label: "Disable backdrop",
3045
3149
  defaultValue: backdropDisabled,
3046
3150
  onChange: (backdropDisabled2) => updateData(__spreadProps(__spreadValues({}, data), { backdropDisabled: backdropDisabled2 }))
3047
3151
  }
3048
- ), !backdropDisabled && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
3152
+ ), !backdropDisabled && /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
3049
3153
  ColorInput2,
3050
3154
  {
3051
3155
  label: "Backdrop color",
3052
3156
  defaultValue: (_b = data.backdropColor) != null ? _b : "#F5F5F5",
3053
3157
  onChange: (backdropColor) => updateData(__spreadProps(__spreadValues({}, data), { backdropColor }))
3054
3158
  }
3055
- ), /* @__PURE__ */ React60.createElement(
3159
+ ), /* @__PURE__ */ React58.createElement(
3056
3160
  ColorInput2,
3057
3161
  {
3058
3162
  label: "Canvas color",
3059
3163
  defaultValue: (_c = data.canvasColor) != null ? _c : "#FFFFFF",
3060
3164
  onChange: (canvasColor) => updateData(__spreadProps(__spreadValues({}, data), { canvasColor }))
3061
3165
  }
3062
- ), /* @__PURE__ */ React60.createElement(
3166
+ ), /* @__PURE__ */ React58.createElement(
3063
3167
  NullableColorInput,
3064
3168
  {
3065
3169
  label: "Canvas border color",
3066
3170
  defaultValue: (_d = data.borderColor) != null ? _d : null,
3067
3171
  onChange: (borderColor) => updateData(__spreadProps(__spreadValues({}, data), { borderColor }))
3068
3172
  }
3069
- ), /* @__PURE__ */ React60.createElement(
3173
+ ), /* @__PURE__ */ React58.createElement(
3070
3174
  SliderInput,
3071
3175
  {
3072
- iconLabel: /* @__PURE__ */ React60.createElement(RoundedCornerOutlined, null),
3176
+ iconLabel: /* @__PURE__ */ React58.createElement(RoundedCornerOutlined, null),
3073
3177
  units: "px",
3074
3178
  step: 4,
3075
3179
  marks: true,
@@ -3079,14 +3183,14 @@ function EmailLayoutSidebarFields({ data, setData }) {
3079
3183
  defaultValue: (_e = data.borderRadius) != null ? _e : 0,
3080
3184
  onChange: (borderRadius) => updateData(__spreadProps(__spreadValues({}, data), { borderRadius }))
3081
3185
  }
3082
- )), /* @__PURE__ */ React60.createElement(
3186
+ )), /* @__PURE__ */ React58.createElement(
3083
3187
  NullableFontFamily,
3084
3188
  {
3085
3189
  label: "Font family",
3086
3190
  defaultValue: "MODERN_SANS",
3087
3191
  onChange: (fontFamily) => updateData(__spreadProps(__spreadValues({}, data), { fontFamily }))
3088
3192
  }
3089
- ), /* @__PURE__ */ React60.createElement(
3193
+ ), /* @__PURE__ */ React58.createElement(
3090
3194
  ColorInput2,
3091
3195
  {
3092
3196
  label: "Text color",
@@ -3107,7 +3211,7 @@ function HeadingSidebarPanel({ data, setData }) {
3107
3211
  setErrors(res.error);
3108
3212
  }
3109
3213
  };
3110
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Heading block" }, /* @__PURE__ */ React60.createElement(
3214
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Heading block" }, /* @__PURE__ */ React58.createElement(
3111
3215
  TextInput,
3112
3216
  {
3113
3217
  label: "Content",
@@ -3117,7 +3221,7 @@ function HeadingSidebarPanel({ data, setData }) {
3117
3221
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text }) }));
3118
3222
  }
3119
3223
  }
3120
- ), /* @__PURE__ */ React60.createElement(
3224
+ ), /* @__PURE__ */ React58.createElement(
3121
3225
  RadioGroupInput,
3122
3226
  {
3123
3227
  label: "Level",
@@ -3126,13 +3230,22 @@ function HeadingSidebarPanel({ data, setData }) {
3126
3230
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { level }) }));
3127
3231
  }
3128
3232
  },
3129
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "h1" }, "H1"),
3130
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "h2" }, "H2"),
3131
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "h3" }, "H3")
3132
- ), /* @__PURE__ */ React60.createElement(
3233
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "h1" }, "H1"),
3234
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "h2" }, "H2"),
3235
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "h3" }, "H3")
3236
+ ), /* @__PURE__ */ React58.createElement(
3133
3237
  MultiStylePropertyPanel,
3134
3238
  {
3135
- names: ["color", "backgroundColor", "fontFamily", "fontWeight", "textAlign", "padding"],
3239
+ names: [
3240
+ "color",
3241
+ "backgroundColor",
3242
+ "fontFamily",
3243
+ "fontWeight",
3244
+ "lineHeight",
3245
+ "letterSpacing",
3246
+ "textAlign",
3247
+ "padding"
3248
+ ],
3136
3249
  value: data.style,
3137
3250
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
3138
3251
  }
@@ -3150,7 +3263,7 @@ function HtmlSidebarPanel({ data, setData }) {
3150
3263
  setErrors(res.error);
3151
3264
  }
3152
3265
  };
3153
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Html block" }, /* @__PURE__ */ React60.createElement(
3266
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Html block" }, /* @__PURE__ */ React58.createElement(
3154
3267
  TextInput,
3155
3268
  {
3156
3269
  label: "Content",
@@ -3158,7 +3271,7 @@ function HtmlSidebarPanel({ data, setData }) {
3158
3271
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.contents) != null ? _b : "",
3159
3272
  onChange: (contents) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contents }) }))
3160
3273
  }
3161
- ), /* @__PURE__ */ React60.createElement(
3274
+ ), /* @__PURE__ */ React58.createElement(
3162
3275
  MultiStylePropertyPanel,
3163
3276
  {
3164
3277
  names: ["color", "backgroundColor", "fontFamily", "fontSize", "textAlign", "padding"],
@@ -3167,9 +3280,160 @@ function HtmlSidebarPanel({ data, setData }) {
3167
3280
  }
3168
3281
  ));
3169
3282
  }
3283
+ function ImageLibraryDialog({ open, onClose, onPick }) {
3284
+ const { loadImages, deleteImage } = useImageCallbacks();
3285
+ const [images, setImages] = useState(null);
3286
+ const [error, setError] = useState(null);
3287
+ const [query, setQuery] = useState("");
3288
+ const [busy, setBusy] = useState(false);
3289
+ const refresh = () => __async(null, null, function* () {
3290
+ if (!loadImages) return;
3291
+ setBusy(true);
3292
+ setError(null);
3293
+ try {
3294
+ const list = yield loadImages();
3295
+ setImages(list);
3296
+ } catch (e) {
3297
+ setError(e instanceof Error ? e.message : "Failed to load images");
3298
+ } finally {
3299
+ setBusy(false);
3300
+ }
3301
+ });
3302
+ useEffect(() => {
3303
+ if (open) {
3304
+ setQuery("");
3305
+ void refresh();
3306
+ }
3307
+ }, [open]);
3308
+ const filtered = useMemo(() => {
3309
+ if (!images) return null;
3310
+ const q = query.trim().toLowerCase();
3311
+ if (!q) return images;
3312
+ return images.filter((img) => {
3313
+ var _a;
3314
+ const haystack = `${(_a = img.alt) != null ? _a : ""} ${img.url}`.toLowerCase();
3315
+ return haystack.includes(q);
3316
+ });
3317
+ }, [images, query]);
3318
+ const handleDelete = (url) => __async(null, null, function* () {
3319
+ if (!deleteImage) return;
3320
+ const ok = window.confirm("Delete this image from the library?");
3321
+ if (!ok) return;
3322
+ setBusy(true);
3323
+ try {
3324
+ yield deleteImage(url);
3325
+ yield refresh();
3326
+ } catch (e) {
3327
+ setError(e instanceof Error ? e.message : "Failed to delete image");
3328
+ setBusy(false);
3329
+ }
3330
+ });
3331
+ return /* @__PURE__ */ React58.createElement(Dialog, { open, onClose, maxWidth: "md", fullWidth: true }, /* @__PURE__ */ React58.createElement(DialogTitle, null, "Image library"), /* @__PURE__ */ React58.createElement(DialogContent, { dividers: true }, /* @__PURE__ */ React58.createElement(
3332
+ TextField,
3333
+ {
3334
+ fullWidth: true,
3335
+ size: "small",
3336
+ placeholder: "Search by alt text or URL",
3337
+ value: query,
3338
+ onChange: (e) => setQuery(e.target.value),
3339
+ autoFocus: true,
3340
+ InputProps: {
3341
+ startAdornment: /* @__PURE__ */ React58.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React58.createElement(SearchOutlined, { fontSize: "small" }))
3342
+ },
3343
+ sx: { mb: 2 }
3344
+ }
3345
+ ), error && /* @__PURE__ */ React58.createElement(Alert, { severity: "error", sx: { mb: 2 } }, error), busy && !images && /* @__PURE__ */ React58.createElement(Stack, { alignItems: "center", sx: { py: 4 } }, /* @__PURE__ */ React58.createElement(CircularProgress, { size: 28 })), filtered && filtered.length === 0 && /* @__PURE__ */ React58.createElement(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.createElement(
3346
+ Box,
3347
+ {
3348
+ sx: {
3349
+ display: "grid",
3350
+ gridTemplateColumns: "repeat(auto-fill, minmax(140px, 1fr))",
3351
+ gap: 1.5
3352
+ }
3353
+ },
3354
+ filtered.map((img) => /* @__PURE__ */ React58.createElement(
3355
+ ImageTile,
3356
+ {
3357
+ key: img.url,
3358
+ image: img,
3359
+ onPick: () => onPick(img),
3360
+ onDelete: deleteImage ? () => handleDelete(img.url) : void 0
3361
+ }
3362
+ ))
3363
+ )), /* @__PURE__ */ React58.createElement(DialogActions, null, /* @__PURE__ */ React58.createElement(Button$1, { onClick: onClose }, "Close")));
3364
+ }
3365
+ function ImageTile({
3366
+ image,
3367
+ onPick,
3368
+ onDelete
3369
+ }) {
3370
+ var _a, _b;
3371
+ const src = (_a = image.thumbnailUrl) != null ? _a : image.url;
3372
+ const label = image.alt || image.url.split("/").pop() || "image";
3373
+ return /* @__PURE__ */ React58.createElement(
3374
+ Box,
3375
+ {
3376
+ sx: {
3377
+ position: "relative",
3378
+ borderRadius: 1,
3379
+ border: 1,
3380
+ borderColor: "divider",
3381
+ overflow: "hidden",
3382
+ cursor: "pointer",
3383
+ transition: "border-color 120ms",
3384
+ "&:hover": { borderColor: "primary.main" },
3385
+ "&:hover .delete-btn": { opacity: 1 }
3386
+ },
3387
+ onClick: onPick
3388
+ },
3389
+ /* @__PURE__ */ React58.createElement(
3390
+ Box,
3391
+ {
3392
+ component: "img",
3393
+ src,
3394
+ alt: (_b = image.alt) != null ? _b : "",
3395
+ sx: { display: "block", width: "100%", aspectRatio: "1 / 1", objectFit: "cover", backgroundColor: "#f5f5f5" }
3396
+ }
3397
+ ),
3398
+ /* @__PURE__ */ React58.createElement(Box, { sx: { p: 0.75, fontSize: 11, color: "text.secondary", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, label),
3399
+ onDelete && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Delete from library" }, /* @__PURE__ */ React58.createElement(
3400
+ IconButton,
3401
+ {
3402
+ size: "small",
3403
+ className: "delete-btn",
3404
+ onClick: (e) => {
3405
+ e.stopPropagation();
3406
+ onDelete();
3407
+ },
3408
+ sx: {
3409
+ position: "absolute",
3410
+ top: 4,
3411
+ right: 4,
3412
+ opacity: 0,
3413
+ backgroundColor: "rgba(255,255,255,0.85)",
3414
+ transition: "opacity 120ms",
3415
+ "&:hover": { backgroundColor: "rgba(255,255,255,0.95)" }
3416
+ },
3417
+ "aria-label": "Delete image"
3418
+ },
3419
+ /* @__PURE__ */ React58.createElement(DeleteOutline, { fontSize: "small" })
3420
+ ))
3421
+ );
3422
+ }
3423
+
3424
+ // src/app/inspector-drawer/configuration-panel/input-panels/image-sidebar-panel.tsx
3425
+ function isHttpUrl(value) {
3426
+ if (!value) return false;
3427
+ return /^http:\/\//i.test(value.trim());
3428
+ }
3170
3429
  function ImageSidebarPanel({ data, setData }) {
3171
3430
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
3172
3431
  const [, setErrors] = useState(null);
3432
+ const { uploadImage, loadImages } = useImageCallbacks();
3433
+ const fileInputRef = useRef(null);
3434
+ const [uploading, setUploading] = useState(false);
3435
+ const [uploadError, setUploadError] = useState(null);
3436
+ const [libraryOpen, setLibraryOpen] = useState(false);
3173
3437
  const updateData = (d) => {
3174
3438
  const res = ImagePropsSchema.safeParse(d);
3175
3439
  if (res.success) {
@@ -3179,24 +3443,88 @@ function ImageSidebarPanel({ data, setData }) {
3179
3443
  setErrors(res.error);
3180
3444
  }
3181
3445
  };
3182
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Image block" }, /* @__PURE__ */ React60.createElement(
3446
+ const applyUploadedImage = (uploaded) => {
3447
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2;
3448
+ updateData(__spreadProps(__spreadValues({}, data), {
3449
+ props: __spreadProps(__spreadValues({}, data.props), {
3450
+ url: uploaded.url,
3451
+ width: (_c2 = (_b2 = uploaded.width) != null ? _b2 : (_a2 = data.props) == null ? void 0 : _a2.width) != null ? _c2 : null,
3452
+ height: (_f2 = (_e2 = uploaded.height) != null ? _e2 : (_d2 = data.props) == null ? void 0 : _d2.height) != null ? _f2 : null,
3453
+ alt: (_i2 = (_h2 = uploaded.alt) != null ? _h2 : (_g2 = data.props) == null ? void 0 : _g2.alt) != null ? _i2 : ""
3454
+ })
3455
+ }));
3456
+ };
3457
+ const handleFile = (file) => __async(null, null, function* () {
3458
+ if (!uploadImage) return;
3459
+ setUploading(true);
3460
+ setUploadError(null);
3461
+ try {
3462
+ const uploaded = yield uploadImage(file);
3463
+ applyUploadedImage(uploaded);
3464
+ } catch (e) {
3465
+ setUploadError(e instanceof Error ? e.message : "Upload failed");
3466
+ } finally {
3467
+ setUploading(false);
3468
+ }
3469
+ });
3470
+ const url = (_b = (_a = data.props) == null ? void 0 : _a.url) != null ? _b : "";
3471
+ const showHttpWarning = isHttpUrl(url);
3472
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Image block" }, (uploadImage || loadImages) && /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 1 }, uploadImage && /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
3473
+ Button$1,
3474
+ {
3475
+ fullWidth: true,
3476
+ variant: "outlined",
3477
+ size: "small",
3478
+ startIcon: uploading ? /* @__PURE__ */ React58.createElement(CircularProgress, { size: 14 }) : /* @__PURE__ */ React58.createElement(CloudUploadOutlined, { fontSize: "small" }),
3479
+ disabled: uploading,
3480
+ onClick: () => {
3481
+ var _a2;
3482
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
3483
+ }
3484
+ },
3485
+ uploading ? "Uploading\u2026" : "Upload"
3486
+ ), /* @__PURE__ */ React58.createElement(
3487
+ "input",
3488
+ {
3489
+ ref: fileInputRef,
3490
+ type: "file",
3491
+ accept: "image/*",
3492
+ hidden: true,
3493
+ onChange: (e) => __async(null, null, function* () {
3494
+ var _a2;
3495
+ const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
3496
+ e.target.value = "";
3497
+ if (file) yield handleFile(file);
3498
+ })
3499
+ }
3500
+ )), loadImages && /* @__PURE__ */ React58.createElement(
3501
+ Button$1,
3502
+ {
3503
+ fullWidth: true,
3504
+ variant: "outlined",
3505
+ size: "small",
3506
+ startIcon: /* @__PURE__ */ React58.createElement(CollectionsOutlined, { fontSize: "small" }),
3507
+ onClick: () => setLibraryOpen(true)
3508
+ },
3509
+ "Library"
3510
+ )), uploadError && /* @__PURE__ */ React58.createElement(Alert, { severity: "error", onClose: () => setUploadError(null), sx: { mt: 1 } }, uploadError), /* @__PURE__ */ React58.createElement(
3183
3511
  TextInput,
3184
3512
  {
3185
3513
  label: "Source URL",
3186
- defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.url) != null ? _b : "",
3514
+ defaultValue: url,
3187
3515
  onChange: (v) => {
3188
- const url = v.trim().length === 0 ? null : v.trim();
3189
- updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url }) }));
3516
+ const next = v.trim().length === 0 ? null : v.trim();
3517
+ updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: next }) }));
3190
3518
  }
3191
3519
  }
3192
- ), /* @__PURE__ */ React60.createElement(
3520
+ ), showHttpWarning && /* @__PURE__ */ React58.createElement(Box, { sx: { mt: -1, mb: 1, display: "flex", alignItems: "flex-start", gap: 0.75 } }, /* @__PURE__ */ React58.createElement(ErrorOutlineOutlined, { fontSize: "small", sx: { color: "warning.main", mt: "2px" } }), /* @__PURE__ */ React58.createElement(Box, { sx: { fontSize: 12, color: "warning.dark" } }, "Non-HTTPS URL: Gmail and other clients strip mixed content. Use https:// for reliable delivery.")), /* @__PURE__ */ React58.createElement(
3193
3521
  TextInput,
3194
3522
  {
3195
3523
  label: "Alt text",
3196
3524
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.alt) != null ? _d : "",
3197
3525
  onChange: (alt) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt }) }))
3198
3526
  }
3199
- ), /* @__PURE__ */ React60.createElement(
3527
+ ), /* @__PURE__ */ React58.createElement(
3200
3528
  TextInput,
3201
3529
  {
3202
3530
  label: "Click through URL",
@@ -3206,37 +3534,47 @@ function ImageSidebarPanel({ data, setData }) {
3206
3534
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { linkHref }) }));
3207
3535
  }
3208
3536
  }
3209
- ), /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React60.createElement(
3537
+ ), /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React58.createElement(
3210
3538
  TextDimensionInput,
3211
3539
  {
3212
3540
  label: "Width",
3213
3541
  defaultValue: (_g = data.props) == null ? void 0 : _g.width,
3214
3542
  onChange: (width) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { width }) }))
3215
3543
  }
3216
- ), /* @__PURE__ */ React60.createElement(
3544
+ ), /* @__PURE__ */ React58.createElement(
3217
3545
  TextDimensionInput,
3218
3546
  {
3219
3547
  label: "Height",
3220
3548
  defaultValue: (_h = data.props) == null ? void 0 : _h.height,
3221
3549
  onChange: (height) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { height }) }))
3222
3550
  }
3223
- )), /* @__PURE__ */ React60.createElement(
3551
+ )), /* @__PURE__ */ React58.createElement(
3224
3552
  RadioGroupInput,
3225
3553
  {
3226
3554
  label: "Alignment",
3227
3555
  defaultValue: (_j = (_i = data.props) == null ? void 0 : _i.contentAlignment) != null ? _j : "middle",
3228
3556
  onChange: (contentAlignment) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }))
3229
3557
  },
3230
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "top" }, /* @__PURE__ */ React60.createElement(VerticalAlignTopOutlined, { fontSize: "small" })),
3231
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "middle" }, /* @__PURE__ */ React60.createElement(VerticalAlignCenterOutlined, { fontSize: "small" })),
3232
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "bottom" }, /* @__PURE__ */ React60.createElement(VerticalAlignBottomOutlined, { fontSize: "small" }))
3233
- ), /* @__PURE__ */ React60.createElement(
3558
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "top" }, /* @__PURE__ */ React58.createElement(VerticalAlignTopOutlined, { fontSize: "small" })),
3559
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "middle" }, /* @__PURE__ */ React58.createElement(VerticalAlignCenterOutlined, { fontSize: "small" })),
3560
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "bottom" }, /* @__PURE__ */ React58.createElement(VerticalAlignBottomOutlined, { fontSize: "small" }))
3561
+ ), /* @__PURE__ */ React58.createElement(
3234
3562
  MultiStylePropertyPanel,
3235
3563
  {
3236
3564
  names: ["backgroundColor", "textAlign", "padding"],
3237
3565
  value: data.style,
3238
3566
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
3239
3567
  }
3568
+ ), loadImages && /* @__PURE__ */ React58.createElement(
3569
+ ImageLibraryDialog,
3570
+ {
3571
+ open: libraryOpen,
3572
+ onClose: () => setLibraryOpen(false),
3573
+ onPick: (image) => {
3574
+ applyUploadedImage(image);
3575
+ setLibraryOpen(false);
3576
+ }
3577
+ }
3240
3578
  ));
3241
3579
  }
3242
3580
  function SignatureSidebarPanel({ data, setData }) {
@@ -3266,74 +3604,74 @@ function SignatureSidebarPanel({ data, setData }) {
3266
3604
  const nameColor = (_z = (_y = data.props) == null ? void 0 : _y.nameColor) != null ? _z : SignaturePropsDefaults.nameColor;
3267
3605
  const textColor = (_B = (_A = data.props) == null ? void 0 : _A.textColor) != null ? _B : SignaturePropsDefaults.textColor;
3268
3606
  const linkColor = (_D = (_C = data.props) == null ? void 0 : _C.linkColor) != null ? _D : SignaturePropsDefaults.linkColor;
3269
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Signature block" }, /* @__PURE__ */ React60.createElement(
3607
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Signature block" }, /* @__PURE__ */ React58.createElement(
3270
3608
  TextInput,
3271
3609
  {
3272
3610
  label: "Greeting",
3273
3611
  defaultValue: greeting,
3274
3612
  onChange: (greeting2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { greeting: greeting2 }) }))
3275
3613
  }
3276
- ), /* @__PURE__ */ React60.createElement(
3614
+ ), /* @__PURE__ */ React58.createElement(
3277
3615
  TextInput,
3278
3616
  {
3279
3617
  label: "Name",
3280
3618
  defaultValue: name,
3281
3619
  onChange: (name2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { name: name2 }) }))
3282
3620
  }
3283
- ), /* @__PURE__ */ React60.createElement(
3621
+ ), /* @__PURE__ */ React58.createElement(
3284
3622
  TextInput,
3285
3623
  {
3286
3624
  label: "Title",
3287
3625
  defaultValue: title,
3288
3626
  onChange: (title2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { title: title2 }) }))
3289
3627
  }
3290
- ), /* @__PURE__ */ React60.createElement(
3628
+ ), /* @__PURE__ */ React58.createElement(
3291
3629
  TextInput,
3292
3630
  {
3293
3631
  label: "Company",
3294
3632
  defaultValue: company,
3295
3633
  onChange: (company2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { company: company2 }) }))
3296
3634
  }
3297
- ), /* @__PURE__ */ React60.createElement(
3635
+ ), /* @__PURE__ */ React58.createElement(
3298
3636
  TextInput,
3299
3637
  {
3300
3638
  label: "Address",
3301
3639
  defaultValue: address,
3302
3640
  onChange: (address2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { address: address2 }) }))
3303
3641
  }
3304
- ), /* @__PURE__ */ React60.createElement(
3642
+ ), /* @__PURE__ */ React58.createElement(
3305
3643
  TextInput,
3306
3644
  {
3307
3645
  label: "Email",
3308
3646
  defaultValue: email,
3309
3647
  onChange: (email2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { email: email2 }) }))
3310
3648
  }
3311
- ), /* @__PURE__ */ React60.createElement(
3649
+ ), /* @__PURE__ */ React58.createElement(
3312
3650
  TextInput,
3313
3651
  {
3314
3652
  label: "Phone",
3315
3653
  defaultValue: phone,
3316
3654
  onChange: (phone2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { phone: phone2 }) }))
3317
3655
  }
3318
- ), /* @__PURE__ */ React60.createElement(
3656
+ ), /* @__PURE__ */ React58.createElement(
3319
3657
  TextInput,
3320
3658
  {
3321
3659
  label: "Website",
3322
3660
  defaultValue: website,
3323
3661
  onChange: (website2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { website: website2 }) }))
3324
3662
  }
3325
- ), /* @__PURE__ */ React60.createElement(
3663
+ ), /* @__PURE__ */ React58.createElement(
3326
3664
  TextInput,
3327
3665
  {
3328
3666
  label: "Image URL",
3329
3667
  defaultValue: imageUrl,
3330
3668
  onChange: (imageUrl2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }))
3331
3669
  }
3332
- ), /* @__PURE__ */ React60.createElement(
3670
+ ), /* @__PURE__ */ React58.createElement(
3333
3671
  SliderInput,
3334
3672
  {
3335
3673
  label: "Image size",
3336
- iconLabel: /* @__PURE__ */ React60.createElement(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
3674
+ iconLabel: /* @__PURE__ */ React58.createElement(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
3337
3675
  units: "px",
3338
3676
  step: 4,
3339
3677
  min: 32,
@@ -3341,47 +3679,47 @@ function SignatureSidebarPanel({ data, setData }) {
3341
3679
  defaultValue: imageSize,
3342
3680
  onChange: (imageSize2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageSize: imageSize2 }) }))
3343
3681
  }
3344
- ), /* @__PURE__ */ React60.createElement(
3682
+ ), /* @__PURE__ */ React58.createElement(
3345
3683
  RadioGroupInput,
3346
3684
  {
3347
3685
  label: "Image shape",
3348
3686
  defaultValue: imageShape,
3349
3687
  onChange: (imageShape2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageShape: imageShape2 }) }))
3350
3688
  },
3351
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "circle" }, "Circle"),
3352
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "square" }, "Square"),
3353
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "rounded" }, "Rounded")
3354
- ), /* @__PURE__ */ React60.createElement(
3689
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "circle" }, "Circle"),
3690
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "square" }, "Square"),
3691
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "rounded" }, "Rounded")
3692
+ ), /* @__PURE__ */ React58.createElement(
3355
3693
  RadioGroupInput,
3356
3694
  {
3357
3695
  label: "Layout",
3358
3696
  defaultValue: layout,
3359
3697
  onChange: (layout2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { layout: layout2 }) }))
3360
3698
  },
3361
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "horizontal" }, "Horizontal"),
3362
- /* @__PURE__ */ React60.createElement(ToggleButton, { value: "vertical" }, "Vertical")
3363
- ), /* @__PURE__ */ React60.createElement(
3699
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "horizontal" }, "Horizontal"),
3700
+ /* @__PURE__ */ React58.createElement(ToggleButton, { value: "vertical" }, "Vertical")
3701
+ ), /* @__PURE__ */ React58.createElement(
3364
3702
  ColorInput2,
3365
3703
  {
3366
3704
  label: "Name color",
3367
3705
  defaultValue: nameColor,
3368
3706
  onChange: (nameColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { nameColor: nameColor2 }) }))
3369
3707
  }
3370
- ), /* @__PURE__ */ React60.createElement(
3708
+ ), /* @__PURE__ */ React58.createElement(
3371
3709
  ColorInput2,
3372
3710
  {
3373
3711
  label: "Text color",
3374
3712
  defaultValue: textColor,
3375
3713
  onChange: (textColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { textColor: textColor2 }) }))
3376
3714
  }
3377
- ), /* @__PURE__ */ React60.createElement(
3715
+ ), /* @__PURE__ */ React58.createElement(
3378
3716
  ColorInput2,
3379
3717
  {
3380
3718
  label: "Link color",
3381
3719
  defaultValue: linkColor,
3382
3720
  onChange: (linkColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { linkColor: linkColor2 }) }))
3383
3721
  }
3384
- ), /* @__PURE__ */ React60.createElement(
3722
+ ), /* @__PURE__ */ React58.createElement(
3385
3723
  MultiStylePropertyPanel,
3386
3724
  {
3387
3725
  names: ["backgroundColor", "fontFamily", "padding"],
@@ -3402,11 +3740,11 @@ function SpacerSidebarPanel({ data, setData }) {
3402
3740
  setErrors(res.error);
3403
3741
  }
3404
3742
  };
3405
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Spacer block" }, /* @__PURE__ */ React60.createElement(
3743
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Spacer block" }, /* @__PURE__ */ React58.createElement(
3406
3744
  SliderInput,
3407
3745
  {
3408
3746
  label: "Height",
3409
- iconLabel: /* @__PURE__ */ React60.createElement(HeightOutlined, { sx: { color: "text.secondary" } }),
3747
+ iconLabel: /* @__PURE__ */ React58.createElement(HeightOutlined, { sx: { color: "text.secondary" } }),
3410
3748
  units: "px",
3411
3749
  step: 4,
3412
3750
  min: 4,
@@ -3428,7 +3766,7 @@ function TextSidebarPanel({ data, setData }) {
3428
3766
  setErrors(res.error);
3429
3767
  }
3430
3768
  };
3431
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Text block" }, /* @__PURE__ */ React60.createElement(
3769
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Text block" }, /* @__PURE__ */ React58.createElement(
3432
3770
  TextInput,
3433
3771
  {
3434
3772
  label: "Content",
@@ -3436,17 +3774,27 @@ function TextSidebarPanel({ data, setData }) {
3436
3774
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.text) != null ? _b : "",
3437
3775
  onChange: (text) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text }) }))
3438
3776
  }
3439
- ), /* @__PURE__ */ React60.createElement(
3777
+ ), /* @__PURE__ */ React58.createElement(
3440
3778
  BooleanInput,
3441
3779
  {
3442
3780
  label: "Markdown",
3443
3781
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.markdown) != null ? _d : false,
3444
3782
  onChange: (markdown) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { markdown }) }))
3445
3783
  }
3446
- ), /* @__PURE__ */ React60.createElement(
3784
+ ), /* @__PURE__ */ React58.createElement(
3447
3785
  MultiStylePropertyPanel,
3448
3786
  {
3449
- names: ["color", "backgroundColor", "fontFamily", "fontSize", "fontWeight", "textAlign", "padding"],
3787
+ names: [
3788
+ "color",
3789
+ "backgroundColor",
3790
+ "fontFamily",
3791
+ "fontSize",
3792
+ "fontWeight",
3793
+ "lineHeight",
3794
+ "letterSpacing",
3795
+ "textAlign",
3796
+ "padding"
3797
+ ],
3450
3798
  value: data.style,
3451
3799
  onChange: (style) => updateData(__spreadProps(__spreadValues({}, data), { style }))
3452
3800
  }
@@ -3455,7 +3803,7 @@ function TextSidebarPanel({ data, setData }) {
3455
3803
 
3456
3804
  // src/app/inspector-drawer/configuration-panel/index.tsx
3457
3805
  function renderMessage(val) {
3458
- return /* @__PURE__ */ React60.createElement(Box, { sx: { m: 3, p: 1, border: "1px dashed", borderColor: "divider" } }, /* @__PURE__ */ React60.createElement(Typography, { color: "text.secondary" }, val));
3806
+ return /* @__PURE__ */ React58.createElement(Box, { sx: { m: 3, p: 1, border: "1px dashed", borderColor: "divider" } }, /* @__PURE__ */ React58.createElement(Typography, { color: "text.secondary" }, val));
3459
3807
  }
3460
3808
  function ConfigurationPanel() {
3461
3809
  const document2 = useDocument();
@@ -3471,55 +3819,55 @@ function ConfigurationPanel() {
3471
3819
  const { data, type } = block;
3472
3820
  switch (type) {
3473
3821
  case "Avatar":
3474
- return /* @__PURE__ */ React60.createElement(AvatarSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3822
+ return /* @__PURE__ */ React58.createElement(AvatarSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3475
3823
  case "Button":
3476
- return /* @__PURE__ */ React60.createElement(ButtonSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3824
+ return /* @__PURE__ */ React58.createElement(ButtonSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3477
3825
  case "ColumnsContainer":
3478
- return /* @__PURE__ */ React60.createElement(ColumnsContainerPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3826
+ return /* @__PURE__ */ React58.createElement(ColumnsContainerPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3479
3827
  case "Container":
3480
- return /* @__PURE__ */ React60.createElement(ContainerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3828
+ return /* @__PURE__ */ React58.createElement(ContainerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3481
3829
  case "Divider":
3482
- return /* @__PURE__ */ React60.createElement(DividerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3830
+ return /* @__PURE__ */ React58.createElement(DividerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3483
3831
  case "Heading":
3484
- return /* @__PURE__ */ React60.createElement(HeadingSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3832
+ return /* @__PURE__ */ React58.createElement(HeadingSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3485
3833
  case "Html":
3486
- return /* @__PURE__ */ React60.createElement(HtmlSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3834
+ return /* @__PURE__ */ React58.createElement(HtmlSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3487
3835
  case "Image":
3488
- return /* @__PURE__ */ React60.createElement(ImageSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3836
+ return /* @__PURE__ */ React58.createElement(ImageSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3489
3837
  case "EmailLayout":
3490
- return /* @__PURE__ */ React60.createElement(EmailLayoutSidebarFields, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3838
+ return /* @__PURE__ */ React58.createElement(EmailLayoutSidebarFields, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3491
3839
  case "Spacer":
3492
- return /* @__PURE__ */ React60.createElement(SpacerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3840
+ return /* @__PURE__ */ React58.createElement(SpacerSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3493
3841
  case "Signature":
3494
- return /* @__PURE__ */ React60.createElement(SignatureSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3842
+ return /* @__PURE__ */ React58.createElement(SignatureSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3495
3843
  case "Text":
3496
- return /* @__PURE__ */ React60.createElement(TextSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3844
+ return /* @__PURE__ */ React58.createElement(TextSidebarPanel, { key: selectedBlockId, data, setData: (data2) => setBlock({ type, data: data2 }) });
3497
3845
  default:
3498
- return /* @__PURE__ */ React60.createElement("pre", null, JSON.stringify(block, null, " "));
3846
+ return /* @__PURE__ */ React58.createElement("pre", null, JSON.stringify(block, null, " "));
3499
3847
  }
3500
3848
  }
3501
3849
  function StylesPanel() {
3502
3850
  const block = useDocument().root;
3503
3851
  if (!block) {
3504
- return /* @__PURE__ */ React60.createElement("p", null, "Block not found");
3852
+ return /* @__PURE__ */ React58.createElement("p", null, "Block not found");
3505
3853
  }
3506
3854
  const { data, type } = block;
3507
3855
  if (type !== "EmailLayout") {
3508
3856
  throw new Error('Expected "root" element to be of type EmailLayout');
3509
3857
  }
3510
- return /* @__PURE__ */ React60.createElement(EmailLayoutSidebarFields, { key: "root", data, setData: (data2) => setDocument({ root: { type, data: data2 } }) });
3858
+ return /* @__PURE__ */ React58.createElement(EmailLayoutSidebarFields, { key: "root", data, setData: (data2) => setDocument({ root: { type, data: data2 } }) });
3511
3859
  }
3512
3860
  function TemplateDownloadButton() {
3513
3861
  const doc = useDocument();
3514
3862
  const href = useMemo(() => {
3515
3863
  return `data:text/plain,${encodeURIComponent(JSON.stringify(doc, null, " "))}`;
3516
3864
  }, [doc]);
3517
- return /* @__PURE__ */ React60.createElement(
3865
+ return /* @__PURE__ */ React58.createElement(
3518
3866
  Button$1,
3519
3867
  {
3520
3868
  variant: "outlined",
3521
3869
  color: "primary",
3522
- startIcon: /* @__PURE__ */ React60.createElement(FileDownloadOutlined, null),
3870
+ startIcon: /* @__PURE__ */ React58.createElement(FileDownloadOutlined, null),
3523
3871
  href,
3524
3872
  download: "emailTemplate.json",
3525
3873
  fullWidth: true
@@ -3551,9 +3899,9 @@ function TemplatePanel({ deleteTemplate, copyTemplate }) {
3551
3899
  }
3552
3900
  };
3553
3901
  if (!currentTemplateId) {
3554
- return /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Template" }, "No template selected");
3902
+ return /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Template" }, "No template selected");
3555
3903
  }
3556
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Template" }, /* @__PURE__ */ React60.createElement(Stack, { spacing: 2 }, !persistenceEnabled && /* @__PURE__ */ React60.createElement(
3904
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Template" }, /* @__PURE__ */ React58.createElement(Stack, { spacing: 2 }, !persistenceEnabled && /* @__PURE__ */ React58.createElement(
3557
3905
  Typography,
3558
3906
  {
3559
3907
  variant: "body2",
@@ -3566,110 +3914,449 @@ function TemplatePanel({ deleteTemplate, copyTemplate }) {
3566
3914
  }
3567
3915
  },
3568
3916
  "Save functionality is disabled. To enable saving, provide the necessary callback functions."
3569
- ), persistenceEnabled && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
3917
+ ), persistenceEnabled && /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
3570
3918
  Button$1,
3571
3919
  {
3572
3920
  variant: "outlined",
3573
3921
  color: "primary",
3574
- startIcon: /* @__PURE__ */ React60.createElement(ContentCopyOutlined, null),
3922
+ startIcon: /* @__PURE__ */ React58.createElement(ContentCopyOutlined, null),
3575
3923
  onClick: handleCopyToSamples,
3576
3924
  fullWidth: true,
3577
3925
  disabled: !copyTemplate
3578
3926
  },
3579
3927
  "Save as Sample Template"
3580
- ), /* @__PURE__ */ React60.createElement(
3928
+ ), /* @__PURE__ */ React58.createElement(
3581
3929
  Button$1,
3582
3930
  {
3583
3931
  variant: "outlined",
3584
3932
  color: "error",
3585
- startIcon: /* @__PURE__ */ React60.createElement(DeleteOutlined, null),
3933
+ startIcon: /* @__PURE__ */ React58.createElement(DeleteOutlined, null),
3586
3934
  onClick: handleDelete,
3587
3935
  fullWidth: true,
3588
3936
  disabled: !deleteTemplate
3589
3937
  },
3590
3938
  "Delete Template"
3591
- )))), persistenceEnabled && /* @__PURE__ */ React60.createElement(BaseSidebarPanel, { title: "Export" }, /* @__PURE__ */ React60.createElement(Stack, { spacing: 2 }, /* @__PURE__ */ React60.createElement(TemplateDownloadButton, null))));
3939
+ )))), persistenceEnabled && /* @__PURE__ */ React58.createElement(BaseSidebarPanel, { title: "Export" }, /* @__PURE__ */ React58.createElement(Stack, { spacing: 2 }, /* @__PURE__ */ React58.createElement(TemplateDownloadButton, null))));
3592
3940
  }
3941
+
3942
+ // src/app/variables/variable-utils.ts
3593
3943
  var VARIABLE_NAME_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
3594
- function validateName(name, index, all) {
3595
- if (!name.trim()) return "Name is required";
3596
- if (!VARIABLE_NAME_RE.test(name)) return "Use letters, digits, underscore; start with a letter or underscore";
3597
- const duplicate = all.some((v, i) => i !== index && v.name === name);
3944
+ var MAX_VARIABLE_NAME_LENGTH = 64;
3945
+ var RESERVED_VARIABLE_NAMES = /* @__PURE__ */ new Set(["this", "true", "false", "null", "undefined"]);
3946
+ var HANDLEBARS_KEYWORDS = /* @__PURE__ */ new Set(["if", "each", "unless", "else", "with"]);
3947
+ function validateVariableName(name, siblings, indexBeingEdited) {
3948
+ const trimmed = name.trim();
3949
+ if (!trimmed) return "Name is required";
3950
+ if (trimmed.length > MAX_VARIABLE_NAME_LENGTH) return `Max ${MAX_VARIABLE_NAME_LENGTH} characters`;
3951
+ if (!VARIABLE_NAME_RE.test(trimmed)) return "Use letters, digits, underscore; start with a letter or underscore";
3952
+ if (RESERVED_VARIABLE_NAMES.has(trimmed)) return "Reserved word; pick another name";
3953
+ const duplicate = siblings.some((v, i) => i !== indexBeingEdited && v.name === trimmed);
3598
3954
  if (duplicate) return "Already declared";
3599
3955
  return null;
3600
3956
  }
3957
+ var TOKEN_ROOT_RE = /\{\{\s*(?:#(?:if|each|unless|with)\s+)?([a-zA-Z_][a-zA-Z0-9_]*)(?:\.[\w.]+)?\s*\}\}/g;
3958
+ function extractTokenRoots(text) {
3959
+ if (!text) return [];
3960
+ const roots = /* @__PURE__ */ new Set();
3961
+ for (const m of text.matchAll(TOKEN_ROOT_RE)) {
3962
+ const name = m[1];
3963
+ if (RESERVED_VARIABLE_NAMES.has(name) || HANDLEBARS_KEYWORDS.has(name)) continue;
3964
+ roots.add(name);
3965
+ }
3966
+ return [...roots];
3967
+ }
3968
+ function forEachTextFieldInDocument(doc, visit) {
3969
+ var _a, _b;
3970
+ const root = doc.root;
3971
+ if (root && root.type === "EmailLayout" && typeof ((_a = root.data) == null ? void 0 : _a.subject) === "string") {
3972
+ visit(root.data.subject);
3973
+ }
3974
+ for (const [id, block] of Object.entries(doc)) {
3975
+ if (id === "root" || !block || typeof block !== "object") continue;
3976
+ const type = block.type;
3977
+ const props = (_b = block.data) == null ? void 0 : _b.props;
3978
+ if (!props) continue;
3979
+ if ((type === "Text" || type === "Heading" || type === "Button") && typeof props.text === "string") {
3980
+ visit(props.text);
3981
+ } else if (type === "Html" && typeof props.contents === "string") {
3982
+ visit(props.contents);
3983
+ }
3984
+ }
3985
+ }
3986
+ function collectTokenUsage(doc) {
3987
+ const usage = /* @__PURE__ */ new Map();
3988
+ forEachTextFieldInDocument(doc, (value) => {
3989
+ var _a;
3990
+ for (const root of extractTokenRoots(value)) {
3991
+ usage.set(root, ((_a = usage.get(root)) != null ? _a : 0) + 1);
3992
+ }
3993
+ });
3994
+ return usage;
3995
+ }
3996
+ function escapeRegex(name) {
3997
+ return name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3998
+ }
3999
+ function buildRenameReplacers(oldName, newName) {
4000
+ const esc = escapeRegex(oldName);
4001
+ const simple = new RegExp(`\\{\\{\\s*${esc}(\\.[\\w.]+)?\\s*\\}\\}`, "g");
4002
+ const helper = new RegExp(`(\\{\\{\\s*#(?:if|each|unless|with)\\s+)${esc}(\\.[\\w.]+)?(\\s*\\}\\})`, "g");
4003
+ return (text) => text.replace(helper, `$1${newName}$2$3`).replace(simple, `{{${newName}$1}}`);
4004
+ }
4005
+ function buildRenamePatch(doc, oldName, newName) {
4006
+ var _a;
4007
+ if (oldName === newName) return {};
4008
+ const rewrite = buildRenameReplacers(oldName, newName);
4009
+ const patch = {};
4010
+ const root = doc.root;
4011
+ if (root && root.type === "EmailLayout") {
4012
+ const layoutData = root.data;
4013
+ const oldSubject = (_a = layoutData.subject) != null ? _a : "";
4014
+ const newSubject = rewrite(oldSubject);
4015
+ if (newSubject !== oldSubject) {
4016
+ patch.root = __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, layoutData), { subject: newSubject }) });
4017
+ }
4018
+ }
4019
+ for (const [id, block] of Object.entries(doc)) {
4020
+ if (id === "root" || !block || typeof block !== "object") continue;
4021
+ const type = block.type;
4022
+ const data = block.data;
4023
+ const props = data == null ? void 0 : data.props;
4024
+ if (!props) continue;
4025
+ if ((type === "Text" || type === "Heading" || type === "Button") && typeof props.text === "string") {
4026
+ const nextText = rewrite(props.text);
4027
+ if (nextText !== props.text) {
4028
+ patch[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { text: nextText }) }) });
4029
+ }
4030
+ } else if (type === "Html" && typeof props.contents === "string") {
4031
+ const nextContents = rewrite(props.contents);
4032
+ if (nextContents !== props.contents) {
4033
+ patch[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { contents: nextContents }) }) });
4034
+ }
4035
+ }
4036
+ }
4037
+ return patch;
4038
+ }
4039
+ function substituteSampleValues(text, samples) {
4040
+ if (!text) return text;
4041
+ let out = text;
4042
+ out = out.replace(
4043
+ /\{\{\s*#(?:if|each|unless|with)\s+[^}]*\}\}/g,
4044
+ ""
4045
+ );
4046
+ out = out.replace(/\{\{\s*\/(?:if|each|unless|with)\s*\}\}/g, "");
4047
+ out = out.replace(/\{\{\s*else\s*\}\}/g, "");
4048
+ out = out.replace(TOKEN_ROOT_RE, (match, root) => {
4049
+ var _a;
4050
+ if (!samples.has(root)) return match;
4051
+ return (_a = samples.get(root)) != null ? _a : "";
4052
+ });
4053
+ return out;
4054
+ }
4055
+ function buildSampleValueMap(variables) {
4056
+ const m = /* @__PURE__ */ new Map();
4057
+ if (!variables) return m;
4058
+ for (const v of variables) {
4059
+ if (v.name && typeof v.sampleValue === "string" && v.sampleValue.length > 0) {
4060
+ m.set(v.name, v.sampleValue);
4061
+ }
4062
+ }
4063
+ return m;
4064
+ }
4065
+ function applySampleValuesToDocument(doc, samples) {
4066
+ if (samples.size === 0) return doc;
4067
+ const next = __spreadValues({}, doc);
4068
+ const root = doc.root;
4069
+ if (root && root.type === "EmailLayout") {
4070
+ const layoutData = root.data;
4071
+ if (typeof layoutData.subject === "string") {
4072
+ const newSubject = substituteSampleValues(layoutData.subject, samples);
4073
+ if (newSubject !== layoutData.subject) {
4074
+ next.root = __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, layoutData), { subject: newSubject }) });
4075
+ }
4076
+ }
4077
+ }
4078
+ for (const [id, block] of Object.entries(doc)) {
4079
+ if (id === "root" || !block || typeof block !== "object") continue;
4080
+ const type = block.type;
4081
+ const data = block.data;
4082
+ const props = data == null ? void 0 : data.props;
4083
+ if (!props) continue;
4084
+ if ((type === "Text" || type === "Heading" || type === "Button") && typeof props.text === "string") {
4085
+ const newText = substituteSampleValues(props.text, samples);
4086
+ if (newText !== props.text) {
4087
+ next[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { text: newText }) }) });
4088
+ }
4089
+ } else if (type === "Html" && typeof props.contents === "string") {
4090
+ const newContents = substituteSampleValues(props.contents, samples);
4091
+ if (newContents !== props.contents) {
4092
+ next[id] = __spreadProps(__spreadValues({}, block), { data: __spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, props), { contents: newContents }) }) });
4093
+ }
4094
+ }
4095
+ }
4096
+ return next;
4097
+ }
4098
+
4099
+ // src/app/inspector-drawer/variables-panel.tsx
4100
+ function toPersistShape(v) {
4101
+ return {
4102
+ name: v.name,
4103
+ description: v.description ? v.description : void 0,
4104
+ sampleValue: v.sampleValue ? v.sampleValue : void 0
4105
+ };
4106
+ }
3601
4107
  function VariablesPanel() {
3602
4108
  var _a;
3603
4109
  const document2 = useDocument();
4110
+ const lastFocused = useLastFocusedEditable();
3604
4111
  const root = document2.root;
3605
4112
  if (!root || root.type !== "EmailLayout") {
3606
- return /* @__PURE__ */ React60.createElement(Box, { p: 2 }, /* @__PURE__ */ React60.createElement(Alert, { severity: "info" }, "Open a template to manage variables."));
4113
+ return /* @__PURE__ */ React58.createElement(Box, { p: 2 }, /* @__PURE__ */ React58.createElement(Alert, { severity: "info" }, "Open a template to manage variables."));
3607
4114
  }
3608
4115
  const data = root.data;
3609
4116
  const variables = ((_a = data.variables) != null ? _a : []).map((v) => {
3610
- var _a2;
4117
+ var _a2, _b;
3611
4118
  return {
3612
4119
  name: v.name,
3613
- description: (_a2 = v.description) != null ? _a2 : ""
4120
+ description: (_a2 = v.description) != null ? _a2 : "",
4121
+ sampleValue: (_b = v.sampleValue) != null ? _b : ""
3614
4122
  };
3615
4123
  });
3616
- const commit = (next) => {
3617
- setDocument({
3618
- root: __spreadProps(__spreadValues({}, root), {
3619
- data: __spreadProps(__spreadValues({}, data), {
3620
- variables: next.map((v) => ({
3621
- name: v.name,
3622
- description: v.description ? v.description : void 0
3623
- }))
3624
- })
4124
+ const usage = useMemo(() => collectTokenUsage(document2), [document2]);
4125
+ const declaredNames = useMemo(() => new Set(variables.map((v) => v.name)), [variables]);
4126
+ const undeclared = useMemo(
4127
+ () => [...usage.keys()].filter((n) => n && !declaredNames.has(n)),
4128
+ [usage, declaredNames]
4129
+ );
4130
+ const writeVariables = (next, extraPatch = {}) => {
4131
+ var _a2;
4132
+ const baseRoot = (_a2 = extraPatch.root) != null ? _a2 : root;
4133
+ const newRoot = __spreadProps(__spreadValues({}, baseRoot), {
4134
+ data: __spreadProps(__spreadValues({}, baseRoot.data), {
4135
+ variables: next.map(toPersistShape)
3625
4136
  })
3626
4137
  });
4138
+ setDocument(__spreadProps(__spreadValues({}, extraPatch), { root: newRoot }));
3627
4139
  };
3628
4140
  const updateAt = (index, patch) => {
3629
4141
  const next = variables.map((v, i) => i === index ? __spreadValues(__spreadValues({}, v), patch) : v);
3630
- commit(next);
4142
+ writeVariables(next);
3631
4143
  };
3632
4144
  const add = () => {
3633
- commit([...variables, { name: "", description: "" }]);
4145
+ writeVariables([...variables, { name: "", description: "", sampleValue: "" }]);
4146
+ };
4147
+ const addFromToken = (name) => {
4148
+ writeVariables([...variables, { name, description: "", sampleValue: "" }]);
3634
4149
  };
3635
4150
  const removeAt = (index) => {
3636
- commit(variables.filter((_, i) => i !== index));
4151
+ var _a2;
4152
+ const v = variables[index];
4153
+ const usageCount = v.name ? (_a2 = usage.get(v.name)) != null ? _a2 : 0 : 0;
4154
+ if (usageCount > 0) {
4155
+ const ok = window.confirm(
4156
+ `"${v.name}" is still referenced in the body (${usageCount} occurrence${usageCount === 1 ? "" : "s"}). Delete anyway?`
4157
+ );
4158
+ if (!ok) return;
4159
+ }
4160
+ writeVariables(variables.filter((_, i) => i !== index));
4161
+ };
4162
+ const commitRename = (index, newName) => {
4163
+ const oldName = variables[index].name;
4164
+ const trimmed = newName.trim();
4165
+ if (trimmed === oldName) return;
4166
+ const error = validateVariableName(trimmed, variables, index);
4167
+ if (error) return;
4168
+ const patch = oldName ? buildRenamePatch(document2, oldName, trimmed) : {};
4169
+ const next = variables.map((v, i) => i === index ? __spreadProps(__spreadValues({}, v), { name: trimmed }) : v);
4170
+ writeVariables(next, patch);
3637
4171
  };
3638
- return /* @__PURE__ */ React60.createElement(Box, { p: 2 }, /* @__PURE__ */ React60.createElement(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { mb: 1 } }, /* @__PURE__ */ React60.createElement(Typography, { variant: "subtitle1", sx: { fontWeight: 600 } }, "Variables"), /* @__PURE__ */ React60.createElement(Tooltip, { title: "Add variable" }, /* @__PURE__ */ React60.createElement(IconButton, { size: "small", onClick: add, "aria-label": "Add variable" }, /* @__PURE__ */ React60.createElement(AddOutlined, { fontSize: "small" })))), /* @__PURE__ */ React60.createElement(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.createElement(Box, { component: "code", sx: { fontFamily: "monospace" } }, "{{name}}"), "."), variables.length === 0 ? /* @__PURE__ */ React60.createElement(Typography, { variant: "body2", sx: { color: "text.secondary" } }, "No variables declared. Click + to add one.") : /* @__PURE__ */ React60.createElement(Stack, { spacing: 2 }, variables.map((v, i) => {
4172
+ const canInsert = Boolean(
4173
+ lastFocused && (lastFocused.field === "subject" || lastFocused.blockId && document2[lastFocused.blockId])
4174
+ );
4175
+ const insertIntoFocused = (name) => {
4176
+ var _a2, _b, _c;
4177
+ const focused = getLastFocusedEditable();
4178
+ if (!focused) return;
4179
+ const token = `{{${name}}}`;
4180
+ if (focused.field === "subject") {
4181
+ const layoutData = root.data;
4182
+ const current2 = (_a2 = layoutData.subject) != null ? _a2 : "";
4183
+ const next2 = current2.slice(0, focused.selectionStart) + token + current2.slice(focused.selectionEnd);
4184
+ setDocument({
4185
+ root: __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, layoutData), { subject: next2 }) })
4186
+ });
4187
+ return;
4188
+ }
4189
+ const block = document2[focused.blockId];
4190
+ if (!block) return;
4191
+ const blockData = block.data;
4192
+ const props = (_b = blockData == null ? void 0 : blockData.props) != null ? _b : {};
4193
+ const field = focused.field;
4194
+ const current = (_c = props[field]) != null ? _c : "";
4195
+ const next = current.slice(0, focused.selectionStart) + token + current.slice(focused.selectionEnd);
4196
+ setDocument({
4197
+ [focused.blockId]: __spreadProps(__spreadValues({}, block), {
4198
+ data: __spreadProps(__spreadValues({}, blockData), { props: __spreadProps(__spreadValues({}, props), { [field]: next }) })
4199
+ })
4200
+ });
4201
+ };
4202
+ const copy = (name) => __async(null, null, function* () {
4203
+ try {
4204
+ yield navigator.clipboard.writeText(`{{${name}}}`);
4205
+ } catch (e) {
4206
+ }
4207
+ });
4208
+ return /* @__PURE__ */ React58.createElement(Box, { p: 2 }, /* @__PURE__ */ React58.createElement(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { mb: 1 } }, /* @__PURE__ */ React58.createElement(Typography, { variant: "subtitle1", sx: { fontWeight: 600 } }, "Variables"), /* @__PURE__ */ React58.createElement(Tooltip, { title: "Add variable" }, /* @__PURE__ */ React58.createElement(IconButton, { size: "small", onClick: add, "aria-label": "Add variable" }, /* @__PURE__ */ React58.createElement(AddOutlined, { fontSize: "small" })))), /* @__PURE__ */ React58.createElement(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.createElement(Box, { component: "code", sx: { fontFamily: "monospace" } }, "{{name}}"), ". In Preview mode, tokens render with the sample values below."), undeclared.length > 0 && /* @__PURE__ */ React58.createElement(Alert, { severity: "warning", sx: { mb: 2 } }, /* @__PURE__ */ React58.createElement(AlertTitle, { sx: { fontSize: 13 } }, "Undeclared in body"), /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 0.5, useFlexGap: true, flexWrap: "wrap" }, undeclared.map((name) => /* @__PURE__ */ React58.createElement(
4209
+ Chip,
4210
+ {
4211
+ key: name,
4212
+ size: "small",
4213
+ label: name,
4214
+ onClick: () => addFromToken(name),
4215
+ onDelete: () => addFromToken(name),
4216
+ deleteIcon: /* @__PURE__ */ React58.createElement(AddOutlined, null),
4217
+ sx: { fontFamily: "monospace" }
4218
+ }
4219
+ ))), /* @__PURE__ */ React58.createElement(Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 0.5 } }, "Click a token to declare it.")), variables.length === 0 ? /* @__PURE__ */ React58.createElement(Typography, { variant: "body2", sx: { color: "text.secondary" } }, "No variables declared. Click + to add one.") : /* @__PURE__ */ React58.createElement(Stack, { spacing: 2 }, variables.map((v, i) => {
3639
4220
  var _a2;
3640
- const nameError = validateName(v.name, i, variables);
3641
- return /* @__PURE__ */ React60.createElement(Stack, { key: i, spacing: 0.75, sx: { pb: 1, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React60.createElement(
3642
- TextField,
4221
+ return /* @__PURE__ */ React58.createElement(
4222
+ VariableRow,
3643
4223
  {
3644
- label: "Name",
3645
- size: "small",
3646
- fullWidth: true,
3647
- value: v.name,
3648
- onChange: (e) => updateAt(i, { name: e.target.value }),
3649
- error: Boolean(nameError),
3650
- helperText: nameError != null ? nameError : " "
4224
+ key: i,
4225
+ index: i,
4226
+ variable: v,
4227
+ siblings: variables,
4228
+ usageCount: v.name ? (_a2 = usage.get(v.name)) != null ? _a2 : 0 : 0,
4229
+ canInsert,
4230
+ onCommitRename: (name) => commitRename(i, name),
4231
+ onChangeDescription: (description) => updateAt(i, { description }),
4232
+ onChangeSampleValue: (sampleValue) => updateAt(i, { sampleValue }),
4233
+ onRemove: () => removeAt(i),
4234
+ onInsert: () => v.name && insertIntoFocused(v.name),
4235
+ onCopy: () => v.name && copy(v.name)
3651
4236
  }
3652
- ), /* @__PURE__ */ React60.createElement(Tooltip, { title: "Remove" }, /* @__PURE__ */ React60.createElement(
3653
- IconButton,
3654
- {
3655
- size: "small",
3656
- onClick: () => removeAt(i),
3657
- "aria-label": `Remove ${v.name || "variable"}`,
3658
- sx: { mt: 0.5 }
4237
+ );
4238
+ })));
4239
+ }
4240
+ function VariableRow({
4241
+ index,
4242
+ variable,
4243
+ siblings,
4244
+ usageCount,
4245
+ canInsert,
4246
+ onCommitRename,
4247
+ onChangeDescription,
4248
+ onChangeSampleValue,
4249
+ onRemove,
4250
+ onInsert,
4251
+ onCopy
4252
+ }) {
4253
+ var _a, _b;
4254
+ const [draftName, setDraftName] = useState(variable.name);
4255
+ const [isEditing, setIsEditing] = useState(false);
4256
+ useEffect(() => {
4257
+ if (!isEditing) setDraftName(variable.name);
4258
+ }, [variable.name, isEditing]);
4259
+ const nameError = validateVariableName(draftName, siblings, index);
4260
+ const unused = Boolean(variable.name) && usageCount === 0;
4261
+ const hasName = Boolean(variable.name);
4262
+ const commit = () => {
4263
+ setIsEditing(false);
4264
+ if (nameError) {
4265
+ setDraftName(variable.name);
4266
+ return;
4267
+ }
4268
+ if (draftName.trim() !== variable.name) {
4269
+ onCommitRename(draftName.trim());
4270
+ }
4271
+ };
4272
+ return /* @__PURE__ */ React58.createElement(Stack, { spacing: 0.75, sx: { pb: 1, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 1, alignItems: "flex-start" }, /* @__PURE__ */ React58.createElement(
4273
+ TextField,
4274
+ {
4275
+ label: "Name",
4276
+ size: "small",
4277
+ fullWidth: true,
4278
+ value: draftName,
4279
+ onChange: (e) => {
4280
+ setDraftName(e.target.value);
4281
+ setIsEditing(true);
3659
4282
  },
3660
- /* @__PURE__ */ React60.createElement(DeleteOutline, { fontSize: "small" })
3661
- ))), /* @__PURE__ */ React60.createElement(
3662
- TextField,
3663
- {
3664
- label: "Description",
3665
- size: "small",
3666
- fullWidth: true,
3667
- value: (_a2 = v.description) != null ? _a2 : "",
3668
- onChange: (e) => updateAt(i, { description: e.target.value }),
3669
- placeholder: "Optional"
4283
+ onFocus: () => setIsEditing(true),
4284
+ onBlur: commit,
4285
+ onKeyDown: (e) => {
4286
+ if (e.key === "Enter") {
4287
+ e.target.blur();
4288
+ } else if (e.key === "Escape") {
4289
+ setDraftName(variable.name);
4290
+ setIsEditing(false);
4291
+ e.target.blur();
4292
+ }
4293
+ },
4294
+ error: Boolean(nameError),
4295
+ helperText: nameError != null ? nameError : " "
4296
+ }
4297
+ ), /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 0.25, sx: { mt: 0.5 } }, /* @__PURE__ */ React58.createElement(Tooltip, { title: "Copy {{name}}" }, /* @__PURE__ */ React58.createElement("span", null, /* @__PURE__ */ React58.createElement(
4298
+ IconButton,
4299
+ {
4300
+ size: "small",
4301
+ onClick: onCopy,
4302
+ disabled: !hasName,
4303
+ "aria-label": `Copy ${variable.name || "variable"} token`
4304
+ },
4305
+ /* @__PURE__ */ React58.createElement(ContentCopyOutlined, { fontSize: "small" })
4306
+ ))), /* @__PURE__ */ React58.createElement(Tooltip, { title: canInsert ? "Insert at cursor" : "Focus a text field first" }, /* @__PURE__ */ React58.createElement("span", null, /* @__PURE__ */ React58.createElement(
4307
+ IconButton,
4308
+ {
4309
+ size: "small",
4310
+ onClick: onInsert,
4311
+ disabled: !hasName || !canInsert,
4312
+ "aria-label": `Insert ${variable.name || "variable"} at cursor`
4313
+ },
4314
+ /* @__PURE__ */ React58.createElement(InputOutlined, { fontSize: "small" })
4315
+ ))), /* @__PURE__ */ React58.createElement(Tooltip, { title: "Remove" }, /* @__PURE__ */ React58.createElement(
4316
+ IconButton,
4317
+ {
4318
+ size: "small",
4319
+ onClick: onRemove,
4320
+ "aria-label": `Remove ${variable.name || "variable"}`
4321
+ },
4322
+ /* @__PURE__ */ React58.createElement(DeleteOutline, { fontSize: "small" })
4323
+ )))), /* @__PURE__ */ React58.createElement(
4324
+ TextField,
4325
+ {
4326
+ label: "Description",
4327
+ size: "small",
4328
+ fullWidth: true,
4329
+ value: (_a = variable.description) != null ? _a : "",
4330
+ onChange: (e) => onChangeDescription(e.target.value),
4331
+ placeholder: "Optional"
4332
+ }
4333
+ ), /* @__PURE__ */ React58.createElement(
4334
+ TextField,
4335
+ {
4336
+ label: "Sample value",
4337
+ size: "small",
4338
+ fullWidth: true,
4339
+ value: (_b = variable.sampleValue) != null ? _b : "",
4340
+ onChange: (e) => onChangeSampleValue(e.target.value),
4341
+ placeholder: "Shown in Preview mode",
4342
+ InputProps: {
4343
+ startAdornment: /* @__PURE__ */ React58.createElement(
4344
+ DataObjectOutlined,
4345
+ {
4346
+ fontSize: "small",
4347
+ sx: { color: "text.secondary", mr: 0.75 }
4348
+ }
4349
+ )
3670
4350
  }
3671
- ));
3672
- })));
4351
+ }
4352
+ ), /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 0.5, sx: { pt: 0.25 } }, hasName && (unused ? /* @__PURE__ */ React58.createElement(Chip, { size: "small", color: "warning", variant: "outlined", label: "Unused in body" }) : /* @__PURE__ */ React58.createElement(
4353
+ Chip,
4354
+ {
4355
+ size: "small",
4356
+ variant: "outlined",
4357
+ label: `${usageCount} ref${usageCount === 1 ? "" : "s"}`
4358
+ }
4359
+ ))));
3673
4360
  }
3674
4361
 
3675
4362
  // src/app/inspector-drawer/index.tsx
@@ -3686,13 +4373,13 @@ function InspectorDrawer({
3686
4373
  const renderCurrentSidebarPanel = () => {
3687
4374
  switch (selectedSidebarTab) {
3688
4375
  case "block-configuration":
3689
- return /* @__PURE__ */ React60.createElement(ConfigurationPanel, null);
4376
+ return /* @__PURE__ */ React58.createElement(ConfigurationPanel, null);
3690
4377
  case "styles":
3691
- return /* @__PURE__ */ React60.createElement(StylesPanel, null);
4378
+ return /* @__PURE__ */ React58.createElement(StylesPanel, null);
3692
4379
  case "variables":
3693
- return /* @__PURE__ */ React60.createElement(VariablesPanel, null);
4380
+ return /* @__PURE__ */ React58.createElement(VariablesPanel, null);
3694
4381
  case "template-settings":
3695
- return /* @__PURE__ */ React60.createElement(
4382
+ return /* @__PURE__ */ React58.createElement(
3696
4383
  TemplatePanel,
3697
4384
  {
3698
4385
  deleteTemplate,
@@ -3701,7 +4388,7 @@ function InspectorDrawer({
3701
4388
  );
3702
4389
  }
3703
4390
  };
3704
- return /* @__PURE__ */ React60.createElement(
4391
+ return /* @__PURE__ */ React58.createElement(
3705
4392
  Drawer,
3706
4393
  {
3707
4394
  variant: "persistent",
@@ -3723,7 +4410,7 @@ function InspectorDrawer({
3723
4410
  width: inspectorDrawerOpen ? INSPECTOR_DRAWER_WIDTH : 0
3724
4411
  }
3725
4412
  },
3726
- /* @__PURE__ */ React60.createElement(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: 49, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React60.createElement(Box, { px: 1 }, /* @__PURE__ */ React60.createElement(
4413
+ /* @__PURE__ */ React58.createElement(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: 49, borderBottom: 1, borderColor: "divider" } }, /* @__PURE__ */ React58.createElement(Box, { px: 1 }, /* @__PURE__ */ React58.createElement(
3727
4414
  Tabs,
3728
4415
  {
3729
4416
  value: selectedSidebarTab,
@@ -3731,12 +4418,12 @@ function InspectorDrawer({
3731
4418
  variant: "fullWidth",
3732
4419
  sx: { "& .MuiTab-root": { minWidth: 0, px: 1, fontSize: 13 } }
3733
4420
  },
3734
- /* @__PURE__ */ React60.createElement(Tab, { value: "styles", label: "Styles" }),
3735
- /* @__PURE__ */ React60.createElement(Tab, { value: "block-configuration", label: "Inspect" }),
3736
- /* @__PURE__ */ React60.createElement(Tab, { value: "variables", label: "Variables" }),
3737
- /* @__PURE__ */ React60.createElement(Tab, { value: "template-settings", label: "Settings" })
4421
+ /* @__PURE__ */ React58.createElement(Tab, { value: "styles", label: "Styles" }),
4422
+ /* @__PURE__ */ React58.createElement(Tab, { value: "block-configuration", label: "Inspect" }),
4423
+ /* @__PURE__ */ React58.createElement(Tab, { value: "variables", label: "Variables" }),
4424
+ /* @__PURE__ */ React58.createElement(Tab, { value: "template-settings", label: "Settings" })
3738
4425
  ))),
3739
- /* @__PURE__ */ React60.createElement(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" } }, renderCurrentSidebarPanel())
4426
+ /* @__PURE__ */ React58.createElement(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" } }, renderCurrentSidebarPanel())
3740
4427
  );
3741
4428
  }
3742
4429
  var SnackbarContext = createContext(null);
@@ -3757,7 +4444,7 @@ function SnackbarProvider({ children }) {
3757
4444
  const handleClose = () => {
3758
4445
  setMessage(null);
3759
4446
  };
3760
- return /* @__PURE__ */ React60.createElement(SnackbarContext.Provider, { value: { showMessage } }, children, /* @__PURE__ */ React60.createElement(
4447
+ return /* @__PURE__ */ React58.createElement(SnackbarContext.Provider, { value: { showMessage } }, children, /* @__PURE__ */ React58.createElement(
3761
4448
  Snackbar,
3762
4449
  {
3763
4450
  anchorOrigin: { vertical: "top", horizontal: "center" },
@@ -3823,7 +4510,7 @@ function TemplateRow({
3823
4510
  const hasActions = Boolean(
3824
4511
  onDuplicate || onRename || onDelete || onPromote || onDemote || onDuplicateAsTemplate
3825
4512
  );
3826
- return /* @__PURE__ */ React60.createElement(
4513
+ return /* @__PURE__ */ React58.createElement(
3827
4514
  Box,
3828
4515
  {
3829
4516
  role: "button",
@@ -3849,7 +4536,7 @@ function TemplateRow({
3849
4536
  "&:focus-visible": { outline: "2px solid", outlineColor: "primary.main" }
3850
4537
  }
3851
4538
  },
3852
- /* @__PURE__ */ React60.createElement(Stack, { direction: "row", alignItems: "flex-start", spacing: 1 }, /* @__PURE__ */ React60.createElement(Box, { sx: { flexGrow: 1, minWidth: 0 } }, /* @__PURE__ */ React60.createElement(Stack, { direction: "row", alignItems: "baseline", spacing: 1, sx: { minWidth: 0 } }, /* @__PURE__ */ React60.createElement(
4539
+ /* @__PURE__ */ React58.createElement(Stack, { direction: "row", alignItems: "flex-start", spacing: 1 }, /* @__PURE__ */ React58.createElement(Box, { sx: { flexGrow: 1, minWidth: 0 } }, /* @__PURE__ */ React58.createElement(Stack, { direction: "row", alignItems: "baseline", spacing: 1, sx: { minWidth: 0 } }, /* @__PURE__ */ React58.createElement(
3853
4540
  Typography,
3854
4541
  {
3855
4542
  variant: "body2",
@@ -3863,14 +4550,14 @@ function TemplateRow({
3863
4550
  title: template.slug
3864
4551
  },
3865
4552
  template.slug
3866
- ), updated && /* @__PURE__ */ React60.createElement(
4553
+ ), updated && /* @__PURE__ */ React58.createElement(
3867
4554
  Typography,
3868
4555
  {
3869
4556
  variant: "caption",
3870
4557
  sx: { color: "text.secondary", flexShrink: 0, fontSize: "0.7rem" }
3871
4558
  },
3872
4559
  updated
3873
- )), template.description && /* @__PURE__ */ React60.createElement(
4560
+ )), template.description && /* @__PURE__ */ React58.createElement(
3874
4561
  Typography,
3875
4562
  {
3876
4563
  variant: "caption",
@@ -3884,7 +4571,7 @@ function TemplateRow({
3884
4571
  }
3885
4572
  },
3886
4573
  template.description
3887
- ), template.tags && template.tags.length > 0 && /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 0.5, sx: { mt: 0.5, flexWrap: "wrap", gap: 0.5 } }, template.tags.map((tag) => /* @__PURE__ */ React60.createElement(
4574
+ ), template.tags && template.tags.length > 0 && /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 0.5, sx: { mt: 0.5, flexWrap: "wrap", gap: 0.5 } }, template.tags.map((tag) => /* @__PURE__ */ React58.createElement(
3888
4575
  Chip,
3889
4576
  {
3890
4577
  key: tag,
@@ -3893,7 +4580,7 @@ function TemplateRow({
3893
4580
  sx: { height: 18, fontSize: "0.65rem", "& .MuiChip-label": { px: 0.75 } }
3894
4581
  }
3895
4582
  ))))),
3896
- hasActions && hover && /* @__PURE__ */ React60.createElement(
4583
+ hasActions && hover && /* @__PURE__ */ React58.createElement(
3897
4584
  Stack,
3898
4585
  {
3899
4586
  direction: "row",
@@ -3909,7 +4596,7 @@ function TemplateRow({
3909
4596
  p: 0.25
3910
4597
  }
3911
4598
  },
3912
- onDuplicateAsTemplate && /* @__PURE__ */ React60.createElement(Tooltip, { title: "Duplicate as template" }, /* @__PURE__ */ React60.createElement(
4599
+ onDuplicateAsTemplate && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Duplicate as template" }, /* @__PURE__ */ React58.createElement(
3913
4600
  IconButton,
3914
4601
  {
3915
4602
  size: "small",
@@ -3918,9 +4605,9 @@ function TemplateRow({
3918
4605
  onDuplicateAsTemplate();
3919
4606
  }
3920
4607
  },
3921
- /* @__PURE__ */ React60.createElement(LibraryAddOutlined, { fontSize: "small" })
4608
+ /* @__PURE__ */ React58.createElement(LibraryAddOutlined, { fontSize: "small" })
3922
4609
  )),
3923
- onDuplicate && /* @__PURE__ */ React60.createElement(Tooltip, { title: "Duplicate" }, /* @__PURE__ */ React60.createElement(
4610
+ onDuplicate && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Duplicate" }, /* @__PURE__ */ React58.createElement(
3924
4611
  IconButton,
3925
4612
  {
3926
4613
  size: "small",
@@ -3929,9 +4616,9 @@ function TemplateRow({
3929
4616
  onDuplicate();
3930
4617
  }
3931
4618
  },
3932
- /* @__PURE__ */ React60.createElement(ContentCopyOutlined, { fontSize: "small" })
4619
+ /* @__PURE__ */ React58.createElement(ContentCopyOutlined, { fontSize: "small" })
3933
4620
  )),
3934
- onRename && /* @__PURE__ */ React60.createElement(Tooltip, { title: "Rename" }, /* @__PURE__ */ React60.createElement(
4621
+ onRename && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Rename" }, /* @__PURE__ */ React58.createElement(
3935
4622
  IconButton,
3936
4623
  {
3937
4624
  size: "small",
@@ -3940,9 +4627,9 @@ function TemplateRow({
3940
4627
  onRename();
3941
4628
  }
3942
4629
  },
3943
- /* @__PURE__ */ React60.createElement(DriveFileRenameOutlineOutlined, { fontSize: "small" })
4630
+ /* @__PURE__ */ React58.createElement(DriveFileRenameOutlineOutlined, { fontSize: "small" })
3944
4631
  )),
3945
- onPromote && /* @__PURE__ */ React60.createElement(Tooltip, { title: "Promote to sample" }, /* @__PURE__ */ React60.createElement(
4632
+ onPromote && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Promote to sample" }, /* @__PURE__ */ React58.createElement(
3946
4633
  IconButton,
3947
4634
  {
3948
4635
  size: "small",
@@ -3951,9 +4638,9 @@ function TemplateRow({
3951
4638
  onPromote();
3952
4639
  }
3953
4640
  },
3954
- /* @__PURE__ */ React60.createElement(FileUploadOutlined, { fontSize: "small" })
4641
+ /* @__PURE__ */ React58.createElement(FileUploadOutlined, { fontSize: "small" })
3955
4642
  )),
3956
- onDemote && /* @__PURE__ */ React60.createElement(Tooltip, { title: "Demote to template" }, /* @__PURE__ */ React60.createElement(
4643
+ onDemote && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Demote to template" }, /* @__PURE__ */ React58.createElement(
3957
4644
  IconButton,
3958
4645
  {
3959
4646
  size: "small",
@@ -3962,9 +4649,9 @@ function TemplateRow({
3962
4649
  onDemote();
3963
4650
  }
3964
4651
  },
3965
- /* @__PURE__ */ React60.createElement(FileDownloadOutlined, { fontSize: "small" })
4652
+ /* @__PURE__ */ React58.createElement(FileDownloadOutlined, { fontSize: "small" })
3966
4653
  )),
3967
- onDelete && /* @__PURE__ */ React60.createElement(Tooltip, { title: "Delete" }, /* @__PURE__ */ React60.createElement(
4654
+ onDelete && /* @__PURE__ */ React58.createElement(Tooltip, { title: "Delete" }, /* @__PURE__ */ React58.createElement(
3968
4655
  IconButton,
3969
4656
  {
3970
4657
  size: "small",
@@ -3973,7 +4660,7 @@ function TemplateRow({
3973
4660
  onDelete();
3974
4661
  }
3975
4662
  },
3976
- /* @__PURE__ */ React60.createElement(DeleteOutlined, { fontSize: "small" })
4663
+ /* @__PURE__ */ React58.createElement(DeleteOutlined, { fontSize: "small" })
3977
4664
  ))
3978
4665
  )
3979
4666
  );
@@ -4024,7 +4711,7 @@ function RenameDialog({
4024
4711
  setSubmitting(false);
4025
4712
  }
4026
4713
  });
4027
- return /* @__PURE__ */ React60.createElement(Dialog, { open, onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React60.createElement(DialogTitle, null, "Rename template"), /* @__PURE__ */ React60.createElement(DialogContent, null, /* @__PURE__ */ React60.createElement(
4714
+ return /* @__PURE__ */ React58.createElement(Dialog, { open, onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React58.createElement(DialogTitle, null, "Rename template"), /* @__PURE__ */ React58.createElement(DialogContent, null, /* @__PURE__ */ React58.createElement(
4028
4715
  TextField,
4029
4716
  {
4030
4717
  autoFocus: true,
@@ -4043,7 +4730,7 @@ function RenameDialog({
4043
4730
  }
4044
4731
  }
4045
4732
  }
4046
- )), /* @__PURE__ */ React60.createElement(DialogActions, null, /* @__PURE__ */ React60.createElement(Button$1, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ React60.createElement(
4733
+ )), /* @__PURE__ */ React58.createElement(DialogActions, null, /* @__PURE__ */ React58.createElement(Button$1, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ React58.createElement(
4047
4734
  Button$1,
4048
4735
  {
4049
4736
  onClick: handleSubmit,
@@ -4112,7 +4799,7 @@ function SaveTemplateDialog({
4112
4799
  setInternalError("");
4113
4800
  onClose();
4114
4801
  };
4115
- return /* @__PURE__ */ React60.createElement(
4802
+ return /* @__PURE__ */ React58.createElement(
4116
4803
  Dialog,
4117
4804
  {
4118
4805
  open,
@@ -4120,8 +4807,8 @@ function SaveTemplateDialog({
4120
4807
  maxWidth: "sm",
4121
4808
  fullWidth: true
4122
4809
  },
4123
- /* @__PURE__ */ React60.createElement(DialogTitle, null, "Save Email Template"),
4124
- /* @__PURE__ */ React60.createElement(DialogContent, null, /* @__PURE__ */ React60.createElement(Box, { sx: { pt: 1 } }, /* @__PURE__ */ React60.createElement(
4810
+ /* @__PURE__ */ React58.createElement(DialogTitle, null, "Save Email Template"),
4811
+ /* @__PURE__ */ React58.createElement(DialogContent, null, /* @__PURE__ */ React58.createElement(Box, { sx: { pt: 1 } }, /* @__PURE__ */ React58.createElement(
4125
4812
  TextField,
4126
4813
  {
4127
4814
  autoFocus: true,
@@ -4143,7 +4830,7 @@ function SaveTemplateDialog({
4143
4830
  disabled: isSubmitting
4144
4831
  }
4145
4832
  ))),
4146
- /* @__PURE__ */ React60.createElement(DialogActions, null, /* @__PURE__ */ React60.createElement(Button$1, { onClick: handleCancel, disabled: isSubmitting }, "Cancel"), /* @__PURE__ */ React60.createElement(
4833
+ /* @__PURE__ */ React58.createElement(DialogActions, null, /* @__PURE__ */ React58.createElement(Button$1, { onClick: handleCancel, disabled: isSubmitting }, "Cancel"), /* @__PURE__ */ React58.createElement(
4147
4834
  Button$1,
4148
4835
  {
4149
4836
  onClick: handleSave,
@@ -4409,7 +5096,7 @@ function SamplesDrawer({
4409
5096
  return null;
4410
5097
  }
4411
5098
  const existingSlugs = templates.map((t) => t.slug);
4412
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
5099
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
4413
5100
  Drawer,
4414
5101
  {
4415
5102
  variant: "persistent",
@@ -4424,7 +5111,7 @@ function SamplesDrawer({
4424
5111
  transitionDuration: { enter: enterDuration, exit: exitDuration },
4425
5112
  sx: { width: samplesDrawerOpen ? SAMPLES_DRAWER_WIDTH : 0 }
4426
5113
  },
4427
- /* @__PURE__ */ React60.createElement(
5114
+ /* @__PURE__ */ React58.createElement(
4428
5115
  Stack,
4429
5116
  {
4430
5117
  py: 1,
@@ -4434,16 +5121,16 @@ function SamplesDrawer({
4434
5121
  spacing: 1.5,
4435
5122
  sx: { overflowY: "auto" }
4436
5123
  },
4437
- /* @__PURE__ */ React60.createElement(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { pt: 1 } }, /* @__PURE__ */ React60.createElement(Typography, { variant: "h6", component: "h1" }, "Templates"), saveAs && /* @__PURE__ */ React60.createElement(Tooltip, { title: "New template" }, /* @__PURE__ */ React60.createElement(
5124
+ /* @__PURE__ */ React58.createElement(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { pt: 1 } }, /* @__PURE__ */ React58.createElement(Typography, { variant: "h6", component: "h1" }, "Templates"), saveAs && /* @__PURE__ */ React58.createElement(Tooltip, { title: "New template" }, /* @__PURE__ */ React58.createElement(
4438
5125
  IconButton,
4439
5126
  {
4440
5127
  size: "small",
4441
5128
  onClick: openNewTemplateDialog,
4442
5129
  "aria-label": "New template"
4443
5130
  },
4444
- /* @__PURE__ */ React60.createElement(AddOutlined, { fontSize: "small" })
5131
+ /* @__PURE__ */ React58.createElement(AddOutlined, { fontSize: "small" })
4445
5132
  ))),
4446
- loadTemplates && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
5133
+ loadTemplates && /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
4447
5134
  TextField,
4448
5135
  {
4449
5136
  size: "small",
@@ -4451,10 +5138,10 @@ function SamplesDrawer({
4451
5138
  value: search,
4452
5139
  onChange: (e) => setSearch(e.target.value),
4453
5140
  InputProps: {
4454
- startAdornment: /* @__PURE__ */ React60.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React60.createElement(SearchOutlined, { fontSize: "small" }))
5141
+ startAdornment: /* @__PURE__ */ React58.createElement(InputAdornment, { position: "start" }, /* @__PURE__ */ React58.createElement(SearchOutlined, { fontSize: "small" }))
4455
5142
  }
4456
5143
  }
4457
- ), /* @__PURE__ */ React60.createElement(
5144
+ ), /* @__PURE__ */ React58.createElement(
4458
5145
  TextField,
4459
5146
  {
4460
5147
  select: true,
@@ -4463,8 +5150,8 @@ function SamplesDrawer({
4463
5150
  value: sortKey,
4464
5151
  onChange: (e) => setSortKey(e.target.value)
4465
5152
  },
4466
- SORT_OPTIONS.map((opt) => /* @__PURE__ */ React60.createElement(MenuItem, { key: opt.value, value: opt.value }, opt.label))
4467
- ), allTags.length > 0 && /* @__PURE__ */ React60.createElement(Stack, { direction: "row", sx: { flexWrap: "wrap", gap: 0.5 } }, allTags.map((tag) => /* @__PURE__ */ React60.createElement(
5153
+ SORT_OPTIONS.map((opt) => /* @__PURE__ */ React58.createElement(MenuItem, { key: opt.value, value: opt.value }, opt.label))
5154
+ ), allTags.length > 0 && /* @__PURE__ */ React58.createElement(Stack, { direction: "row", sx: { flexWrap: "wrap", gap: 0.5 } }, allTags.map((tag) => /* @__PURE__ */ React58.createElement(
4468
5155
  Chip,
4469
5156
  {
4470
5157
  key: tag,
@@ -4475,7 +5162,7 @@ function SamplesDrawer({
4475
5162
  variant: activeTags.includes(tag) ? "filled" : "outlined",
4476
5163
  onClick: () => toggleTag(tag)
4477
5164
  }
4478
- ))), /* @__PURE__ */ React60.createElement(Box, null, /* @__PURE__ */ React60.createElement(Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Your Templates"), loadingTemplates ? /* @__PURE__ */ React60.createElement(Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React60.createElement(CircularProgress, { size: 24 })) : templatesError ? /* @__PURE__ */ React60.createElement(Alert, { severity: "error", sx: { my: 1 } }, templatesError) : filteredTemplates.length > 0 ? /* @__PURE__ */ React60.createElement(Stack, { spacing: 0.25, sx: { width: "100%" } }, filteredTemplates.map((template) => /* @__PURE__ */ React60.createElement(
5165
+ ))), /* @__PURE__ */ React58.createElement(Box, null, /* @__PURE__ */ React58.createElement(Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Your Templates"), loadingTemplates ? /* @__PURE__ */ React58.createElement(Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React58.createElement(CircularProgress, { size: 24 })) : templatesError ? /* @__PURE__ */ React58.createElement(Alert, { severity: "error", sx: { my: 1 } }, templatesError) : filteredTemplates.length > 0 ? /* @__PURE__ */ React58.createElement(Stack, { spacing: 0.25, sx: { width: "100%" } }, filteredTemplates.map((template) => /* @__PURE__ */ React58.createElement(
4479
5166
  TemplateRow,
4480
5167
  {
4481
5168
  key: template.id,
@@ -4487,8 +5174,8 @@ function SamplesDrawer({
4487
5174
  onDelete: deleteTemplate ? () => handleDelete(template) : void 0,
4488
5175
  onPromote: setTemplateKind ? () => handleSetKind(template, "sample") : void 0
4489
5176
  }
4490
- ))) : /* @__PURE__ */ React60.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, templateRows.length === 0 ? "No saved templates yet" : "No templates match your filters")), /* @__PURE__ */ React60.createElement(Divider$1, null)),
4491
- /* @__PURE__ */ React60.createElement(Box, null, /* @__PURE__ */ React60.createElement(Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Sample Templates"), loadingSamples ? /* @__PURE__ */ React60.createElement(Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React60.createElement(CircularProgress, { size: 24 })) : sampleRows.length > 0 ? /* @__PURE__ */ React60.createElement(Stack, { spacing: 0.25, sx: { width: "100%" } }, sampleRows.map((sample) => /* @__PURE__ */ React60.createElement(
5177
+ ))) : /* @__PURE__ */ React58.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, templateRows.length === 0 ? "No saved templates yet" : "No templates match your filters")), /* @__PURE__ */ React58.createElement(Divider$1, null)),
5178
+ /* @__PURE__ */ React58.createElement(Box, null, /* @__PURE__ */ React58.createElement(Typography, { variant: "subtitle2", component: "h2", sx: { fontWeight: "bold", mb: 0.5 } }, "Sample Templates"), loadingSamples ? /* @__PURE__ */ React58.createElement(Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React58.createElement(CircularProgress, { size: 24 })) : sampleRows.length > 0 ? /* @__PURE__ */ React58.createElement(Stack, { spacing: 0.25, sx: { width: "100%" } }, sampleRows.map((sample) => /* @__PURE__ */ React58.createElement(
4492
5179
  TemplateRow,
4493
5180
  {
4494
5181
  key: sample.id,
@@ -4498,9 +5185,9 @@ function SamplesDrawer({
4498
5185
  onDuplicateAsTemplate: saveAs ? () => handleDuplicateAsTemplate(sample) : void 0,
4499
5186
  onDemote: setTemplateKind && sample.id !== "empty-email" ? () => handleSetKind(sample, "template") : void 0
4500
5187
  }
4501
- ))) : /* @__PURE__ */ React60.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, "No samples available"))
5188
+ ))) : /* @__PURE__ */ React58.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, "No samples available"))
4502
5189
  )
4503
- ), renameTarget && /* @__PURE__ */ React60.createElement(
5190
+ ), renameTarget && /* @__PURE__ */ React58.createElement(
4504
5191
  RenameDialog,
4505
5192
  {
4506
5193
  open: !!renameTarget,
@@ -4509,7 +5196,7 @@ function SamplesDrawer({
4509
5196
  onClose: () => setRenameTarget(null),
4510
5197
  onSubmit: handleRenameSubmit
4511
5198
  }
4512
- ), /* @__PURE__ */ React60.createElement(
5199
+ ), /* @__PURE__ */ React58.createElement(
4513
5200
  SaveTemplateDialog,
4514
5201
  {
4515
5202
  open: !!pendingSaveAs,
@@ -4536,7 +5223,7 @@ var ICON_SX = {
4536
5223
  borderColor: "cadet.300"
4537
5224
  };
4538
5225
  function BlockTypeButton({ label, icon, onClick }) {
4539
- return /* @__PURE__ */ React60.createElement(
5226
+ return /* @__PURE__ */ React58.createElement(
4540
5227
  Button$1,
4541
5228
  {
4542
5229
  sx: BUTTON_SX2,
@@ -4545,14 +5232,14 @@ function BlockTypeButton({ label, icon, onClick }) {
4545
5232
  onClick();
4546
5233
  }
4547
5234
  },
4548
- /* @__PURE__ */ React60.createElement(Box, { sx: ICON_SX }, icon),
4549
- /* @__PURE__ */ React60.createElement(Typography, { variant: "body2" }, label)
5235
+ /* @__PURE__ */ React58.createElement(Box, { sx: ICON_SX }, icon),
5236
+ /* @__PURE__ */ React58.createElement(Typography, { variant: "body2" }, label)
4550
5237
  );
4551
5238
  }
4552
5239
  var BUTTONS = [
4553
5240
  {
4554
5241
  label: "Heading",
4555
- icon: /* @__PURE__ */ React60.createElement(HMobiledataOutlined, null),
5242
+ icon: /* @__PURE__ */ React58.createElement(HMobiledataOutlined, null),
4556
5243
  block: () => ({
4557
5244
  type: "Heading",
4558
5245
  data: {
@@ -4565,7 +5252,7 @@ var BUTTONS = [
4565
5252
  },
4566
5253
  {
4567
5254
  label: "Text",
4568
- icon: /* @__PURE__ */ React60.createElement(NotesOutlined, null),
5255
+ icon: /* @__PURE__ */ React58.createElement(NotesOutlined, null),
4569
5256
  block: () => ({
4570
5257
  type: "Text",
4571
5258
  data: {
@@ -4579,7 +5266,7 @@ var BUTTONS = [
4579
5266
  },
4580
5267
  {
4581
5268
  label: "Button",
4582
- icon: /* @__PURE__ */ React60.createElement(SmartButtonOutlined, null),
5269
+ icon: /* @__PURE__ */ React58.createElement(SmartButtonOutlined, null),
4583
5270
  block: () => ({
4584
5271
  type: "Button",
4585
5272
  data: {
@@ -4593,7 +5280,7 @@ var BUTTONS = [
4593
5280
  },
4594
5281
  {
4595
5282
  label: "Image",
4596
- icon: /* @__PURE__ */ React60.createElement(ImageOutlined, null),
5283
+ icon: /* @__PURE__ */ React58.createElement(ImageOutlined, null),
4597
5284
  block: () => ({
4598
5285
  type: "Image",
4599
5286
  data: {
@@ -4609,7 +5296,7 @@ var BUTTONS = [
4609
5296
  },
4610
5297
  {
4611
5298
  label: "Avatar",
4612
- icon: /* @__PURE__ */ React60.createElement(AccountCircleOutlined, null),
5299
+ icon: /* @__PURE__ */ React58.createElement(AccountCircleOutlined, null),
4613
5300
  block: () => ({
4614
5301
  type: "Avatar",
4615
5302
  data: {
@@ -4623,7 +5310,7 @@ var BUTTONS = [
4623
5310
  },
4624
5311
  {
4625
5312
  label: "Personal Signature",
4626
- icon: /* @__PURE__ */ React60.createElement(ContactMailOutlined, null),
5313
+ icon: /* @__PURE__ */ React58.createElement(ContactMailOutlined, null),
4627
5314
  block: () => ({
4628
5315
  type: "Signature",
4629
5316
  data: {
@@ -4645,7 +5332,7 @@ var BUTTONS = [
4645
5332
  },
4646
5333
  {
4647
5334
  label: "Company Signature",
4648
- icon: /* @__PURE__ */ React60.createElement(BusinessOutlined, null),
5335
+ icon: /* @__PURE__ */ React58.createElement(BusinessOutlined, null),
4649
5336
  block: () => ({
4650
5337
  type: "Signature",
4651
5338
  data: {
@@ -4665,7 +5352,7 @@ var BUTTONS = [
4665
5352
  },
4666
5353
  {
4667
5354
  label: "Divider",
4668
- icon: /* @__PURE__ */ React60.createElement(HorizontalRuleOutlined, null),
5355
+ icon: /* @__PURE__ */ React58.createElement(HorizontalRuleOutlined, null),
4669
5356
  block: () => ({
4670
5357
  type: "Divider",
4671
5358
  data: {
@@ -4678,7 +5365,7 @@ var BUTTONS = [
4678
5365
  },
4679
5366
  {
4680
5367
  label: "Spacer",
4681
- icon: /* @__PURE__ */ React60.createElement(Crop32Outlined, null),
5368
+ icon: /* @__PURE__ */ React58.createElement(Crop32Outlined, null),
4682
5369
  block: () => ({
4683
5370
  type: "Spacer",
4684
5371
  data: {}
@@ -4686,7 +5373,7 @@ var BUTTONS = [
4686
5373
  },
4687
5374
  {
4688
5375
  label: "Html",
4689
- icon: /* @__PURE__ */ React60.createElement(HtmlOutlined, null),
5376
+ icon: /* @__PURE__ */ React58.createElement(HtmlOutlined, null),
4690
5377
  block: () => ({
4691
5378
  type: "Html",
4692
5379
  data: {
@@ -4701,7 +5388,7 @@ var BUTTONS = [
4701
5388
  },
4702
5389
  {
4703
5390
  label: "Columns",
4704
- icon: /* @__PURE__ */ React60.createElement(ViewColumnOutlined, null),
5391
+ icon: /* @__PURE__ */ React58.createElement(ViewColumnOutlined, null),
4705
5392
  block: () => ({
4706
5393
  type: "ColumnsContainer",
4707
5394
  data: {
@@ -4716,7 +5403,7 @@ var BUTTONS = [
4716
5403
  },
4717
5404
  {
4718
5405
  label: "Container",
4719
- icon: /* @__PURE__ */ React60.createElement(LibraryAddOutlined, null),
5406
+ icon: /* @__PURE__ */ React58.createElement(LibraryAddOutlined, null),
4720
5407
  block: () => ({
4721
5408
  type: "Container",
4722
5409
  data: {
@@ -4740,7 +5427,7 @@ function BlocksMenu({ anchorEl, setAnchorEl, onSelect }) {
4740
5427
  if (anchorEl === null) {
4741
5428
  return null;
4742
5429
  }
4743
- return /* @__PURE__ */ React60.createElement(
5430
+ return /* @__PURE__ */ React58.createElement(
4744
5431
  Menu,
4745
5432
  {
4746
5433
  open: true,
@@ -4749,7 +5436,7 @@ function BlocksMenu({ anchorEl, setAnchorEl, onSelect }) {
4749
5436
  anchorOrigin: { vertical: "bottom", horizontal: "center" },
4750
5437
  transformOrigin: { vertical: "top", horizontal: "center" }
4751
5438
  },
4752
- /* @__PURE__ */ React60.createElement(Box, { sx: { p: 1, display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr" } }, BUTTONS.map((k, i) => /* @__PURE__ */ React60.createElement(BlockTypeButton, { key: i, label: k.label, icon: k.icon, onClick: () => onClick(k.block()) })))
5439
+ /* @__PURE__ */ React58.createElement(Box, { sx: { p: 1, display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr" } }, BUTTONS.map((k, i) => /* @__PURE__ */ React58.createElement(BlockTypeButton, { key: i, label: k.label, icon: k.icon, onClick: () => onClick(k.block()) })))
4753
5440
  );
4754
5441
  }
4755
5442
  function DividerButton({ buttonElement, onClick }) {
@@ -4776,7 +5463,7 @@ function DividerButton({ buttonElement, onClick }) {
4776
5463
  window.removeEventListener("mousemove", listener);
4777
5464
  };
4778
5465
  }, [buttonElement, setVisible]);
4779
- return /* @__PURE__ */ React60.createElement(Fade, { in: visible }, /* @__PURE__ */ React60.createElement(
5466
+ return /* @__PURE__ */ React58.createElement(Fade, { in: visible }, /* @__PURE__ */ React58.createElement(
4780
5467
  IconButton,
4781
5468
  {
4782
5469
  size: "small",
@@ -4799,11 +5486,11 @@ function DividerButton({ buttonElement, onClick }) {
4799
5486
  onClick();
4800
5487
  }
4801
5488
  },
4802
- /* @__PURE__ */ React60.createElement(AddOutlined, { fontSize: "small" })
5489
+ /* @__PURE__ */ React58.createElement(AddOutlined, { fontSize: "small" })
4803
5490
  ));
4804
5491
  }
4805
5492
  function PlaceholderButton({ onClick }) {
4806
- return /* @__PURE__ */ React60.createElement(
5493
+ return /* @__PURE__ */ React58.createElement(
4807
5494
  ButtonBase,
4808
5495
  {
4809
5496
  onClick: (ev) => {
@@ -4819,7 +5506,7 @@ function PlaceholderButton({ onClick }) {
4819
5506
  bgcolor: "rgba(0,0,0, 0.05)"
4820
5507
  }
4821
5508
  },
4822
- /* @__PURE__ */ React60.createElement(
5509
+ /* @__PURE__ */ React58.createElement(
4823
5510
  AddOutlined,
4824
5511
  {
4825
5512
  sx: {
@@ -4843,12 +5530,12 @@ function AddBlockButton({ onSelect, placeholder }) {
4843
5530
  };
4844
5531
  const renderButton2 = () => {
4845
5532
  if (placeholder) {
4846
- return /* @__PURE__ */ React60.createElement(PlaceholderButton, { onClick: handleButtonClick });
5533
+ return /* @__PURE__ */ React58.createElement(PlaceholderButton, { onClick: handleButtonClick });
4847
5534
  } else {
4848
- return /* @__PURE__ */ React60.createElement(DividerButton, { buttonElement, onClick: handleButtonClick });
5535
+ return /* @__PURE__ */ React58.createElement(DividerButton, { buttonElement, onClick: handleButtonClick });
4849
5536
  }
4850
5537
  };
4851
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement("div", { ref: setButtonElement, style: { position: "relative" } }, renderButton2()), /* @__PURE__ */ React60.createElement(BlocksMenu, { anchorEl: menuAnchorEl, setAnchorEl: setMenuAnchorEl, onSelect }));
5538
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement("div", { ref: setButtonElement, style: { position: "relative" } }, renderButton2()), /* @__PURE__ */ React58.createElement(BlocksMenu, { anchorEl: menuAnchorEl, setAnchorEl: setMenuAnchorEl, onSelect }));
4852
5539
  }
4853
5540
 
4854
5541
  // src/editor/blocks/helpers/editor-children-ids/index.tsx
@@ -4875,9 +5562,9 @@ function EditorChildrenIds({ childrenIds, onChange }) {
4875
5562
  });
4876
5563
  };
4877
5564
  if (!childrenIds || childrenIds.length === 0) {
4878
- return /* @__PURE__ */ React60.createElement(AddBlockButton, { placeholder: true, onSelect: appendBlock });
5565
+ return /* @__PURE__ */ React58.createElement(AddBlockButton, { placeholder: true, onSelect: appendBlock });
4879
5566
  }
4880
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, childrenIds.map((childId, i) => /* @__PURE__ */ React60.createElement(Fragment, { key: childId }, /* @__PURE__ */ React60.createElement(AddBlockButton, { onSelect: (block) => insertBlock(block, i) }), /* @__PURE__ */ React60.createElement(EditorBlock, { id: childId }))), /* @__PURE__ */ React60.createElement(AddBlockButton, { onSelect: appendBlock }));
5567
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, childrenIds.map((childId, i) => /* @__PURE__ */ React58.createElement(Fragment, { key: childId }, /* @__PURE__ */ React58.createElement(AddBlockButton, { onSelect: (block) => insertBlock(block, i) }), /* @__PURE__ */ React58.createElement(EditorBlock, { id: childId }))), /* @__PURE__ */ React58.createElement(AddBlockButton, { onSelect: appendBlock }));
4881
5568
  }
4882
5569
 
4883
5570
  // src/editor/blocks/columns-container/columns-container-editor.tsx
@@ -4904,15 +5591,15 @@ function ColumnsContainerEditor({ style, props }) {
4904
5591
  });
4905
5592
  setSelectedBlockId(blockId);
4906
5593
  };
4907
- return /* @__PURE__ */ React60.createElement(
5594
+ return /* @__PURE__ */ React58.createElement(
4908
5595
  columns_container_default,
4909
5596
  {
4910
5597
  props: restProps,
4911
5598
  style,
4912
5599
  columns: [
4913
- /* @__PURE__ */ React60.createElement(EditorChildrenIds, { childrenIds: (_b = columns == null ? void 0 : columns[0]) == null ? void 0 : _b.childrenIds, onChange: (change) => updateColumn(0, change) }),
4914
- /* @__PURE__ */ React60.createElement(EditorChildrenIds, { childrenIds: (_c = columns == null ? void 0 : columns[1]) == null ? void 0 : _c.childrenIds, onChange: (change) => updateColumn(1, change) }),
4915
- /* @__PURE__ */ React60.createElement(EditorChildrenIds, { childrenIds: (_d = columns == null ? void 0 : columns[2]) == null ? void 0 : _d.childrenIds, onChange: (change) => updateColumn(2, change) })
5600
+ /* @__PURE__ */ React58.createElement(EditorChildrenIds, { childrenIds: (_b = columns == null ? void 0 : columns[0]) == null ? void 0 : _b.childrenIds, onChange: (change) => updateColumn(0, change) }),
5601
+ /* @__PURE__ */ React58.createElement(EditorChildrenIds, { childrenIds: (_c = columns == null ? void 0 : columns[1]) == null ? void 0 : _c.childrenIds, onChange: (change) => updateColumn(1, change) }),
5602
+ /* @__PURE__ */ React58.createElement(EditorChildrenIds, { childrenIds: (_d = columns == null ? void 0 : columns[2]) == null ? void 0 : _d.childrenIds, onChange: (change) => updateColumn(2, change) })
4916
5603
  ]
4917
5604
  }
4918
5605
  );
@@ -4922,7 +5609,7 @@ function ContainerEditor({ style, props }) {
4922
5609
  const childrenIds = (_a = props == null ? void 0 : props.childrenIds) != null ? _a : [];
4923
5610
  const document2 = useDocument();
4924
5611
  const currentBlockId = useCurrentBlockId();
4925
- return /* @__PURE__ */ React60.createElement(container_default, { style }, /* @__PURE__ */ React60.createElement(
5612
+ return /* @__PURE__ */ React58.createElement(container_default, { style }, /* @__PURE__ */ React58.createElement(
4926
5613
  EditorChildrenIds,
4927
5614
  {
4928
5615
  childrenIds,
@@ -5122,7 +5809,7 @@ function EmailLayoutEditor(props) {
5122
5809
  lineHeight: "1.5",
5123
5810
  margin: "0"
5124
5811
  };
5125
- const editorChildren = /* @__PURE__ */ React60.createElement(
5812
+ const editorChildren = /* @__PURE__ */ React58.createElement(
5126
5813
  EditorChildrenIds,
5127
5814
  {
5128
5815
  childrenIds,
@@ -5141,7 +5828,7 @@ function EmailLayoutEditor(props) {
5141
5828
  }
5142
5829
  );
5143
5830
  if (props.backdropDisabled) {
5144
- return /* @__PURE__ */ React60.createElement(
5831
+ return /* @__PURE__ */ React58.createElement(
5145
5832
  "div",
5146
5833
  {
5147
5834
  onClick: () => {
@@ -5154,10 +5841,10 @@ function EmailLayoutEditor(props) {
5154
5841
  minHeight: "100%"
5155
5842
  })
5156
5843
  },
5157
- /* @__PURE__ */ React60.createElement("div", { style: { maxWidth: "600px" } }, editorChildren)
5844
+ /* @__PURE__ */ React58.createElement("div", { style: { maxWidth: "600px" } }, editorChildren)
5158
5845
  );
5159
5846
  }
5160
- return /* @__PURE__ */ React60.createElement(
5847
+ return /* @__PURE__ */ React58.createElement(
5161
5848
  "div",
5162
5849
  {
5163
5850
  onClick: () => {
@@ -5170,7 +5857,7 @@ function EmailLayoutEditor(props) {
5170
5857
  minHeight: "100%"
5171
5858
  })
5172
5859
  },
5173
- /* @__PURE__ */ React60.createElement(
5860
+ /* @__PURE__ */ React58.createElement(
5174
5861
  "table",
5175
5862
  {
5176
5863
  align: "center",
@@ -5194,7 +5881,7 @@ function EmailLayoutEditor(props) {
5194
5881
  cellPadding: "0",
5195
5882
  border: 0
5196
5883
  },
5197
- /* @__PURE__ */ React60.createElement("tbody", null, /* @__PURE__ */ React60.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React60.createElement("td", null, editorChildren)))
5884
+ /* @__PURE__ */ React58.createElement("tbody", null, /* @__PURE__ */ React58.createElement("tr", { style: { width: "100%" } }, /* @__PURE__ */ React58.createElement("td", null, editorChildren)))
5198
5885
  )
5199
5886
  );
5200
5887
  }
@@ -5353,7 +6040,7 @@ function TuneMenu({ blockId }) {
5353
6040
  resetDocument(nDocument);
5354
6041
  setSelectedBlockId(blockId);
5355
6042
  };
5356
- return /* @__PURE__ */ React60.createElement(Paper, { sx, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React60.createElement(Stack, null, /* @__PURE__ */ React60.createElement(Tooltip, { title: "Move up", placement: "left-start" }, /* @__PURE__ */ React60.createElement(IconButton, { onClick: () => handleMoveClick("up"), sx: { color: "text.primary" } }, /* @__PURE__ */ React60.createElement(ArrowUpwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60.createElement(Tooltip, { title: "Move down", placement: "left-start" }, /* @__PURE__ */ React60.createElement(IconButton, { onClick: () => handleMoveClick("down"), sx: { color: "text.primary" } }, /* @__PURE__ */ React60.createElement(ArrowDownwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60.createElement(Tooltip, { title: "Copy block", placement: "left-start" }, /* @__PURE__ */ React60.createElement(IconButton, { onClick: handleCopyClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React60.createElement(ContentCopyOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60.createElement(Tooltip, { title: "Delete", placement: "left-start" }, /* @__PURE__ */ React60.createElement(IconButton, { onClick: handleDeleteClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React60.createElement(DeleteOutlined, { fontSize: "small" })))));
6043
+ return /* @__PURE__ */ React58.createElement(Paper, { sx, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React58.createElement(Stack, null, /* @__PURE__ */ React58.createElement(Tooltip, { title: "Move up", placement: "left-start" }, /* @__PURE__ */ React58.createElement(IconButton, { onClick: () => handleMoveClick("up"), sx: { color: "text.primary" } }, /* @__PURE__ */ React58.createElement(ArrowUpwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58.createElement(Tooltip, { title: "Move down", placement: "left-start" }, /* @__PURE__ */ React58.createElement(IconButton, { onClick: () => handleMoveClick("down"), sx: { color: "text.primary" } }, /* @__PURE__ */ React58.createElement(ArrowDownwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58.createElement(Tooltip, { title: "Copy block", placement: "left-start" }, /* @__PURE__ */ React58.createElement(IconButton, { onClick: handleCopyClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React58.createElement(ContentCopyOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58.createElement(Tooltip, { title: "Delete", placement: "left-start" }, /* @__PURE__ */ React58.createElement(IconButton, { onClick: handleDeleteClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React58.createElement(DeleteOutlined, { fontSize: "small" })))));
5357
6044
  }
5358
6045
 
5359
6046
  // src/editor/blocks/helpers/block-wrappers/editor-block-wrapper.tsx
@@ -5371,9 +6058,9 @@ function EditorBlockWrapper({ children }) {
5371
6058
  if (selectedBlockId !== blockId) {
5372
6059
  return null;
5373
6060
  }
5374
- return /* @__PURE__ */ React60.createElement(TuneMenu, { blockId });
6061
+ return /* @__PURE__ */ React58.createElement(TuneMenu, { blockId });
5375
6062
  };
5376
- return /* @__PURE__ */ React60.createElement(
6063
+ return /* @__PURE__ */ React58.createElement(
5377
6064
  Box,
5378
6065
  {
5379
6066
  sx: {
@@ -5503,18 +6190,34 @@ function ButtonEditor({ style, props }) {
5503
6190
  width: fullWidth ? "100%" : void 0,
5504
6191
  textAlign: "center"
5505
6192
  });
5506
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React60.createElement(
6193
+ const trackFocus = (e) => {
6194
+ var _a2, _b2;
6195
+ const el = e.currentTarget;
6196
+ setLastFocusedEditable({
6197
+ blockId,
6198
+ field: "text",
6199
+ selectionStart: (_a2 = el.selectionStart) != null ? _a2 : el.value.length,
6200
+ selectionEnd: (_b2 = el.selectionEnd) != null ? _b2 : el.value.length
6201
+ });
6202
+ };
6203
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React58.createElement(
5507
6204
  "input",
5508
6205
  {
5509
6206
  type: "text",
5510
6207
  value: localText,
5511
6208
  onChange: handleTextChange,
5512
- style: inputStyle,
5513
- onClick: (e) => e.stopPropagation()
6209
+ onFocus: trackFocus,
6210
+ onSelect: trackFocus,
6211
+ onKeyUp: trackFocus,
6212
+ onClick: (e) => {
6213
+ e.stopPropagation();
6214
+ trackFocus(e);
6215
+ },
6216
+ style: inputStyle
5514
6217
  }
5515
6218
  ));
5516
6219
  }
5517
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React60.createElement("span", { style: linkStyle }, /* @__PURE__ */ React60.createElement("span", null, text)));
6220
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, /* @__PURE__ */ React58.createElement("span", { style: linkStyle }, /* @__PURE__ */ React58.createElement("span", null, text)));
5518
6221
  }
5519
6222
  function getFontFamily9(fontFamily) {
5520
6223
  switch (fontFamily) {
@@ -5578,7 +6281,7 @@ function getFontSize2(level) {
5578
6281
  }
5579
6282
  }
5580
6283
  function HeadingEditor({ style, props }) {
5581
- var _a, _b, _c, _d, _e, _f;
6284
+ var _a, _b, _c, _d, _e, _f, _g, _h;
5582
6285
  const blockId = useCurrentBlockId();
5583
6286
  const selectedBlockId = useSelectedBlockId();
5584
6287
  const document2 = useDocument();
@@ -5596,7 +6299,9 @@ function HeadingEditor({ style, props }) {
5596
6299
  color: (_c = style == null ? void 0 : style.color) != null ? _c : void 0,
5597
6300
  backgroundColor: (_d = style == null ? void 0 : style.backgroundColor) != null ? _d : void 0,
5598
6301
  fontWeight: (_e = style == null ? void 0 : style.fontWeight) != null ? _e : "bold",
5599
- textAlign: (_f = style == null ? void 0 : style.textAlign) != null ? _f : void 0,
6302
+ lineHeight: (_f = style == null ? void 0 : style.lineHeight) != null ? _f : void 0,
6303
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
6304
+ textAlign: (_g = style == null ? void 0 : style.textAlign) != null ? _g : void 0,
5600
6305
  margin: 0,
5601
6306
  fontFamily,
5602
6307
  fontSize: getFontSize2(level),
@@ -5610,7 +6315,7 @@ function HeadingEditor({ style, props }) {
5610
6315
  resize: "none",
5611
6316
  backgroundColor: "transparent",
5612
6317
  overflow: "hidden",
5613
- lineHeight: "inherit",
6318
+ lineHeight: (_h = hStyle.lineHeight) != null ? _h : "inherit",
5614
6319
  margin: 0,
5615
6320
  display: "block",
5616
6321
  width: "100%"
@@ -5636,27 +6341,43 @@ function HeadingEditor({ style, props }) {
5636
6341
  element.style.height = `${element.scrollHeight}px`;
5637
6342
  }
5638
6343
  };
6344
+ const trackFocus = (e) => {
6345
+ var _a2, _b2;
6346
+ const el = e.currentTarget;
6347
+ setLastFocusedEditable({
6348
+ blockId,
6349
+ field: "text",
6350
+ selectionStart: (_a2 = el.selectionStart) != null ? _a2 : el.value.length,
6351
+ selectionEnd: (_b2 = el.selectionEnd) != null ? _b2 : el.value.length
6352
+ });
6353
+ };
5639
6354
  if (isSelected) {
5640
- return /* @__PURE__ */ React60.createElement(
6355
+ return /* @__PURE__ */ React58.createElement(
5641
6356
  "textarea",
5642
6357
  {
5643
6358
  value: localText,
5644
6359
  onChange: handleTextChange,
6360
+ onFocus: trackFocus,
6361
+ onSelect: trackFocus,
6362
+ onKeyUp: trackFocus,
6363
+ onClick: (e) => {
6364
+ e.stopPropagation();
6365
+ trackFocus(e);
6366
+ },
5645
6367
  style: textareaStyle,
5646
6368
  rows: 1,
5647
6369
  onInput: (e) => adjustTextareaHeight(e.target),
5648
- ref: (el) => el && adjustTextareaHeight(el),
5649
- onClick: (e) => e.stopPropagation()
6370
+ ref: (el) => el && adjustTextareaHeight(el)
5650
6371
  }
5651
6372
  );
5652
6373
  }
5653
6374
  switch (level) {
5654
6375
  case "h1":
5655
- return /* @__PURE__ */ React60.createElement("h1", { style: hStyle }, textContent);
6376
+ return /* @__PURE__ */ React58.createElement("h1", { style: hStyle }, textContent);
5656
6377
  case "h2":
5657
- return /* @__PURE__ */ React60.createElement("h2", { style: hStyle }, textContent);
6378
+ return /* @__PURE__ */ React58.createElement("h2", { style: hStyle }, textContent);
5658
6379
  case "h3":
5659
- return /* @__PURE__ */ React60.createElement("h3", { style: hStyle }, textContent);
6380
+ return /* @__PURE__ */ React58.createElement("h3", { style: hStyle }, textContent);
5660
6381
  }
5661
6382
  }
5662
6383
  function HtmlEditor({ style, props }) {
@@ -5711,23 +6432,39 @@ function HtmlEditor({ style, props }) {
5711
6432
  margin: 0,
5712
6433
  backgroundColor: "transparent"
5713
6434
  });
5714
- return /* @__PURE__ */ React60.createElement("div", { style: cssStyle }, /* @__PURE__ */ React60.createElement(
6435
+ const trackFocus = (e) => {
6436
+ var _a2, _b2;
6437
+ const el = e.currentTarget;
6438
+ setLastFocusedEditable({
6439
+ blockId,
6440
+ field: "contents",
6441
+ selectionStart: (_a2 = el.selectionStart) != null ? _a2 : el.value.length,
6442
+ selectionEnd: (_b2 = el.selectionEnd) != null ? _b2 : el.value.length
6443
+ });
6444
+ };
6445
+ return /* @__PURE__ */ React58.createElement("div", { style: cssStyle }, /* @__PURE__ */ React58.createElement(
5715
6446
  "textarea",
5716
6447
  {
5717
6448
  value: localContents,
5718
6449
  onChange: handleChange,
6450
+ onFocus: trackFocus,
6451
+ onSelect: trackFocus,
6452
+ onKeyUp: trackFocus,
6453
+ onClick: (e) => {
6454
+ e.stopPropagation();
6455
+ trackFocus(e);
6456
+ },
5719
6457
  style: textareaStyle,
5720
6458
  rows: 3,
5721
6459
  onInput: (e) => adjustTextareaHeight(e.target),
5722
- ref: (el) => el && adjustTextareaHeight(el),
5723
- onClick: (e) => e.stopPropagation()
6460
+ ref: (el) => el && adjustTextareaHeight(el)
5724
6461
  }
5725
6462
  ));
5726
6463
  }
5727
6464
  if (!contents) {
5728
- return /* @__PURE__ */ React60.createElement("div", { style: cssStyle });
6465
+ return /* @__PURE__ */ React58.createElement("div", { style: cssStyle });
5729
6466
  }
5730
- return /* @__PURE__ */ React60.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: contents } });
6467
+ return /* @__PURE__ */ React58.createElement("div", { style: cssStyle, dangerouslySetInnerHTML: { __html: contents } });
5731
6468
  }
5732
6469
  function getImageBorderRadius2(shape, size) {
5733
6470
  switch (shape) {
@@ -5842,7 +6579,7 @@ function SignatureEditor({ style, props }) {
5842
6579
  backgroundColor: (_p = style == null ? void 0 : style.backgroundColor) != null ? _p : void 0,
5843
6580
  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
5844
6581
  };
5845
- const imageElement = imageUrl ? /* @__PURE__ */ React60.createElement(
6582
+ const imageElement = imageUrl ? /* @__PURE__ */ React58.createElement(
5846
6583
  "img",
5847
6584
  {
5848
6585
  src: imageUrl,
@@ -5860,7 +6597,7 @@ function SignatureEditor({ style, props }) {
5860
6597
  }
5861
6598
  }
5862
6599
  ) : null;
5863
- const greetingElement = isSelected ? /* @__PURE__ */ React60.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React60.createElement(
6600
+ const greetingElement = isSelected ? /* @__PURE__ */ React58.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React58.createElement(
5864
6601
  "input",
5865
6602
  {
5866
6603
  value: localGreeting,
@@ -5871,8 +6608,8 @@ function SignatureEditor({ style, props }) {
5871
6608
  placeholder: "Greeting (e.g. Best regards,)",
5872
6609
  style: __spreadValues(__spreadValues({}, inputBase), greetingStyle)
5873
6610
  }
5874
- )) : greeting ? /* @__PURE__ */ React60.createElement("p", { style: greetingStyle }, greeting) : null;
5875
- const textContent = isSelected ? /* @__PURE__ */ React60.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React60.createElement(
6611
+ )) : greeting ? /* @__PURE__ */ React58.createElement("p", { style: greetingStyle }, greeting) : null;
6612
+ const textContent = isSelected ? /* @__PURE__ */ React58.createElement("div", { onClick: (e) => e.stopPropagation() }, /* @__PURE__ */ React58.createElement(
5876
6613
  "input",
5877
6614
  {
5878
6615
  value: localName,
@@ -5883,7 +6620,7 @@ function SignatureEditor({ style, props }) {
5883
6620
  placeholder: "Name",
5884
6621
  style: __spreadValues(__spreadValues({}, inputBase), nameStyle)
5885
6622
  }
5886
- ), /* @__PURE__ */ React60.createElement(
6623
+ ), /* @__PURE__ */ React58.createElement(
5887
6624
  "input",
5888
6625
  {
5889
6626
  value: localTitle,
@@ -5894,7 +6631,7 @@ function SignatureEditor({ style, props }) {
5894
6631
  placeholder: "Title",
5895
6632
  style: __spreadValues(__spreadValues({}, inputBase), detailStyle)
5896
6633
  }
5897
- ), /* @__PURE__ */ React60.createElement(
6634
+ ), /* @__PURE__ */ React58.createElement(
5898
6635
  "input",
5899
6636
  {
5900
6637
  value: localCompany,
@@ -5905,7 +6642,7 @@ function SignatureEditor({ style, props }) {
5905
6642
  placeholder: "Company",
5906
6643
  style: __spreadValues(__spreadValues({}, inputBase), detailStyle)
5907
6644
  }
5908
- ), /* @__PURE__ */ React60.createElement(
6645
+ ), /* @__PURE__ */ React58.createElement(
5909
6646
  "input",
5910
6647
  {
5911
6648
  value: localAddress,
@@ -5916,7 +6653,7 @@ function SignatureEditor({ style, props }) {
5916
6653
  placeholder: "Address",
5917
6654
  style: __spreadValues(__spreadValues({}, inputBase), detailStyle)
5918
6655
  }
5919
- ), /* @__PURE__ */ React60.createElement(
6656
+ ), /* @__PURE__ */ React58.createElement(
5920
6657
  "input",
5921
6658
  {
5922
6659
  value: localEmail,
@@ -5927,7 +6664,7 @@ function SignatureEditor({ style, props }) {
5927
6664
  placeholder: "Email",
5928
6665
  style: __spreadProps(__spreadValues(__spreadValues({}, inputBase), linkStyle), { marginTop: 4, display: "block" })
5929
6666
  }
5930
- ), /* @__PURE__ */ React60.createElement(
6667
+ ), /* @__PURE__ */ React58.createElement(
5931
6668
  "input",
5932
6669
  {
5933
6670
  value: localPhone,
@@ -5938,7 +6675,7 @@ function SignatureEditor({ style, props }) {
5938
6675
  placeholder: "Phone",
5939
6676
  style: __spreadProps(__spreadValues(__spreadValues({}, inputBase), linkStyle), { display: "block" })
5940
6677
  }
5941
- ), /* @__PURE__ */ React60.createElement(
6678
+ ), /* @__PURE__ */ React58.createElement(
5942
6679
  "input",
5943
6680
  {
5944
6681
  value: localWebsite,
@@ -5949,11 +6686,11 @@ function SignatureEditor({ style, props }) {
5949
6686
  placeholder: "Website",
5950
6687
  style: __spreadProps(__spreadValues(__spreadValues({}, inputBase), linkStyle), { display: "block" })
5951
6688
  }
5952
- )) : /* @__PURE__ */ React60.createElement("div", null, name && /* @__PURE__ */ React60.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, address), (email || phone || website) && /* @__PURE__ */ React60.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, email && /* @__PURE__ */ React60.createElement("span", { style: linkStyle }, email), email && (phone || website) && /* @__PURE__ */ React60.createElement("span", { style: detailStyle }, " \xB7 "), phone && /* @__PURE__ */ React60.createElement("span", { style: linkStyle }, phone), phone && website && /* @__PURE__ */ React60.createElement("span", { style: detailStyle }, " \xB7 "), website && /* @__PURE__ */ React60.createElement("span", { style: linkStyle }, website)), !name && !title && !company && !email && !phone && !website && /* @__PURE__ */ React60.createElement("p", { style: detailStyle }, "Click to edit signature"));
6689
+ )) : /* @__PURE__ */ React58.createElement("div", null, name && /* @__PURE__ */ React58.createElement("p", { style: nameStyle }, name), title && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, title), company && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, company), address && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, address), (email || phone || website) && /* @__PURE__ */ React58.createElement("p", { style: __spreadProps(__spreadValues({}, detailStyle), { marginTop: 4 }) }, email && /* @__PURE__ */ React58.createElement("span", { style: linkStyle }, email), email && (phone || website) && /* @__PURE__ */ React58.createElement("span", { style: detailStyle }, " \xB7 "), phone && /* @__PURE__ */ React58.createElement("span", { style: linkStyle }, phone), phone && website && /* @__PURE__ */ React58.createElement("span", { style: detailStyle }, " \xB7 "), website && /* @__PURE__ */ React58.createElement("span", { style: linkStyle }, website)), !name && !title && !company && !email && !phone && !website && /* @__PURE__ */ React58.createElement("p", { style: detailStyle }, "Click to edit signature"));
5953
6690
  if (layout === "vertical") {
5954
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React60.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
6691
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, greetingElement, imageElement && /* @__PURE__ */ React58.createElement("div", { style: { marginBottom: 12 } }, imageElement), textContent);
5955
6692
  }
5956
- return /* @__PURE__ */ React60.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React60.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React60.createElement("tbody", null, /* @__PURE__ */ React60.createElement("tr", null, imageElement && /* @__PURE__ */ React60.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React60.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
6693
+ return /* @__PURE__ */ React58.createElement("div", { style: wrapperStyle }, greetingElement, /* @__PURE__ */ React58.createElement("table", { cellPadding: "0", cellSpacing: "0", border: 0, role: "presentation" }, /* @__PURE__ */ React58.createElement("tbody", null, /* @__PURE__ */ React58.createElement("tr", null, imageElement && /* @__PURE__ */ React58.createElement("td", { style: { verticalAlign: "middle", paddingRight: 16 } }, imageElement), /* @__PURE__ */ React58.createElement("td", { style: { verticalAlign: "middle" } }, textContent)))));
5957
6694
  }
5958
6695
  function getFontFamily10(fontFamily) {
5959
6696
  switch (fontFamily) {
@@ -6007,7 +6744,7 @@ function getPadding13(padding) {
6007
6744
  return void 0;
6008
6745
  }
6009
6746
  function TextEditor({ style, props }) {
6010
- var _a, _b, _c, _d, _e, _f, _g;
6747
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
6011
6748
  const blockId = useCurrentBlockId();
6012
6749
  const selectedBlockId = useSelectedBlockId();
6013
6750
  const document2 = useDocument();
@@ -6027,7 +6764,9 @@ function TextEditor({ style, props }) {
6027
6764
  fontSize: (_e = style == null ? void 0 : style.fontSize) != null ? _e : void 0,
6028
6765
  fontFamily,
6029
6766
  fontWeight: (_f = style == null ? void 0 : style.fontWeight) != null ? _f : void 0,
6030
- textAlign: (_g = style == null ? void 0 : style.textAlign) != null ? _g : void 0,
6767
+ lineHeight: (_g = style == null ? void 0 : style.lineHeight) != null ? _g : void 0,
6768
+ letterSpacing: (style == null ? void 0 : style.letterSpacing) != null ? `${style.letterSpacing}px` : void 0,
6769
+ textAlign: (_h = style == null ? void 0 : style.textAlign) != null ? _h : void 0,
6031
6770
  padding: getPadding13(style == null ? void 0 : style.padding),
6032
6771
  width: "100%",
6033
6772
  minHeight: "1em"
@@ -6038,7 +6777,7 @@ function TextEditor({ style, props }) {
6038
6777
  resize: "none",
6039
6778
  backgroundColor: "transparent",
6040
6779
  overflow: "hidden",
6041
- lineHeight: "inherit",
6780
+ lineHeight: (_i = wStyle.lineHeight) != null ? _i : "inherit",
6042
6781
  margin: 0,
6043
6782
  display: "block",
6044
6783
  width: "100%",
@@ -6067,51 +6806,67 @@ function TextEditor({ style, props }) {
6067
6806
  element.style.height = `${element.scrollHeight}px`;
6068
6807
  }
6069
6808
  };
6809
+ const trackFocus = (e) => {
6810
+ var _a2, _b2;
6811
+ const el = e.currentTarget;
6812
+ setLastFocusedEditable({
6813
+ blockId,
6814
+ field: "text",
6815
+ selectionStart: (_a2 = el.selectionStart) != null ? _a2 : el.value.length,
6816
+ selectionEnd: (_b2 = el.selectionEnd) != null ? _b2 : el.value.length
6817
+ });
6818
+ };
6070
6819
  if (isSelected) {
6071
- return /* @__PURE__ */ React60.createElement(
6820
+ return /* @__PURE__ */ React58.createElement(
6072
6821
  "textarea",
6073
6822
  {
6074
6823
  value: localText,
6075
6824
  onChange: handleTextChange,
6825
+ onFocus: trackFocus,
6826
+ onSelect: trackFocus,
6827
+ onKeyUp: trackFocus,
6828
+ onClick: (e) => {
6829
+ e.stopPropagation();
6830
+ trackFocus(e);
6831
+ },
6076
6832
  style: textareaStyle,
6077
6833
  rows: 1,
6078
6834
  onInput: (e) => adjustTextareaHeight(e.target),
6079
- ref: (el) => el && adjustTextareaHeight(el),
6080
- onClick: (e) => e.stopPropagation()
6835
+ ref: (el) => el && adjustTextareaHeight(el)
6081
6836
  }
6082
6837
  );
6083
6838
  }
6084
6839
  if (isMarkdown) {
6085
- return /* @__PURE__ */ React60.createElement(EmailMarkdown, { style: wStyle, markdown: textContent });
6840
+ return /* @__PURE__ */ React58.createElement(EmailMarkdown, { style: wStyle, markdown: textContent });
6086
6841
  }
6087
- return /* @__PURE__ */ React60.createElement("div", { style: wStyle }, textContent);
6842
+ return /* @__PURE__ */ React58.createElement("div", { style: wStyle }, textContent);
6088
6843
  }
6089
6844
 
6090
6845
  // src/editor/core.tsx
6091
6846
  var EDITOR_DICTIONARY = buildBlockConfigurationDictionary({
6092
6847
  Avatar: {
6093
6848
  schema: AvatarPropsSchema,
6094
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(avatar_default, __spreadValues({}, props)))
6849
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(avatar_default, __spreadValues({}, props)))
6095
6850
  },
6096
6851
  Button: {
6097
6852
  schema: ButtonPropsSchema,
6098
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(ButtonEditor, __spreadValues({}, props)))
6853
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(ButtonEditor, __spreadValues({}, props)))
6099
6854
  },
6100
6855
  Container: {
6101
6856
  schema: container_props_schema_default,
6102
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(ContainerEditor, __spreadValues({}, props)))
6857
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(ContainerEditor, __spreadValues({}, props)))
6103
6858
  },
6104
6859
  ColumnsContainer: {
6105
6860
  schema: columns_container_props_schema_default2,
6106
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(ColumnsContainerEditor, __spreadValues({}, props)))
6861
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(ColumnsContainerEditor, __spreadValues({}, props)))
6107
6862
  },
6108
6863
  Heading: {
6109
6864
  schema: HeadingPropsSchema,
6110
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(HeadingEditor, __spreadValues({}, props)))
6865
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(HeadingEditor, __spreadValues({}, props)))
6111
6866
  },
6112
6867
  Html: {
6113
6868
  schema: HtmlPropsSchema,
6114
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(HtmlEditor, __spreadValues({}, props)))
6869
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(HtmlEditor, __spreadValues({}, props)))
6115
6870
  },
6116
6871
  Image: {
6117
6872
  schema: ImagePropsSchema,
@@ -6123,28 +6878,28 @@ var EDITOR_DICTIONARY = buildBlockConfigurationDictionary({
6123
6878
  linkHref: null
6124
6879
  })
6125
6880
  });
6126
- return /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(image_default, __spreadValues({}, props)));
6881
+ return /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(image_default, __spreadValues({}, props)));
6127
6882
  }
6128
6883
  },
6129
6884
  Text: {
6130
6885
  schema: TextPropsSchema,
6131
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(TextEditor, __spreadValues({}, props)))
6886
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(TextEditor, __spreadValues({}, props)))
6132
6887
  },
6133
6888
  EmailLayout: {
6134
6889
  schema: email_layout_props_schema_default,
6135
- Component: (p) => /* @__PURE__ */ React60.createElement(EmailLayoutEditor, __spreadValues({}, p))
6890
+ Component: (p) => /* @__PURE__ */ React58.createElement(EmailLayoutEditor, __spreadValues({}, p))
6136
6891
  },
6137
6892
  Spacer: {
6138
6893
  schema: SpacerPropsSchema,
6139
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(spacer_default, __spreadValues({}, props)))
6894
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(spacer_default, __spreadValues({}, props)))
6140
6895
  },
6141
6896
  Divider: {
6142
6897
  schema: DividerPropsSchema,
6143
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(divider_default, __spreadValues({}, props)))
6898
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(divider_default, __spreadValues({}, props)))
6144
6899
  },
6145
6900
  Signature: {
6146
6901
  schema: SignaturePropsSchema,
6147
- Component: (props) => /* @__PURE__ */ React60.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React60.createElement(SignatureEditor, __spreadValues({}, props)))
6902
+ Component: (props) => /* @__PURE__ */ React58.createElement(EditorBlockWrapper, null, /* @__PURE__ */ React58.createElement(SignatureEditor, __spreadValues({}, props)))
6148
6903
  }
6149
6904
  });
6150
6905
  var EditorBlock2 = buildBlockComponent(EDITOR_DICTIONARY);
@@ -6160,7 +6915,7 @@ function EditorBlock({ id }) {
6160
6915
  if (!block) {
6161
6916
  throw new Error("Could not find block");
6162
6917
  }
6163
- return /* @__PURE__ */ React60.createElement(EditorBlockContext.Provider, { value: id }, /* @__PURE__ */ React60.createElement(EditorBlock2, __spreadValues({}, block)));
6918
+ return /* @__PURE__ */ React58.createElement(EditorBlockContext.Provider, { value: id }, /* @__PURE__ */ React58.createElement(EditorBlock2, __spreadValues({}, block)));
6164
6919
  }
6165
6920
  function ToggleInspectorPanelButton() {
6166
6921
  const inspectorDrawerOpen = useInspectorDrawerOpen();
@@ -6168,20 +6923,20 @@ function ToggleInspectorPanelButton() {
6168
6923
  toggleInspectorDrawerOpen();
6169
6924
  };
6170
6925
  if (inspectorDrawerOpen) {
6171
- return /* @__PURE__ */ React60.createElement(IconButton, { onClick: handleClick }, /* @__PURE__ */ React60.createElement(LastPageOutlined, { fontSize: "small" }));
6926
+ return /* @__PURE__ */ React58.createElement(IconButton, { onClick: handleClick }, /* @__PURE__ */ React58.createElement(LastPageOutlined, { fontSize: "small" }));
6172
6927
  }
6173
- return /* @__PURE__ */ React60.createElement(IconButton, { onClick: handleClick }, /* @__PURE__ */ React60.createElement(AppRegistrationOutlined, { fontSize: "small" }));
6928
+ return /* @__PURE__ */ React58.createElement(IconButton, { onClick: handleClick }, /* @__PURE__ */ React58.createElement(AppRegistrationOutlined, { fontSize: "small" }));
6174
6929
  }
6175
6930
  function useIcon() {
6176
6931
  const samplesDrawerOpen = useSamplesDrawerOpen();
6177
6932
  if (samplesDrawerOpen) {
6178
- return /* @__PURE__ */ React60.createElement(FirstPageOutlined, { fontSize: "small" });
6933
+ return /* @__PURE__ */ React58.createElement(FirstPageOutlined, { fontSize: "small" });
6179
6934
  }
6180
- return /* @__PURE__ */ React60.createElement(MenuOutlined, { fontSize: "small" });
6935
+ return /* @__PURE__ */ React58.createElement(MenuOutlined, { fontSize: "small" });
6181
6936
  }
6182
6937
  function ToggleSamplesPanelButton() {
6183
6938
  const icon = useIcon();
6184
- return /* @__PURE__ */ React60.createElement(IconButton, { onClick: toggleSamplesDrawerOpen }, icon);
6939
+ return /* @__PURE__ */ React58.createElement(IconButton, { onClick: toggleSamplesDrawerOpen }, icon);
6185
6940
  }
6186
6941
  function formatHtml(html2, spaces = 2) {
6187
6942
  try {
@@ -6243,7 +6998,7 @@ function HighlightedCodePanel({ type, value }) {
6243
6998
  if (code === null) {
6244
6999
  return null;
6245
7000
  }
6246
- return /* @__PURE__ */ React60.createElement(
7001
+ return /* @__PURE__ */ React58.createElement(
6247
7002
  "pre",
6248
7003
  {
6249
7004
  style: {
@@ -6269,17 +7024,17 @@ function HighlightedCodePanel({ type, value }) {
6269
7024
  function HtmlPanel() {
6270
7025
  const document2 = useDocument();
6271
7026
  const code = useMemo(() => renderToStaticMarkup(document2, { rootBlockId: "root" }), [document2]);
6272
- return /* @__PURE__ */ React60.createElement(HighlightedCodePanel, { type: "html", value: code });
7027
+ return /* @__PURE__ */ React58.createElement(HighlightedCodePanel, { type: "html", value: code });
6273
7028
  }
6274
7029
  function JsonPanel() {
6275
7030
  const document2 = useDocument();
6276
7031
  const code = useMemo(() => JSON.stringify(document2, null, " "), [document2]);
6277
- return /* @__PURE__ */ React60.createElement(HighlightedCodePanel, { type: "json", value: code });
7032
+ return /* @__PURE__ */ React58.createElement(HighlightedCodePanel, { type: "json", value: code });
6278
7033
  }
6279
7034
  function TextPanel() {
6280
7035
  const document2 = useDocument();
6281
7036
  const text = useMemo(() => renderToText(document2, { rootBlockId: "root" }), [document2]);
6282
- return /* @__PURE__ */ React60.createElement(
7037
+ return /* @__PURE__ */ React58.createElement(
6283
7038
  "pre",
6284
7039
  {
6285
7040
  style: {
@@ -6315,35 +7070,35 @@ function MainTabsGroup() {
6315
7070
  setSelectedMainTab("editor");
6316
7071
  }
6317
7072
  };
6318
- return /* @__PURE__ */ React60.createElement(Tabs, { value: selectedMainTab, onChange: handleChange }, /* @__PURE__ */ React60.createElement(
7073
+ return /* @__PURE__ */ React58.createElement(Tabs, { value: selectedMainTab, onChange: handleChange }, /* @__PURE__ */ React58.createElement(
6319
7074
  Tab,
6320
7075
  {
6321
7076
  value: "editor",
6322
- label: /* @__PURE__ */ React60.createElement(Tooltip, { title: "Edit" }, /* @__PURE__ */ React60.createElement(EditOutlined, { fontSize: "small" }))
7077
+ label: /* @__PURE__ */ React58.createElement(Tooltip, { title: "Edit" }, /* @__PURE__ */ React58.createElement(EditOutlined, { fontSize: "small" }))
6323
7078
  }
6324
- ), /* @__PURE__ */ React60.createElement(
7079
+ ), /* @__PURE__ */ React58.createElement(
6325
7080
  Tab,
6326
7081
  {
6327
7082
  value: "preview",
6328
- label: /* @__PURE__ */ React60.createElement(Tooltip, { title: "Preview" }, /* @__PURE__ */ React60.createElement(PreviewOutlined, { fontSize: "small" }))
7083
+ label: /* @__PURE__ */ React58.createElement(Tooltip, { title: "Preview" }, /* @__PURE__ */ React58.createElement(PreviewOutlined, { fontSize: "small" }))
6329
7084
  }
6330
- ), /* @__PURE__ */ React60.createElement(
7085
+ ), /* @__PURE__ */ React58.createElement(
6331
7086
  Tab,
6332
7087
  {
6333
7088
  value: "html",
6334
- label: /* @__PURE__ */ React60.createElement(Tooltip, { title: "HTML output" }, /* @__PURE__ */ React60.createElement(CodeOutlined, { fontSize: "small" }))
7089
+ label: /* @__PURE__ */ React58.createElement(Tooltip, { title: "HTML output" }, /* @__PURE__ */ React58.createElement(CodeOutlined, { fontSize: "small" }))
6335
7090
  }
6336
- ), /* @__PURE__ */ React60.createElement(
7091
+ ), /* @__PURE__ */ React58.createElement(
6337
7092
  Tab,
6338
7093
  {
6339
7094
  value: "text",
6340
- label: /* @__PURE__ */ React60.createElement(Tooltip, { title: "Plain text output" }, /* @__PURE__ */ React60.createElement(SubjectOutlined, { fontSize: "small" }))
7095
+ label: /* @__PURE__ */ React58.createElement(Tooltip, { title: "Plain text output" }, /* @__PURE__ */ React58.createElement(SubjectOutlined, { fontSize: "small" }))
6341
7096
  }
6342
- ), /* @__PURE__ */ React60.createElement(
7097
+ ), /* @__PURE__ */ React58.createElement(
6343
7098
  Tab,
6344
7099
  {
6345
7100
  value: "json",
6346
- label: /* @__PURE__ */ React60.createElement(Tooltip, { title: "JSON output" }, /* @__PURE__ */ React60.createElement(DataObjectOutlined, { fontSize: "small" }))
7101
+ label: /* @__PURE__ */ React58.createElement(Tooltip, { title: "JSON output" }, /* @__PURE__ */ React58.createElement(DataObjectOutlined, { fontSize: "small" }))
6347
7102
  }
6348
7103
  ));
6349
7104
  }
@@ -6389,7 +7144,7 @@ function SaveButton({ loadTemplates, saveAs }) {
6389
7144
  return false;
6390
7145
  }
6391
7146
  });
6392
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
7147
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
6393
7148
  IconButton,
6394
7149
  {
6395
7150
  onClick: handleSave,
@@ -6400,8 +7155,8 @@ function SaveButton({ loadTemplates, saveAs }) {
6400
7155
  }
6401
7156
  }
6402
7157
  },
6403
- /* @__PURE__ */ React60.createElement(Tooltip, { title: isSample ? "Save as new template" : "Save template" }, /* @__PURE__ */ React60.createElement(SaveOutlined, { fontSize: "small" }))
6404
- ), /* @__PURE__ */ React60.createElement(
7158
+ /* @__PURE__ */ React58.createElement(Tooltip, { title: isSample ? "Save as new template" : "Save template" }, /* @__PURE__ */ React58.createElement(SaveOutlined, { fontSize: "small" }))
7159
+ ), /* @__PURE__ */ React58.createElement(
6405
7160
  SaveTemplateDialog,
6406
7161
  {
6407
7162
  open: saveDialogOpen,
@@ -6471,7 +7226,7 @@ function NewTemplateButton({ loadTemplates, saveAs }) {
6471
7226
  }
6472
7227
  return false;
6473
7228
  });
6474
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
7229
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
6475
7230
  IconButton,
6476
7231
  {
6477
7232
  onClick: handleNewTemplate,
@@ -6482,8 +7237,8 @@ function NewTemplateButton({ loadTemplates, saveAs }) {
6482
7237
  }
6483
7238
  }
6484
7239
  },
6485
- /* @__PURE__ */ React60.createElement(Tooltip, { title: "New template" }, /* @__PURE__ */ React60.createElement(Add, { fontSize: "small" }))
6486
- ), /* @__PURE__ */ React60.createElement(
7240
+ /* @__PURE__ */ React58.createElement(Tooltip, { title: "New template" }, /* @__PURE__ */ React58.createElement(Add, { fontSize: "small" }))
7241
+ ), /* @__PURE__ */ React58.createElement(
6487
7242
  SaveTemplateDialog,
6488
7243
  {
6489
7244
  open: saveDialogOpen,
@@ -6510,7 +7265,18 @@ function SubjectInput() {
6510
7265
  root: __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, data), { subject: value }) })
6511
7266
  });
6512
7267
  };
6513
- return /* @__PURE__ */ React60.createElement(
7268
+ const trackFocus = (e) => {
7269
+ var _a2, _b;
7270
+ const target = e.target;
7271
+ if (!target || typeof target.value !== "string") return;
7272
+ setLastFocusedEditable({
7273
+ blockId: "subject",
7274
+ field: "subject",
7275
+ selectionStart: (_a2 = target.selectionStart) != null ? _a2 : target.value.length,
7276
+ selectionEnd: (_b = target.selectionEnd) != null ? _b : target.value.length
7277
+ });
7278
+ };
7279
+ return /* @__PURE__ */ React58.createElement(
6514
7280
  Box,
6515
7281
  {
6516
7282
  sx: {
@@ -6527,19 +7293,191 @@ function SubjectInput() {
6527
7293
  gap: 1.5
6528
7294
  }
6529
7295
  },
6530
- /* @__PURE__ */ React60.createElement(Box, { sx: { color: "text.secondary", fontSize: 13, fontWeight: 600, minWidth: 56 } }, "Subject"),
6531
- /* @__PURE__ */ React60.createElement(
7296
+ /* @__PURE__ */ React58.createElement(Box, { sx: { color: "text.secondary", fontSize: 13, fontWeight: 600, minWidth: 56 } }, "Subject"),
7297
+ /* @__PURE__ */ React58.createElement(
6532
7298
  InputBase,
6533
7299
  {
6534
7300
  fullWidth: true,
6535
7301
  placeholder: "Email subject \u2014 supports {{variables}}",
6536
7302
  value: subject,
6537
7303
  onChange: (e) => handleChange(e.target.value),
7304
+ onFocus: trackFocus,
7305
+ onSelect: trackFocus,
7306
+ onKeyUp: trackFocus,
7307
+ onClick: trackFocus,
6538
7308
  sx: { fontSize: 14 }
6539
7309
  }
6540
7310
  )
6541
7311
  );
6542
7312
  }
7313
+ function SubjectPreview() {
7314
+ var _a, _b;
7315
+ const document2 = useDocument();
7316
+ const root = document2.root;
7317
+ if (!root || root.type !== "EmailLayout") return null;
7318
+ const data = root.data;
7319
+ const subject = (_a = data.subject) != null ? _a : "";
7320
+ if (!subject) return null;
7321
+ const samples = buildSampleValueMap((_b = data.variables) != null ? _b : []);
7322
+ const rendered = substituteSampleValues(subject, samples);
7323
+ return /* @__PURE__ */ React58.createElement(
7324
+ Box,
7325
+ {
7326
+ sx: {
7327
+ px: 3,
7328
+ py: 1.25,
7329
+ borderBottom: 1,
7330
+ borderColor: "divider",
7331
+ backgroundColor: "white",
7332
+ position: "sticky",
7333
+ top: 49,
7334
+ zIndex: "appBar",
7335
+ display: "flex",
7336
+ alignItems: "center",
7337
+ gap: 1.5
7338
+ }
7339
+ },
7340
+ /* @__PURE__ */ React58.createElement(Box, { sx: { color: "text.secondary", fontSize: 13, fontWeight: 600, minWidth: 56 } }, "Subject"),
7341
+ /* @__PURE__ */ React58.createElement(Box, { sx: { fontSize: 14 } }, rendered)
7342
+ );
7343
+ }
7344
+ function generateId3() {
7345
+ return `block-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
7346
+ }
7347
+ function buildImageBlock(uploaded) {
7348
+ var _a, _b, _c;
7349
+ return {
7350
+ type: "Image",
7351
+ data: {
7352
+ props: {
7353
+ url: uploaded.url,
7354
+ width: (_a = uploaded.width) != null ? _a : null,
7355
+ height: (_b = uploaded.height) != null ? _b : null,
7356
+ alt: (_c = uploaded.alt) != null ? _c : "",
7357
+ contentAlignment: "middle"
7358
+ },
7359
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
7360
+ }
7361
+ };
7362
+ }
7363
+ function appendImageBlock(uploaded) {
7364
+ var _a;
7365
+ const doc = getDocument();
7366
+ const root = doc.root;
7367
+ if (!root || root.type !== "EmailLayout") return;
7368
+ const id = generateId3();
7369
+ const childrenIds = [...(_a = root.data.childrenIds) != null ? _a : [], id];
7370
+ setDocument({
7371
+ [id]: buildImageBlock(uploaded),
7372
+ root: __spreadProps(__spreadValues({}, root), { data: __spreadProps(__spreadValues({}, root.data), { childrenIds }) })
7373
+ });
7374
+ setSelectedBlockId(id);
7375
+ }
7376
+ function findImageFile(items) {
7377
+ var _a;
7378
+ if (!items) return null;
7379
+ const fileList = items instanceof FileList ? Array.from(items) : Array.from(items);
7380
+ for (const item of fileList) {
7381
+ const file = item instanceof File ? item : (_a = item.getAsFile) == null ? void 0 : _a.call(item);
7382
+ if (file && file.type.startsWith("image/")) return file;
7383
+ }
7384
+ return null;
7385
+ }
7386
+ function ImageDropPasteHandler({ enabled, children }) {
7387
+ const { uploadImage } = useImageCallbacks();
7388
+ const wrapperRef = useRef(null);
7389
+ const dragDepth = useRef(0);
7390
+ const [dragging, setDragging] = useState(false);
7391
+ const [uploading, setUploading] = useState(false);
7392
+ const active = enabled && Boolean(uploadImage);
7393
+ useEffect(() => {
7394
+ if (!active || !uploadImage) return;
7395
+ const handlePaste = (e) => __async(null, null, function* () {
7396
+ var _a;
7397
+ const target = e.target;
7398
+ if ((target == null ? void 0 : target.tagName) === "INPUT" || (target == null ? void 0 : target.tagName) === "TEXTAREA" || (target == null ? void 0 : target.isContentEditable)) return;
7399
+ const file = findImageFile((_a = e.clipboardData) == null ? void 0 : _a.files);
7400
+ if (!file) return;
7401
+ e.preventDefault();
7402
+ setUploading(true);
7403
+ try {
7404
+ const uploaded = yield uploadImage(file);
7405
+ appendImageBlock(uploaded);
7406
+ } catch (e2) {
7407
+ } finally {
7408
+ setUploading(false);
7409
+ }
7410
+ });
7411
+ window.addEventListener("paste", handlePaste);
7412
+ return () => window.removeEventListener("paste", handlePaste);
7413
+ }, [active, uploadImage]);
7414
+ if (!active) return /* @__PURE__ */ React58.createElement(React58.Fragment, null, children);
7415
+ const onDragEnter = (e) => {
7416
+ var _a, _b;
7417
+ if (!Array.from((_b = (_a = e.dataTransfer) == null ? void 0 : _a.items) != null ? _b : []).some((i) => i.kind === "file")) return;
7418
+ dragDepth.current += 1;
7419
+ setDragging(true);
7420
+ };
7421
+ const onDragLeave = () => {
7422
+ dragDepth.current = Math.max(0, dragDepth.current - 1);
7423
+ if (dragDepth.current === 0) setDragging(false);
7424
+ };
7425
+ const onDragOver = (e) => {
7426
+ var _a, _b;
7427
+ if (!Array.from((_b = (_a = e.dataTransfer) == null ? void 0 : _a.items) != null ? _b : []).some((i) => i.kind === "file")) return;
7428
+ e.preventDefault();
7429
+ e.dataTransfer.dropEffect = "copy";
7430
+ };
7431
+ const onDrop = (e) => __async(null, null, function* () {
7432
+ var _a;
7433
+ dragDepth.current = 0;
7434
+ setDragging(false);
7435
+ const file = findImageFile((_a = e.dataTransfer) == null ? void 0 : _a.files);
7436
+ if (!file || !uploadImage) return;
7437
+ e.preventDefault();
7438
+ setUploading(true);
7439
+ try {
7440
+ const uploaded = yield uploadImage(file);
7441
+ appendImageBlock(uploaded);
7442
+ } catch (e2) {
7443
+ } finally {
7444
+ setUploading(false);
7445
+ }
7446
+ });
7447
+ return /* @__PURE__ */ React58.createElement(
7448
+ Box,
7449
+ {
7450
+ ref: wrapperRef,
7451
+ onDragEnter,
7452
+ onDragLeave,
7453
+ onDragOver,
7454
+ onDrop,
7455
+ sx: { position: "relative" }
7456
+ },
7457
+ children,
7458
+ (dragging || uploading) && /* @__PURE__ */ React58.createElement(
7459
+ Box,
7460
+ {
7461
+ sx: {
7462
+ position: "absolute",
7463
+ inset: 0,
7464
+ backgroundColor: "rgba(33, 150, 243, 0.06)",
7465
+ border: "2px dashed",
7466
+ borderColor: "primary.main",
7467
+ borderRadius: 1,
7468
+ display: "flex",
7469
+ alignItems: "flex-start",
7470
+ justifyContent: "center",
7471
+ paddingTop: 12,
7472
+ color: "primary.dark",
7473
+ pointerEvents: "none",
7474
+ zIndex: 10
7475
+ }
7476
+ },
7477
+ /* @__PURE__ */ React58.createElement(Box, { sx: { display: "flex", alignItems: "center", gap: 1, fontWeight: 600, fontSize: 14 } }, /* @__PURE__ */ React58.createElement(CloudUploadOutlined, null), uploading ? "Uploading\u2026" : "Drop image to insert")
7478
+ )
7479
+ );
7480
+ }
6543
7481
 
6544
7482
  // src/app/email-canvas/index.tsx
6545
7483
  function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true }) {
@@ -6570,21 +7508,29 @@ function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true })
6570
7508
  }
6571
7509
  };
6572
7510
  const renderMainPanel = () => {
7511
+ var _a;
6573
7512
  switch (selectedMainTab) {
6574
7513
  case "editor":
6575
- return /* @__PURE__ */ React60.createElement(Box, { sx: mainBoxSx }, /* @__PURE__ */ React60.createElement(EditorBlock, { id: "root" }));
6576
- case "preview":
6577
- return /* @__PURE__ */ React60.createElement(Box, { sx: mainBoxSx }, /* @__PURE__ */ React60.createElement(Reader, { document: document2, rootBlockId: "root" }));
7514
+ return /* @__PURE__ */ React58.createElement(Box, { sx: mainBoxSx }, /* @__PURE__ */ React58.createElement(EditorBlock, { id: "root" }));
7515
+ case "preview": {
7516
+ const rootBlock = document2.root;
7517
+ const layoutData = rootBlock && rootBlock.type === "EmailLayout" ? rootBlock.data : void 0;
7518
+ const samples = buildSampleValueMap(
7519
+ (_a = layoutData == null ? void 0 : layoutData.variables) != null ? _a : []
7520
+ );
7521
+ const previewDoc = applySampleValuesToDocument(document2, samples);
7522
+ return /* @__PURE__ */ React58.createElement(Box, { sx: mainBoxSx }, /* @__PURE__ */ React58.createElement(Reader, { document: previewDoc, rootBlockId: "root" }));
7523
+ }
6578
7524
  case "html":
6579
- return /* @__PURE__ */ React60.createElement(HtmlPanel, null);
7525
+ return /* @__PURE__ */ React58.createElement(HtmlPanel, null);
6580
7526
  case "text":
6581
- return /* @__PURE__ */ React60.createElement(TextPanel, null);
7527
+ return /* @__PURE__ */ React58.createElement(TextPanel, null);
6582
7528
  case "json":
6583
- return /* @__PURE__ */ React60.createElement(JsonPanel, null);
7529
+ return /* @__PURE__ */ React58.createElement(JsonPanel, null);
6584
7530
  }
6585
7531
  };
6586
7532
  const showSaveButtons = persistenceEnabled;
6587
- return /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(
7533
+ return /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(
6588
7534
  Stack,
6589
7535
  {
6590
7536
  sx: {
@@ -6601,13 +7547,13 @@ function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true })
6601
7547
  justifyContent: "space-between",
6602
7548
  alignItems: "center"
6603
7549
  },
6604
- samplesDrawerEnabled && /* @__PURE__ */ React60.createElement(ToggleSamplesPanelButton, null),
6605
- /* @__PURE__ */ React60.createElement(Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React60.createElement(MainTabsGroup, null)), /* @__PURE__ */ React60.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React60.createElement(ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React60.createElement(ToggleButton, { value: "desktop" }, /* @__PURE__ */ React60.createElement(Tooltip, { title: "Desktop view" }, /* @__PURE__ */ React60.createElement(MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React60.createElement(ToggleButton, { value: "mobile" }, /* @__PURE__ */ React60.createElement(Tooltip, { title: "Mobile view" }, /* @__PURE__ */ React60.createElement(PhoneIphoneOutlined, { fontSize: "small" })))), showSaveButtons && /* @__PURE__ */ React60.createElement(React60.Fragment, null, /* @__PURE__ */ React60.createElement(NewTemplateButton, { loadTemplates, saveAs }), /* @__PURE__ */ React60.createElement(SaveButton, { loadTemplates, saveAs })))),
6606
- /* @__PURE__ */ React60.createElement(ToggleInspectorPanelButton, null)
6607
- ), selectedMainTab === "editor" && /* @__PURE__ */ React60.createElement(SubjectInput, null), /* @__PURE__ */ React60.createElement(Box, { sx: {
7550
+ samplesDrawerEnabled && /* @__PURE__ */ React58.createElement(ToggleSamplesPanelButton, null),
7551
+ /* @__PURE__ */ React58.createElement(Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React58.createElement(MainTabsGroup, null)), /* @__PURE__ */ React58.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React58.createElement(ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React58.createElement(ToggleButton, { value: "desktop" }, /* @__PURE__ */ React58.createElement(Tooltip, { title: "Desktop view" }, /* @__PURE__ */ React58.createElement(MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React58.createElement(ToggleButton, { value: "mobile" }, /* @__PURE__ */ React58.createElement(Tooltip, { title: "Mobile view" }, /* @__PURE__ */ React58.createElement(PhoneIphoneOutlined, { fontSize: "small" })))), showSaveButtons && /* @__PURE__ */ React58.createElement(React58.Fragment, null, /* @__PURE__ */ React58.createElement(NewTemplateButton, { loadTemplates, saveAs }), /* @__PURE__ */ React58.createElement(SaveButton, { loadTemplates, saveAs })))),
7552
+ /* @__PURE__ */ React58.createElement(ToggleInspectorPanelButton, null)
7553
+ ), selectedMainTab === "editor" && /* @__PURE__ */ React58.createElement(SubjectInput, null), selectedMainTab === "preview" && /* @__PURE__ */ React58.createElement(SubjectPreview, null), /* @__PURE__ */ React58.createElement(ImageDropPasteHandler, { enabled: selectedMainTab === "editor" }, /* @__PURE__ */ React58.createElement(Box, { sx: {
6608
7554
  paddingBottom: "50px",
6609
7555
  minWidth: 370
6610
- } }, renderMainPanel()));
7556
+ } }, renderMainPanel())));
6611
7557
  }
6612
7558
 
6613
7559
  // src/app/index.tsx
@@ -6688,7 +7634,7 @@ var EmailEditorInternal = forwardRef((props, ref) => {
6688
7634
  return getDocument();
6689
7635
  }
6690
7636
  }));
6691
- return /* @__PURE__ */ React60.createElement(Stack, { position: "relative", id: "drawer-container", sx: { minHeight } }, /* @__PURE__ */ React60.createElement(
7637
+ return /* @__PURE__ */ React58.createElement(Stack, { position: "relative", id: "drawer-container", sx: { minHeight } }, /* @__PURE__ */ React58.createElement(
6692
7638
  InspectorDrawer,
6693
7639
  {
6694
7640
  enterDuration: drawerEnterDuration,
@@ -6696,7 +7642,7 @@ var EmailEditorInternal = forwardRef((props, ref) => {
6696
7642
  deleteTemplate,
6697
7643
  copyTemplate
6698
7644
  }
6699
- ), /* @__PURE__ */ React60.createElement(
7645
+ ), /* @__PURE__ */ React58.createElement(
6700
7646
  SamplesDrawer,
6701
7647
  {
6702
7648
  enterDuration: drawerEnterDuration,
@@ -6712,7 +7658,7 @@ var EmailEditorInternal = forwardRef((props, ref) => {
6712
7658
  setTemplateKind,
6713
7659
  saveAs
6714
7660
  }
6715
- ), /* @__PURE__ */ React60.createElement(
7661
+ ), /* @__PURE__ */ React58.createElement(
6716
7662
  Stack,
6717
7663
  {
6718
7664
  sx: {
@@ -6721,7 +7667,7 @@ var EmailEditorInternal = forwardRef((props, ref) => {
6721
7667
  transition: [marginLeftTransition, marginRightTransition].join(", ")
6722
7668
  }
6723
7669
  },
6724
- /* @__PURE__ */ React60.createElement(TemplatePanel2, { loadTemplates, saveAs, samplesDrawerEnabled })
7670
+ /* @__PURE__ */ React58.createElement(TemplatePanel2, { loadTemplates, saveAs, samplesDrawerEnabled })
6725
7671
  ));
6726
7672
  });
6727
7673
  var EmailEditor = forwardRef((props, ref) => {
@@ -6744,6 +7690,9 @@ var EmailEditor = forwardRef((props, ref) => {
6744
7690
  renameTemplate,
6745
7691
  setTemplateKind,
6746
7692
  saveAs,
7693
+ uploadImage,
7694
+ loadImages,
7695
+ deleteImage,
6747
7696
  theme
6748
7697
  } = props;
6749
7698
  const resolvedTemplate = useMemo(
@@ -6758,7 +7707,11 @@ var EmailEditor = forwardRef((props, ref) => {
6758
7707
  useEffect(() => {
6759
7708
  setPersistenceEnabled(persistenceEnabled);
6760
7709
  }, [persistenceEnabled]);
6761
- return /* @__PURE__ */ React60.createElement(ThemeProvider, { theme: theme || theme_default }, /* @__PURE__ */ React60.createElement(CssBaseline, null), /* @__PURE__ */ React60.createElement("div", { style: { height: "100%", overflow: "auto" } }, /* @__PURE__ */ React60.createElement(SnackbarProvider, null, /* @__PURE__ */ React60.createElement(
7710
+ const imageCallbacks = useMemo(
7711
+ () => ({ uploadImage, loadImages, deleteImage }),
7712
+ [uploadImage, loadImages, deleteImage]
7713
+ );
7714
+ return /* @__PURE__ */ React58.createElement(ThemeProvider, { theme: theme || theme_default }, /* @__PURE__ */ React58.createElement(CssBaseline, null), /* @__PURE__ */ React58.createElement("div", { style: { height: "100%", overflow: "auto" } }, /* @__PURE__ */ React58.createElement(SnackbarProvider, null, /* @__PURE__ */ React58.createElement(ImageCallbacksProvider, { callbacks: imageCallbacks }, /* @__PURE__ */ React58.createElement(
6762
7715
  EmailEditorProvider,
6763
7716
  {
6764
7717
  initialTemplate: resolvedTemplate,
@@ -6767,7 +7720,7 @@ var EmailEditor = forwardRef((props, ref) => {
6767
7720
  onSave,
6768
7721
  onChange
6769
7722
  },
6770
- /* @__PURE__ */ React60.createElement(
7723
+ /* @__PURE__ */ React58.createElement(
6771
7724
  EmailEditorInternal,
6772
7725
  {
6773
7726
  ref,
@@ -6786,7 +7739,7 @@ var EmailEditor = forwardRef((props, ref) => {
6786
7739
  onChange
6787
7740
  }
6788
7741
  )
6789
- ))));
7742
+ )))));
6790
7743
  });
6791
7744
  EmailEditor.displayName = "EmailEditor";
6792
7745
  EmailEditorInternal.displayName = "EmailEditorInternal";