react-email-studio 3.1.1 → 3.3.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/CHANGELOG.md +27 -0
- package/README.md +5 -1
- package/TUTORIAL.md +1 -2
- package/dist/index.cjs +278 -152
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -5
- package/dist/index.d.ts +13 -5
- package/dist/index.js +282 -158
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -34,6 +34,8 @@ __export(index_exports, {
|
|
|
34
34
|
ReactEmailEditor: () => ReactEmailEditor,
|
|
35
35
|
base64ToUtf8: () => base64ToUtf8,
|
|
36
36
|
emailPreviewDevices: () => DEVICES,
|
|
37
|
+
extractHtmlForDesign: () => extractHtmlForDesign,
|
|
38
|
+
htmlToEmailDesignTemplate: () => htmlToEmailDesignTemplate,
|
|
37
39
|
jsonToHtml: () => jsonToHtml,
|
|
38
40
|
utf8ToBase64: () => utf8ToBase64
|
|
39
41
|
});
|
|
@@ -152,7 +154,6 @@ var I18N = {
|
|
|
152
154
|
delete: "Delete",
|
|
153
155
|
moveUp: "Move Up",
|
|
154
156
|
moveDown: "Move Down",
|
|
155
|
-
mergeTags: "Merge Tags",
|
|
156
157
|
autoSaved: "Auto-saved",
|
|
157
158
|
search: "Search blocks\u2026",
|
|
158
159
|
zoomIn: "Zoom In",
|
|
@@ -169,7 +170,7 @@ var I18N = {
|
|
|
169
170
|
blockPaletteGroupActions: "Buttons & links",
|
|
170
171
|
blockPaletteGroupWidgets: "Widgets",
|
|
171
172
|
closePanel: "Close",
|
|
172
|
-
canvasEmptyHint: "Drag blocks from the library into
|
|
173
|
+
canvasEmptyHint: "Drag row layouts or blocks from the library. Drop blocks into a column or onto the mail preview area.",
|
|
173
174
|
emailContentSettings: "Email content",
|
|
174
175
|
loadingDesign: "Loading design\u2026"
|
|
175
176
|
},
|
|
@@ -211,7 +212,6 @@ var I18N = {
|
|
|
211
212
|
delete: "Supprimer",
|
|
212
213
|
moveUp: "Monter",
|
|
213
214
|
moveDown: "Descendre",
|
|
214
|
-
mergeTags: "Balises fusion",
|
|
215
215
|
autoSaved: "Auto-sauvegard\xE9",
|
|
216
216
|
search: "Rechercher\u2026",
|
|
217
217
|
colorScheme: "Sch\xE9ma de couleurs",
|
|
@@ -271,7 +271,6 @@ var I18N = {
|
|
|
271
271
|
delete: "L\xF6schen",
|
|
272
272
|
moveUp: "Nach oben",
|
|
273
273
|
moveDown: "Nach unten",
|
|
274
|
-
mergeTags: "Merge-Tags",
|
|
275
274
|
autoSaved: "Auto-gespeichert",
|
|
276
275
|
search: "Bl\xF6cke suchen\u2026",
|
|
277
276
|
colorScheme: "Farbschema",
|
|
@@ -329,7 +328,6 @@ var I18N = {
|
|
|
329
328
|
delete: "Eliminar",
|
|
330
329
|
moveUp: "Subir",
|
|
331
330
|
moveDown: "Bajar",
|
|
332
|
-
mergeTags: "Etiquetas de fusi\xF3n",
|
|
333
331
|
autoSaved: "Auto-guardado",
|
|
334
332
|
search: "Buscar bloques\u2026",
|
|
335
333
|
zoomIn: "Zoom +",
|
|
@@ -1127,7 +1125,7 @@ function rowToHtml(row) {
|
|
|
1127
1125
|
const r = row.ratios[i] ?? 1;
|
|
1128
1126
|
const cs = row.columnStyles && row.columnStyles[i] ? row.columnStyles[i] : {};
|
|
1129
1127
|
const colShell = emailSurfaceBgCss(cs);
|
|
1130
|
-
const
|
|
1128
|
+
const pad3 = cs.padding && typeof cs.padding === "object" && !Array.isArray(cs.padding) ? `padding:${(() => {
|
|
1131
1129
|
const o = cs.padding;
|
|
1132
1130
|
const t = numOr2(o.top, 0);
|
|
1133
1131
|
const rgt = numOr2(o.right, t);
|
|
@@ -1143,7 +1141,7 @@ function rowToHtml(row) {
|
|
|
1143
1141
|
const bl = numOr2(x.bl, tr2);
|
|
1144
1142
|
return `border-radius:${tl}px ${tr2}px ${br}px ${bl}px;`;
|
|
1145
1143
|
})() : typeof cs.borderRadius === "number" && Number.isFinite(cs.borderRadius) ? `border-radius:${cs.borderRadius}px;` : "";
|
|
1146
|
-
return `<div style="flex:${r} 1 0;min-width:0;box-sizing:border-box;${
|
|
1144
|
+
return `<div style="flex:${r} 1 0;min-width:0;box-sizing:border-box;${pad3}${rad}${colShell}">${cell.map(blockToHtml).join("")}</div>`;
|
|
1147
1145
|
}).join("")}</div>`;
|
|
1148
1146
|
const innerTrim = inner.replace(/>\s+</g, "><").trim();
|
|
1149
1147
|
const body = innerTrim || " ";
|
|
@@ -1363,8 +1361,8 @@ function layoutColumnBorderRadiusForDoc(r) {
|
|
|
1363
1361
|
}
|
|
1364
1362
|
return 0;
|
|
1365
1363
|
}
|
|
1366
|
-
function columnPaddingNonZero(
|
|
1367
|
-
return
|
|
1364
|
+
function columnPaddingNonZero(pad3) {
|
|
1365
|
+
return pad3.top !== 0 || pad3.right !== 0 || pad3.bottom !== 0 || pad3.left !== 0;
|
|
1368
1366
|
}
|
|
1369
1367
|
function columnRadiusNonZero(r) {
|
|
1370
1368
|
if (typeof r === "number") return r !== 0;
|
|
@@ -1721,9 +1719,9 @@ function mapBlockToInternal(b, layoutDepth = 0) {
|
|
|
1721
1719
|
if (asNum(s.fontWeight) != null) block.props.fontWeight = s.fontWeight;
|
|
1722
1720
|
if (asNum(s.borderRadius) != null) block.props.borderRadius = s.borderRadius;
|
|
1723
1721
|
if (s.padding && typeof s.padding === "object") {
|
|
1724
|
-
const
|
|
1725
|
-
block.props.paddingV = asNum(
|
|
1726
|
-
block.props.paddingH = asNum(
|
|
1722
|
+
const pad3 = s.padding;
|
|
1723
|
+
block.props.paddingV = asNum(pad3.top) ?? block.props.paddingV;
|
|
1724
|
+
block.props.paddingH = asNum(pad3.right) ?? block.props.paddingH;
|
|
1727
1725
|
}
|
|
1728
1726
|
if (asStr(s.textAlign)) block.props.align = s.textAlign;
|
|
1729
1727
|
break;
|
|
@@ -2238,10 +2236,15 @@ function useLiveCountdown(endDate) {
|
|
|
2238
2236
|
const s = Math.floor(diff % 6e4 / 1e3);
|
|
2239
2237
|
return [d, h, m, s];
|
|
2240
2238
|
}
|
|
2241
|
-
function
|
|
2239
|
+
function layoutSplitChromeBorder(_C, preview) {
|
|
2242
2240
|
if (preview) return {};
|
|
2243
|
-
return {
|
|
2241
|
+
return {
|
|
2242
|
+
border: "1px dotted rgba(148, 163, 184, 0.5)",
|
|
2243
|
+
boxSizing: "border-box"
|
|
2244
|
+
};
|
|
2244
2245
|
}
|
|
2246
|
+
var CONTENT_BLOCK_HOVER_BORDER = "1px dotted rgba(148, 163, 184, 0.5)";
|
|
2247
|
+
var EMPTY_CELL_COLUMN_MIN_H = "min(320px, 42vh)";
|
|
2245
2248
|
function blockLinkCaptureHandler(preview, e) {
|
|
2246
2249
|
if (preview) return;
|
|
2247
2250
|
const t = e.target;
|
|
@@ -2273,6 +2276,7 @@ function radiusCssLayout(v) {
|
|
|
2273
2276
|
return "0px";
|
|
2274
2277
|
}
|
|
2275
2278
|
function ContentBlock({ block, selected, onClick, preview, C }) {
|
|
2279
|
+
const [hover, setHover] = (0, import_react.useState)(false);
|
|
2276
2280
|
const { type, props: p } = block;
|
|
2277
2281
|
const numOr2 = (v, fb) => typeof v === "number" && Number.isFinite(v) ? v : fb;
|
|
2278
2282
|
const boxPx = (v) => {
|
|
@@ -2316,14 +2320,19 @@ function ContentBlock({ block, selected, onClick, preview, C }) {
|
|
|
2316
2320
|
onClick: preview ? void 0 : onClick || void 0,
|
|
2317
2321
|
onClickCapture: (e) => blockLinkCaptureHandler(preview, e),
|
|
2318
2322
|
onAuxClickCapture: (e) => blockLinkCaptureHandler(preview, e),
|
|
2323
|
+
onMouseEnter: preview ? void 0 : () => setHover(true),
|
|
2324
|
+
onMouseLeave: preview ? void 0 : () => setHover(false),
|
|
2319
2325
|
style: {
|
|
2320
2326
|
cursor: preview ? "default" : onClick ? "pointer" : "default",
|
|
2321
2327
|
outline: selected && !preview ? `2px solid ${C.accent}` : "2px solid transparent",
|
|
2322
2328
|
outlineOffset: 1,
|
|
2323
2329
|
borderRadius: 3,
|
|
2324
|
-
transition: "outline .12s",
|
|
2330
|
+
transition: "outline .12s, border-color .12s",
|
|
2325
2331
|
position: "relative",
|
|
2326
|
-
...
|
|
2332
|
+
...preview ? {} : {
|
|
2333
|
+
border: hover ? CONTENT_BLOCK_HOVER_BORDER : "1px solid transparent",
|
|
2334
|
+
boxSizing: "border-box"
|
|
2335
|
+
},
|
|
2327
2336
|
...shellBg,
|
|
2328
2337
|
padding: paddingCss(p.padding),
|
|
2329
2338
|
margin: marginCss(p.margin)
|
|
@@ -2542,6 +2551,8 @@ function NestedRowBlock({
|
|
|
2542
2551
|
rowId,
|
|
2543
2552
|
cellIdx,
|
|
2544
2553
|
parentBlockIdx,
|
|
2554
|
+
/** When this layout sits inside another layout column, meta uses `contentIdx` + `inner` like other nested blocks. */
|
|
2555
|
+
selectionInner,
|
|
2545
2556
|
editorId,
|
|
2546
2557
|
selectedKey,
|
|
2547
2558
|
selContentMeta,
|
|
@@ -2553,7 +2564,7 @@ function NestedRowBlock({
|
|
|
2553
2564
|
C
|
|
2554
2565
|
}) {
|
|
2555
2566
|
const p = block.props;
|
|
2556
|
-
const rowSelected = !preview && selContentMeta && selContentMeta.rowId === rowId && selContentMeta.cellIdx === cellIdx && selContentMeta.contentIdx === parentBlockIdx && !selContentMeta.inner &&
|
|
2567
|
+
const rowSelected = !preview && selContentMeta && selContentMeta.rowId === rowId && selContentMeta.cellIdx === cellIdx && selectedKey === block.id && (selectionInner == null ? selContentMeta.contentIdx === parentBlockIdx && !selContentMeta.inner : selContentMeta.contentIdx === parentBlockIdx && selContentMeta.inner && selContentMeta.inner.cellIdx === selectionInner.cellIdx && selContentMeta.inner.contentIdx === selectionInner.contentIdx);
|
|
2557
2568
|
const rowStyle = {
|
|
2558
2569
|
padding: p.padding ?? 8,
|
|
2559
2570
|
position: "relative",
|
|
@@ -2561,7 +2572,7 @@ function NestedRowBlock({
|
|
|
2561
2572
|
outline: rowSelected ? `2px solid ${C.accent}` : "2px solid transparent",
|
|
2562
2573
|
outlineOffset: 1,
|
|
2563
2574
|
transition: "outline .12s",
|
|
2564
|
-
...
|
|
2575
|
+
...layoutSplitChromeBorder(C, preview),
|
|
2565
2576
|
...backgroundLayerStyle({
|
|
2566
2577
|
bgColor: p.bgColor,
|
|
2567
2578
|
bgImage: p.bgImage,
|
|
@@ -2577,7 +2588,13 @@ function NestedRowBlock({
|
|
|
2577
2588
|
style: rowStyle,
|
|
2578
2589
|
onClick: preview ? void 0 : (e) => {
|
|
2579
2590
|
e.stopPropagation();
|
|
2580
|
-
onSelectContent(
|
|
2591
|
+
onSelectContent(
|
|
2592
|
+
block.id,
|
|
2593
|
+
rowId,
|
|
2594
|
+
cellIdx,
|
|
2595
|
+
parentBlockIdx,
|
|
2596
|
+
selectionInner ?? null
|
|
2597
|
+
);
|
|
2581
2598
|
},
|
|
2582
2599
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: p.gap ?? 12 }, children: (p.cells || []).map((innerBlocks, ici) => {
|
|
2583
2600
|
const cS = p.columnStyles && p.columnStyles[ici] || {};
|
|
@@ -2587,7 +2604,10 @@ function NestedRowBlock({
|
|
|
2587
2604
|
style: {
|
|
2588
2605
|
flex: p.ratios?.[ici] ?? 1,
|
|
2589
2606
|
minWidth: 0,
|
|
2590
|
-
|
|
2607
|
+
minHeight: preview ? void 0 : EMPTY_CELL_COLUMN_MIN_H,
|
|
2608
|
+
display: "flex",
|
|
2609
|
+
flexDirection: "column",
|
|
2610
|
+
...layoutSplitChromeBorder(C, preview),
|
|
2591
2611
|
...backgroundLayerStyle(cS),
|
|
2592
2612
|
padding: paddingCssLayout(cS.padding),
|
|
2593
2613
|
borderRadius: radiusCssLayout(cS.borderRadius),
|
|
@@ -2643,7 +2663,13 @@ function BlockItem({
|
|
|
2643
2663
|
if (!onSelectContent) return;
|
|
2644
2664
|
e.stopPropagation();
|
|
2645
2665
|
if (isSplitLayoutBlock(cb)) {
|
|
2646
|
-
onSelectContent(
|
|
2666
|
+
onSelectContent(
|
|
2667
|
+
cb.id,
|
|
2668
|
+
rowId,
|
|
2669
|
+
cellIdx,
|
|
2670
|
+
nest ? nest.parentBlockIdx : ci,
|
|
2671
|
+
nest ? { cellIdx: innerCellIdx, contentIdx: ci } : null
|
|
2672
|
+
);
|
|
2647
2673
|
} else {
|
|
2648
2674
|
onSelectContent(
|
|
2649
2675
|
cb.id,
|
|
@@ -2714,6 +2740,7 @@ function BlockItem({
|
|
|
2714
2740
|
rowId,
|
|
2715
2741
|
cellIdx,
|
|
2716
2742
|
parentBlockIdx: nest ? nest.parentBlockIdx : ci,
|
|
2743
|
+
selectionInner: nest ? { cellIdx: innerCellIdx, contentIdx: ci } : null,
|
|
2717
2744
|
editorId,
|
|
2718
2745
|
selectedKey,
|
|
2719
2746
|
selContentMeta,
|
|
@@ -2797,6 +2824,7 @@ function Cell({
|
|
|
2797
2824
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { position: "absolute", left: -4, top: "50%", transform: "translateY(-50%)", width: 8, height: 8, borderRadius: "50%", background: C.accent } }),
|
|
2798
2825
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { position: "absolute", right: -4, top: "50%", transform: "translateY(-50%)", width: 8, height: 8, borderRadius: "50%", background: C.accent } })
|
|
2799
2826
|
] }) : null;
|
|
2827
|
+
const cellEmpty = !preview && blocks.length === 0;
|
|
2800
2828
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2801
2829
|
"div",
|
|
2802
2830
|
{
|
|
@@ -2806,17 +2834,43 @@ function Cell({
|
|
|
2806
2834
|
onDragLeave: handleDragLeave,
|
|
2807
2835
|
onDrop: handleDrop,
|
|
2808
2836
|
style: {
|
|
2809
|
-
flex: 1,
|
|
2810
|
-
|
|
2837
|
+
flex: cellEmpty ? 1 : void 0,
|
|
2838
|
+
display: "flex",
|
|
2839
|
+
flexDirection: "column",
|
|
2840
|
+
minHeight: preview ? void 0 : cellEmpty ? 0 : 44,
|
|
2811
2841
|
borderRadius: 4,
|
|
2812
|
-
...preview ? {} : insertAt !== null ? { border: `1px dotted ${C.accent}`, background: `${C.accent}0a` } :
|
|
2813
|
-
background: insertAt !== null ? `${C.accent}0a` : "transparent",
|
|
2842
|
+
...preview ? {} : insertAt !== null && !cellEmpty ? { border: `1px dotted ${C.accent}`, background: `${C.accent}0a` } : {},
|
|
2843
|
+
background: insertAt !== null && !cellEmpty ? `${C.accent}0a` : "transparent",
|
|
2814
2844
|
transition: "border-color .15s,background .15s",
|
|
2815
2845
|
padding: preview ? 0 : 0,
|
|
2816
2846
|
position: "relative"
|
|
2817
2847
|
},
|
|
2818
2848
|
children: [
|
|
2819
|
-
|
|
2849
|
+
cellEmpty && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2850
|
+
"div",
|
|
2851
|
+
{
|
|
2852
|
+
style: {
|
|
2853
|
+
flex: 1,
|
|
2854
|
+
display: "flex",
|
|
2855
|
+
alignItems: "center",
|
|
2856
|
+
justifyContent: "center",
|
|
2857
|
+
margin: 4,
|
|
2858
|
+
borderRadius: 8,
|
|
2859
|
+
boxSizing: "border-box",
|
|
2860
|
+
textAlign: "center",
|
|
2861
|
+
userSelect: "none",
|
|
2862
|
+
transition: "color .15s, border-color .15s, background .15s, box-shadow .15s",
|
|
2863
|
+
border: insertAt !== null ? `2px dashed ${C.accent}` : `2px dashed ${C.border}`,
|
|
2864
|
+
background: insertAt !== null ? `${C.accent}14` : `${C.canvas}`,
|
|
2865
|
+
boxShadow: insertAt !== null ? `inset 0 0 0 1px ${C.accent}22` : `inset 0 0 0 1px ${C.border}99`,
|
|
2866
|
+
color: insertAt !== null ? C.accent2 : C.muted,
|
|
2867
|
+
fontSize: 11,
|
|
2868
|
+
fontWeight: insertAt !== null ? 700 : 500,
|
|
2869
|
+
letterSpacing: "0.02em"
|
|
2870
|
+
},
|
|
2871
|
+
children: insertAt !== null ? "Release to drop" : "Drop here"
|
|
2872
|
+
}
|
|
2873
|
+
),
|
|
2820
2874
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Line, { idx: 0 }),
|
|
2821
2875
|
blocks.map((cb, ci) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2822
2876
|
BlockItem,
|
|
@@ -2867,7 +2921,6 @@ function LayoutRow({
|
|
|
2867
2921
|
transition: "outline .12s",
|
|
2868
2922
|
padding: row.padding,
|
|
2869
2923
|
position: "relative",
|
|
2870
|
-
...editChromeBorder(C, preview),
|
|
2871
2924
|
...backgroundLayerStyle({
|
|
2872
2925
|
bgColor: row.bgColor,
|
|
2873
2926
|
bgImage: row.bgImage,
|
|
@@ -2906,8 +2959,9 @@ function LayoutRow({
|
|
|
2906
2959
|
id: editorId ? `${editorId}-col-${row.id}-${ci}` : void 0,
|
|
2907
2960
|
style: {
|
|
2908
2961
|
flex: row.ratios[ci] ?? 1,
|
|
2909
|
-
minHeight: 50,
|
|
2910
|
-
|
|
2962
|
+
minHeight: preview ? 50 : EMPTY_CELL_COLUMN_MIN_H,
|
|
2963
|
+
display: "flex",
|
|
2964
|
+
flexDirection: "column",
|
|
2911
2965
|
...backgroundLayerStyle(cS),
|
|
2912
2966
|
padding: paddingCssLayout(cS.padding),
|
|
2913
2967
|
borderRadius: radiusCssLayout(cS.borderRadius),
|
|
@@ -3081,13 +3135,13 @@ var FONTS = [
|
|
|
3081
3135
|
"Trebuchet MS,sans-serif",
|
|
3082
3136
|
"Impact,sans-serif"
|
|
3083
3137
|
];
|
|
3084
|
-
function paddingToCss(
|
|
3085
|
-
if (typeof
|
|
3086
|
-
if (
|
|
3087
|
-
const t = typeof
|
|
3088
|
-
const r = typeof
|
|
3089
|
-
const b = typeof
|
|
3090
|
-
const l = typeof
|
|
3138
|
+
function paddingToCss(pad3, fallback) {
|
|
3139
|
+
if (typeof pad3 === "number" && Number.isFinite(pad3)) return `${Math.max(0, pad3)}px`;
|
|
3140
|
+
if (pad3 && typeof pad3 === "object" && !Array.isArray(pad3)) {
|
|
3141
|
+
const t = typeof pad3.top === "number" && Number.isFinite(pad3.top) ? pad3.top : fallback;
|
|
3142
|
+
const r = typeof pad3.right === "number" && Number.isFinite(pad3.right) ? pad3.right : t;
|
|
3143
|
+
const b = typeof pad3.bottom === "number" && Number.isFinite(pad3.bottom) ? pad3.bottom : t;
|
|
3144
|
+
const l = typeof pad3.left === "number" && Number.isFinite(pad3.left) ? pad3.left : r;
|
|
3091
3145
|
return `${t}px ${r}px ${b}px ${l}px`;
|
|
3092
3146
|
}
|
|
3093
3147
|
return `${fallback}px`;
|
|
@@ -3301,11 +3355,8 @@ function ToolbarTypographyControls({ editor, C }) {
|
|
|
3301
3355
|
}
|
|
3302
3356
|
function FormattingToolbar({
|
|
3303
3357
|
editor,
|
|
3304
|
-
C
|
|
3305
|
-
mergeTags,
|
|
3306
|
-
onMergeTagInsert
|
|
3358
|
+
C
|
|
3307
3359
|
}) {
|
|
3308
|
-
const [mergeSel, setMergeSel] = (0, import_react2.useState)("");
|
|
3309
3360
|
const [linkPanelOpen, setLinkPanelOpen] = (0, import_react2.useState)(false);
|
|
3310
3361
|
const [linkUrlValue, setLinkUrlValue] = (0, import_react2.useState)("");
|
|
3311
3362
|
const ibtn = (active) => toolbarIconBtn(C, active);
|
|
@@ -3625,8 +3676,6 @@ function TextRichEditor({
|
|
|
3625
3676
|
value,
|
|
3626
3677
|
onChange,
|
|
3627
3678
|
typography,
|
|
3628
|
-
mergeTags,
|
|
3629
|
-
onMergeTagInsert,
|
|
3630
3679
|
placeholder = "Write your message\u2026",
|
|
3631
3680
|
headerTitle = "Rich editor",
|
|
3632
3681
|
C
|
|
@@ -3770,15 +3819,7 @@ function TextRichEditor({
|
|
|
3770
3819
|
]
|
|
3771
3820
|
}
|
|
3772
3821
|
),
|
|
3773
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3774
|
-
FormattingToolbar,
|
|
3775
|
-
{
|
|
3776
|
-
editor,
|
|
3777
|
-
C,
|
|
3778
|
-
mergeTags,
|
|
3779
|
-
onMergeTagInsert
|
|
3780
|
-
}
|
|
3781
|
-
),
|
|
3822
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FormattingToolbar, { editor, C }),
|
|
3782
3823
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: proseStyle }),
|
|
3783
3824
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3784
3825
|
"div",
|
|
@@ -3829,15 +3870,7 @@ function TextRichEditor({
|
|
|
3829
3870
|
background: C.inputBg
|
|
3830
3871
|
},
|
|
3831
3872
|
children: [
|
|
3832
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3833
|
-
FormattingToolbar,
|
|
3834
|
-
{
|
|
3835
|
-
editor,
|
|
3836
|
-
C,
|
|
3837
|
-
mergeTags,
|
|
3838
|
-
onMergeTagInsert
|
|
3839
|
-
}
|
|
3840
|
-
),
|
|
3873
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FormattingToolbar, { editor, C }),
|
|
3841
3874
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: proseStyle }),
|
|
3842
3875
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3843
3876
|
"div",
|
|
@@ -4837,7 +4870,7 @@ function BlockSurfaceBgInspector({
|
|
|
4837
4870
|
] }) : null
|
|
4838
4871
|
] });
|
|
4839
4872
|
}
|
|
4840
|
-
function ContentBlockEditor({ block, onChange,
|
|
4873
|
+
function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
4841
4874
|
const { IS, CI } = useIS(C);
|
|
4842
4875
|
const imageFileRef = (0, import_react4.useRef)(null);
|
|
4843
4876
|
const p = block.props;
|
|
@@ -4856,7 +4889,6 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
4856
4889
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", checked: !!p[k], onChange: (e) => set(k, e.target.checked), style: { width: 15, height: 15, accentColor: C.accent } }),
|
|
4857
4890
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: C.muted, fontSize: 12 }, children: p[k] ? "On" : "Off" })
|
|
4858
4891
|
] }) });
|
|
4859
|
-
const TagPicker = (_field) => null;
|
|
4860
4892
|
const FONTS2 = ["Georgia,serif", "Arial,sans-serif", "Verdana,sans-serif", "'Courier New',monospace", "Trebuchet MS,sans-serif", "Impact,sans-serif"];
|
|
4861
4893
|
const ImgUpload = (key) => {
|
|
4862
4894
|
if (!onUpload) return null;
|
|
@@ -4905,12 +4937,12 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
4905
4937
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Letter spacing", value: p.letterSpacing ?? 0, onChange: (n) => set("letterSpacing", n), min: 0, max: 30, step: 0.5, C }),
|
|
4906
4938
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PR, { label: "Line height", C, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "number", style: useIS(C).IS, min: 0.8, max: 4, step: 0.05, value: p.lineHeight ?? 1.2, onChange: (e) => set("lineHeight", +e.target.value) }) }),
|
|
4907
4939
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4908
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
4940
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4909
4941
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4910
4942
|
] });
|
|
4911
4943
|
case "text":
|
|
4912
4944
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
4913
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PR, { label: "Content
|
|
4945
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PR, { label: "Content", C, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4914
4946
|
"textarea",
|
|
4915
4947
|
{
|
|
4916
4948
|
style: { ...IS, minHeight: 200, resize: "vertical", fontFamily: "ui-monospace, SFMono-Regular, Menlo, Consolas, monospace", fontSize: 12, lineHeight: 1.45 },
|
|
@@ -4921,24 +4953,6 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
4921
4953
|
},
|
|
4922
4954
|
block.id
|
|
4923
4955
|
) }),
|
|
4924
|
-
mergeTags && mergeTags.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PR, { label: "Insert merge tag", C, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
4925
|
-
"select",
|
|
4926
|
-
{
|
|
4927
|
-
style: IS,
|
|
4928
|
-
defaultValue: "",
|
|
4929
|
-
onChange: (e) => {
|
|
4930
|
-
const v = e.target.value;
|
|
4931
|
-
if (v) {
|
|
4932
|
-
set("content", normalizeRichHtmlForStorage((p.content || "") + " " + v));
|
|
4933
|
-
e.target.value = "";
|
|
4934
|
-
}
|
|
4935
|
-
},
|
|
4936
|
-
children: [
|
|
4937
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "Choose\u2026" }),
|
|
4938
|
-
mergeTags.map((t) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: t.value, children: t.name }, t.name))
|
|
4939
|
-
]
|
|
4940
|
-
}
|
|
4941
|
-
) }) : null,
|
|
4942
4956
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Font size", value: p.fontSize ?? 15, onChange: (n) => set("fontSize", n), min: 8, max: 96, step: 1, C }),
|
|
4943
4957
|
Col("color", "Color"),
|
|
4944
4958
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlignButtons, { value: p.align, onChange: (v) => set("align", v), options: ["left", "center", "right", "justify"], C }),
|
|
@@ -4949,7 +4963,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
4949
4963
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PR, { label: "Line height", C, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "number", style: useIS(C).IS, min: 1, max: 4, step: 0.05, value: p.lineHeight ?? 1.65, onChange: (e) => set("lineHeight", +e.target.value) }) }),
|
|
4950
4964
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Letter spacing", value: p.letterSpacing ?? 0, onChange: (n) => set("letterSpacing", n), min: 0, max: 30, step: 0.5, C }),
|
|
4951
4965
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4952
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
4966
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4953
4967
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4954
4968
|
] });
|
|
4955
4969
|
case "html":
|
|
@@ -4968,15 +4982,13 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
4968
4982
|
letterSpacing: p.letterSpacing,
|
|
4969
4983
|
padding: p.padding
|
|
4970
4984
|
},
|
|
4971
|
-
mergeTags,
|
|
4972
|
-
onMergeTagInsert: (tag) => set("content", (p.content || "") + " " + tag),
|
|
4973
4985
|
placeholder: "Write your rich content\u2026",
|
|
4974
4986
|
headerTitle: "Rich editor",
|
|
4975
4987
|
C
|
|
4976
4988
|
}
|
|
4977
4989
|
) }, block.id),
|
|
4978
4990
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4979
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
4991
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4980
4992
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4981
4993
|
] });
|
|
4982
4994
|
case "image":
|
|
@@ -4999,7 +5011,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
4999
5011
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlignButtons, { value: p.align, onChange: (v) => set("align", v), options: ["left", "center", "right"], C }),
|
|
5000
5012
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BorderRadiusEditor, { value: p.borderRadius, onChange: (br) => set("borderRadius", br), C }),
|
|
5001
5013
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5002
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5014
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5003
5015
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5004
5016
|
] });
|
|
5005
5017
|
case "button":
|
|
@@ -5019,7 +5031,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5019
5031
|
Sel("fontWeight", "Weight", ["400", "500", "600", "700", "800"]),
|
|
5020
5032
|
Tog("fullWidth", "Full Width"),
|
|
5021
5033
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "backdrop", p, set, C, onUpload, syncKey: block.id }),
|
|
5022
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5034
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5023
5035
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5024
5036
|
] });
|
|
5025
5037
|
case "link":
|
|
@@ -5034,7 +5046,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5034
5046
|
Sel("fontFamily", "Font", FONTS2),
|
|
5035
5047
|
Tog("underline", "Underline"),
|
|
5036
5048
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5037
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5049
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5038
5050
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5039
5051
|
] });
|
|
5040
5052
|
case "divider":
|
|
@@ -5043,14 +5055,14 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5043
5055
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Thickness", value: p.thickness ?? 1, onChange: (n) => set("thickness", n), min: 1, max: 20, step: 1, C }),
|
|
5044
5056
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DividerStyleButtons, { value: p.style, onChange: (s) => set("style", s), C }),
|
|
5045
5057
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5046
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5058
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5047
5059
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5048
5060
|
] });
|
|
5049
5061
|
case "spacer":
|
|
5050
5062
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
5051
5063
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Height", value: p.height ?? 24, onChange: (n) => set("height", n), min: 4, max: 300, step: 1, C }),
|
|
5052
5064
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5053
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5065
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5054
5066
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5055
5067
|
] });
|
|
5056
5068
|
case "social":
|
|
@@ -5099,7 +5111,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5099
5111
|
Sel("shape", "Shape", ["circle", "square"]),
|
|
5100
5112
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Gap", value: p.gap ?? 6, onChange: (n) => set("gap", n), min: 0, max: 40, step: 1, C }),
|
|
5101
5113
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5102
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5114
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5103
5115
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5104
5116
|
] });
|
|
5105
5117
|
case "video":
|
|
@@ -5159,7 +5171,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5159
5171
|
] }),
|
|
5160
5172
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Height", value: p.height ?? 280, onChange: (n) => set("height", n), min: 80, max: 720, step: 1, C }),
|
|
5161
5173
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5162
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5174
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5163
5175
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5164
5176
|
] });
|
|
5165
5177
|
case "menu":
|
|
@@ -5185,7 +5197,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5185
5197
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Font size", value: p.fontSize ?? 14, onChange: (n) => set("fontSize", n), min: 8, max: 48, step: 1, C }),
|
|
5186
5198
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Item gap", value: p.gap ?? 20, onChange: (n) => set("gap", n), min: 0, max: 80, step: 1, C }),
|
|
5187
5199
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5188
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5200
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5189
5201
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5190
5202
|
] });
|
|
5191
5203
|
case "timer": {
|
|
@@ -5225,7 +5237,7 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5225
5237
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AlignButtons, { value: p.align, onChange: (v) => set("align", v), options: ["left", "center", "right"], C }),
|
|
5226
5238
|
Tog("showLabels", "Show Labels"),
|
|
5227
5239
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "backdrop", p, set, C, onUpload, syncKey: block.id }),
|
|
5228
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5240
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5229
5241
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5230
5242
|
] });
|
|
5231
5243
|
}
|
|
@@ -5322,8 +5334,8 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5322
5334
|
Tog("striped", "Striped rows"),
|
|
5323
5335
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NumRangePx, { label: "Font size", value: p.fontSize ?? 13, onChange: (n) => set("fontSize", n), min: 10, max: 24, step: 1, C }),
|
|
5324
5336
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5325
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (
|
|
5326
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { label: "Cell padding", value: p.cellPadding, onChange: (
|
|
5337
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5338
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { label: "Cell padding", value: p.cellPadding, onChange: (pad3) => set("cellPadding", pad3), C }),
|
|
5327
5339
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5328
5340
|
] });
|
|
5329
5341
|
case "layout":
|
|
@@ -5376,6 +5388,19 @@ function ContentBlockEditor({ block, onChange, mergeTags, onClose, onUpload, C }
|
|
|
5376
5388
|
return null;
|
|
5377
5389
|
}
|
|
5378
5390
|
}
|
|
5391
|
+
function inferLayoutRowBgStep(r) {
|
|
5392
|
+
if (r.bgGradient) return "gradient";
|
|
5393
|
+
if (String(r.bgImage || "").trim()) return "image";
|
|
5394
|
+
if (String(r.bgColor || "").trim()) return "solid";
|
|
5395
|
+
return null;
|
|
5396
|
+
}
|
|
5397
|
+
function inferColumnBgStep(columnStyles, selCol) {
|
|
5398
|
+
const cs = (columnStyles || {})[selCol] || {};
|
|
5399
|
+
if (cs.bgGradient) return "gradient";
|
|
5400
|
+
if (String(cs.bgImage || "").trim()) return "image";
|
|
5401
|
+
if (String(cs.bgColor || "").trim()) return "solid";
|
|
5402
|
+
return null;
|
|
5403
|
+
}
|
|
5379
5404
|
function LayoutRowEditor({
|
|
5380
5405
|
row,
|
|
5381
5406
|
onChange,
|
|
@@ -5387,49 +5412,37 @@ function LayoutRowEditor({
|
|
|
5387
5412
|
customizationHint
|
|
5388
5413
|
}) {
|
|
5389
5414
|
const { IS, CI } = useIS(C);
|
|
5390
|
-
const
|
|
5391
|
-
const
|
|
5392
|
-
const [
|
|
5415
|
+
const colCount = Math.max(1, row.ratios?.length || row.cells?.length || 1);
|
|
5416
|
+
const ratioList = row.ratios?.length ? row.ratios : [1];
|
|
5417
|
+
const [selCol, setSelCol] = (0, import_react4.useState)(0);
|
|
5418
|
+
const [rowBgPickerMode, setRowBgPickerMode] = (0, import_react4.useState)(null);
|
|
5419
|
+
const [colBgPickerMode, setColBgPickerMode] = (0, import_react4.useState)(null);
|
|
5420
|
+
const inferredRowBg = (0, import_react4.useMemo)(() => inferLayoutRowBgStep(row), [row.bgGradient, row.bgImage, row.bgColor]);
|
|
5421
|
+
const inferredColBg = (0, import_react4.useMemo)(
|
|
5422
|
+
() => inferColumnBgStep(row.columnStyles, selCol),
|
|
5423
|
+
[row.columnStyles, selCol]
|
|
5424
|
+
);
|
|
5425
|
+
const rowBgUiStep = inferredRowBg ?? rowBgPickerMode;
|
|
5426
|
+
const colBgUiStep = inferredColBg ?? colBgPickerMode;
|
|
5393
5427
|
(0, import_react4.useEffect)(() => {
|
|
5394
|
-
if (initialCol !== null && initialCol !== void 0) {
|
|
5395
|
-
setSelCol(initialCol);
|
|
5428
|
+
if (initialCol !== null && initialCol !== void 0 && initialCol >= 0) {
|
|
5429
|
+
setSelCol(Math.min(initialCol, colCount - 1));
|
|
5430
|
+
} else {
|
|
5431
|
+
setSelCol((c) => Math.min(Math.max(0, c), colCount - 1));
|
|
5396
5432
|
}
|
|
5397
|
-
}, [initialCol]);
|
|
5433
|
+
}, [initialCol, row.id, colCount]);
|
|
5398
5434
|
(0, import_react4.useEffect)(() => {
|
|
5399
|
-
|
|
5400
|
-
setRowBgUiStep("gradient");
|
|
5401
|
-
return;
|
|
5402
|
-
}
|
|
5403
|
-
if (String(row.bgImage || "").trim()) {
|
|
5404
|
-
setRowBgUiStep("image");
|
|
5405
|
-
return;
|
|
5406
|
-
}
|
|
5407
|
-
if (String(row.bgColor || "").trim()) {
|
|
5408
|
-
setRowBgUiStep("solid");
|
|
5409
|
-
return;
|
|
5410
|
-
}
|
|
5411
|
-
setRowBgUiStep(null);
|
|
5435
|
+
setRowBgPickerMode(null);
|
|
5412
5436
|
}, [row.id]);
|
|
5413
5437
|
(0, import_react4.useEffect)(() => {
|
|
5414
|
-
|
|
5415
|
-
setColBgUiStep(null);
|
|
5416
|
-
return;
|
|
5417
|
-
}
|
|
5418
|
-
const cs = (row.columnStyles || {})[selCol] || {};
|
|
5419
|
-
if (cs.bgGradient) {
|
|
5420
|
-
setColBgUiStep("gradient");
|
|
5421
|
-
return;
|
|
5422
|
-
}
|
|
5423
|
-
if (String(cs.bgImage || "").trim()) {
|
|
5424
|
-
setColBgUiStep("image");
|
|
5425
|
-
return;
|
|
5426
|
-
}
|
|
5427
|
-
if (String(cs.bgColor || "").trim()) {
|
|
5428
|
-
setColBgUiStep("solid");
|
|
5429
|
-
return;
|
|
5430
|
-
}
|
|
5431
|
-
setColBgUiStep(null);
|
|
5438
|
+
setColBgPickerMode(null);
|
|
5432
5439
|
}, [selCol, row.id]);
|
|
5440
|
+
(0, import_react4.useEffect)(() => {
|
|
5441
|
+
if (inferredRowBg) setRowBgPickerMode(null);
|
|
5442
|
+
}, [inferredRowBg]);
|
|
5443
|
+
(0, import_react4.useEffect)(() => {
|
|
5444
|
+
if (inferredColBg) setColBgPickerMode(null);
|
|
5445
|
+
}, [inferredColBg]);
|
|
5433
5446
|
const set = (k, v) => onChange({ ...row, [k]: v });
|
|
5434
5447
|
const applyColumnCount = (n) => {
|
|
5435
5448
|
const prevCells = [...row.cells || []];
|
|
@@ -5445,16 +5458,13 @@ function LayoutRowEditor({
|
|
|
5445
5458
|
}
|
|
5446
5459
|
onChange({ ...row, cols: n, preset: "custom", cells, ratios });
|
|
5447
5460
|
};
|
|
5448
|
-
const colCount = Math.max(1, row.ratios?.length || row.cells?.length || 1);
|
|
5449
|
-
const ratioList = row.ratios?.length ? row.ratios : [1];
|
|
5450
5461
|
const updCol = (i, upd) => {
|
|
5451
5462
|
const styles = { ...row.columnStyles || {} };
|
|
5452
5463
|
styles[i] = { ...styles[i] || {}, ...upd };
|
|
5453
5464
|
set("columnStyles", styles);
|
|
5454
5465
|
};
|
|
5455
5466
|
const setColBgMode = (mode) => {
|
|
5456
|
-
|
|
5457
|
-
setColBgUiStep(mode);
|
|
5467
|
+
setColBgPickerMode(mode);
|
|
5458
5468
|
const cs = (row.columnStyles || {})[selCol] || {};
|
|
5459
5469
|
if (mode === "solid") {
|
|
5460
5470
|
updCol(selCol, { bgGradient: null, bgImage: "" });
|
|
@@ -5472,7 +5482,7 @@ function LayoutRowEditor({
|
|
|
5472
5482
|
const total = ratioList.reduce((a, b) => a + b, 0) || 1;
|
|
5473
5483
|
const POS_OPTS = ["center", "top", "bottom", "left", "right", "top left", "top right", "bottom left", "bottom right"];
|
|
5474
5484
|
const setRowBgMode = (mode) => {
|
|
5475
|
-
|
|
5485
|
+
setRowBgPickerMode(mode);
|
|
5476
5486
|
if (mode === "solid") {
|
|
5477
5487
|
set("bgGradient", null);
|
|
5478
5488
|
set("bgImage", "");
|
|
@@ -5630,7 +5640,7 @@ function LayoutRowEditor({
|
|
|
5630
5640
|
},
|
|
5631
5641
|
i
|
|
5632
5642
|
)) }),
|
|
5633
|
-
|
|
5643
|
+
colCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { background: C.surface, padding: 10, borderRadius: 8, border: `1px solid ${C.border}` }, children: [
|
|
5634
5644
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BgModeButtons, { value: colBgUiStep, onChange: setColBgMode, C }),
|
|
5635
5645
|
colBgUiStep === null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { fontSize: 11, color: C.muted, marginBottom: 10, lineHeight: 1.45 }, children: "Choose Color, Gradient, or Image \u2014 then edit column background details." }) : null,
|
|
5636
5646
|
colBgUiStep === "solid" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PR, { label: `col ${selCol + 1} bg`, C, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
@@ -5718,7 +5728,7 @@ function LayoutRowEditor({
|
|
|
5718
5728
|
}
|
|
5719
5729
|
) })
|
|
5720
5730
|
] }) : null,
|
|
5721
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { label: "Column padding", value: (row.columnStyles || {})[selCol]?.padding, onChange: (
|
|
5731
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PaddingEditor, { label: "Column padding", value: (row.columnStyles || {})[selCol]?.padding, onChange: (pad3) => updCol(selCol, { padding: pad3 }), C }),
|
|
5722
5732
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(BorderRadiusEditor, { label: "Column radius", value: (row.columnStyles || {})[selCol]?.borderRadius, onChange: (br) => updCol(selCol, { borderRadius: br }), C })
|
|
5723
5733
|
] })
|
|
5724
5734
|
] })
|
|
@@ -5995,8 +6005,8 @@ function MobilePhoneScaleSlot({ variantKey, children }) {
|
|
|
5995
6005
|
const pw = phone.offsetWidth;
|
|
5996
6006
|
const ph = phone.offsetHeight;
|
|
5997
6007
|
if (cw < 12 || ch < 12 || pw < 12 || ph < 12) return;
|
|
5998
|
-
const
|
|
5999
|
-
const raw = Math.min(1, (cw -
|
|
6008
|
+
const pad3 = 20;
|
|
6009
|
+
const raw = Math.min(1, (cw - pad3) / pw, (ch - pad3) / ph);
|
|
6000
6010
|
const s = Number.isFinite(raw) ? Math.max(0.2, raw) : 1;
|
|
6001
6011
|
setFit({ s, w: pw * s, h: ph * s });
|
|
6002
6012
|
};
|
|
@@ -6521,7 +6531,6 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
6521
6531
|
const [locale, setLocale] = (0, import_react8.useState)(
|
|
6522
6532
|
typeof opt.locale === "string" ? opt.locale : "en"
|
|
6523
6533
|
);
|
|
6524
|
-
const [mergeTags, setMergeTagsState] = (0, import_react8.useState)(() => opt.mergeTags ?? []);
|
|
6525
6534
|
const [zoom, setZoom] = (0, import_react8.useState)(100);
|
|
6526
6535
|
const [rightRailWidth, setRightRailWidth] = (0, import_react8.useState)(RIGHT_RAIL_DEFAULT_W);
|
|
6527
6536
|
const [ctxMenu, setCtxMenu] = (0, import_react8.useState)(null);
|
|
@@ -6867,6 +6876,43 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
6867
6876
|
}
|
|
6868
6877
|
}
|
|
6869
6878
|
};
|
|
6879
|
+
const insertBlockFromLibrary = (contentType) => {
|
|
6880
|
+
if (!rows.length) return;
|
|
6881
|
+
if (selContentMeta?.inner) {
|
|
6882
|
+
const { rowId, cellIdx, contentIdx, inner } = selContentMeta;
|
|
6883
|
+
dropContent(rowId, cellIdx, {
|
|
6884
|
+
kind: "new",
|
|
6885
|
+
contentType,
|
|
6886
|
+
insertAt: null,
|
|
6887
|
+
nested: { parentBlockIdx: contentIdx, innerCellIdx: inner.cellIdx }
|
|
6888
|
+
});
|
|
6889
|
+
return;
|
|
6890
|
+
}
|
|
6891
|
+
if (selContentMeta?.rowId && typeof selContentMeta.cellIdx === "number" && selContentMeta.cellIdx >= 0) {
|
|
6892
|
+
const r = rows.find((x) => x.id === selContentMeta.rowId);
|
|
6893
|
+
if (r && selContentMeta.cellIdx < r.cells.length) {
|
|
6894
|
+
dropContent(selContentMeta.rowId, selContentMeta.cellIdx, {
|
|
6895
|
+
kind: "new",
|
|
6896
|
+
contentType,
|
|
6897
|
+
insertAt: null
|
|
6898
|
+
});
|
|
6899
|
+
return;
|
|
6900
|
+
}
|
|
6901
|
+
}
|
|
6902
|
+
if (selectedRowId) {
|
|
6903
|
+
const targetRow = rows.find((r) => r.id === selectedRowId);
|
|
6904
|
+
if (targetRow) {
|
|
6905
|
+
dropContent(targetRow.id, 0, {
|
|
6906
|
+
kind: "new",
|
|
6907
|
+
contentType,
|
|
6908
|
+
insertAt: null
|
|
6909
|
+
});
|
|
6910
|
+
return;
|
|
6911
|
+
}
|
|
6912
|
+
}
|
|
6913
|
+
const main = rows[0];
|
|
6914
|
+
dropContent(main.id, 0, { kind: "new", contentType, insertAt: null });
|
|
6915
|
+
};
|
|
6870
6916
|
const deleteContent = (rowId, cellIdx, ci, inner = null) => {
|
|
6871
6917
|
if (!inner) {
|
|
6872
6918
|
mutate((prev) => prev.map((r) => {
|
|
@@ -6916,7 +6962,7 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
6916
6962
|
}));
|
|
6917
6963
|
return;
|
|
6918
6964
|
}
|
|
6919
|
-
const loc = { type: "nested", rowId, outerCellIdx: cellIdx, blockIdx:
|
|
6965
|
+
const loc = { type: "nested", rowId, outerCellIdx: cellIdx, blockIdx: ci, innerCellIdx: inner.cellIdx };
|
|
6920
6966
|
mutate((prev) => updateColumnAt(prev, loc, (c) => c.map((b, j) => j === inner.contentIdx ? upd : b)));
|
|
6921
6967
|
};
|
|
6922
6968
|
const selectContent = (contentId, rowId, cellIdx, parentBlockIdx, inner = null) => {
|
|
@@ -7463,6 +7509,8 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
7463
7509
|
if (data.layoutPresetKey) {
|
|
7464
7510
|
const preset = LAYOUT_PRESETS.find((p) => p.key === data.layoutPresetKey);
|
|
7465
7511
|
if (preset) mutate((prev) => [...prev, makeLayoutRow(preset)]);
|
|
7512
|
+
} else if (data.contentType && typeof data.contentType === "string") {
|
|
7513
|
+
insertBlockFromLibrary(data.contentType);
|
|
7466
7514
|
}
|
|
7467
7515
|
} catch {
|
|
7468
7516
|
}
|
|
@@ -7503,6 +7551,21 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
7503
7551
|
}
|
|
7504
7552
|
return base;
|
|
7505
7553
|
})(),
|
|
7554
|
+
onDragOver: (e) => {
|
|
7555
|
+
e.preventDefault();
|
|
7556
|
+
e.stopPropagation();
|
|
7557
|
+
},
|
|
7558
|
+
onDrop: (e) => {
|
|
7559
|
+
e.preventDefault();
|
|
7560
|
+
e.stopPropagation();
|
|
7561
|
+
try {
|
|
7562
|
+
const data = JSON.parse(e.dataTransfer.getData("application/json") || "{}");
|
|
7563
|
+
if (data.contentType && typeof data.contentType === "string") {
|
|
7564
|
+
insertBlockFromLibrary(data.contentType);
|
|
7565
|
+
}
|
|
7566
|
+
} catch {
|
|
7567
|
+
}
|
|
7568
|
+
},
|
|
7506
7569
|
children: [
|
|
7507
7570
|
rows.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { id: eid("canvas-empty"), style: { padding: "56px 20px", textAlign: "center", color: C.muted, border: `2px dashed ${C.border}`, borderRadius: 7 }, children: [
|
|
7508
7571
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { fontSize: 30, marginBottom: 10 }, children: "\u2709" }),
|
|
@@ -7647,7 +7710,6 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
7647
7710
|
setSelMeta(null);
|
|
7648
7711
|
setSelectedRowId(null);
|
|
7649
7712
|
},
|
|
7650
|
-
mergeTags,
|
|
7651
7713
|
onUpload,
|
|
7652
7714
|
C
|
|
7653
7715
|
}
|
|
@@ -7715,12 +7777,8 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
7715
7777
|
onDragStart: (e) => {
|
|
7716
7778
|
e.dataTransfer.setData("application/json", JSON.stringify({ contentType: bt.type }));
|
|
7717
7779
|
},
|
|
7718
|
-
onClick: () =>
|
|
7719
|
-
|
|
7720
|
-
if (!targetRow) return;
|
|
7721
|
-
dropContent(targetRow.id, 0, { kind: "new", contentType: bt.type, insertAt: null });
|
|
7722
|
-
},
|
|
7723
|
-
title: `Drag into a cell or click to add to ${selectedRowId ? "selected row" : "last row"}`,
|
|
7780
|
+
onClick: () => insertBlockFromLibrary(bt.type),
|
|
7781
|
+
title: selContentMeta?.inner ? "Click to add inside the selected nested column" : selContentMeta?.rowId ? "Click to add in the selected column" : selectedRowId ? "Click to add to column 1 of the selected row" : "Click to add to the first row, first column",
|
|
7724
7782
|
style: {
|
|
7725
7783
|
display: "flex",
|
|
7726
7784
|
flexDirection: "row",
|
|
@@ -8090,12 +8148,80 @@ var ReactEmailEditor = (0, import_react8.forwardRef)(
|
|
|
8090
8148
|
);
|
|
8091
8149
|
}
|
|
8092
8150
|
);
|
|
8151
|
+
|
|
8152
|
+
// src/lib/htmlToEmailDesign.ts
|
|
8153
|
+
var pad = (n) => ({ top: n, right: n, bottom: n, left: n });
|
|
8154
|
+
function extractHtmlForDesign(html) {
|
|
8155
|
+
const t = String(html ?? "").trim();
|
|
8156
|
+
if (!t) return "";
|
|
8157
|
+
const head = t.slice(0, 800).toLowerCase();
|
|
8158
|
+
if (!head.includes("<html") && !head.includes("<!doctype")) {
|
|
8159
|
+
return normalizeRichHtmlForStorage(t);
|
|
8160
|
+
}
|
|
8161
|
+
try {
|
|
8162
|
+
const doc = new DOMParser().parseFromString(t, "text/html");
|
|
8163
|
+
const body = doc.body;
|
|
8164
|
+
if (!body) return normalizeRichHtmlForStorage(t);
|
|
8165
|
+
return normalizeRichHtmlForStorage(body.innerHTML);
|
|
8166
|
+
} catch {
|
|
8167
|
+
return normalizeRichHtmlForStorage(t);
|
|
8168
|
+
}
|
|
8169
|
+
}
|
|
8170
|
+
function htmlToEmailDesignTemplate(html) {
|
|
8171
|
+
const inner = extractHtmlForDesign(html);
|
|
8172
|
+
if (!inner) return null;
|
|
8173
|
+
const doc = {
|
|
8174
|
+
type: "email_document",
|
|
8175
|
+
settings: {
|
|
8176
|
+
width: 600,
|
|
8177
|
+
backgroundColor: "#f1f5f9",
|
|
8178
|
+
contentBackgroundColor: "#ffffff",
|
|
8179
|
+
fontFamily: "Arial, Helvetica, sans-serif",
|
|
8180
|
+
lineHeightBase: 1.6,
|
|
8181
|
+
color: "#111827",
|
|
8182
|
+
responsive: true,
|
|
8183
|
+
rtl: false
|
|
8184
|
+
},
|
|
8185
|
+
rows: [
|
|
8186
|
+
{
|
|
8187
|
+
id: "row_html_import",
|
|
8188
|
+
type: "row",
|
|
8189
|
+
layout: { columns: 1, gap: 0, stackOnMobile: true, align: "center" },
|
|
8190
|
+
styles: {
|
|
8191
|
+
backgroundColor: "#ffffff",
|
|
8192
|
+
backgroundRepeat: "no-repeat",
|
|
8193
|
+
backgroundSize: "cover",
|
|
8194
|
+
padding: pad(24),
|
|
8195
|
+
textAlign: "left"
|
|
8196
|
+
},
|
|
8197
|
+
columns: [
|
|
8198
|
+
{
|
|
8199
|
+
id: "col_html_import",
|
|
8200
|
+
layout: { width: "100%", verticalAlign: "top", mobileWidth: "100%" },
|
|
8201
|
+
styles: { padding: pad(0), backgroundColor: "" },
|
|
8202
|
+
blocks: [
|
|
8203
|
+
{
|
|
8204
|
+
id: "block_html_import",
|
|
8205
|
+
type: "html",
|
|
8206
|
+
content: { html: inner },
|
|
8207
|
+
styles: {}
|
|
8208
|
+
}
|
|
8209
|
+
]
|
|
8210
|
+
}
|
|
8211
|
+
]
|
|
8212
|
+
}
|
|
8213
|
+
]
|
|
8214
|
+
};
|
|
8215
|
+
return doc;
|
|
8216
|
+
}
|
|
8093
8217
|
// Annotate the CommonJS export names for ESM import in node:
|
|
8094
8218
|
0 && (module.exports = {
|
|
8095
8219
|
EmailPreviewModal,
|
|
8096
8220
|
ReactEmailEditor,
|
|
8097
8221
|
base64ToUtf8,
|
|
8098
8222
|
emailPreviewDevices,
|
|
8223
|
+
extractHtmlForDesign,
|
|
8224
|
+
htmlToEmailDesignTemplate,
|
|
8099
8225
|
jsonToHtml,
|
|
8100
8226
|
utf8ToBase64
|
|
8101
8227
|
});
|