@mjml-agent-editor/editor 0.5.0 → 0.5.2

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
@@ -3158,7 +3158,9 @@ function registerBlocks(editor, blocks, category, media) {
3158
3158
  category,
3159
3159
  media: block.media ?? media,
3160
3160
  content: withClosedTags(block.mjml),
3161
- attributes: tileAttributes(block.id)
3161
+ attributes: tileAttributes(block.id),
3162
+ // Selected once dropped, as grapesjs-mjml's own blocks are, so its Settings open.
3163
+ select: true
3162
3164
  });
3163
3165
  }
3164
3166
  }
@@ -3201,6 +3203,15 @@ function builtinBlock(labels) {
3201
3203
  }
3202
3204
  var CANVAS_CSS = 'img:not([src]), img[src=""] { min-height: 120px; background: #f4f4f5; outline: 1px dashed #a1a1aa; outline-offset: -1px; }';
3203
3205
 
3206
+ // src/components/editor/settings-follow.ts
3207
+ function clickShowsSettings(selected, target) {
3208
+ return !!selected && !!target && selected.contains(target);
3209
+ }
3210
+ function dropShowsSettings(added, selected) {
3211
+ const first = Array.isArray(added) ? added[0] : added;
3212
+ return first !== void 0 && first === selected;
3213
+ }
3214
+
3204
3215
  // src/components/editor/table-type.ts
3205
3216
  import { isSafeLink as isSafeLink2 } from "@mjml-agent-editor/core";
3206
3217
  var DROPPED = "script, style, link, iframe, frame, object, embed, applet, base, meta, animate, set, svg, math, template";
@@ -3300,6 +3311,8 @@ function fixPluginTypes(editor) {
3300
3311
  editor.Components.addType(type.id, {
3301
3312
  ...type.id === "mj-column" && { view: groupedColumnView(view) },
3302
3313
  ...type.id === "mj-group" && { view: redrawnGroupView(view) },
3314
+ ...type.id === "mj-social" && { view: stackedSocialGroupView(view) },
3315
+ ...type.id === "mj-social-element" && { view: socialIconView(view) },
3303
3316
  model: {
3304
3317
  defaults: {
3305
3318
  "style-default": {},
@@ -3358,6 +3371,75 @@ function redrawnGroupView(base) {
3358
3371
  }
3359
3372
  };
3360
3373
  }
3374
+ function socialLayout(mode, align) {
3375
+ if (mode !== "vertical") {
3376
+ return {
3377
+ icon: { display: "inline-table", gridColumn: "", gridTemplateColumns: "", alignItems: "" },
3378
+ column: { display: "", gridTemplateColumns: "", justifyContent: "" }
3379
+ };
3380
+ }
3381
+ const side = align === "left" ? "start" : align === "right" ? "end" : "center";
3382
+ return {
3383
+ icon: {
3384
+ display: "grid",
3385
+ gridColumn: "1 / -1",
3386
+ gridTemplateColumns: "subgrid",
3387
+ alignItems: "center"
3388
+ },
3389
+ column: { display: "grid", gridTemplateColumns: "auto auto", justifyContent: side }
3390
+ };
3391
+ }
3392
+ var groupLayout = (group) => {
3393
+ const attributes = group?.getAttributes() ?? {};
3394
+ return socialLayout(attributes.mode, attributes.align);
3395
+ };
3396
+ function stackedSocialGroupView(base) {
3397
+ return {
3398
+ render() {
3399
+ const drawn = base.render.call(this);
3400
+ Object.assign(this.getChildrenContainer().style, groupLayout(this.model).column);
3401
+ return drawn;
3402
+ }
3403
+ };
3404
+ }
3405
+ function socialLabel(icon) {
3406
+ const row = icon.querySelector("tr");
3407
+ const cell = Array.from(row?.cells ?? []).find((td) => !td.querySelector("table"));
3408
+ return cell?.firstElementChild ?? null;
3409
+ }
3410
+ function socialIconView(base) {
3411
+ return {
3412
+ // The label decides whether MJML draws a label cell, so a change to it redraws the icon.
3413
+ init() {
3414
+ base.init.call(this);
3415
+ this.listenTo(this.model.components(), "add remove", this.render);
3416
+ },
3417
+ // A change to the group's attributes redraws its icons, so each lays out the cell as well.
3418
+ render() {
3419
+ const drawn = base.render.call(this);
3420
+ const { icon, column } = groupLayout(this.model.parent());
3421
+ Object.assign(this.el.style, icon);
3422
+ if (icon.display === "grid") {
3423
+ for (const part of this.el.querySelectorAll(
3424
+ ":scope > tbody, :scope > tbody > tr"
3425
+ )) {
3426
+ part.style.display = "contents";
3427
+ }
3428
+ }
3429
+ if (this.el.parentElement) Object.assign(this.el.parentElement.style, column);
3430
+ return drawn;
3431
+ },
3432
+ // With its label, so MJML draws the label's cell, and on the side `icon-position` says.
3433
+ getInnerMjmlTemplate() {
3434
+ const { start, end } = base.getInnerMjmlTemplate.call(this);
3435
+ return { start: `${start}${this.model.getInnerHTML()}`, end };
3436
+ },
3437
+ // The label's components are drawn in that cell; the plugin's container is the `<img>`.
3438
+ getChildrenContainer() {
3439
+ return socialLabel(this.el) ?? base.getChildrenContainer.call(this);
3440
+ }
3441
+ };
3442
+ }
3361
3443
 
3362
3444
  // src/components/editor/EmailEditor.tsx
3363
3445
  import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
@@ -3483,7 +3565,6 @@ function EmailEditor({
3483
3565
  requestAnimationFrame(() => blockSearchRef.current?.focus());
3484
3566
  };
3485
3567
  const [composeTarget, setComposeTarget] = useState5(null);
3486
- const selectionSource = useRef5("other");
3487
3568
  const editorRef = useRef5(null);
3488
3569
  const { running: turnRunning, locked: readOnly, setLocked } = useAgentTurn();
3489
3570
  const readOnlyRef = useRef5(false);
@@ -3639,23 +3720,24 @@ function EmailEditor({
3639
3720
  decorate(c);
3640
3721
  });
3641
3722
  editor.on("load", () => {
3642
- const body = editor.Canvas.getBody();
3643
- body?.addEventListener(
3644
- "mousedown",
3645
- () => {
3646
- selectionSource.current = "canvas";
3647
- },
3648
- true
3723
+ editor.Canvas.getBody()?.addEventListener(
3724
+ "click",
3725
+ (e) => setTimeout(() => {
3726
+ if (clickShowsSettings(editor.getSelected()?.getEl(), e.target)) {
3727
+ setSidebarView("settings");
3728
+ }
3729
+ })
3649
3730
  );
3650
3731
  editor.Canvas.getDocument()?.addEventListener("keydown", onBlockSearchKey);
3651
3732
  showBodyInLayers();
3652
3733
  });
3653
3734
  editor.on("component:selected", (c) => {
3654
3735
  keepStructureOpen();
3655
- if (selectionSource.current === "canvas") setSidebarView("settings");
3656
- selectionSource.current = "other";
3657
3736
  buildCrumbs(c);
3658
3737
  });
3738
+ editor.on("block:drag:stop", (added) => {
3739
+ if (dropShowsSettings(added, editor.getSelected())) setSidebarView("settings");
3740
+ });
3659
3741
  editor.on("component:deselected", () => {
3660
3742
  buildCrumbs(editor.getSelected());
3661
3743
  });
@@ -3922,7 +4004,6 @@ function EmailEditor({
3922
4004
  {
3923
4005
  view: sidebarView,
3924
4006
  onViewChange: setSidebarView,
3925
- markLayersSource: () => selectionSource.current = "layers",
3926
4007
  blockSearchRef
3927
4008
  }
3928
4009
  ),
@@ -3966,7 +4047,6 @@ function EmailEditor({
3966
4047
  function LeftSidebar({
3967
4048
  view,
3968
4049
  onViewChange,
3969
- markLayersSource,
3970
4050
  blockSearchRef
3971
4051
  }) {
3972
4052
  const editor = useEditorMaybe2();
@@ -4074,36 +4154,29 @@ function LeftSidebar({
4074
4154
  ] })
4075
4155
  }
4076
4156
  ) }),
4077
- /* @__PURE__ */ jsxs7(
4078
- "div",
4079
- {
4080
- className: cn("flex min-h-0 flex-1 flex-col", view !== "layers" && "hidden"),
4081
- onMouseDownCapture: markLayersSource,
4082
- children: [
4083
- /* @__PURE__ */ jsxs7("label", { className: "flex items-center justify-between gap-2 border-b border-panel-border px-3 py-2 text-xs text-panel-muted-fg", children: [
4084
- /* @__PURE__ */ jsx8("span", { children: labels.expandAll }),
4085
- /* @__PURE__ */ jsx8(
4086
- Switch,
4087
- {
4088
- checked: layersExpanded,
4089
- onCheckedChange: toggleLayers,
4090
- className: "data-[state=checked]:bg-brand data-[state=unchecked]:bg-panel-border"
4091
- }
4092
- )
4093
- ] }),
4094
- /* @__PURE__ */ jsx8(
4095
- "div",
4096
- {
4097
- id: "gjs-layers",
4098
- className: "min-h-0 flex-1 overflow-y-auto",
4099
- onDoubleClickCapture: (e) => {
4100
- if (e.target.closest("[data-name]")) e.stopPropagation();
4101
- }
4102
- }
4103
- )
4104
- ]
4105
- }
4106
- )
4157
+ /* @__PURE__ */ jsxs7("div", { className: cn("flex min-h-0 flex-1 flex-col", view !== "layers" && "hidden"), children: [
4158
+ /* @__PURE__ */ jsxs7("label", { className: "flex items-center justify-between gap-2 border-b border-panel-border px-3 py-2 text-xs text-panel-muted-fg", children: [
4159
+ /* @__PURE__ */ jsx8("span", { children: labels.expandAll }),
4160
+ /* @__PURE__ */ jsx8(
4161
+ Switch,
4162
+ {
4163
+ checked: layersExpanded,
4164
+ onCheckedChange: toggleLayers,
4165
+ className: "data-[state=checked]:bg-brand data-[state=unchecked]:bg-panel-border"
4166
+ }
4167
+ )
4168
+ ] }),
4169
+ /* @__PURE__ */ jsx8(
4170
+ "div",
4171
+ {
4172
+ id: "gjs-layers",
4173
+ className: "min-h-0 flex-1 overflow-y-auto",
4174
+ onDoubleClickCapture: (e) => {
4175
+ if (e.target.closest("[data-name]")) e.stopPropagation();
4176
+ }
4177
+ }
4178
+ )
4179
+ ] })
4107
4180
  ] });
4108
4181
  }
4109
4182
  function Breadcrumb({