@mjml-agent-editor/editor 0.4.3 → 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,9 +3498,10 @@ function EmailEditor({
3446
3498
  setLocked(false);
3447
3499
  };
3448
3500
  }, [turn, setLocked]);
3501
+ const inert = readOnly || loading;
3449
3502
  const wasLocked = useRef5(false);
3450
3503
  useEffect5(() => {
3451
- if (readOnly) {
3504
+ if (inert) {
3452
3505
  wasLocked.current = true;
3453
3506
  return;
3454
3507
  }
@@ -3463,7 +3516,7 @@ function EmailEditor({
3463
3516
  cancelAnimationFrame(frame);
3464
3517
  root.style.overflow = overflow;
3465
3518
  };
3466
- }, [readOnly]);
3519
+ }, [inert]);
3467
3520
  const [crumbs, setCrumbs] = useState5([]);
3468
3521
  const [picker, setPicker] = useState5(
3469
3522
  null
@@ -3565,7 +3618,7 @@ function EmailEditor({
3565
3618
  fixPluginTypes(editor);
3566
3619
  registerBlocks(editor, blocks, labels.blockCategorySections, SECTION_SVG);
3567
3620
  setupLayerNames(editor, labels);
3568
- 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"]);
3569
3622
  const showBodyInLayers = () => {
3570
3623
  const body = findByTag("mj-body");
3571
3624
  if (!body) return;
@@ -3851,9 +3904,14 @@ function EmailEditor({
3851
3904
  "div",
3852
3905
  {
3853
3906
  className: "relative flex h-full min-h-0 flex-1",
3854
- inert: readOnly,
3907
+ inert,
3855
3908
  onKeyDown: (e) => onBlockSearchKey(e.nativeEvent),
3856
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
+ ] }),
3857
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: [
3858
3916
  /* @__PURE__ */ jsx8(Spinner, {}),
3859
3917
  " ",
@@ -3895,12 +3953,7 @@ function EmailEditor({
3895
3953
  editorRef.current?.AssetManager.close();
3896
3954
  }
3897
3955
  }
3898
- ),
3899
- 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: [
3900
- /* @__PURE__ */ jsx8(Spinner, {}),
3901
- " ",
3902
- labels.loadingEditor
3903
- ] })
3956
+ )
3904
3957
  ] }),
3905
3958
  /* @__PURE__ */ jsx8(Breadcrumb, { crumbs, onSelect: (c) => editorRef.current?.select(c) })
3906
3959
  ] })