@savvycal/mjml-editor 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"InteractivePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/InteractivePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAID,wBAAgB,kBAAkB,CAAC,EACjC,UAAiB,EACjB,WAAuB,GACxB,EAAE,uBAAuB,2CAkLzB"}
1
+ {"version":3,"file":"InteractivePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/InteractivePreview.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,UAAU,uBAAuB;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAID,wBAAgB,kBAAkB,CAAC,EACjC,UAAiB,EACjB,WAAuB,GACxB,EAAE,uBAAuB,2CAqLzB"}
@@ -1,5 +1,5 @@
1
- import { jsxs as r, jsx as s } from "react/jsx-runtime";
2
- import { useRef as w, useState as b, useEffect as c, useCallback as E } from "react";
1
+ import { jsxs as n, jsx as s } from "react/jsx-runtime";
2
+ import { useRef as w, useState as h, useEffect as a, useCallback as E } from "react";
3
3
  import { useEditor as y } from "../../context/EditorContext.js";
4
4
  import { renderMjmlInteractive as C } from "../../lib/mjml/renderer.js";
5
5
  const I = 375;
@@ -7,31 +7,31 @@ function S({
7
7
  showHeader: p = !0,
8
8
  previewMode: g = "desktop"
9
9
  }) {
10
- const { state: n, selectBlock: d } = y(), o = w(null), [m, x] = b(n.document), [v, k] = b({
10
+ const { state: r, selectBlock: d } = y(), o = w(null), [m, x] = h(r.document), [k, v] = h({
11
11
  html: "",
12
12
  errors: []
13
13
  });
14
- c(() => {
14
+ a(() => {
15
15
  const e = setTimeout(() => {
16
- x(n.document);
16
+ x(r.document);
17
17
  }, 300);
18
18
  return () => clearTimeout(e);
19
- }, [n.document]), c(() => {
19
+ }, [r.document]), a(() => {
20
20
  let e = !1;
21
21
  return C(m).then((t) => {
22
- e || k(t);
22
+ e || v(t);
23
23
  }), () => {
24
24
  e = !0;
25
25
  };
26
26
  }, [m]);
27
- const { html: u, errors: l } = v, i = E(
27
+ const { html: u, errors: l } = k, i = E(
28
28
  (e) => {
29
29
  e.data?.type === "BLOCK_SELECTED" && d(e.data.blockId);
30
30
  },
31
31
  [d]
32
32
  );
33
- c(() => (window.addEventListener("message", i), () => window.removeEventListener("message", i)), [i]);
34
- const a = n.selectedBlockId ? `.block-${n.selectedBlockId} { outline: 2px solid #6366f1 !important; outline-offset: -2px; position: relative; }` : "", f = `
33
+ a(() => (window.addEventListener("message", i), () => window.removeEventListener("message", i)), [i]);
34
+ const c = r.selectedBlockId ? `.block-${r.selectedBlockId} { outline: 2px solid #6366f1 !important; outline-offset: -2px; position: relative; }` : "", b = `
35
35
  (function() {
36
36
  document.addEventListener('click', function(e) {
37
37
  e.preventDefault();
@@ -60,15 +60,15 @@ function S({
60
60
  }, true);
61
61
  })();
62
62
  `;
63
- return c(() => {
63
+ return a(() => {
64
64
  if (o.current) {
65
65
  const e = o.current.contentDocument;
66
66
  if (e) {
67
67
  e.open(), e.write(u), e.close();
68
68
  const t = e.createElement("script");
69
- t.textContent = f, e.body.appendChild(t);
70
- const h = e.createElement("style");
71
- h.textContent = `
69
+ t.textContent = b, e.body.appendChild(t);
70
+ const f = e.createElement("style");
71
+ f.textContent = `
72
72
  [class*="block-"] {
73
73
  cursor: pointer;
74
74
  transition: outline 0.15s ease;
@@ -77,22 +77,22 @@ function S({
77
77
  outline: 1px dashed #94a3b8 !important;
78
78
  outline-offset: -1px;
79
79
  }
80
- ${a}
81
- `, e.head.appendChild(h);
80
+ ${c}
81
+ `, e.head.appendChild(f);
82
82
  }
83
83
  }
84
- }, [u, a, f]), c(() => {
84
+ }, [u, c, b]), a(() => {
85
85
  if (o.current) {
86
86
  const e = o.current.contentDocument;
87
87
  if (e) {
88
88
  let t = e.getElementById("selection-highlight");
89
- t || (t = e.createElement("style"), t.id = "selection-highlight", e.head.appendChild(t)), t.textContent = a;
89
+ t || (t = e.createElement("style"), t.id = "selection-highlight", e.head.appendChild(t)), t.textContent = c;
90
90
  }
91
91
  }
92
- }, [n.selectedBlockId, a]), /* @__PURE__ */ r("div", { className: "flex flex-col h-full", children: [
93
- p && /* @__PURE__ */ r("div", { className: "h-11 px-4 flex items-center justify-between border-b border-border bg-background", children: [
92
+ }, [r.selectedBlockId, c]), /* @__PURE__ */ n("div", { className: "flex flex-col h-full", children: [
93
+ p && /* @__PURE__ */ n("div", { className: "h-11 px-4 flex items-center justify-between border-b border-border bg-background", children: [
94
94
  /* @__PURE__ */ s("span", { className: "text-sm font-semibold text-foreground", children: "Preview" }),
95
- l.length > 0 && /* @__PURE__ */ r("span", { className: "text-xs font-medium text-amber-600 bg-amber-50 px-2 py-0.5 rounded-md", children: [
95
+ l.length > 0 && /* @__PURE__ */ n("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/30 px-2 py-0.5 rounded-md", children: [
96
96
  l.length,
97
97
  " warning",
98
98
  l.length !== 1 ? "s" : ""
@@ -111,17 +111,24 @@ function S({
111
111
  sandbox: "allow-same-origin allow-scripts"
112
112
  }
113
113
  ) }),
114
- l.length > 0 && /* @__PURE__ */ r("div", { className: "max-h-28 overflow-auto border-t border-border bg-amber-50/50 p-3", children: [
115
- /* @__PURE__ */ s("div", { className: "text-xs font-semibold text-amber-700 mb-2", children: "Warnings" }),
116
- /* @__PURE__ */ s("div", { className: "space-y-1", children: l.map((e, t) => /* @__PURE__ */ r("div", { className: "text-xs text-amber-600", children: [
117
- /* @__PURE__ */ r("span", { className: "font-mono", children: [
118
- "Line ",
119
- e.line,
120
- ":"
121
- ] }),
122
- " ",
123
- e.message
124
- ] }, t)) })
114
+ l.length > 0 && /* @__PURE__ */ n("div", { className: "max-h-28 overflow-auto border-t border-border bg-amber-50/50 dark:bg-amber-900/20 p-3", children: [
115
+ /* @__PURE__ */ s("div", { className: "text-xs font-semibold text-amber-700 dark:text-amber-300 mb-2", children: "Warnings" }),
116
+ /* @__PURE__ */ s("div", { className: "space-y-1", children: l.map((e, t) => /* @__PURE__ */ n(
117
+ "div",
118
+ {
119
+ className: "text-xs text-amber-600 dark:text-amber-400",
120
+ children: [
121
+ /* @__PURE__ */ n("span", { className: "font-mono", children: [
122
+ "Line ",
123
+ e.line,
124
+ ":"
125
+ ] }),
126
+ " ",
127
+ e.message
128
+ ]
129
+ },
130
+ t
131
+ )) })
125
132
  ] })
126
133
  ] });
127
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OutlineTree.d.ts","sourceRoot":"","sources":["../../../src/components/editor/OutlineTree.tsx"],"names":[],"mappings":"AA8BA,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AA+NpD,UAAU,gBAAgB;IACxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,wBAAgB,WAAW,CAAC,EAAE,aAAa,EAAE,EAAE,gBAAgB,2CAiI9D"}
1
+ {"version":3,"file":"OutlineTree.d.ts","sourceRoot":"","sources":["../../../src/components/editor/OutlineTree.tsx"],"names":[],"mappings":"AA8BA,eAAO,MAAM,gBAAgB,sBAAsB,CAAC;AA+NpD,UAAU,gBAAgB;IACxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,wBAAgB,WAAW,CAAC,EAAE,aAAa,EAAE,EAAE,gBAAgB,2CAkI9D"}
@@ -217,6 +217,7 @@ function he({ onTogglePanel: t }) {
217
217
  variant: "outline",
218
218
  size: "sm",
219
219
  onClick: x,
220
+ disabled: !a,
220
221
  className: "w-full h-8 gap-1.5 text-xs font-medium",
221
222
  children: [
222
223
  /* @__PURE__ */ e(I, { className: "h-3.5 w-3.5" }),
@@ -1 +1 @@
1
- {"version":3,"file":"SourcePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/SourcePreview.tsx"],"names":[],"mappings":"AAGA,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,UAAgB,GACjB,EAAE,kBAAkB,2CAkFpB"}
1
+ {"version":3,"file":"SourcePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/SourcePreview.tsx"],"names":[],"mappings":"AAGA,UAAU,kBAAkB;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,UAAU,EACV,UAAgB,GACjB,EAAE,kBAAkB,2CAqFpB"}
@@ -1,41 +1,41 @@
1
1
  import { jsxs as r, jsx as n } from "react/jsx-runtime";
2
- import { useRef as h, useState as f, useEffect as a } from "react";
3
- import { renderMjmlString as x } from "../../lib/mjml/renderer.js";
2
+ import { useRef as x, useState as b, useEffect as i } from "react";
3
+ import { renderMjmlString as h } from "../../lib/mjml/renderer.js";
4
4
  function w({
5
5
  mjmlSource: s,
6
- debounceMs: c = 300
6
+ debounceMs: m = 300
7
7
  }) {
8
- const l = h(null), [o, u] = f(s), [b, m] = f({
8
+ const a = x(null), [l, f] = b(s), [u, d] = b({
9
9
  html: "",
10
10
  errors: []
11
11
  });
12
- a(() => {
12
+ i(() => {
13
13
  const e = setTimeout(() => {
14
- u(s);
15
- }, c);
14
+ f(s);
15
+ }, m);
16
16
  return () => clearTimeout(e);
17
- }, [s, c]), a(() => {
18
- if (!o.trim()) {
19
- m({ html: "", errors: [] });
17
+ }, [s, m]), i(() => {
18
+ if (!l.trim()) {
19
+ d({ html: "", errors: [] });
20
20
  return;
21
21
  }
22
22
  let e = !1;
23
- return x(o).then((i) => {
24
- e || m(i);
23
+ return h(l).then((o) => {
24
+ e || d(o);
25
25
  }), () => {
26
26
  e = !0;
27
27
  };
28
- }, [o]);
29
- const { html: d, errors: t } = b;
30
- return a(() => {
31
- if (l.current) {
32
- const e = l.current.contentDocument;
33
- e && (e.open(), e.write(d), e.close());
28
+ }, [l]);
29
+ const { html: c, errors: t } = u;
30
+ return i(() => {
31
+ if (a.current) {
32
+ const e = a.current.contentDocument;
33
+ e && (e.open(), e.write(c), e.close());
34
34
  }
35
- }, [d]), /* @__PURE__ */ r("div", { className: "flex flex-col h-full", children: [
35
+ }, [c]), /* @__PURE__ */ r("div", { className: "flex flex-col h-full", children: [
36
36
  /* @__PURE__ */ r("div", { className: "h-11 px-4 flex items-center justify-between border-b border-border bg-background", children: [
37
37
  /* @__PURE__ */ n("span", { className: "text-sm font-semibold text-foreground", children: "Preview" }),
38
- t.length > 0 && /* @__PURE__ */ r("span", { className: "text-xs font-medium text-amber-600 bg-amber-50 px-2 py-0.5 rounded-md", children: [
38
+ t.length > 0 && /* @__PURE__ */ r("span", { className: "text-xs font-medium text-amber-600 dark:text-amber-400 bg-amber-50 dark:bg-amber-900/30 px-2 py-0.5 rounded-md", children: [
39
39
  t.length,
40
40
  " warning",
41
41
  t.length !== 1 ? "s" : ""
@@ -44,23 +44,30 @@ function w({
44
44
  /* @__PURE__ */ n("div", { className: "flex-1 overflow-auto bg-muted", children: /* @__PURE__ */ n(
45
45
  "iframe",
46
46
  {
47
- ref: l,
47
+ ref: a,
48
48
  title: "Source Preview",
49
49
  className: "w-full h-full border-0 bg-white",
50
50
  sandbox: "allow-same-origin"
51
51
  }
52
52
  ) }),
53
- t.length > 0 && /* @__PURE__ */ r("div", { className: "max-h-28 overflow-auto border-t border-border bg-amber-50/50 p-3", children: [
54
- /* @__PURE__ */ n("div", { className: "text-xs font-semibold text-amber-700 mb-2", children: "Warnings" }),
55
- /* @__PURE__ */ n("div", { className: "space-y-1", children: t.map((e, i) => /* @__PURE__ */ r("div", { className: "text-xs text-amber-600", children: [
56
- /* @__PURE__ */ r("span", { className: "font-mono", children: [
57
- "Line ",
58
- e.line,
59
- ":"
60
- ] }),
61
- " ",
62
- e.message
63
- ] }, i)) })
53
+ t.length > 0 && /* @__PURE__ */ r("div", { className: "max-h-28 overflow-auto border-t border-border bg-amber-50/50 dark:bg-amber-900/20 p-3", children: [
54
+ /* @__PURE__ */ n("div", { className: "text-xs font-semibold text-amber-700 dark:text-amber-300 mb-2", children: "Warnings" }),
55
+ /* @__PURE__ */ n("div", { className: "space-y-1", children: t.map((e, o) => /* @__PURE__ */ r(
56
+ "div",
57
+ {
58
+ className: "text-xs text-amber-600 dark:text-amber-400",
59
+ children: [
60
+ /* @__PURE__ */ r("span", { className: "font-mono", children: [
61
+ "Line ",
62
+ e.line,
63
+ ":"
64
+ ] }),
65
+ " ",
66
+ e.message
67
+ ]
68
+ },
69
+ o
70
+ )) })
64
71
  ] })
65
72
  ] });
66
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"VisualEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/VisualEditor.tsx"],"names":[],"mappings":"AAeA,UAAU,iBAAiB;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,EAC3B,aAAa,EACb,cAAc,GACf,EAAE,iBAAiB,2CAwEnB"}
1
+ {"version":3,"file":"VisualEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/VisualEditor.tsx"],"names":[],"mappings":"AAyBA,UAAU,iBAAiB;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,EAC3B,aAAa,EACb,cAAc,GACf,EAAE,iBAAiB,2CAuGnB"}
@@ -1,43 +1,70 @@
1
- import { jsx as r, jsxs as g } from "react/jsx-runtime";
2
- import { useEditor as b } from "../../context/EditorContext.js";
3
- import { ScrollArea as p } from "../ui/scroll-area.js";
4
- import { VisualSection as N } from "./visual-blocks/VisualSection.js";
5
- import { useFontLoader as y } from "../../hooks/useFontLoader.js";
6
- import { useStyleLoader as _, VISUAL_EDITOR_SCOPE_CLASS as A } from "../../hooks/useStyleLoader.js";
7
- const E = 256, L = 300, i = 12, c = 24;
1
+ import { jsx as e, jsxs as s } from "react/jsx-runtime";
2
+ import { useEditor as x } from "../../context/EditorContext.js";
3
+ import { ScrollArea as a } from "../ui/scroll-area.js";
4
+ import { VisualSection as y } from "./visual-blocks/VisualSection.js";
5
+ import { useFontLoader as k } from "../../hooks/useFontLoader.js";
6
+ import { useStyleLoader as E, VISUAL_EDITOR_SCOPE_CLASS as L } from "../../hooks/useStyleLoader.js";
7
+ import { createEmptyDocument as S } from "../../lib/mjml/parser.js";
8
+ function _(o) {
9
+ return o.tagName !== "mjml" ? !1 : o.children?.some((n) => n.tagName === "mj-body") ?? !1;
10
+ }
11
+ const v = 256, A = 300, m = 12, u = 24;
8
12
  function G({
9
- leftPanelOpen: s,
10
- rightPanelOpen: l
13
+ leftPanelOpen: o,
14
+ rightPanelOpen: n
11
15
  }) {
12
- const { state: a, selectBlock: m } = b();
13
- y(), _();
14
- const o = a.document.children?.find((t) => t.tagName === "mj-body"), e = o?.attributes.width || "600px", u = o?.attributes["background-color"], h = (t) => {
15
- t.target === t.currentTarget && m(null);
16
- }, d = s ? E + i + c : 16, n = l ? L + i + c : 16, f = (parseInt(e, 10) || 600) + d + n;
17
- return /* @__PURE__ */ r(
18
- p,
16
+ const { state: d, selectBlock: h, setDocument: f } = x();
17
+ k(), E();
18
+ const b = () => {
19
+ f(S());
20
+ };
21
+ if (!_(d.document))
22
+ return /* @__PURE__ */ e(
23
+ a,
24
+ {
25
+ className: "h-full",
26
+ viewportStyle: { backgroundColor: "#ffffff" },
27
+ children: /* @__PURE__ */ e("div", { className: "flex items-center justify-center p-8 min-h-[400px]", children: /* @__PURE__ */ s("div", { className: "bg-red-50 border border-red-200 rounded-lg p-6 max-w-md text-center", children: [
28
+ /* @__PURE__ */ e("p", { className: "text-red-700 font-medium mb-2", children: "Invalid MJML structure" }),
29
+ /* @__PURE__ */ e("p", { className: "text-red-600 text-sm mb-4", children: "The document is missing required elements like mj-body. Reset to a blank template to continue editing." }),
30
+ /* @__PURE__ */ e(
31
+ "button",
32
+ {
33
+ onClick: b,
34
+ className: "px-4 py-2 bg-red-600 text-white text-sm font-medium rounded-md hover:bg-red-700 transition-colors",
35
+ children: "Reset to blank template"
36
+ }
37
+ )
38
+ ] }) })
39
+ }
40
+ );
41
+ const r = d.document.children?.find((t) => t.tagName === "mj-body"), i = r?.attributes.width || "600px", p = r?.attributes["background-color"], g = (t) => {
42
+ t.target === t.currentTarget && h(null);
43
+ }, c = o ? v + m + u : 16, l = n ? A + m + u : 16, N = (parseInt(i, 10) || 600) + c + l;
44
+ return /* @__PURE__ */ e(
45
+ a,
19
46
  {
20
47
  className: "h-full",
21
48
  orientation: "both",
22
- viewportStyle: { backgroundColor: u || "#ffffff" },
23
- children: /* @__PURE__ */ r(
49
+ viewportStyle: { backgroundColor: p || "#ffffff" },
50
+ children: /* @__PURE__ */ e(
24
51
  "div",
25
52
  {
26
53
  className: "py-8",
27
54
  style: {
28
- paddingLeft: d,
29
- paddingRight: n,
30
- minWidth: f
55
+ paddingLeft: c,
56
+ paddingRight: l,
57
+ minWidth: N
31
58
  },
32
- onClick: h,
33
- children: /* @__PURE__ */ g(
59
+ onClick: g,
60
+ children: /* @__PURE__ */ s(
34
61
  "div",
35
62
  {
36
- className: `light mx-auto w-full ${A}`,
37
- style: { maxWidth: e },
63
+ className: `light mx-auto w-full ${L}`,
64
+ style: { maxWidth: i },
38
65
  children: [
39
- o?.children?.map((t) => /* @__PURE__ */ r(N, { node: t }, t._id)),
40
- (!o?.children || o.children.length === 0) && /* @__PURE__ */ r("div", { className: "bg-surface rounded-lg border-2 border-dashed border-border p-12 text-center", children: /* @__PURE__ */ r("p", { className: "text-muted-foreground", children: "Add a section to get started" }) })
66
+ r?.children?.map((t) => /* @__PURE__ */ e(y, { node: t }, t._id)),
67
+ (!r?.children || r.children.length === 0) && /* @__PURE__ */ e("div", { className: "bg-zinc-100 rounded-lg border-2 border-dashed border-zinc-300 p-12 text-center", children: /* @__PURE__ */ e("p", { className: "text-zinc-500", children: "Add a section to get started" }) })
41
68
  ]
42
69
  }
43
70
  )
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Hook that injects <link> tags into the document head for each mj-font.
3
+ * Also loads MJML's default Ubuntu font to match preview rendering.
3
4
  * This enables custom fonts to render in the visual editor.
4
5
  */
5
6
  export declare function useFontLoader(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"useFontLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useFontLoader.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,wBAAgB,aAAa,SA6C5B"}
1
+ {"version":3,"file":"useFontLoader.d.ts","sourceRoot":"","sources":["../../src/hooks/useFontLoader.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,wBAAgB,aAAa,SAgD5B"}
@@ -1,21 +1,24 @@
1
- import { useEffect as l } from "react";
2
- import { useEditor as m } from "../context/EditorContext.js";
3
- const t = "mjml-editor-font-";
4
- function d() {
5
- const { fonts: c } = m();
6
- l(() => (document.querySelectorAll(`link[id^="${t}"]`).forEach((e) => {
7
- const o = e.id.replace(t, "").replace(/-/g, " ");
8
- c.some(
9
- (n) => n.name === o || n.name.replace(/\s+/g, "-") === e.id.replace(t, "")
1
+ import { useMemo as m, useEffect as s } from "react";
2
+ import { useEditor as a } from "../context/EditorContext.js";
3
+ const o = "mjml-editor-font-", i = {
4
+ name: "Ubuntu",
5
+ href: "https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700"
6
+ };
7
+ function u() {
8
+ const { fonts: c } = a(), n = m(() => [i, ...c], [c]);
9
+ s(() => (document.querySelectorAll(`link[id^="${o}"]`).forEach((e) => {
10
+ const r = e.id.replace(o, "").replace(/-/g, " ");
11
+ n.some(
12
+ (l) => l.name === r || l.name.replace(/\s+/g, "-") === e.id.replace(o, "")
10
13
  ) || e.remove();
11
- }), c.forEach((e) => {
12
- const o = `${t}${e.name.replace(/\s+/g, "-")}`;
13
- let r = document.getElementById(o);
14
- r ? r.href !== e.href && (r.href = e.href) : (r = document.createElement("link"), r.id = o, r.rel = "stylesheet", r.href = e.href, document.head.appendChild(r));
14
+ }), n.forEach((e) => {
15
+ const r = `${o}${e.name.replace(/\s+/g, "-")}`;
16
+ let t = document.getElementById(r);
17
+ t ? t.href !== e.href && (t.href = e.href) : (t = document.createElement("link"), t.id = r, t.rel = "stylesheet", t.href = e.href, document.head.appendChild(t));
15
18
  }), () => {
16
- document.querySelectorAll(`link[id^="${t}"]`).forEach((e) => e.remove());
17
- }), [c]);
19
+ document.querySelectorAll(`link[id^="${o}"]`).forEach((e) => e.remove());
20
+ }), [n]);
18
21
  }
19
22
  export {
20
- d as useFontLoader
23
+ u as useFontLoader
21
24
  };
@@ -9,24 +9,24 @@ function m(r) {
9
9
  ...r,
10
10
  children: r.children?.map(m)
11
11
  };
12
- const t = r.attributes["mj-class"] || "", e = `block-${r._id}`, s = t ? `${t} ${e}` : e;
12
+ const t = r.attributes["mj-class"] || "", e = `block-${r._id}`, n = t ? `${t} ${e}` : e;
13
13
  return {
14
14
  ...r,
15
- attributes: { ...r.attributes, "mj-class": s },
15
+ attributes: { ...r.attributes, "mj-class": n },
16
16
  children: r.children?.map(m)
17
17
  };
18
18
  }
19
- function g(r) {
20
- return p(r);
19
+ function p(r) {
20
+ return g(r);
21
21
  }
22
- function p(r, t = 0) {
23
- const e = " ".repeat(t), s = r.tagName, n = Object.entries(r.attributes || {}).filter(
24
- ([a, l]) => a !== "_id" && l !== "" && l !== void 0
25
- ).map(([a, l]) => `${a}="${h(l)}"`).join(" "), i = n ? `<${s} ${n}>` : `<${s}>`, c = `</${s}>`;
22
+ function g(r, t = 0) {
23
+ const e = " ".repeat(t), n = r.tagName, l = Object.entries(r.attributes || {}).filter(
24
+ ([a, s]) => a !== "_id" && s !== "" && s !== void 0
25
+ ).map(([a, s]) => `${a}="${h(s)}"`).join(" "), i = l ? `<${n} ${l}>` : `<${n}>`, c = `</${n}>`;
26
26
  if (r.content !== void 0)
27
27
  return `${e}${i}${r.content}${c}`;
28
28
  if (r.children && r.children.length > 0) {
29
- const a = r.children.map((l) => p(l, t + 1)).join(`
29
+ const a = r.children.map((s) => g(s, t + 1)).join(`
30
30
  `);
31
31
  return `${e}${i}
32
32
  ${a}
@@ -48,23 +48,23 @@ async function $(r) {
48
48
  };
49
49
  } catch (t) {
50
50
  return console.error("MJML render error:", t), {
51
- html: '<p style="color: red; padding: 20px;">Error rendering email preview</p>',
51
+ html: '<p style="color: #dc2626; padding: 20px; background: white; margin: 0;">Error rendering email preview</p>',
52
52
  errors: [{ line: 0, message: String(t), tagName: "mjml" }]
53
53
  };
54
54
  }
55
55
  }
56
56
  async function d(r) {
57
57
  try {
58
- const t = await u(), e = m(r), s = g(e), n = t(s, {
58
+ const t = await u(), e = m(r), n = p(e), l = t(n, {
59
59
  validationLevel: "soft"
60
60
  });
61
61
  return {
62
- html: n.html,
63
- errors: n.errors || []
62
+ html: l.html,
63
+ errors: l.errors || []
64
64
  };
65
65
  } catch (t) {
66
66
  return console.error("MJML render error:", t), {
67
- html: '<p style="color: red; padding: 20px;">Error rendering email preview</p>',
67
+ html: '<p style="color: #dc2626; padding: 20px; background: white; margin: 0;">Error rendering email preview</p>',
68
68
  errors: [{ line: 0, message: String(t), tagName: "mjml" }]
69
69
  };
70
70
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvycal/mjml-editor",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {