@savvycal/mjml-editor 0.6.0 → 0.8.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,2CAqLzB"}
1
+ {"version":3,"file":"InteractivePreview.d.ts","sourceRoot":"","sources":["../../../src/components/editor/InteractivePreview.tsx"],"names":[],"mappings":"AAIA,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,2CAuLzB"}
@@ -1,37 +1,38 @@
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
- import { useEditor as y } from "../../context/EditorContext.js";
4
- import { renderMjmlInteractive as C } from "../../lib/mjml/renderer.js";
5
- const I = 375;
6
- function S({
7
- showHeader: p = !0,
8
- previewMode: g = "desktop"
1
+ import { jsxs as r, jsx as l } from "react/jsx-runtime";
2
+ import { useRef as E, useState as p, useEffect as a, useCallback as y } from "react";
3
+ import { useEditor as C } from "../../context/EditorContext.js";
4
+ import { useNonce as I } from "../../context/NonceContext.js";
5
+ import { renderMjmlInteractive as N } from "../../lib/mjml/renderer.js";
6
+ const L = 375;
7
+ function R({
8
+ showHeader: g = !0,
9
+ previewMode: x = "desktop"
9
10
  }) {
10
- const { state: r, selectBlock: d } = y(), o = w(null), [m, x] = h(r.document), [k, v] = h({
11
+ const { state: n, selectBlock: m } = C(), i = I(), o = E(null), [u, k] = p(n.document), [v, w] = p({
11
12
  html: "",
12
13
  errors: []
13
14
  });
14
15
  a(() => {
15
16
  const e = setTimeout(() => {
16
- x(r.document);
17
+ k(n.document);
17
18
  }, 300);
18
19
  return () => clearTimeout(e);
19
- }, [r.document]), a(() => {
20
+ }, [n.document]), a(() => {
20
21
  let e = !1;
21
- return C(m).then((t) => {
22
- e || v(t);
22
+ return N(u).then((t) => {
23
+ e || w(t);
23
24
  }), () => {
24
25
  e = !0;
25
26
  };
26
- }, [m]);
27
- const { html: u, errors: l } = k, i = E(
27
+ }, [u]);
28
+ const { html: f, errors: s } = v, d = y(
28
29
  (e) => {
29
- e.data?.type === "BLOCK_SELECTED" && d(e.data.blockId);
30
+ e.data?.type === "BLOCK_SELECTED" && m(e.data.blockId);
30
31
  },
31
- [d]
32
+ [m]
32
33
  );
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 = `
34
+ a(() => (window.addEventListener("message", d), () => window.removeEventListener("message", d)), [d]);
35
+ const c = n.selectedBlockId ? `.block-${n.selectedBlockId} { outline: 2px solid #6366f1 !important; outline-offset: -2px; position: relative; }` : "", b = `
35
36
  (function() {
36
37
  document.addEventListener('click', function(e) {
37
38
  e.preventDefault();
@@ -64,11 +65,11 @@ function S({
64
65
  if (o.current) {
65
66
  const e = o.current.contentDocument;
66
67
  if (e) {
67
- e.open(), e.write(u), e.close();
68
+ e.open(), e.write(f), e.close();
68
69
  const t = e.createElement("script");
69
- t.textContent = b, e.body.appendChild(t);
70
- const f = e.createElement("style");
71
- f.textContent = `
70
+ i && (t.nonce = i), t.textContent = b, e.body.appendChild(t);
71
+ const h = e.createElement("style");
72
+ h.textContent = `
72
73
  [class*="block-"] {
73
74
  cursor: pointer;
74
75
  transition: outline 0.15s ease;
@@ -78,10 +79,10 @@ function S({
78
79
  outline-offset: -1px;
79
80
  }
80
81
  ${c}
81
- `, e.head.appendChild(f);
82
+ `, e.head.appendChild(h);
82
83
  }
83
84
  }
84
- }, [u, c, b]), a(() => {
85
+ }, [f, c, b, i]), a(() => {
85
86
  if (o.current) {
86
87
  const e = o.current.contentDocument;
87
88
  if (e) {
@@ -89,36 +90,36 @@ function S({
89
90
  t || (t = e.createElement("style"), t.id = "selection-highlight", e.head.appendChild(t)), t.textContent = c;
90
91
  }
91
92
  }
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
- /* @__PURE__ */ s("span", { className: "text-sm font-semibold text-foreground", children: "Preview" }),
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
- l.length,
93
+ }, [n.selectedBlockId, c]), /* @__PURE__ */ r("div", { className: "flex flex-col h-full", children: [
94
+ g && /* @__PURE__ */ r("div", { className: "h-11 px-4 flex items-center justify-between border-b border-border bg-background", children: [
95
+ /* @__PURE__ */ l("span", { className: "text-sm font-semibold text-foreground", children: "Preview" }),
96
+ s.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: [
97
+ s.length,
97
98
  " warning",
98
- l.length !== 1 ? "s" : ""
99
+ s.length !== 1 ? "s" : ""
99
100
  ] })
100
101
  ] }),
101
- /* @__PURE__ */ s("div", { className: "flex-1 overflow-auto bg-muted flex justify-center", children: /* @__PURE__ */ s(
102
+ /* @__PURE__ */ l("div", { className: "flex-1 overflow-auto bg-muted flex justify-center", children: /* @__PURE__ */ l(
102
103
  "iframe",
103
104
  {
104
105
  ref: o,
105
106
  title: "Email Preview",
106
107
  className: "h-full border-0 bg-white transition-all duration-200",
107
108
  style: {
108
- width: g === "mobile" ? I : "100%",
109
+ width: x === "mobile" ? L : "100%",
109
110
  maxWidth: "100%"
110
111
  },
111
112
  sandbox: "allow-same-origin allow-scripts"
112
113
  }
113
114
  ) }),
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(
115
+ s.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: [
116
+ /* @__PURE__ */ l("div", { className: "text-xs font-semibold text-amber-700 dark:text-amber-300 mb-2", children: "Warnings" }),
117
+ /* @__PURE__ */ l("div", { className: "space-y-1", children: s.map((e, t) => /* @__PURE__ */ r(
117
118
  "div",
118
119
  {
119
120
  className: "text-xs text-amber-600 dark:text-amber-400",
120
121
  children: [
121
- /* @__PURE__ */ n("span", { className: "font-mono", children: [
122
+ /* @__PURE__ */ r("span", { className: "font-mono", children: [
122
123
  "Line ",
123
124
  e.line,
124
125
  ":"
@@ -133,5 +134,5 @@ function S({
133
134
  ] });
134
135
  }
135
136
  export {
136
- S as InteractivePreview
137
+ R as InteractivePreview
137
138
  };
@@ -48,7 +48,13 @@ interface MjmlEditorProps {
48
48
  * @default false
49
49
  */
50
50
  defaultRightPanelOpen?: boolean;
51
+ /**
52
+ * CSP nonce to apply to dynamically injected script tags.
53
+ * Required when the host application uses a Content Security Policy
54
+ * with `script-src 'nonce-...'`.
55
+ */
56
+ nonce?: string;
51
57
  }
52
- export declare function MjmlEditor({ value, onChange, className, defaultTheme, liquidSchema, extensions, applyThemeToDocument, showThemeToggle, defaultLeftPanelOpen, defaultRightPanelOpen, }: MjmlEditorProps): import("react/jsx-runtime").JSX.Element;
58
+ export declare function MjmlEditor({ value, onChange, className, defaultTheme, liquidSchema, extensions, applyThemeToDocument, showThemeToggle, defaultLeftPanelOpen, defaultRightPanelOpen, nonce, }: MjmlEditorProps): import("react/jsx-runtime").JSX.Element;
53
59
  export {};
54
60
  //# sourceMappingURL=MjmlEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MjmlEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/MjmlEditor.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAY,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAcnD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAoKD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAuB,EACvB,YAAY,EACZ,UAAU,EACV,oBAA2B,EAC3B,eAAsB,EACtB,oBAA2B,EAC3B,qBAA6B,GAC9B,EAAE,eAAe,2CA8CjB"}
1
+ {"version":3,"file":"MjmlEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/MjmlEditor.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAY,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAcnD,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC3C,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAoKD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,SAAS,EACT,YAAuB,EACvB,YAAY,EACZ,UAAU,EACV,oBAA2B,EAC3B,eAAsB,EACtB,oBAA2B,EAC3B,qBAA6B,EAC7B,KAAK,GACN,EAAE,eAAe,2CAgDjB"}
@@ -1,25 +1,26 @@
1
- import { jsx as e, jsxs as w, Fragment as L } from "react/jsx-runtime";
2
- import { useState as a, useEffect as d, useCallback as D, useRef as M } from "react";
1
+ import { jsx as e, jsxs as P, Fragment as L } from "react/jsx-runtime";
2
+ import { useState as a, useEffect as s, useCallback as D, useRef as M } from "react";
3
3
  import { EditorProvider as O, useEditor as j } from "../../context/EditorContext.js";
4
4
  import { ThemeProvider as x, useTheme as C } from "../../context/ThemeContext.js";
5
5
  import { LiquidSchemaProvider as S } from "../../context/LiquidSchemaContext.js";
6
6
  import { ExtensionsProvider as K } from "../../context/ExtensionsContext.js";
7
- import { OutlineTree as R, GLOBAL_STYLES_ID as B } from "./OutlineTree.js";
7
+ import { NonceProvider as N } from "../../context/NonceContext.js";
8
+ import { OutlineTree as R, GLOBAL_STYLES_ID as w } from "./OutlineTree.js";
8
9
  import { EditorCanvas as A } from "./EditorCanvas.js";
9
10
  import { BlockInspector as F } from "./BlockInspector.js";
10
- import { GlobalStylesPanel as N } from "./GlobalStylesPanel.js";
11
- import { FloatingPanel as I } from "../ui/floating-panel.js";
12
- import { createEmptyDocument as P, parseMjml as $, serializeMjml as z } from "../../lib/mjml/parser.js";
13
- function G(n) {
11
+ import { GlobalStylesPanel as $ } from "./GlobalStylesPanel.js";
12
+ import { FloatingPanel as B } from "../ui/floating-panel.js";
13
+ import { createEmptyDocument as I, parseMjml as z, serializeMjml as G } from "../../lib/mjml/parser.js";
14
+ function H(n) {
14
15
  if (!n || n.trim() === "")
15
- return P();
16
+ return I();
16
17
  try {
17
- return $(n);
18
+ return z(n);
18
19
  } catch (o) {
19
- return console.error("Failed to parse MJML:", o), P();
20
+ return console.error("Failed to parse MJML:", o), I();
20
21
  }
21
22
  }
22
- function H({
23
+ function _({
23
24
  className: n,
24
25
  children: o
25
26
  }) {
@@ -32,28 +33,28 @@ function H({
32
33
  }
33
34
  );
34
35
  }
35
- function _({
36
+ function q({
36
37
  onChange: n,
37
38
  showThemeToggle: o = !0,
38
39
  defaultLeftPanelOpen: l = !0,
39
- defaultRightPanelOpen: T = !1
40
+ defaultRightPanelOpen: E = !1
40
41
  }) {
41
- const { state: r, undo: u, redo: f, canUndo: m, canRedo: p, deleteBlock: h, selectBlock: g } = j(), [s, k] = a(l), [c, i] = a(T), [E, b] = a("edit"), y = M(n);
42
- return d(() => {
42
+ const { state: r, undo: m, redo: f, canUndo: u, canRedo: p, deleteBlock: h, selectBlock: g } = j(), [c, v] = a(l), [d, i] = a(E), [k, b] = a("edit"), y = M(n);
43
+ return s(() => {
43
44
  y.current = n;
44
- }, [n]), d(() => {
45
+ }, [n]), s(() => {
45
46
  r.selectedBlockId && i(!0);
46
- }, [r.selectedBlockId]), d(() => {
47
- const v = z(r.document);
48
- y.current(v);
49
- }, [r.document]), d(() => {
50
- const v = (t) => {
47
+ }, [r.selectedBlockId]), s(() => {
48
+ const T = G(r.document);
49
+ y.current(T);
50
+ }, [r.document]), s(() => {
51
+ const T = (t) => {
51
52
  if (!(t.target instanceof HTMLInputElement || t.target instanceof HTMLTextAreaElement || t.target?.isContentEditable)) {
52
53
  if ((t.metaKey || t.ctrlKey) && t.key === "z") {
53
- t.preventDefault(), t.shiftKey ? p && f() : m && u();
54
+ t.preventDefault(), t.shiftKey ? p && f() : u && m();
54
55
  return;
55
56
  }
56
- if ((t.key === "Delete" || t.key === "Backspace") && r.selectedBlockId && r.selectedBlockId !== B) {
57
+ if ((t.key === "Delete" || t.key === "Backspace") && r.selectedBlockId && r.selectedBlockId !== w) {
57
58
  t.preventDefault(), h(r.selectedBlockId);
58
59
  return;
59
60
  }
@@ -63,46 +64,46 @@ function _({
63
64
  }
64
65
  }
65
66
  };
66
- return window.addEventListener("keydown", v), () => window.removeEventListener("keydown", v);
67
+ return window.addEventListener("keydown", T), () => window.removeEventListener("keydown", T);
67
68
  }, [
68
- u,
69
- f,
70
69
  m,
70
+ f,
71
+ u,
71
72
  p,
72
73
  h,
73
74
  g,
74
75
  r.selectedBlockId
75
- ]), /* @__PURE__ */ w("div", { className: "relative h-full overflow-hidden", children: [
76
+ ]), /* @__PURE__ */ P("div", { className: "relative h-full overflow-hidden", children: [
76
77
  /* @__PURE__ */ e("div", { className: "absolute inset-0 bg-canvas", children: /* @__PURE__ */ e(
77
78
  A,
78
79
  {
79
- activeTab: E,
80
+ activeTab: k,
80
81
  onTabChange: b,
81
- leftPanelOpen: s,
82
- rightPanelOpen: c,
82
+ leftPanelOpen: c,
83
+ rightPanelOpen: d,
83
84
  showThemeToggle: o
84
85
  }
85
86
  ) }),
86
- E === "edit" && /* @__PURE__ */ w(L, { children: [
87
+ k === "edit" && /* @__PURE__ */ P(L, { children: [
87
88
  /* @__PURE__ */ e(
88
- I,
89
+ B,
89
90
  {
90
91
  side: "left",
91
- isOpen: s,
92
- onToggle: () => k(!s),
92
+ isOpen: c,
93
+ onToggle: () => v(!c),
93
94
  width: 256,
94
- children: /* @__PURE__ */ e(R, { onTogglePanel: () => k(!1) })
95
+ children: /* @__PURE__ */ e(R, { onTogglePanel: () => v(!1) })
95
96
  }
96
97
  ),
97
98
  /* @__PURE__ */ e(
98
- I,
99
+ B,
99
100
  {
100
101
  side: "right",
101
- isOpen: c,
102
- onToggle: () => i(!c),
102
+ isOpen: d,
103
+ onToggle: () => i(!d),
103
104
  width: 300,
104
- children: r.selectedBlockId === B ? /* @__PURE__ */ e(
105
- N,
105
+ children: r.selectedBlockId === w ? /* @__PURE__ */ e(
106
+ $,
106
107
  {
107
108
  onTogglePanel: () => i(!1)
108
109
  }
@@ -112,45 +113,46 @@ function _({
112
113
  ] })
113
114
  ] });
114
115
  }
115
- function ne({
116
+ function le({
116
117
  value: n,
117
118
  onChange: o,
118
119
  className: l,
119
- defaultTheme: T = "system",
120
+ defaultTheme: E = "system",
120
121
  liquidSchema: r,
121
- extensions: u,
122
+ extensions: m,
122
123
  applyThemeToDocument: f = !0,
123
- showThemeToggle: m = !0,
124
+ showThemeToggle: u = !0,
124
125
  defaultLeftPanelOpen: p = !0,
125
- defaultRightPanelOpen: h = !1
126
+ defaultRightPanelOpen: h = !1,
127
+ nonce: g
126
128
  }) {
127
- const [g, s] = a(!1);
128
- d(() => {
129
- s(!0);
129
+ const [c, v] = a(!1);
130
+ s(() => {
131
+ v(!0);
130
132
  }, []);
131
- const [k] = a(() => G(n)), c = D(
132
- (i) => {
133
- o(i);
133
+ const [d] = a(() => H(n)), i = D(
134
+ (k) => {
135
+ o(k);
134
136
  },
135
137
  [o]
136
138
  );
137
- return g ? /* @__PURE__ */ e(
139
+ return c ? /* @__PURE__ */ e(
138
140
  x,
139
141
  {
140
- defaultTheme: T,
142
+ defaultTheme: E,
141
143
  applyToDocument: f,
142
- children: /* @__PURE__ */ e(K, { extensions: u, children: /* @__PURE__ */ e(S, { schema: r, children: /* @__PURE__ */ e(H, { className: l, children: /* @__PURE__ */ e(O, { initialDocument: k, children: /* @__PURE__ */ e(
143
- _,
144
+ children: /* @__PURE__ */ e(N, { nonce: g, children: /* @__PURE__ */ e(K, { extensions: m, children: /* @__PURE__ */ e(S, { schema: r, children: /* @__PURE__ */ e(_, { className: l, children: /* @__PURE__ */ e(O, { initialDocument: d, children: /* @__PURE__ */ e(
145
+ q,
144
146
  {
145
- onChange: c,
146
- showThemeToggle: m,
147
+ onChange: i,
148
+ showThemeToggle: u,
147
149
  defaultLeftPanelOpen: p,
148
150
  defaultRightPanelOpen: h
149
151
  }
150
- ) }) }) }) })
152
+ ) }) }) }) }) })
151
153
  }
152
154
  ) : /* @__PURE__ */ e("div", { className: `h-full w-full bg-background ${l || ""}` });
153
155
  }
154
156
  export {
155
- ne as MjmlEditor
157
+ le as MjmlEditor
156
158
  };
@@ -1 +1 @@
1
- {"version":3,"file":"SourceEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/SourceEditor.tsx"],"names":[],"mappings":"AA2DA,wBAAgB,YAAY,4CA4H3B"}
1
+ {"version":3,"file":"SourceEditor.d.ts","sourceRoot":"","sources":["../../../src/components/editor/SourceEditor.tsx"],"names":[],"mappings":"AA0DA,wBAAgB,YAAY,4CAkH3B"}
@@ -1,116 +1,111 @@
1
- import { jsxs as n, jsx as t } from "react/jsx-runtime";
2
- import { useState as f, useRef as g, useEffect as p, useCallback as b, useMemo as N } from "react";
3
- import { AlertTriangle as y } from "lucide-react";
1
+ import { jsxs as m, jsx as n } from "react/jsx-runtime";
2
+ import { useState as f, useRef as g, useEffect as p, useCallback as v, useMemo as y } from "react";
4
3
  import k from "@uiw/react-codemirror";
5
- import { EditorState as M } from "@codemirror/state";
6
- import { indentUnit as E, bracketMatching as j, syntaxHighlighting as w, HighlightStyle as C } from "@codemirror/language";
7
- import { lineNumbers as L, highlightActiveLineGutter as D, highlightActiveLine as W, EditorView as R, keymap as A } from "@codemirror/view";
8
- import { history as T, indentWithTab as z, defaultKeymap as H, historyKeymap as J } from "@codemirror/commands";
9
- import { highlightSelectionMatches as K, searchKeymap as U } from "@codemirror/search";
10
- import { xml as V } from "@codemirror/lang-xml";
11
- import { tags as r } from "@lezer/highlight";
12
- import { useEditor as _ } from "../../context/EditorContext.js";
13
- import { serializeMjml as x, parseMjml as B } from "../../lib/mjml/parser.js";
14
- import { ResizableSplitPane as I } from "../ui/resizable-split-pane.js";
4
+ import { EditorState as N } from "@codemirror/state";
5
+ import { indentUnit as M, bracketMatching as E, syntaxHighlighting as j, HighlightStyle as C } from "@codemirror/language";
6
+ import { lineNumbers as w, highlightActiveLineGutter as L, highlightActiveLine as D, EditorView as W, keymap as R } from "@codemirror/view";
7
+ import { history as z, indentWithTab as A, defaultKeymap as H, historyKeymap as K } from "@codemirror/commands";
8
+ import { highlightSelectionMatches as T, searchKeymap as U } from "@codemirror/search";
9
+ import { xml as _ } from "@codemirror/lang-xml";
10
+ import { tags as t } from "@lezer/highlight";
11
+ import { useEditor as B } from "../../context/EditorContext.js";
12
+ import { serializeMjml as b, parseMjml as I } from "../../lib/mjml/parser.js";
13
+ import { ResizableSplitPane as J } from "../ui/resizable-split-pane.js";
15
14
  import { SourcePreview as O } from "./SourcePreview.js";
16
- const P = 350, Y = C.define([
15
+ const P = 350, V = C.define([
17
16
  {
18
- tag: r.tagName,
17
+ tag: t.tagName,
19
18
  color: "var(--cm-tag, oklch(0.74 0.1 158))",
20
19
  fontWeight: "600"
21
20
  },
22
21
  {
23
- tag: r.attributeName,
22
+ tag: t.attributeName,
24
23
  color: "var(--cm-attribute-name, oklch(0.76 0.09 80))"
25
24
  },
26
25
  {
27
- tag: [r.attributeValue, r.string],
26
+ tag: [t.attributeValue, t.string],
28
27
  color: "var(--cm-attribute-value, oklch(0.77 0.1 255))"
29
28
  },
30
29
  {
31
- tag: [r.angleBracket, r.bracket],
30
+ tag: [t.angleBracket, t.bracket],
32
31
  color: "var(--cm-punctuation, oklch(0.7 0.02 250))"
33
32
  },
34
- { tag: r.comment, color: "var(--cm-comment, oklch(0.63 0.01 250))" },
33
+ { tag: t.comment, color: "var(--cm-comment, oklch(0.63 0.01 250))" },
35
34
  {
36
- tag: r.invalid,
35
+ tag: t.invalid,
37
36
  color: "var(--cm-invalid, oklch(0.7 0.16 25))",
38
37
  textDecoration: "underline"
39
38
  }
40
39
  ]);
41
- function le() {
42
- const { state: s, setDocument: u } = _(), [a, d] = f(""), [c, i] = f(null), l = g(!1), m = g("");
40
+ function ae() {
41
+ const { state: s, setDocument: u } = B(), [o, d] = f(""), [a, i] = f(null), c = g(!1), l = g("");
43
42
  p(() => {
44
- if (l.current) {
45
- l.current = !1;
43
+ if (c.current) {
44
+ c.current = !1;
46
45
  return;
47
46
  }
48
- const e = x(s.document);
49
- m.current = e, d(e), i(null);
47
+ const e = b(s.document);
48
+ l.current = e, d(e), i(null);
50
49
  }, [s.document]);
51
- const h = b(
50
+ const h = v(
52
51
  (e) => {
53
52
  try {
54
- const o = B(e);
55
- if (o.tagName !== "mjml") {
53
+ const r = I(e);
54
+ if (r.tagName !== "mjml") {
56
55
  i("Invalid MJML: Document must have an <mjml> root element");
57
56
  return;
58
57
  }
59
- m.current = x(o), l.current = !0, u(o), i(null);
60
- } catch (o) {
61
- i(o instanceof Error ? o.message : "Failed to parse MJML");
58
+ l.current = b(r), c.current = !0, u(r), i(null);
59
+ } catch (r) {
60
+ i(r instanceof Error ? r.message : "Failed to parse MJML");
62
61
  }
63
62
  },
64
63
  [u]
65
- ), v = N(
64
+ ), x = y(
66
65
  () => [
66
+ w(),
67
67
  L(),
68
68
  D(),
69
- W(),
69
+ z(),
70
+ N.tabSize.of(2),
71
+ M.of(" "),
72
+ E(),
70
73
  T(),
71
- M.tabSize.of(2),
72
- E.of(" "),
73
- j(),
74
- K(),
75
- w(Y),
76
- R.lineWrapping,
77
- A.of([
78
- z,
74
+ j(V),
75
+ W.lineWrapping,
76
+ R.of([
77
+ A,
79
78
  ...H,
80
- ...J,
79
+ ...K,
81
80
  ...U
82
81
  ]),
83
- V()
82
+ _()
84
83
  ],
85
84
  []
86
- ), S = b((e) => {
85
+ ), S = v((e) => {
87
86
  d(e), i(null);
88
87
  }, []);
89
88
  return p(() => {
90
- if (a === m.current)
89
+ if (o === l.current)
91
90
  return;
92
91
  const e = window.setTimeout(() => {
93
- h(a);
92
+ h(o);
94
93
  }, P);
95
94
  return () => window.clearTimeout(e);
96
- }, [a, h]), /* @__PURE__ */ n(
97
- I,
95
+ }, [o, h]), /* @__PURE__ */ m(
96
+ J,
98
97
  {
99
98
  defaultLeftWidth: 50,
100
99
  minLeftWidth: 30,
101
100
  maxLeftWidth: 70,
102
101
  children: [
103
- /* @__PURE__ */ n("div", { className: "flex flex-col h-full bg-background", children: [
104
- /* @__PURE__ */ t("div", { className: "px-4 pt-4", children: /* @__PURE__ */ n("div", { className: "flex items-start gap-3 p-3 rounded-md bg-amber-50 border border-amber-200 text-amber-800", children: [
105
- /* @__PURE__ */ t(y, { className: "h-4 w-4 mt-0.5 flex-shrink-0" }),
106
- /* @__PURE__ */ t("p", { className: "text-sm", children: "You are editing raw MJML source. Valid changes sync to the visual editor automatically." })
107
- ] }) }),
108
- /* @__PURE__ */ t("div", { className: "flex-1 min-h-0 p-4", children: /* @__PURE__ */ t(
102
+ /* @__PURE__ */ m("div", { className: "flex flex-col h-full bg-background", children: [
103
+ /* @__PURE__ */ n("div", { className: "flex-1 min-h-0 p-4", children: /* @__PURE__ */ n(
109
104
  k,
110
105
  {
111
- value: a,
106
+ value: o,
112
107
  onChange: S,
113
- extensions: v,
108
+ extensions: x,
114
109
  basicSetup: !1,
115
110
  theme: "none",
116
111
  className: "source-editor h-full overflow-hidden rounded-md border border-border bg-muted text-foreground",
@@ -118,16 +113,16 @@ function le() {
118
113
  spellCheck: !1
119
114
  }
120
115
  ) }),
121
- /* @__PURE__ */ n("div", { className: "px-4 pb-4 flex items-center gap-3", children: [
122
- !c && /* @__PURE__ */ t("span", { className: "text-sm text-foreground-muted", children: "Changes sync automatically" }),
123
- c && /* @__PURE__ */ t("span", { className: "text-sm text-destructive", children: c })
116
+ /* @__PURE__ */ m("div", { className: "px-4 pb-4 flex items-center gap-3", children: [
117
+ !a && /* @__PURE__ */ n("span", { className: "text-sm text-foreground-muted", children: "Changes sync automatically" }),
118
+ a && /* @__PURE__ */ n("span", { className: "text-sm text-destructive", children: a })
124
119
  ] })
125
120
  ] }),
126
- /* @__PURE__ */ t(O, { mjmlSource: a, debounceMs: 300 })
121
+ /* @__PURE__ */ n(O, { mjmlSource: o, debounceMs: 300 })
127
122
  ]
128
123
  }
129
124
  );
130
125
  }
131
126
  export {
132
- le as SourceEditor
127
+ ae as SourceEditor
133
128
  };
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ interface NonceProviderProps {
3
+ children: ReactNode;
4
+ nonce?: string;
5
+ }
6
+ export declare function NonceProvider({ children, nonce }: NonceProviderProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function useNonce(): string | undefined;
8
+ export {};
9
+ //# sourceMappingURL=NonceContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NonceContext.d.ts","sourceRoot":"","sources":["../../src/context/NonceContext.tsx"],"names":[],"mappings":"AACA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAIlE,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,kBAAkB,2CAIpE;AAED,wBAAgB,QAAQ,uBAEvB"}
@@ -0,0 +1,13 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { useContext as n, createContext as c } from "react";
3
+ const o = c(void 0);
4
+ function x({ children: e, nonce: t }) {
5
+ return /* @__PURE__ */ r(o.Provider, { value: t, children: e });
6
+ }
7
+ function f() {
8
+ return n(o);
9
+ }
10
+ export {
11
+ x as NonceProvider,
12
+ f as useNonce
13
+ };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { MjmlEditor } from './components/editor/MjmlEditor';
2
2
  export { ThemeProvider, useTheme } from './context/ThemeContext';
3
3
  export { ThemeToggle } from './components/ui/theme-toggle';
4
+ export { useNonce } from './context/NonceContext';
4
5
  export type { MjmlNode, MjmlTagName, ContentBlockType, EditorState, EditorAction, EditorExtensions, } from './types/mjml';
5
6
  export type { LiquidSchema, LiquidSchemaItem } from './types/liquid';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,YAAY,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAG5D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAG3D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD,YAAY,EACV,QAAQ,EACR,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { MjmlEditor as r } from "./components/editor/MjmlEditor.js";
2
- import { ThemeProvider as t, useTheme as T } from "./context/ThemeContext.js";
3
- import { ThemeToggle as h } from "./components/ui/theme-toggle.js";
2
+ import { ThemeProvider as t, useTheme as f } from "./context/ThemeContext.js";
3
+ import { ThemeToggle as x } from "./components/ui/theme-toggle.js";
4
+ import { useNonce as h } from "./context/NonceContext.js";
4
5
  export {
5
6
  r as MjmlEditor,
6
7
  t as ThemeProvider,
7
- h as ThemeToggle,
8
- T as useTheme
8
+ x as ThemeToggle,
9
+ h as useNonce,
10
+ f as useTheme
9
11
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvycal/mjml-editor",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {