@mjml-agent-editor/editor 0.4.2 → 0.5.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/canvas.js CHANGED
@@ -1957,6 +1957,13 @@ var SCHEMA = {
1957
1957
  { attr: "direction", label: "reverseColumns", group: "advanced", control: { type: "toggle", on: "rtl" } },
1958
1958
  { attr: "border", label: "border", group: "advanced", control: { type: "text", placeholder: "1px solid #cccccc" } }
1959
1959
  ],
1960
+ // MJML allows a group these and `width` only: padding or a border fails strict. Its width is
1961
+ // not offered, as the canvas does not draw it: the plugin's group drops MJML's rule for it.
1962
+ "mj-group": [
1963
+ { attr: "vertical-align", label: "verticalAlign", group: "layout", control: { type: "segmented", options: VERTICAL_ALIGN } },
1964
+ { attr: "background-color", label: "backgroundColor", group: "style", control: { type: "color" } },
1965
+ { attr: "direction", label: "reverseColumns", group: "advanced", control: { type: "toggle", on: "rtl" } }
1966
+ ],
1960
1967
  "mj-column": [
1961
1968
  { attr: "vertical-align", label: "verticalAlign", group: "layout", control: { type: "segmented", options: VERTICAL_ALIGN }, default: "top" },
1962
1969
  { attr: "padding", label: "padding", group: "spacing", control: { type: "box", units: PX_PCT } },
@@ -2315,8 +2322,12 @@ var COLUMN_RATIOS = {
2315
2322
  [1, 2, 1]
2316
2323
  ]
2317
2324
  };
2318
- function columnsOf(section) {
2319
- const children = section.components().models;
2325
+ function columnsOf(container) {
2326
+ let children = container.components().models;
2327
+ const only = children.length === 1 ? children[0] : null;
2328
+ if (tagOf2(container) === "mj-section" && only && tagOf2(only) === "mj-group") {
2329
+ children = only.components().models;
2330
+ }
2320
2331
  return children.length > 0 && children.every((c) => tagOf2(c) === "mj-column") ? children : null;
2321
2332
  }
2322
2333
  function ratioWidths(ratio) {
@@ -2379,6 +2390,7 @@ function StructureSection({
2379
2390
  }) {
2380
2391
  switch (tagOf3(component)) {
2381
2392
  case "mj-section":
2393
+ case "mj-group":
2382
2394
  return /* @__PURE__ */ jsx6(ColumnWidths, { component, labels, locked });
2383
2395
  case "mj-social":
2384
2396
  return /* @__PURE__ */ jsx6(
@@ -2833,11 +2845,11 @@ function ElementSettings({
2833
2845
  ] }),
2834
2846
  /* @__PURE__ */ jsx7(StructureSection, { editor, component, labels, locked }),
2835
2847
  GROUPS.map((group) => {
2836
- const inGroup = visible.filter((f) => f.group === group);
2837
- if (inGroup.length === 0) return null;
2848
+ const inGroup2 = visible.filter((f) => f.group === group);
2849
+ if (inGroup2.length === 0) return null;
2838
2850
  return /* @__PURE__ */ jsxs6("section", { className: "border-b border-panel-border/60 py-2", children: [
2839
2851
  /* @__PURE__ */ jsx7("h3", { className: "px-3 pb-1 text-[10px] font-semibold tracking-wider text-panel-muted-fg/80 uppercase", children: groupName(group, labels) }),
2840
- inGroup.map(row)
2852
+ inGroup2.map(row)
2841
2853
  ] }, group);
2842
2854
  }),
2843
2855
  advancedCount > 0 && /* @__PURE__ */ jsxs6("section", { className: "py-1", children: [
@@ -3284,12 +3296,17 @@ function fixPluginTypes(editor) {
3284
3296
  for (const type of editor.Components.getTypes()) {
3285
3297
  if (!type.id.startsWith("mj-") || type.id === "mj-table") continue;
3286
3298
  const base = type.model.prototype.getAttrToHTML;
3299
+ const view = type.view.prototype;
3287
3300
  editor.Components.addType(type.id, {
3301
+ ...type.id === "mj-column" && { view: groupedColumnView(view) },
3302
+ ...type.id === "mj-group" && { view: redrawnGroupView(view) },
3288
3303
  model: {
3289
3304
  defaults: {
3290
3305
  "style-default": {},
3291
3306
  ...type.id === "mj-column" && {
3292
- droppable: (source) => COLUMN_CHILDREN.has(String(source.get("tagName")))
3307
+ droppable: (source) => COLUMN_CHILDREN.has(String(source.get("tagName"))),
3308
+ // The plugin moves a column only within sections, so a group's could not even swap.
3309
+ draggable: '[data-gjs-type="mj-section"], [data-gjs-type="mj-group"]'
3293
3310
  },
3294
3311
  // GrapesJS's own is an SVG's markup, which the canvas wrote into `src` and saved.
3295
3312
  ...type.id === "mj-image" && { src: "" }
@@ -3306,6 +3323,41 @@ function fixPluginTypes(editor) {
3306
3323
  });
3307
3324
  }
3308
3325
  }
3326
+ var inGroup = (column) => column.parent()?.get("type") === "mj-group";
3327
+ function groupedColumnView(base) {
3328
+ return {
3329
+ getMjmlTemplate() {
3330
+ if (!inGroup(this.model)) return base.getMjmlTemplate.call(this);
3331
+ const siblings = "<mj-column></mj-column>".repeat(
3332
+ Math.max((this.model.collection?.length ?? 1) - 1, 0)
3333
+ );
3334
+ const width = (c) => {
3335
+ const value = c?.getAttributes().width;
3336
+ return typeof value === "string" && value ? ` width="${value.replace(/"/g, "")}"` : "";
3337
+ };
3338
+ let body = this.model;
3339
+ while (body && body.get("type") !== "mj-body") body = body.parent();
3340
+ return {
3341
+ start: `<mjml><mj-body${width(body)}><mj-section><mj-group${width(this.model.parent())}>`,
3342
+ end: `${siblings}</mj-group></mj-section></mj-body></mjml>`
3343
+ };
3344
+ },
3345
+ getTemplateFromEl(container) {
3346
+ if (!inGroup(this.model)) return base.getTemplateFromEl.call(this, container);
3347
+ return container.firstChild?.querySelector(
3348
+ "div > table > tbody > tr > td > div > div"
3349
+ ) ?? null;
3350
+ }
3351
+ };
3352
+ }
3353
+ function redrawnGroupView(base) {
3354
+ return {
3355
+ init() {
3356
+ base.init.call(this);
3357
+ this.listenTo(this.model.components(), "add remove", this.render);
3358
+ }
3359
+ };
3360
+ }
3309
3361
 
3310
3362
  // src/components/editor/EmailEditor.tsx
3311
3363
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
@@ -3446,6 +3498,25 @@ function EmailEditor({
3446
3498
  setLocked(false);
3447
3499
  };
3448
3500
  }, [turn, setLocked]);
3501
+ const inert = readOnly || loading;
3502
+ const wasLocked = useRef5(false);
3503
+ useEffect5(() => {
3504
+ if (inert) {
3505
+ wasLocked.current = true;
3506
+ return;
3507
+ }
3508
+ const root = wasLocked.current && editorRef.current?.Canvas.getDocument()?.documentElement;
3509
+ wasLocked.current = false;
3510
+ if (!root) return;
3511
+ const overflow = root.style.overflow;
3512
+ root.style.overflow = "hidden";
3513
+ void root.offsetHeight;
3514
+ const frame = requestAnimationFrame(() => root.style.overflow = overflow);
3515
+ return () => {
3516
+ cancelAnimationFrame(frame);
3517
+ root.style.overflow = overflow;
3518
+ };
3519
+ }, [inert]);
3449
3520
  const [crumbs, setCrumbs] = useState5([]);
3450
3521
  const [picker, setPicker] = useState5(
3451
3522
  null
@@ -3547,7 +3618,7 @@ function EmailEditor({
3547
3618
  fixPluginTypes(editor);
3548
3619
  registerBlocks(editor, blocks, labels.blockCategorySections, SECTION_SVG);
3549
3620
  setupLayerNames(editor, labels);
3550
- const STRUCTURE = /* @__PURE__ */ new Set(["mj-wrapper", "mj-section", "mj-column"]);
3621
+ const STRUCTURE = /* @__PURE__ */ new Set(["mj-wrapper", "mj-section", "mj-group", "mj-column"]);
3551
3622
  const showBodyInLayers = () => {
3552
3623
  const body = findByTag("mj-body");
3553
3624
  if (!body) return;
@@ -3833,9 +3904,14 @@ function EmailEditor({
3833
3904
  "div",
3834
3905
  {
3835
3906
  className: "relative flex h-full min-h-0 flex-1",
3836
- inert: readOnly,
3907
+ inert,
3837
3908
  onKeyDown: (e) => onBlockSearchKey(e.nativeEvent),
3838
3909
  children: [
3910
+ loading && /* @__PURE__ */ jsxs7("div", { className: "absolute inset-0 z-30 flex items-center justify-center gap-2 bg-white/70 text-sm text-zinc-500", children: [
3911
+ /* @__PURE__ */ jsx8(Spinner, {}),
3912
+ " ",
3913
+ labels.loadingEditor
3914
+ ] }),
3839
3915
  readOnly && /* @__PURE__ */ jsx8("div", { className: "absolute inset-0 z-30 flex cursor-not-allowed items-start justify-center bg-white/20 pt-3", children: /* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-2 rounded-full bg-panel px-3 py-1 text-xs text-panel-fg shadow", children: [
3840
3916
  /* @__PURE__ */ jsx8(Spinner, {}),
3841
3917
  " ",
@@ -3877,12 +3953,7 @@ function EmailEditor({
3877
3953
  editorRef.current?.AssetManager.close();
3878
3954
  }
3879
3955
  }
3880
- ),
3881
- loading && /* @__PURE__ */ jsxs7("div", { className: "absolute inset-0 z-10 flex items-center justify-center gap-2 bg-white/70 text-sm text-zinc-500", children: [
3882
- /* @__PURE__ */ jsx8(Spinner, {}),
3883
- " ",
3884
- labels.loadingEditor
3885
- ] })
3956
+ )
3886
3957
  ] }),
3887
3958
  /* @__PURE__ */ jsx8(Breadcrumb, { crumbs, onSelect: (c) => editorRef.current?.select(c) })
3888
3959
  ] })