react-email-studio 3.8.2 → 3.8.3
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/CHANGELOG.md +7 -0
- package/README.md +3 -1
- package/dist/index.cjs +136 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +136 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -827,6 +827,65 @@ function countBlocksInDesign(rows) {
|
|
|
827
827
|
}, 0);
|
|
828
828
|
return rows.reduce((sum, r) => sum + r.cells.reduce((s, c) => s + colBlocks(c), 0), 0);
|
|
829
829
|
}
|
|
830
|
+
function isSingleBlockInRow(row) {
|
|
831
|
+
if (!row?.cells) return false;
|
|
832
|
+
let count = 0;
|
|
833
|
+
for (const col of row.cells) {
|
|
834
|
+
if (!Array.isArray(col)) continue;
|
|
835
|
+
count += col.length;
|
|
836
|
+
if (count > 1) return false;
|
|
837
|
+
}
|
|
838
|
+
return count === 1;
|
|
839
|
+
}
|
|
840
|
+
function resolveBlockMovePlan(rows, rowId, cellIdx, blockIndex, inner) {
|
|
841
|
+
const rowIndex = rows.findIndex((r) => r.id === rowId);
|
|
842
|
+
const row = rowIndex >= 0 ? rows[rowIndex] : void 0;
|
|
843
|
+
if (!row) return null;
|
|
844
|
+
if (inner) {
|
|
845
|
+
const loc = toColumnLoc(rowId, cellIdx, {
|
|
846
|
+
parentBlockIdx: inner.parentBlockIdx,
|
|
847
|
+
innerCellIdx: inner.cellIdx
|
|
848
|
+
});
|
|
849
|
+
const col2 = getColumnBlocks(rows, loc);
|
|
850
|
+
const idx = inner.contentIdx;
|
|
851
|
+
return {
|
|
852
|
+
mode: "column",
|
|
853
|
+
blockIndex: idx,
|
|
854
|
+
canMoveUp: idx > 0,
|
|
855
|
+
canMoveDown: idx < col2.length - 1
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
const col = row.cells?.[cellIdx];
|
|
859
|
+
const colLen = Array.isArray(col) ? col.length : 0;
|
|
860
|
+
if (colLen > 1) {
|
|
861
|
+
return {
|
|
862
|
+
mode: "column",
|
|
863
|
+
blockIndex,
|
|
864
|
+
canMoveUp: blockIndex > 0,
|
|
865
|
+
canMoveDown: blockIndex < colLen - 1
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
if (colLen === 1 && (isRootContentRow(row) || isSingleBlockInRow(row))) {
|
|
869
|
+
return {
|
|
870
|
+
mode: "row",
|
|
871
|
+
canMoveUp: rowIndex > 0,
|
|
872
|
+
canMoveDown: rowIndex < rows.length - 1
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
if (colLen === 1) {
|
|
876
|
+
return {
|
|
877
|
+
mode: "row",
|
|
878
|
+
canMoveUp: rowIndex > 0,
|
|
879
|
+
canMoveDown: rowIndex < rows.length - 1
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
return {
|
|
883
|
+
mode: "column",
|
|
884
|
+
blockIndex,
|
|
885
|
+
canMoveUp: false,
|
|
886
|
+
canMoveDown: false
|
|
887
|
+
};
|
|
888
|
+
}
|
|
830
889
|
|
|
831
890
|
// src/lib/htmlUtils.ts
|
|
832
891
|
function escHtmlAttr(s) {
|
|
@@ -7444,50 +7503,64 @@ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
|
7444
7503
|
function ContextMenu({ x, y, items, onClose, C }) {
|
|
7445
7504
|
const ref = useRef4(null);
|
|
7446
7505
|
useEffect5(() => {
|
|
7447
|
-
const
|
|
7448
|
-
|
|
7449
|
-
|
|
7506
|
+
const onPointerDown = (ev) => {
|
|
7507
|
+
if (ref.current?.contains(ev.target)) return;
|
|
7508
|
+
onClose();
|
|
7509
|
+
};
|
|
7510
|
+
const onKeyDown = (ev) => {
|
|
7511
|
+
if (ev.key === "Escape") onClose();
|
|
7512
|
+
};
|
|
7513
|
+
window.addEventListener("pointerdown", onPointerDown);
|
|
7514
|
+
window.addEventListener("keydown", onKeyDown);
|
|
7450
7515
|
return () => {
|
|
7451
|
-
window.removeEventListener("
|
|
7452
|
-
window.removeEventListener("keydown",
|
|
7516
|
+
window.removeEventListener("pointerdown", onPointerDown);
|
|
7517
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
7453
7518
|
};
|
|
7454
7519
|
}, [onClose]);
|
|
7455
|
-
return /* @__PURE__ */ jsx8(
|
|
7456
|
-
"
|
|
7520
|
+
return /* @__PURE__ */ jsx8(
|
|
7521
|
+
"div",
|
|
7457
7522
|
{
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7523
|
+
ref,
|
|
7524
|
+
onPointerDown: (e) => e.stopPropagation(),
|
|
7525
|
+
style: { position: "fixed", left: x, top: y, zIndex: 9999, background: C.sidebar, border: `1px solid ${C.border}`, borderRadius: 7, padding: "4px 0", boxShadow: `0 8px 32px rgba(0,0,0,.4)`, minWidth: 160 },
|
|
7526
|
+
children: items.map((item, i) => item.sep ? /* @__PURE__ */ jsx8("div", { style: { height: 1, background: C.border, margin: "3px 0" } }, i) : /* @__PURE__ */ jsxs6(
|
|
7527
|
+
"button",
|
|
7528
|
+
{
|
|
7529
|
+
type: "button",
|
|
7530
|
+
disabled: !!item.disabled,
|
|
7531
|
+
onClick: () => {
|
|
7532
|
+
if (item.disabled) return;
|
|
7533
|
+
item.action();
|
|
7534
|
+
onClose();
|
|
7535
|
+
},
|
|
7536
|
+
style: {
|
|
7537
|
+
display: "block",
|
|
7538
|
+
width: "100%",
|
|
7539
|
+
background: "none",
|
|
7540
|
+
border: "none",
|
|
7541
|
+
padding: "7px 14px",
|
|
7542
|
+
textAlign: "left",
|
|
7543
|
+
cursor: item.disabled ? "not-allowed" : "pointer",
|
|
7544
|
+
fontSize: 12,
|
|
7545
|
+
color: item.disabled ? C.muted : item.danger ? C.danger : C.text,
|
|
7546
|
+
fontWeight: item.bold ? 700 : 400,
|
|
7547
|
+
opacity: item.disabled ? 0.45 : 1
|
|
7548
|
+
},
|
|
7549
|
+
onMouseEnter: (e) => {
|
|
7550
|
+
if (!item.disabled) e.currentTarget.style.background = C.surface;
|
|
7551
|
+
},
|
|
7552
|
+
onMouseLeave: (e) => {
|
|
7553
|
+
e.currentTarget.style.background = "none";
|
|
7554
|
+
},
|
|
7555
|
+
children: [
|
|
7556
|
+
item.icon && /* @__PURE__ */ jsx8("span", { style: { marginRight: 8 }, children: item.icon }),
|
|
7557
|
+
item.label
|
|
7558
|
+
]
|
|
7559
|
+
},
|
|
7560
|
+
i
|
|
7561
|
+
))
|
|
7562
|
+
}
|
|
7563
|
+
);
|
|
7491
7564
|
}
|
|
7492
7565
|
|
|
7493
7566
|
// src/editor/overlays/ConfirmDialog.tsx
|
|
@@ -8091,10 +8164,27 @@ var ReactEmailEditorComponent = forwardRef(
|
|
|
8091
8164
|
else dropContent(rowId, cellIdx, { kind: "duplicate", fromIdx: contentIdx });
|
|
8092
8165
|
}
|
|
8093
8166
|
};
|
|
8167
|
+
const shiftBlockFromMenu = (rowId, cellIdx, ci, dir, inner = null) => {
|
|
8168
|
+
const blockIndex = inner ? inner.contentIdx : ci;
|
|
8169
|
+
const plan = resolveBlockMovePlan(rowsRef.current, rowId, cellIdx, blockIndex, inner);
|
|
8170
|
+
if (!plan) return;
|
|
8171
|
+
if (dir < 0 && !plan.canMoveUp || dir > 0 && !plan.canMoveDown) return;
|
|
8172
|
+
if (plan.mode === "row") {
|
|
8173
|
+
moveRow(rowId, dir);
|
|
8174
|
+
return;
|
|
8175
|
+
}
|
|
8176
|
+
moveContent(rowId, cellIdx, plan.blockIndex, dir, inner);
|
|
8177
|
+
};
|
|
8094
8178
|
const handleContextMenu = (e, rowId, cellIdx, ci, inner = null) => {
|
|
8179
|
+
e.preventDefault();
|
|
8180
|
+
e.stopPropagation();
|
|
8181
|
+
const blockIndex = inner ? inner.contentIdx : ci;
|
|
8182
|
+
const plan = resolveBlockMovePlan(rowsRef.current, rowId, cellIdx, blockIndex, inner);
|
|
8183
|
+
const canMoveUp = plan?.canMoveUp ?? false;
|
|
8184
|
+
const canMoveDown = plan?.canMoveDown ?? false;
|
|
8095
8185
|
setCtxMenu({ x: e.clientX, y: e.clientY, items: [
|
|
8096
|
-
{ icon: "\u2191", label: "Move Up", action: () =>
|
|
8097
|
-
{ icon: "\u2193", label: "Move Down", action: () =>
|
|
8186
|
+
{ icon: "\u2191", label: "Move Up", disabled: !canMoveUp, action: () => shiftBlockFromMenu(rowId, cellIdx, ci, -1, inner) },
|
|
8187
|
+
{ icon: "\u2193", label: "Move Down", disabled: !canMoveDown, action: () => shiftBlockFromMenu(rowId, cellIdx, ci, 1, inner) },
|
|
8098
8188
|
{ sep: true },
|
|
8099
8189
|
{ icon: "\u29C9", label: "Duplicate", action: () => dropContent(rowId, cellIdx, inner ? { kind: "duplicate", fromIdx: inner.contentIdx, fromNested: { parentBlockIdx: inner.parentBlockIdx, innerCellIdx: inner.cellIdx } } : { kind: "duplicate", fromIdx: ci }) },
|
|
8100
8190
|
{ sep: true },
|
|
@@ -8104,17 +8194,14 @@ var ReactEmailEditorComponent = forwardRef(
|
|
|
8104
8194
|
const handleLayoutContextMenu = (e, rowId) => {
|
|
8105
8195
|
e.preventDefault();
|
|
8106
8196
|
e.stopPropagation();
|
|
8107
|
-
const
|
|
8197
|
+
const currentRows = rowsRef.current;
|
|
8198
|
+
const ri = currentRows.findIndex((r) => r.id === rowId);
|
|
8108
8199
|
setSelectedRowId(rowId);
|
|
8109
8200
|
setSelContentId(null);
|
|
8110
8201
|
setSelMeta(null);
|
|
8111
8202
|
setCtxMenu({ x: e.clientX, y: e.clientY, items: [
|
|
8112
|
-
{ icon: "\u2191", label: "Move row up", disabled: ri <= 0, action: () =>
|
|
8113
|
-
|
|
8114
|
-
} },
|
|
8115
|
-
{ icon: "\u2193", label: "Move row down", disabled: ri < 0 || ri >= rows.length - 1, action: () => {
|
|
8116
|
-
if (ri >= 0 && ri < rows.length - 1) moveRow(rowId, 1);
|
|
8117
|
-
} },
|
|
8203
|
+
{ icon: "\u2191", label: "Move row up", disabled: ri <= 0, action: () => moveRow(rowId, -1) },
|
|
8204
|
+
{ icon: "\u2193", label: "Move row down", disabled: ri < 0 || ri >= currentRows.length - 1, action: () => moveRow(rowId, 1) },
|
|
8118
8205
|
{ sep: true },
|
|
8119
8206
|
{ icon: "\u29C9", label: "Duplicate row", action: () => dupRow(rowId) },
|
|
8120
8207
|
{ sep: true },
|