@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.cjs CHANGED
@@ -2846,6 +2846,13 @@ var SCHEMA = {
2846
2846
  { attr: "direction", label: "reverseColumns", group: "advanced", control: { type: "toggle", on: "rtl" } },
2847
2847
  { attr: "border", label: "border", group: "advanced", control: { type: "text", placeholder: "1px solid #cccccc" } }
2848
2848
  ],
2849
+ // MJML allows a group these and `width` only: padding or a border fails strict. Its width is
2850
+ // not offered, as the canvas does not draw it: the plugin's group drops MJML's rule for it.
2851
+ "mj-group": [
2852
+ { attr: "vertical-align", label: "verticalAlign", group: "layout", control: { type: "segmented", options: VERTICAL_ALIGN } },
2853
+ { attr: "background-color", label: "backgroundColor", group: "style", control: { type: "color" } },
2854
+ { attr: "direction", label: "reverseColumns", group: "advanced", control: { type: "toggle", on: "rtl" } }
2855
+ ],
2849
2856
  "mj-column": [
2850
2857
  { attr: "vertical-align", label: "verticalAlign", group: "layout", control: { type: "segmented", options: VERTICAL_ALIGN }, default: "top" },
2851
2858
  { attr: "padding", label: "padding", group: "spacing", control: { type: "box", units: PX_PCT } },
@@ -3204,8 +3211,12 @@ var COLUMN_RATIOS = {
3204
3211
  [1, 2, 1]
3205
3212
  ]
3206
3213
  };
3207
- function columnsOf(section) {
3208
- const children = section.components().models;
3214
+ function columnsOf(container) {
3215
+ let children = container.components().models;
3216
+ const only = children.length === 1 ? children[0] : null;
3217
+ if (tagOf2(container) === "mj-section" && only && tagOf2(only) === "mj-group") {
3218
+ children = only.components().models;
3219
+ }
3209
3220
  return children.length > 0 && children.every((c) => tagOf2(c) === "mj-column") ? children : null;
3210
3221
  }
3211
3222
  function ratioWidths(ratio) {
@@ -3268,6 +3279,7 @@ function StructureSection({
3268
3279
  }) {
3269
3280
  switch (tagOf3(component)) {
3270
3281
  case "mj-section":
3282
+ case "mj-group":
3271
3283
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ColumnWidths, { component, labels, locked });
3272
3284
  case "mj-social":
3273
3285
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
@@ -3722,11 +3734,11 @@ function ElementSettings({
3722
3734
  ] }),
3723
3735
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(StructureSection, { editor, component, labels, locked }),
3724
3736
  GROUPS.map((group) => {
3725
- const inGroup = visible.filter((f) => f.group === group);
3726
- if (inGroup.length === 0) return null;
3737
+ const inGroup2 = visible.filter((f) => f.group === group);
3738
+ if (inGroup2.length === 0) return null;
3727
3739
  return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { className: "border-b border-panel-border/60 py-2", children: [
3728
3740
  /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h3", { className: "px-3 pb-1 text-[10px] font-semibold tracking-wider text-panel-muted-fg/80 uppercase", children: groupName(group, labels) }),
3729
- inGroup.map(row)
3741
+ inGroup2.map(row)
3730
3742
  ] }, group);
3731
3743
  }),
3732
3744
  advancedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("section", { className: "py-1", children: [
@@ -4173,12 +4185,17 @@ function fixPluginTypes(editor) {
4173
4185
  for (const type of editor.Components.getTypes()) {
4174
4186
  if (!type.id.startsWith("mj-") || type.id === "mj-table") continue;
4175
4187
  const base = type.model.prototype.getAttrToHTML;
4188
+ const view = type.view.prototype;
4176
4189
  editor.Components.addType(type.id, {
4190
+ ...type.id === "mj-column" && { view: groupedColumnView(view) },
4191
+ ...type.id === "mj-group" && { view: redrawnGroupView(view) },
4177
4192
  model: {
4178
4193
  defaults: {
4179
4194
  "style-default": {},
4180
4195
  ...type.id === "mj-column" && {
4181
- droppable: (source) => COLUMN_CHILDREN.has(String(source.get("tagName")))
4196
+ droppable: (source) => COLUMN_CHILDREN.has(String(source.get("tagName"))),
4197
+ // The plugin moves a column only within sections, so a group's could not even swap.
4198
+ draggable: '[data-gjs-type="mj-section"], [data-gjs-type="mj-group"]'
4182
4199
  },
4183
4200
  // GrapesJS's own is an SVG's markup, which the canvas wrote into `src` and saved.
4184
4201
  ...type.id === "mj-image" && { src: "" }
@@ -4195,6 +4212,41 @@ function fixPluginTypes(editor) {
4195
4212
  });
4196
4213
  }
4197
4214
  }
4215
+ var inGroup = (column) => column.parent()?.get("type") === "mj-group";
4216
+ function groupedColumnView(base) {
4217
+ return {
4218
+ getMjmlTemplate() {
4219
+ if (!inGroup(this.model)) return base.getMjmlTemplate.call(this);
4220
+ const siblings = "<mj-column></mj-column>".repeat(
4221
+ Math.max((this.model.collection?.length ?? 1) - 1, 0)
4222
+ );
4223
+ const width = (c) => {
4224
+ const value = c?.getAttributes().width;
4225
+ return typeof value === "string" && value ? ` width="${value.replace(/"/g, "")}"` : "";
4226
+ };
4227
+ let body = this.model;
4228
+ while (body && body.get("type") !== "mj-body") body = body.parent();
4229
+ return {
4230
+ start: `<mjml><mj-body${width(body)}><mj-section><mj-group${width(this.model.parent())}>`,
4231
+ end: `${siblings}</mj-group></mj-section></mj-body></mjml>`
4232
+ };
4233
+ },
4234
+ getTemplateFromEl(container) {
4235
+ if (!inGroup(this.model)) return base.getTemplateFromEl.call(this, container);
4236
+ return container.firstChild?.querySelector(
4237
+ "div > table > tbody > tr > td > div > div"
4238
+ ) ?? null;
4239
+ }
4240
+ };
4241
+ }
4242
+ function redrawnGroupView(base) {
4243
+ return {
4244
+ init() {
4245
+ base.init.call(this);
4246
+ this.listenTo(this.model.components(), "add remove", this.render);
4247
+ }
4248
+ };
4249
+ }
4198
4250
 
4199
4251
  // src/components/editor/EmailEditor.tsx
4200
4252
  var import_jsx_runtime17 = require("react/jsx-runtime");
@@ -4335,9 +4387,10 @@ function EmailEditor({
4335
4387
  setLocked(false);
4336
4388
  };
4337
4389
  }, [turn, setLocked]);
4390
+ const inert = readOnly || loading;
4338
4391
  const wasLocked = (0, import_react10.useRef)(false);
4339
4392
  (0, import_react10.useEffect)(() => {
4340
- if (readOnly) {
4393
+ if (inert) {
4341
4394
  wasLocked.current = true;
4342
4395
  return;
4343
4396
  }
@@ -4352,7 +4405,7 @@ function EmailEditor({
4352
4405
  cancelAnimationFrame(frame);
4353
4406
  root.style.overflow = overflow;
4354
4407
  };
4355
- }, [readOnly]);
4408
+ }, [inert]);
4356
4409
  const [crumbs, setCrumbs] = (0, import_react10.useState)([]);
4357
4410
  const [picker, setPicker] = (0, import_react10.useState)(
4358
4411
  null
@@ -4454,7 +4507,7 @@ function EmailEditor({
4454
4507
  fixPluginTypes(editor);
4455
4508
  registerBlocks(editor, blocks, labels.blockCategorySections, SECTION_SVG);
4456
4509
  setupLayerNames(editor, labels);
4457
- const STRUCTURE = /* @__PURE__ */ new Set(["mj-wrapper", "mj-section", "mj-column"]);
4510
+ const STRUCTURE = /* @__PURE__ */ new Set(["mj-wrapper", "mj-section", "mj-group", "mj-column"]);
4458
4511
  const showBodyInLayers = () => {
4459
4512
  const body = findByTag("mj-body");
4460
4513
  if (!body) return;
@@ -4740,9 +4793,14 @@ function EmailEditor({
4740
4793
  "div",
4741
4794
  {
4742
4795
  className: "relative flex h-full min-h-0 flex-1",
4743
- inert: readOnly,
4796
+ inert,
4744
4797
  onKeyDown: (e) => onBlockSearchKey(e.nativeEvent),
4745
4798
  children: [
4799
+ loading && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "absolute inset-0 z-30 flex items-center justify-center gap-2 bg-white/70 text-sm text-zinc-500", children: [
4800
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Spinner, {}),
4801
+ " ",
4802
+ labels.loadingEditor
4803
+ ] }),
4746
4804
  readOnly && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "absolute inset-0 z-30 flex cursor-not-allowed items-start justify-center bg-white/20 pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "flex items-center gap-2 rounded-full bg-panel px-3 py-1 text-xs text-panel-fg shadow", children: [
4747
4805
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Spinner, {}),
4748
4806
  " ",
@@ -4784,12 +4842,7 @@ function EmailEditor({
4784
4842
  editorRef.current?.AssetManager.close();
4785
4843
  }
4786
4844
  }
4787
- ),
4788
- loading && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "absolute inset-0 z-10 flex items-center justify-center gap-2 bg-white/70 text-sm text-zinc-500", children: [
4789
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Spinner, {}),
4790
- " ",
4791
- labels.loadingEditor
4792
- ] })
4845
+ )
4793
4846
  ] }),
4794
4847
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Breadcrumb, { crumbs, onSelect: (c) => editorRef.current?.select(c) })
4795
4848
  ] })