@savvycal/mjml-editor 0.2.0 → 0.3.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":"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"}
1
+ {"version":3,"file":"OutlineTree.d.ts","sourceRoot":"","sources":["../../../src/components/editor/OutlineTree.tsx"],"names":[],"mappings":"AAoCA,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,2CAsK9D"}
@@ -1,28 +1,29 @@
1
- import { jsxs as s, jsx as e, Fragment as H } from "react/jsx-runtime";
2
- import { useRef as j, useState as _, useEffect as L } from "react";
3
- import { Tree as G } from "react-arborist";
4
- import { PanelLeftClose as V, Plus as I, Palette as F, Mail as W, ChevronDown as Y, ChevronRight as y, GripVertical as q, Columns as P, Trash2 as J, MoveVertical as S, Minus as T, MousePointerClick as A, Image as D, Type as z } from "lucide-react";
1
+ import { jsxs as a, jsx as e, Fragment as H } from "react/jsx-runtime";
2
+ import { useRef as C, useState as T, useEffect as L, useCallback as G } from "react";
3
+ import { Tree as V } from "react-arborist";
4
+ import { PanelLeftClose as F, Plus as I, Palette as W, Mail as Y, ChevronDown as q, ChevronRight as y, GripVertical as J, Columns as P, Trash2 as K, MoveVertical as S, Minus as A, MousePointerClick as D, Image as O, Type as z } from "lucide-react";
5
5
  import { useEditor as M } from "../../context/EditorContext.js";
6
- import { Button as d } from "../ui/button.js";
7
- import { Popover as K, PopoverTrigger as Q, PopoverContent as U } from "../ui/popover.js";
8
- import { contentBlockTypes as X } from "../../lib/mjml/schema.js";
9
- import { cn as m } from "../../lib/utils.js";
10
- const C = "__global_styles__", Z = {
6
+ import { Button as m } from "../ui/button.js";
7
+ import { Popover as Q, PopoverTrigger as U, PopoverContent as X } from "../ui/popover.js";
8
+ import { contentBlockTypes as Z } from "../../lib/mjml/schema.js";
9
+ import { isContentBlock as $, canBeChildOf as ee } from "../../lib/mjml/nesting-rules.js";
10
+ import { cn as h } from "../../lib/utils.js";
11
+ const k = "__global_styles__", te = {
11
12
  "mj-section": /* @__PURE__ */ e("div", { className: "w-4 h-4 border border-current rounded-sm" }),
12
13
  "mj-column": /* @__PURE__ */ e(P, { className: "h-4 w-4" }),
13
14
  "mj-text": /* @__PURE__ */ e(z, { className: "h-4 w-4" }),
14
- "mj-image": /* @__PURE__ */ e(D, { className: "h-4 w-4" }),
15
- "mj-button": /* @__PURE__ */ e(A, { className: "h-4 w-4" }),
16
- "mj-divider": /* @__PURE__ */ e(T, { className: "h-4 w-4" }),
15
+ "mj-image": /* @__PURE__ */ e(O, { className: "h-4 w-4" }),
16
+ "mj-button": /* @__PURE__ */ e(D, { className: "h-4 w-4" }),
17
+ "mj-divider": /* @__PURE__ */ e(A, { className: "h-4 w-4" }),
17
18
  "mj-spacer": /* @__PURE__ */ e(S, { className: "h-4 w-4" })
18
- }, $ = {
19
+ }, re = {
19
20
  "mj-text": /* @__PURE__ */ e(z, { className: "h-4 w-4" }),
20
- "mj-image": /* @__PURE__ */ e(D, { className: "h-4 w-4" }),
21
- "mj-button": /* @__PURE__ */ e(A, { className: "h-4 w-4" }),
22
- "mj-divider": /* @__PURE__ */ e(T, { className: "h-4 w-4" }),
21
+ "mj-image": /* @__PURE__ */ e(O, { className: "h-4 w-4" }),
22
+ "mj-button": /* @__PURE__ */ e(D, { className: "h-4 w-4" }),
23
+ "mj-divider": /* @__PURE__ */ e(A, { className: "h-4 w-4" }),
23
24
  "mj-spacer": /* @__PURE__ */ e(S, { className: "h-4 w-4" })
24
25
  };
25
- function ee(t) {
26
+ function oe(t) {
26
27
  return {
27
28
  "mj-section": "Section",
28
29
  "mj-column": "Column",
@@ -39,7 +40,7 @@ function ee(t) {
39
40
  "mj-raw": "Raw HTML"
40
41
  }[t] || t.replace("mj-", "").replace(/-/g, " ");
41
42
  }
42
- function te(t) {
43
+ function ne(t) {
43
44
  return [
44
45
  "mj-section",
45
46
  "mj-column",
@@ -48,54 +49,54 @@ function te(t) {
48
49
  "mj-hero"
49
50
  ].includes(t);
50
51
  }
51
- function k(t) {
52
+ function B(t) {
52
53
  return t === "mj-column";
53
54
  }
54
- function B(t) {
55
+ function _(t) {
55
56
  return t === "mj-section" || t === "mj-group";
56
57
  }
57
- function oe({ node: t, style: c, dragHandle: f }) {
58
- const { state: x, selectBlock: u, deleteBlock: N, addBlock: p, addColumn: v } = M(), [w, a] = _(!1), o = t.data, b = x.selectedBlockId === o._id, r = t.children && t.children.length > 0, l = te(o.tagName), h = (n) => {
59
- n.stopPropagation(), t.select(), u(o._id);
58
+ function ae({ node: t, style: d, dragHandle: f }) {
59
+ const { state: N, selectBlock: u, deleteBlock: x, addBlock: g, addColumn: v } = M(), [b, s] = T(!1), r = t.data, w = N.selectedBlockId === r._id, j = t.children && t.children.length > 0, o = ne(r.tagName), l = (n) => {
60
+ n.stopPropagation(), t.select(), u(r._id);
60
61
  }, i = (n) => {
61
- n.stopPropagation(), N(o._id);
62
- }, g = (n) => {
62
+ n.stopPropagation(), x(r._id);
63
+ }, c = (n) => {
63
64
  n.stopPropagation(), t.toggle();
64
- }, O = (n) => {
65
- const E = o.children?.length || 0;
66
- p(o._id, E, n), a(!1);
65
+ }, p = (n) => {
66
+ const E = r.children?.length || 0;
67
+ g(r._id, E, n), s(!1);
67
68
  }, R = () => {
68
- v(o._id), a(!1);
69
+ v(r._id), s(!1);
69
70
  };
70
- return /* @__PURE__ */ s(
71
+ return /* @__PURE__ */ a(
71
72
  "div",
72
73
  {
73
- style: c,
74
- className: m(
74
+ style: d,
75
+ className: h(
75
76
  "group flex items-center h-8 pr-2 cursor-pointer",
76
77
  "hover:bg-accent/50 transition-colors",
77
- b && "bg-accent",
78
+ w && "bg-accent",
78
79
  t.state.isDragging && "opacity-50"
79
80
  ),
80
- onClick: h,
81
+ onClick: l,
81
82
  children: [
82
- l ? /* @__PURE__ */ e(
83
+ o ? /* @__PURE__ */ e(
83
84
  "button",
84
85
  {
85
- className: m(
86
+ className: h(
86
87
  "flex items-center justify-center w-5 h-5",
87
88
  "text-foreground-muted hover:text-foreground transition-colors"
88
89
  ),
89
- onClick: g,
90
- children: r ? t.isOpen ? /* @__PURE__ */ e(Y, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(y, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(y, { className: "h-3.5 w-3.5 opacity-30" })
90
+ onClick: c,
91
+ children: j ? t.isOpen ? /* @__PURE__ */ e(q, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(y, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ e(y, { className: "h-3.5 w-3.5 opacity-30" })
91
92
  }
92
93
  ) : /* @__PURE__ */ e("div", { className: "w-5" }),
93
- /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-5 h-5 text-foreground-muted", children: Z[o.tagName] || /* @__PURE__ */ e("div", { className: "w-3 h-3 bg-foreground-muted rounded-sm" }) }),
94
- /* @__PURE__ */ e("span", { className: "flex-1 ml-2 text-sm truncate text-foreground", children: ee(o.tagName) }),
95
- /* @__PURE__ */ s(
94
+ /* @__PURE__ */ e("div", { className: "flex items-center justify-center w-5 h-5 text-foreground-muted", children: te[r.tagName] || /* @__PURE__ */ e("div", { className: "w-3 h-3 bg-foreground-muted rounded-sm" }) }),
95
+ /* @__PURE__ */ e("span", { className: "flex-1 ml-2 text-sm truncate text-foreground", children: oe(r.tagName) }),
96
+ /* @__PURE__ */ a(
96
97
  "div",
97
98
  {
98
- className: m(
99
+ className: h(
99
100
  "flex items-center gap-0.5",
100
101
  "opacity-0 group-hover:opacity-100 transition-opacity"
101
102
  ),
@@ -104,16 +105,16 @@ function oe({ node: t, style: c, dragHandle: f }) {
104
105
  "div",
105
106
  {
106
107
  ref: f,
107
- className: m(
108
+ className: h(
108
109
  "flex items-center justify-center w-6 h-6 cursor-grab rounded-md",
109
110
  "text-foreground-muted hover:text-foreground hover:bg-accent/50"
110
111
  ),
111
- children: /* @__PURE__ */ e(q, { className: "h-3.5 w-3.5" })
112
+ children: /* @__PURE__ */ e(J, { className: "h-3.5 w-3.5" })
112
113
  }
113
114
  ),
114
- (k(o.tagName) || B(o.tagName)) && /* @__PURE__ */ s(K, { open: w, onOpenChange: a, children: [
115
- /* @__PURE__ */ e(Q, { asChild: !0, children: /* @__PURE__ */ e(
116
- d,
115
+ (B(r.tagName) || _(r.tagName)) && /* @__PURE__ */ a(Q, { open: b, onOpenChange: s, children: [
116
+ /* @__PURE__ */ e(U, { asChild: !0, children: /* @__PURE__ */ e(
117
+ m,
117
118
  {
118
119
  variant: "ghost",
119
120
  size: "icon-sm",
@@ -122,15 +123,15 @@ function oe({ node: t, style: c, dragHandle: f }) {
122
123
  children: /* @__PURE__ */ e(I, { className: "h-3.5 w-3.5" })
123
124
  }
124
125
  ) }),
125
- /* @__PURE__ */ s(
126
- U,
126
+ /* @__PURE__ */ a(
127
+ X,
127
128
  {
128
129
  className: "w-48 p-1.5 shadow-framer-lg",
129
130
  align: "start",
130
131
  onClick: (n) => n.stopPropagation(),
131
132
  children: [
132
- B(o.tagName) && /* @__PURE__ */ s(
133
- d,
133
+ _(r.tagName) && /* @__PURE__ */ a(
134
+ m,
134
135
  {
135
136
  variant: "ghost",
136
137
  size: "sm",
@@ -142,15 +143,15 @@ function oe({ node: t, style: c, dragHandle: f }) {
142
143
  ]
143
144
  }
144
145
  ),
145
- k(o.tagName) && /* @__PURE__ */ e(H, { children: X.map((n) => /* @__PURE__ */ s(
146
- d,
146
+ B(r.tagName) && /* @__PURE__ */ e(H, { children: Z.map((n) => /* @__PURE__ */ a(
147
+ m,
147
148
  {
148
149
  variant: "ghost",
149
150
  size: "sm",
150
151
  className: "w-full justify-start gap-3 h-8 px-3 text-sm font-normal hover:bg-accent",
151
- onClick: () => O(n.type),
152
+ onClick: () => p(n.type),
152
153
  children: [
153
- /* @__PURE__ */ e("span", { className: "text-foreground-muted", children: $[n.type] }),
154
+ /* @__PURE__ */ e("span", { className: "text-foreground-muted", children: re[n.type] }),
154
155
  n.label
155
156
  ]
156
157
  },
@@ -161,13 +162,13 @@ function oe({ node: t, style: c, dragHandle: f }) {
161
162
  )
162
163
  ] }),
163
164
  /* @__PURE__ */ e(
164
- d,
165
+ m,
165
166
  {
166
167
  variant: "ghost",
167
168
  size: "icon-sm",
168
169
  className: "h-6 w-6 text-foreground-muted hover:text-destructive",
169
170
  onClick: i,
170
- children: /* @__PURE__ */ e(J, { className: "h-3.5 w-3.5" })
171
+ children: /* @__PURE__ */ e(K, { className: "h-3.5 w-3.5" })
171
172
  }
172
173
  )
173
174
  ]
@@ -177,47 +178,61 @@ function oe({ node: t, style: c, dragHandle: f }) {
177
178
  }
178
179
  );
179
180
  }
180
- function he({ onTogglePanel: t }) {
181
- const { state: c, moveBlock: f, addSection: x, selectBlock: u } = M(), N = j(null), p = j(null), [v, w] = _(400);
181
+ function fe({ onTogglePanel: t }) {
182
+ const { state: d, moveBlock: f, addSection: N, selectBlock: u } = M(), x = C(null), g = C(null), [v, b] = T(400);
182
183
  L(() => {
183
- const r = p.current;
184
- if (!r) return;
185
- const l = new ResizeObserver((h) => {
186
- for (const i of h)
187
- w(i.contentRect.height);
184
+ const o = g.current;
185
+ if (!o) return;
186
+ const l = new ResizeObserver((i) => {
187
+ for (const c of i)
188
+ b(c.contentRect.height);
188
189
  });
189
- return l.observe(r), () => l.disconnect();
190
+ return l.observe(o), () => l.disconnect();
190
191
  }, []);
191
- const a = c.document.children?.find((r) => r.tagName === "mj-body"), o = a?.children || [], b = ({
192
- dragIds: r,
192
+ const s = d.document.children?.find((o) => o.tagName === "mj-body"), r = s?.children || [], w = ({
193
+ dragIds: o,
193
194
  parentId: l,
194
- index: h
195
+ index: i
195
196
  }) => {
196
- const i = r[0], g = l || a?._id;
197
- i && g && f(i, g, h);
198
- };
199
- return /* @__PURE__ */ s("div", { className: "flex flex-col h-full", children: [
200
- /* @__PURE__ */ s("div", { className: "flex items-center justify-between h-11 px-3 border-b border-border bg-background", children: [
197
+ const c = o[0], p = l || s?._id;
198
+ c && p && f(c, p, i);
199
+ }, j = G(
200
+ ({
201
+ parentNode: o,
202
+ dragNodes: l
203
+ }) => {
204
+ const i = o?.data?.tagName || "mj-body";
205
+ if ($(i))
206
+ return !0;
207
+ for (const c of l)
208
+ if (!ee(c.data.tagName, i) || o && c.isAncestorOf(o))
209
+ return !0;
210
+ return !1;
211
+ },
212
+ []
213
+ );
214
+ return /* @__PURE__ */ a("div", { className: "flex flex-col h-full", children: [
215
+ /* @__PURE__ */ a("div", { className: "flex items-center justify-between h-11 px-3 border-b border-border bg-background", children: [
201
216
  /* @__PURE__ */ e("span", { className: "text-sm font-semibold text-foreground", children: "Email Structure" }),
202
217
  t && /* @__PURE__ */ e(
203
- d,
218
+ m,
204
219
  {
205
220
  variant: "ghost",
206
221
  size: "icon-sm",
207
222
  onClick: t,
208
223
  className: "h-7 w-7 rounded-md text-foreground-muted hover:text-foreground hover:bg-accent",
209
224
  title: "Collapse panel",
210
- children: /* @__PURE__ */ e(V, { className: "h-4 w-4" })
225
+ children: /* @__PURE__ */ e(F, { className: "h-4 w-4" })
211
226
  }
212
227
  )
213
228
  ] }),
214
- /* @__PURE__ */ e("div", { className: "px-3 py-2 border-b border-border", children: /* @__PURE__ */ s(
215
- d,
229
+ /* @__PURE__ */ e("div", { className: "px-3 py-2 border-b border-border", children: /* @__PURE__ */ a(
230
+ m,
216
231
  {
217
232
  variant: "outline",
218
233
  size: "sm",
219
- onClick: x,
220
- disabled: !a,
234
+ onClick: N,
235
+ disabled: !s,
221
236
  className: "w-full h-8 gap-1.5 text-xs font-medium",
222
237
  children: [
223
238
  /* @__PURE__ */ e(I, { className: "h-3.5 w-3.5" }),
@@ -225,45 +240,45 @@ function he({ onTogglePanel: t }) {
225
240
  ]
226
241
  }
227
242
  ) }),
228
- /* @__PURE__ */ s("div", { className: "px-3 py-1 border-b border-border space-y-0.5", children: [
229
- /* @__PURE__ */ s(
243
+ /* @__PURE__ */ a("div", { className: "px-3 py-1 border-b border-border space-y-0.5", children: [
244
+ /* @__PURE__ */ a(
230
245
  "button",
231
246
  {
232
- onClick: () => u(C),
233
- className: m(
247
+ onClick: () => u(k),
248
+ className: h(
234
249
  "flex items-center gap-2 w-full h-8 px-2 rounded-md text-sm",
235
250
  "hover:bg-accent/50 transition-colors",
236
- c.selectedBlockId === C && "bg-accent"
251
+ d.selectedBlockId === k && "bg-accent"
237
252
  ),
238
253
  children: [
239
- /* @__PURE__ */ e(F, { className: "h-4 w-4 text-foreground-muted" }),
254
+ /* @__PURE__ */ e(W, { className: "h-4 w-4 text-foreground-muted" }),
240
255
  /* @__PURE__ */ e("span", { className: "text-foreground", children: "Global Styles" })
241
256
  ]
242
257
  }
243
258
  ),
244
- /* @__PURE__ */ s(
259
+ /* @__PURE__ */ a(
245
260
  "button",
246
261
  {
247
- onClick: () => u(a?._id || null),
248
- className: m(
262
+ onClick: () => u(s?._id || null),
263
+ className: h(
249
264
  "flex items-center gap-2 w-full h-8 px-2 rounded-md text-sm",
250
265
  "hover:bg-accent/50 transition-colors",
251
- c.selectedBlockId === a?._id && "bg-accent"
266
+ d.selectedBlockId === s?._id && "bg-accent"
252
267
  ),
253
268
  children: [
254
- /* @__PURE__ */ e(W, { className: "h-4 w-4 text-foreground-muted" }),
269
+ /* @__PURE__ */ e(Y, { className: "h-4 w-4 text-foreground-muted" }),
255
270
  /* @__PURE__ */ e("span", { className: "text-foreground", children: "Body" })
256
271
  ]
257
272
  }
258
273
  )
259
274
  ] }),
260
- /* @__PURE__ */ e("div", { ref: p, className: "flex-1 min-h-0", children: o.length > 0 ? /* @__PURE__ */ e(
261
- G,
275
+ /* @__PURE__ */ e("div", { ref: g, className: "flex-1 min-h-0", children: r.length > 0 ? /* @__PURE__ */ e(
276
+ V,
262
277
  {
263
- ref: N,
264
- data: o,
265
- idAccessor: (r) => r._id,
266
- childrenAccessor: (r) => r.children || null,
278
+ ref: x,
279
+ data: r,
280
+ idAccessor: (o) => o._id,
281
+ childrenAccessor: (o) => o.children || null,
267
282
  openByDefault: !0,
268
283
  width: "100%",
269
284
  height: v,
@@ -271,13 +286,14 @@ function he({ onTogglePanel: t }) {
271
286
  rowHeight: 32,
272
287
  paddingTop: 8,
273
288
  paddingBottom: 8,
274
- onMove: b,
275
- children: oe
289
+ onMove: w,
290
+ disableDrop: j,
291
+ children: ae
276
292
  }
277
293
  ) : /* @__PURE__ */ e("div", { className: "flex-1 px-3 py-8 text-center text-sm text-muted-foreground", children: "No content yet" }) })
278
294
  ] });
279
295
  }
280
296
  export {
281
- C as GLOBAL_STYLES_ID,
282
- he as OutlineTree
297
+ k as GLOBAL_STYLES_ID,
298
+ fe as OutlineTree
283
299
  };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * MJML Nesting Rules
3
+ *
4
+ * Defines which MJML elements can be children of which parents.
5
+ * Used to validate drag-and-drop operations in the tree.
6
+ */
7
+ /**
8
+ * Map of parent tag names to their allowed child tag names
9
+ */
10
+ export declare const ALLOWED_CHILDREN: Record<string, string[]>;
11
+ /**
12
+ * Check if a child tag can be placed inside a parent tag
13
+ */
14
+ export declare function canBeChildOf(childTag: string, parentTag: string): boolean;
15
+ /**
16
+ * Check if a tag is a content block (leaf node that cannot have children)
17
+ */
18
+ export declare function isContentBlock(tagName: string): boolean;
19
+ //# sourceMappingURL=nesting-rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nesting-rules.d.ts","sourceRoot":"","sources":["../../../src/lib/mjml/nesting-rules.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA4BrD,CAAC;AAEF;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD"}
@@ -0,0 +1,40 @@
1
+ const j = {
2
+ "mj-body": ["mj-section", "mj-wrapper", "mj-hero"],
3
+ "mj-wrapper": ["mj-section"],
4
+ "mj-section": ["mj-column", "mj-group"],
5
+ "mj-group": ["mj-column"],
6
+ "mj-column": [
7
+ "mj-text",
8
+ "mj-image",
9
+ "mj-button",
10
+ "mj-divider",
11
+ "mj-spacer",
12
+ "mj-social",
13
+ "mj-navbar",
14
+ "mj-table",
15
+ "mj-raw",
16
+ "mj-accordion",
17
+ "mj-carousel"
18
+ ],
19
+ "mj-hero": [
20
+ "mj-text",
21
+ "mj-image",
22
+ "mj-button",
23
+ "mj-divider",
24
+ "mj-spacer",
25
+ "mj-social",
26
+ "mj-navbar",
27
+ "mj-raw"
28
+ ]
29
+ };
30
+ function o(m, e) {
31
+ return j[e]?.includes(m) ?? !1;
32
+ }
33
+ function r(m) {
34
+ return !j[m];
35
+ }
36
+ export {
37
+ j as ALLOWED_CHILDREN,
38
+ o as canBeChildOf,
39
+ r as isContentBlock
40
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=nesting-rules.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nesting-rules.test.d.ts","sourceRoot":"","sources":["../../../src/lib/mjml/nesting-rules.test.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvycal/mjml-editor",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {