react-email-studio 3.2.0 → 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/dist/index.cjs +213 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +211 -83
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -286,6 +286,18 @@ type JsonToHtmlOptions = EmailHtmlOptions;
|
|
|
286
286
|
*/
|
|
287
287
|
declare function jsonToHtml(designInput: unknown, opts?: JsonToHtmlOptions): string;
|
|
288
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Pull usable HTML from a full document (`<!DOCTYPE` / `<html>`) or a fragment string.
|
|
291
|
+
*/
|
|
292
|
+
declare function extractHtmlForDesign(html: string): string;
|
|
293
|
+
/**
|
|
294
|
+
* Wrap HTML (fragment or full email/page document) in a minimal `email_document`
|
|
295
|
+
* with one row, one column, and a single **html** block — suitable for `loadJson`.
|
|
296
|
+
*
|
|
297
|
+
* @returns `null` when there is no non-empty HTML after extraction/normalization.
|
|
298
|
+
*/
|
|
299
|
+
declare function htmlToEmailDesignTemplate(html: string): EmailDocument | null;
|
|
300
|
+
|
|
289
301
|
declare function utf8ToBase64(raw: string): string;
|
|
290
302
|
declare function base64ToUtf8(b64: string): string;
|
|
291
303
|
|
|
@@ -413,4 +425,4 @@ declare const DEVICES: ({
|
|
|
413
425
|
})[];
|
|
414
426
|
declare function PreviewModal({ html, contentWidth, rowCount, blockCount, editorZoom, locale, initialDevice, initialMobileVariant, onClose, C, title, secondaryActionLabel, onSecondaryAction, }: EmailPreviewModalProps): react_jsx_runtime.JSX.Element;
|
|
415
427
|
|
|
416
|
-
export { type BlockBase, type EmailDocument, type EmailDocumentColumn, type EmailDocumentRow, type EmailDocumentSettings, type EmailHtmlOptions, PreviewModal as EmailPreviewModal, type EmailPreviewModalProps, type JsonToHtmlOptions, type MobilePreviewVariant, ReactEmailEditor, type ReactEmailEditorOptions, type ReactEmailEditorProps, type ReactEmailEditorRef, base64ToUtf8, DEVICES as emailPreviewDevices, jsonToHtml, utf8ToBase64 };
|
|
428
|
+
export { type BlockBase, type EmailDocument, type EmailDocumentColumn, type EmailDocumentRow, type EmailDocumentSettings, type EmailHtmlOptions, PreviewModal as EmailPreviewModal, type EmailPreviewModalProps, type JsonToHtmlOptions, type MobilePreviewVariant, ReactEmailEditor, type ReactEmailEditorOptions, type ReactEmailEditorProps, type ReactEmailEditorRef, base64ToUtf8, DEVICES as emailPreviewDevices, extractHtmlForDesign, htmlToEmailDesignTemplate, jsonToHtml, utf8ToBase64 };
|
package/dist/index.d.ts
CHANGED
|
@@ -286,6 +286,18 @@ type JsonToHtmlOptions = EmailHtmlOptions;
|
|
|
286
286
|
*/
|
|
287
287
|
declare function jsonToHtml(designInput: unknown, opts?: JsonToHtmlOptions): string;
|
|
288
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Pull usable HTML from a full document (`<!DOCTYPE` / `<html>`) or a fragment string.
|
|
291
|
+
*/
|
|
292
|
+
declare function extractHtmlForDesign(html: string): string;
|
|
293
|
+
/**
|
|
294
|
+
* Wrap HTML (fragment or full email/page document) in a minimal `email_document`
|
|
295
|
+
* with one row, one column, and a single **html** block — suitable for `loadJson`.
|
|
296
|
+
*
|
|
297
|
+
* @returns `null` when there is no non-empty HTML after extraction/normalization.
|
|
298
|
+
*/
|
|
299
|
+
declare function htmlToEmailDesignTemplate(html: string): EmailDocument | null;
|
|
300
|
+
|
|
289
301
|
declare function utf8ToBase64(raw: string): string;
|
|
290
302
|
declare function base64ToUtf8(b64: string): string;
|
|
291
303
|
|
|
@@ -413,4 +425,4 @@ declare const DEVICES: ({
|
|
|
413
425
|
})[];
|
|
414
426
|
declare function PreviewModal({ html, contentWidth, rowCount, blockCount, editorZoom, locale, initialDevice, initialMobileVariant, onClose, C, title, secondaryActionLabel, onSecondaryAction, }: EmailPreviewModalProps): react_jsx_runtime.JSX.Element;
|
|
415
427
|
|
|
416
|
-
export { type BlockBase, type EmailDocument, type EmailDocumentColumn, type EmailDocumentRow, type EmailDocumentSettings, type EmailHtmlOptions, PreviewModal as EmailPreviewModal, type EmailPreviewModalProps, type JsonToHtmlOptions, type MobilePreviewVariant, ReactEmailEditor, type ReactEmailEditorOptions, type ReactEmailEditorProps, type ReactEmailEditorRef, base64ToUtf8, DEVICES as emailPreviewDevices, jsonToHtml, utf8ToBase64 };
|
|
428
|
+
export { type BlockBase, type EmailDocument, type EmailDocumentColumn, type EmailDocumentRow, type EmailDocumentSettings, type EmailHtmlOptions, PreviewModal as EmailPreviewModal, type EmailPreviewModalProps, type JsonToHtmlOptions, type MobilePreviewVariant, ReactEmailEditor, type ReactEmailEditorOptions, type ReactEmailEditorProps, type ReactEmailEditorRef, base64ToUtf8, DEVICES as emailPreviewDevices, extractHtmlForDesign, htmlToEmailDesignTemplate, jsonToHtml, utf8ToBase64 };
|
package/dist/index.js
CHANGED
|
@@ -136,7 +136,7 @@ var I18N = {
|
|
|
136
136
|
blockPaletteGroupActions: "Buttons & links",
|
|
137
137
|
blockPaletteGroupWidgets: "Widgets",
|
|
138
138
|
closePanel: "Close",
|
|
139
|
-
canvasEmptyHint: "Drag blocks from the library into
|
|
139
|
+
canvasEmptyHint: "Drag row layouts or blocks from the library. Drop blocks into a column or onto the mail preview area.",
|
|
140
140
|
emailContentSettings: "Email content",
|
|
141
141
|
loadingDesign: "Loading design\u2026"
|
|
142
142
|
},
|
|
@@ -1091,7 +1091,7 @@ function rowToHtml(row) {
|
|
|
1091
1091
|
const r = row.ratios[i] ?? 1;
|
|
1092
1092
|
const cs = row.columnStyles && row.columnStyles[i] ? row.columnStyles[i] : {};
|
|
1093
1093
|
const colShell = emailSurfaceBgCss(cs);
|
|
1094
|
-
const
|
|
1094
|
+
const pad3 = cs.padding && typeof cs.padding === "object" && !Array.isArray(cs.padding) ? `padding:${(() => {
|
|
1095
1095
|
const o = cs.padding;
|
|
1096
1096
|
const t = numOr2(o.top, 0);
|
|
1097
1097
|
const rgt = numOr2(o.right, t);
|
|
@@ -1107,7 +1107,7 @@ function rowToHtml(row) {
|
|
|
1107
1107
|
const bl = numOr2(x.bl, tr2);
|
|
1108
1108
|
return `border-radius:${tl}px ${tr2}px ${br}px ${bl}px;`;
|
|
1109
1109
|
})() : typeof cs.borderRadius === "number" && Number.isFinite(cs.borderRadius) ? `border-radius:${cs.borderRadius}px;` : "";
|
|
1110
|
-
return `<div style="flex:${r} 1 0;min-width:0;box-sizing:border-box;${
|
|
1110
|
+
return `<div style="flex:${r} 1 0;min-width:0;box-sizing:border-box;${pad3}${rad}${colShell}">${cell.map(blockToHtml).join("")}</div>`;
|
|
1111
1111
|
}).join("")}</div>`;
|
|
1112
1112
|
const innerTrim = inner.replace(/>\s+</g, "><").trim();
|
|
1113
1113
|
const body = innerTrim || " ";
|
|
@@ -1327,8 +1327,8 @@ function layoutColumnBorderRadiusForDoc(r) {
|
|
|
1327
1327
|
}
|
|
1328
1328
|
return 0;
|
|
1329
1329
|
}
|
|
1330
|
-
function columnPaddingNonZero(
|
|
1331
|
-
return
|
|
1330
|
+
function columnPaddingNonZero(pad3) {
|
|
1331
|
+
return pad3.top !== 0 || pad3.right !== 0 || pad3.bottom !== 0 || pad3.left !== 0;
|
|
1332
1332
|
}
|
|
1333
1333
|
function columnRadiusNonZero(r) {
|
|
1334
1334
|
if (typeof r === "number") return r !== 0;
|
|
@@ -1685,9 +1685,9 @@ function mapBlockToInternal(b, layoutDepth = 0) {
|
|
|
1685
1685
|
if (asNum(s.fontWeight) != null) block.props.fontWeight = s.fontWeight;
|
|
1686
1686
|
if (asNum(s.borderRadius) != null) block.props.borderRadius = s.borderRadius;
|
|
1687
1687
|
if (s.padding && typeof s.padding === "object") {
|
|
1688
|
-
const
|
|
1689
|
-
block.props.paddingV = asNum(
|
|
1690
|
-
block.props.paddingH = asNum(
|
|
1688
|
+
const pad3 = s.padding;
|
|
1689
|
+
block.props.paddingV = asNum(pad3.top) ?? block.props.paddingV;
|
|
1690
|
+
block.props.paddingH = asNum(pad3.right) ?? block.props.paddingH;
|
|
1691
1691
|
}
|
|
1692
1692
|
if (asStr(s.textAlign)) block.props.align = s.textAlign;
|
|
1693
1693
|
break;
|
|
@@ -2202,9 +2202,15 @@ function useLiveCountdown(endDate) {
|
|
|
2202
2202
|
const s = Math.floor(diff % 6e4 / 1e3);
|
|
2203
2203
|
return [d, h, m, s];
|
|
2204
2204
|
}
|
|
2205
|
-
function
|
|
2206
|
-
return {};
|
|
2205
|
+
function layoutSplitChromeBorder(_C, preview) {
|
|
2206
|
+
if (preview) return {};
|
|
2207
|
+
return {
|
|
2208
|
+
border: "1px dotted rgba(148, 163, 184, 0.5)",
|
|
2209
|
+
boxSizing: "border-box"
|
|
2210
|
+
};
|
|
2207
2211
|
}
|
|
2212
|
+
var CONTENT_BLOCK_HOVER_BORDER = "1px dotted rgba(148, 163, 184, 0.5)";
|
|
2213
|
+
var EMPTY_CELL_COLUMN_MIN_H = "min(320px, 42vh)";
|
|
2208
2214
|
function blockLinkCaptureHandler(preview, e) {
|
|
2209
2215
|
if (preview) return;
|
|
2210
2216
|
const t = e.target;
|
|
@@ -2236,6 +2242,7 @@ function radiusCssLayout(v) {
|
|
|
2236
2242
|
return "0px";
|
|
2237
2243
|
}
|
|
2238
2244
|
function ContentBlock({ block, selected, onClick, preview, C }) {
|
|
2245
|
+
const [hover, setHover] = useState(false);
|
|
2239
2246
|
const { type, props: p } = block;
|
|
2240
2247
|
const numOr2 = (v, fb) => typeof v === "number" && Number.isFinite(v) ? v : fb;
|
|
2241
2248
|
const boxPx = (v) => {
|
|
@@ -2279,14 +2286,19 @@ function ContentBlock({ block, selected, onClick, preview, C }) {
|
|
|
2279
2286
|
onClick: preview ? void 0 : onClick || void 0,
|
|
2280
2287
|
onClickCapture: (e) => blockLinkCaptureHandler(preview, e),
|
|
2281
2288
|
onAuxClickCapture: (e) => blockLinkCaptureHandler(preview, e),
|
|
2289
|
+
onMouseEnter: preview ? void 0 : () => setHover(true),
|
|
2290
|
+
onMouseLeave: preview ? void 0 : () => setHover(false),
|
|
2282
2291
|
style: {
|
|
2283
2292
|
cursor: preview ? "default" : onClick ? "pointer" : "default",
|
|
2284
2293
|
outline: selected && !preview ? `2px solid ${C.accent}` : "2px solid transparent",
|
|
2285
2294
|
outlineOffset: 1,
|
|
2286
2295
|
borderRadius: 3,
|
|
2287
|
-
transition: "outline .12s",
|
|
2296
|
+
transition: "outline .12s, border-color .12s",
|
|
2288
2297
|
position: "relative",
|
|
2289
|
-
...
|
|
2298
|
+
...preview ? {} : {
|
|
2299
|
+
border: hover ? CONTENT_BLOCK_HOVER_BORDER : "1px solid transparent",
|
|
2300
|
+
boxSizing: "border-box"
|
|
2301
|
+
},
|
|
2290
2302
|
...shellBg,
|
|
2291
2303
|
padding: paddingCss(p.padding),
|
|
2292
2304
|
margin: marginCss(p.margin)
|
|
@@ -2526,7 +2538,7 @@ function NestedRowBlock({
|
|
|
2526
2538
|
outline: rowSelected ? `2px solid ${C.accent}` : "2px solid transparent",
|
|
2527
2539
|
outlineOffset: 1,
|
|
2528
2540
|
transition: "outline .12s",
|
|
2529
|
-
...
|
|
2541
|
+
...layoutSplitChromeBorder(C, preview),
|
|
2530
2542
|
...backgroundLayerStyle({
|
|
2531
2543
|
bgColor: p.bgColor,
|
|
2532
2544
|
bgImage: p.bgImage,
|
|
@@ -2558,7 +2570,10 @@ function NestedRowBlock({
|
|
|
2558
2570
|
style: {
|
|
2559
2571
|
flex: p.ratios?.[ici] ?? 1,
|
|
2560
2572
|
minWidth: 0,
|
|
2561
|
-
|
|
2573
|
+
minHeight: preview ? void 0 : EMPTY_CELL_COLUMN_MIN_H,
|
|
2574
|
+
display: "flex",
|
|
2575
|
+
flexDirection: "column",
|
|
2576
|
+
...layoutSplitChromeBorder(C, preview),
|
|
2562
2577
|
...backgroundLayerStyle(cS),
|
|
2563
2578
|
padding: paddingCssLayout(cS.padding),
|
|
2564
2579
|
borderRadius: radiusCssLayout(cS.borderRadius),
|
|
@@ -2775,6 +2790,7 @@ function Cell({
|
|
|
2775
2790
|
/* @__PURE__ */ jsx3("div", { style: { position: "absolute", left: -4, top: "50%", transform: "translateY(-50%)", width: 8, height: 8, borderRadius: "50%", background: C.accent } }),
|
|
2776
2791
|
/* @__PURE__ */ jsx3("div", { style: { position: "absolute", right: -4, top: "50%", transform: "translateY(-50%)", width: 8, height: 8, borderRadius: "50%", background: C.accent } })
|
|
2777
2792
|
] }) : null;
|
|
2793
|
+
const cellEmpty = !preview && blocks.length === 0;
|
|
2778
2794
|
return /* @__PURE__ */ jsxs2(
|
|
2779
2795
|
"div",
|
|
2780
2796
|
{
|
|
@@ -2784,17 +2800,43 @@ function Cell({
|
|
|
2784
2800
|
onDragLeave: handleDragLeave,
|
|
2785
2801
|
onDrop: handleDrop,
|
|
2786
2802
|
style: {
|
|
2787
|
-
flex: 1,
|
|
2788
|
-
|
|
2803
|
+
flex: cellEmpty ? 1 : void 0,
|
|
2804
|
+
display: "flex",
|
|
2805
|
+
flexDirection: "column",
|
|
2806
|
+
minHeight: preview ? void 0 : cellEmpty ? 0 : 44,
|
|
2789
2807
|
borderRadius: 4,
|
|
2790
|
-
...preview ? {} : insertAt !== null ? { border: `1px dotted ${C.accent}`, background: `${C.accent}0a` } :
|
|
2791
|
-
background: insertAt !== null ? `${C.accent}0a` : "transparent",
|
|
2808
|
+
...preview ? {} : insertAt !== null && !cellEmpty ? { border: `1px dotted ${C.accent}`, background: `${C.accent}0a` } : {},
|
|
2809
|
+
background: insertAt !== null && !cellEmpty ? `${C.accent}0a` : "transparent",
|
|
2792
2810
|
transition: "border-color .15s,background .15s",
|
|
2793
2811
|
padding: preview ? 0 : 0,
|
|
2794
2812
|
position: "relative"
|
|
2795
2813
|
},
|
|
2796
2814
|
children: [
|
|
2797
|
-
|
|
2815
|
+
cellEmpty && /* @__PURE__ */ jsx3(
|
|
2816
|
+
"div",
|
|
2817
|
+
{
|
|
2818
|
+
style: {
|
|
2819
|
+
flex: 1,
|
|
2820
|
+
display: "flex",
|
|
2821
|
+
alignItems: "center",
|
|
2822
|
+
justifyContent: "center",
|
|
2823
|
+
margin: 4,
|
|
2824
|
+
borderRadius: 8,
|
|
2825
|
+
boxSizing: "border-box",
|
|
2826
|
+
textAlign: "center",
|
|
2827
|
+
userSelect: "none",
|
|
2828
|
+
transition: "color .15s, border-color .15s, background .15s, box-shadow .15s",
|
|
2829
|
+
border: insertAt !== null ? `2px dashed ${C.accent}` : `2px dashed ${C.border}`,
|
|
2830
|
+
background: insertAt !== null ? `${C.accent}14` : `${C.canvas}`,
|
|
2831
|
+
boxShadow: insertAt !== null ? `inset 0 0 0 1px ${C.accent}22` : `inset 0 0 0 1px ${C.border}99`,
|
|
2832
|
+
color: insertAt !== null ? C.accent2 : C.muted,
|
|
2833
|
+
fontSize: 11,
|
|
2834
|
+
fontWeight: insertAt !== null ? 700 : 500,
|
|
2835
|
+
letterSpacing: "0.02em"
|
|
2836
|
+
},
|
|
2837
|
+
children: insertAt !== null ? "Release to drop" : "Drop here"
|
|
2838
|
+
}
|
|
2839
|
+
),
|
|
2798
2840
|
/* @__PURE__ */ jsx3(Line, { idx: 0 }),
|
|
2799
2841
|
blocks.map((cb, ci) => /* @__PURE__ */ jsx3(Fragment, { children: /* @__PURE__ */ jsx3(
|
|
2800
2842
|
BlockItem,
|
|
@@ -2845,7 +2887,6 @@ function LayoutRow({
|
|
|
2845
2887
|
transition: "outline .12s",
|
|
2846
2888
|
padding: row.padding,
|
|
2847
2889
|
position: "relative",
|
|
2848
|
-
...editChromeBorder(C, preview),
|
|
2849
2890
|
...backgroundLayerStyle({
|
|
2850
2891
|
bgColor: row.bgColor,
|
|
2851
2892
|
bgImage: row.bgImage,
|
|
@@ -2884,8 +2925,9 @@ function LayoutRow({
|
|
|
2884
2925
|
id: editorId ? `${editorId}-col-${row.id}-${ci}` : void 0,
|
|
2885
2926
|
style: {
|
|
2886
2927
|
flex: row.ratios[ci] ?? 1,
|
|
2887
|
-
minHeight: 50,
|
|
2888
|
-
|
|
2928
|
+
minHeight: preview ? 50 : EMPTY_CELL_COLUMN_MIN_H,
|
|
2929
|
+
display: "flex",
|
|
2930
|
+
flexDirection: "column",
|
|
2889
2931
|
...backgroundLayerStyle(cS),
|
|
2890
2932
|
padding: paddingCssLayout(cS.padding),
|
|
2891
2933
|
borderRadius: radiusCssLayout(cS.borderRadius),
|
|
@@ -3100,13 +3142,13 @@ var FONTS = [
|
|
|
3100
3142
|
"Trebuchet MS,sans-serif",
|
|
3101
3143
|
"Impact,sans-serif"
|
|
3102
3144
|
];
|
|
3103
|
-
function paddingToCss(
|
|
3104
|
-
if (typeof
|
|
3105
|
-
if (
|
|
3106
|
-
const t = typeof
|
|
3107
|
-
const r = typeof
|
|
3108
|
-
const b = typeof
|
|
3109
|
-
const l = typeof
|
|
3145
|
+
function paddingToCss(pad3, fallback) {
|
|
3146
|
+
if (typeof pad3 === "number" && Number.isFinite(pad3)) return `${Math.max(0, pad3)}px`;
|
|
3147
|
+
if (pad3 && typeof pad3 === "object" && !Array.isArray(pad3)) {
|
|
3148
|
+
const t = typeof pad3.top === "number" && Number.isFinite(pad3.top) ? pad3.top : fallback;
|
|
3149
|
+
const r = typeof pad3.right === "number" && Number.isFinite(pad3.right) ? pad3.right : t;
|
|
3150
|
+
const b = typeof pad3.bottom === "number" && Number.isFinite(pad3.bottom) ? pad3.bottom : t;
|
|
3151
|
+
const l = typeof pad3.left === "number" && Number.isFinite(pad3.left) ? pad3.left : r;
|
|
3110
3152
|
return `${t}px ${r}px ${b}px ${l}px`;
|
|
3111
3153
|
}
|
|
3112
3154
|
return `${fallback}px`;
|
|
@@ -4902,7 +4944,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
4902
4944
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Letter spacing", value: p.letterSpacing ?? 0, onChange: (n) => set("letterSpacing", n), min: 0, max: 30, step: 0.5, C }),
|
|
4903
4945
|
/* @__PURE__ */ jsx6(PR, { label: "Line height", C, children: /* @__PURE__ */ jsx6("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) }) }),
|
|
4904
4946
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4905
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
4947
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4906
4948
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4907
4949
|
] });
|
|
4908
4950
|
case "text":
|
|
@@ -4928,7 +4970,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
4928
4970
|
/* @__PURE__ */ jsx6(PR, { label: "Line height", C, children: /* @__PURE__ */ jsx6("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) }) }),
|
|
4929
4971
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Letter spacing", value: p.letterSpacing ?? 0, onChange: (n) => set("letterSpacing", n), min: 0, max: 30, step: 0.5, C }),
|
|
4930
4972
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4931
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
4973
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4932
4974
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4933
4975
|
] });
|
|
4934
4976
|
case "html":
|
|
@@ -4953,7 +4995,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
4953
4995
|
}
|
|
4954
4996
|
) }, block.id),
|
|
4955
4997
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4956
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
4998
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4957
4999
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4958
5000
|
] });
|
|
4959
5001
|
case "image":
|
|
@@ -4976,7 +5018,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
4976
5018
|
/* @__PURE__ */ jsx6(AlignButtons, { value: p.align, onChange: (v) => set("align", v), options: ["left", "center", "right"], C }),
|
|
4977
5019
|
/* @__PURE__ */ jsx6(BorderRadiusEditor, { value: p.borderRadius, onChange: (br) => set("borderRadius", br), C }),
|
|
4978
5020
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
4979
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5021
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
4980
5022
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
4981
5023
|
] });
|
|
4982
5024
|
case "button":
|
|
@@ -4996,7 +5038,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
4996
5038
|
Sel("fontWeight", "Weight", ["400", "500", "600", "700", "800"]),
|
|
4997
5039
|
Tog("fullWidth", "Full Width"),
|
|
4998
5040
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "backdrop", p, set, C, onUpload, syncKey: block.id }),
|
|
4999
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5041
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5000
5042
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5001
5043
|
] });
|
|
5002
5044
|
case "link":
|
|
@@ -5011,7 +5053,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5011
5053
|
Sel("fontFamily", "Font", FONTS2),
|
|
5012
5054
|
Tog("underline", "Underline"),
|
|
5013
5055
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5014
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5056
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5015
5057
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5016
5058
|
] });
|
|
5017
5059
|
case "divider":
|
|
@@ -5020,14 +5062,14 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5020
5062
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Thickness", value: p.thickness ?? 1, onChange: (n) => set("thickness", n), min: 1, max: 20, step: 1, C }),
|
|
5021
5063
|
/* @__PURE__ */ jsx6(DividerStyleButtons, { value: p.style, onChange: (s) => set("style", s), C }),
|
|
5022
5064
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5023
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5065
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5024
5066
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5025
5067
|
] });
|
|
5026
5068
|
case "spacer":
|
|
5027
5069
|
return /* @__PURE__ */ jsxs4(Fragment4, { children: [
|
|
5028
5070
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Height", value: p.height ?? 24, onChange: (n) => set("height", n), min: 4, max: 300, step: 1, C }),
|
|
5029
5071
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5030
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5072
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5031
5073
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5032
5074
|
] });
|
|
5033
5075
|
case "social":
|
|
@@ -5076,7 +5118,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5076
5118
|
Sel("shape", "Shape", ["circle", "square"]),
|
|
5077
5119
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Gap", value: p.gap ?? 6, onChange: (n) => set("gap", n), min: 0, max: 40, step: 1, C }),
|
|
5078
5120
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5079
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5121
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5080
5122
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5081
5123
|
] });
|
|
5082
5124
|
case "video":
|
|
@@ -5136,7 +5178,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5136
5178
|
] }),
|
|
5137
5179
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Height", value: p.height ?? 280, onChange: (n) => set("height", n), min: 80, max: 720, step: 1, C }),
|
|
5138
5180
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5139
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5181
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5140
5182
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5141
5183
|
] });
|
|
5142
5184
|
case "menu":
|
|
@@ -5162,7 +5204,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5162
5204
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Font size", value: p.fontSize ?? 14, onChange: (n) => set("fontSize", n), min: 8, max: 48, step: 1, C }),
|
|
5163
5205
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Item gap", value: p.gap ?? 20, onChange: (n) => set("gap", n), min: 0, max: 80, step: 1, C }),
|
|
5164
5206
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5165
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5207
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5166
5208
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5167
5209
|
] });
|
|
5168
5210
|
case "timer": {
|
|
@@ -5202,7 +5244,7 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5202
5244
|
/* @__PURE__ */ jsx6(AlignButtons, { value: p.align, onChange: (v) => set("align", v), options: ["left", "center", "right"], C }),
|
|
5203
5245
|
Tog("showLabels", "Show Labels"),
|
|
5204
5246
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "backdrop", p, set, C, onUpload, syncKey: block.id }),
|
|
5205
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5247
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5206
5248
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5207
5249
|
] });
|
|
5208
5250
|
}
|
|
@@ -5299,8 +5341,8 @@ function ContentBlockEditor({ block, onChange, onClose, onUpload, C }) {
|
|
|
5299
5341
|
Tog("striped", "Striped rows"),
|
|
5300
5342
|
/* @__PURE__ */ jsx6(NumRangePx, { label: "Font size", value: p.fontSize ?? 13, onChange: (n) => set("fontSize", n), min: 10, max: 24, step: 1, C }),
|
|
5301
5343
|
/* @__PURE__ */ jsx6(BlockSurfaceBgInspector, { variant: "surface", p, set, C, onUpload, syncKey: block.id }),
|
|
5302
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (
|
|
5303
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { label: "Cell padding", value: p.cellPadding, onChange: (
|
|
5344
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { value: p.padding, onChange: (pad3) => set("padding", pad3), C }),
|
|
5345
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { label: "Cell padding", value: p.cellPadding, onChange: (pad3) => set("cellPadding", pad3), C }),
|
|
5304
5346
|
/* @__PURE__ */ jsx6(MarginEditor, { value: p.margin, onChange: (m) => set("margin", m), C })
|
|
5305
5347
|
] });
|
|
5306
5348
|
case "layout":
|
|
@@ -5693,7 +5735,7 @@ function LayoutRowEditor({
|
|
|
5693
5735
|
}
|
|
5694
5736
|
) })
|
|
5695
5737
|
] }) : null,
|
|
5696
|
-
/* @__PURE__ */ jsx6(PaddingEditor, { label: "Column padding", value: (row.columnStyles || {})[selCol]?.padding, onChange: (
|
|
5738
|
+
/* @__PURE__ */ jsx6(PaddingEditor, { label: "Column padding", value: (row.columnStyles || {})[selCol]?.padding, onChange: (pad3) => updCol(selCol, { padding: pad3 }), C }),
|
|
5697
5739
|
/* @__PURE__ */ jsx6(BorderRadiusEditor, { label: "Column radius", value: (row.columnStyles || {})[selCol]?.borderRadius, onChange: (br) => updCol(selCol, { borderRadius: br }), C })
|
|
5698
5740
|
] })
|
|
5699
5741
|
] })
|
|
@@ -5976,8 +6018,8 @@ function MobilePhoneScaleSlot({ variantKey, children }) {
|
|
|
5976
6018
|
const pw = phone.offsetWidth;
|
|
5977
6019
|
const ph = phone.offsetHeight;
|
|
5978
6020
|
if (cw < 12 || ch < 12 || pw < 12 || ph < 12) return;
|
|
5979
|
-
const
|
|
5980
|
-
const raw = Math.min(1, (cw -
|
|
6021
|
+
const pad3 = 20;
|
|
6022
|
+
const raw = Math.min(1, (cw - pad3) / pw, (ch - pad3) / ph);
|
|
5981
6023
|
const s = Number.isFinite(raw) ? Math.max(0.2, raw) : 1;
|
|
5982
6024
|
setFit({ s, w: pw * s, h: ph * s });
|
|
5983
6025
|
};
|
|
@@ -6847,6 +6889,43 @@ var ReactEmailEditor = forwardRef(
|
|
|
6847
6889
|
}
|
|
6848
6890
|
}
|
|
6849
6891
|
};
|
|
6892
|
+
const insertBlockFromLibrary = (contentType) => {
|
|
6893
|
+
if (!rows.length) return;
|
|
6894
|
+
if (selContentMeta?.inner) {
|
|
6895
|
+
const { rowId, cellIdx, contentIdx, inner } = selContentMeta;
|
|
6896
|
+
dropContent(rowId, cellIdx, {
|
|
6897
|
+
kind: "new",
|
|
6898
|
+
contentType,
|
|
6899
|
+
insertAt: null,
|
|
6900
|
+
nested: { parentBlockIdx: contentIdx, innerCellIdx: inner.cellIdx }
|
|
6901
|
+
});
|
|
6902
|
+
return;
|
|
6903
|
+
}
|
|
6904
|
+
if (selContentMeta?.rowId && typeof selContentMeta.cellIdx === "number" && selContentMeta.cellIdx >= 0) {
|
|
6905
|
+
const r = rows.find((x) => x.id === selContentMeta.rowId);
|
|
6906
|
+
if (r && selContentMeta.cellIdx < r.cells.length) {
|
|
6907
|
+
dropContent(selContentMeta.rowId, selContentMeta.cellIdx, {
|
|
6908
|
+
kind: "new",
|
|
6909
|
+
contentType,
|
|
6910
|
+
insertAt: null
|
|
6911
|
+
});
|
|
6912
|
+
return;
|
|
6913
|
+
}
|
|
6914
|
+
}
|
|
6915
|
+
if (selectedRowId) {
|
|
6916
|
+
const targetRow = rows.find((r) => r.id === selectedRowId);
|
|
6917
|
+
if (targetRow) {
|
|
6918
|
+
dropContent(targetRow.id, 0, {
|
|
6919
|
+
kind: "new",
|
|
6920
|
+
contentType,
|
|
6921
|
+
insertAt: null
|
|
6922
|
+
});
|
|
6923
|
+
return;
|
|
6924
|
+
}
|
|
6925
|
+
}
|
|
6926
|
+
const main = rows[0];
|
|
6927
|
+
dropContent(main.id, 0, { kind: "new", contentType, insertAt: null });
|
|
6928
|
+
};
|
|
6850
6929
|
const deleteContent = (rowId, cellIdx, ci, inner = null) => {
|
|
6851
6930
|
if (!inner) {
|
|
6852
6931
|
mutate((prev) => prev.map((r) => {
|
|
@@ -7443,6 +7522,8 @@ var ReactEmailEditor = forwardRef(
|
|
|
7443
7522
|
if (data.layoutPresetKey) {
|
|
7444
7523
|
const preset = LAYOUT_PRESETS.find((p) => p.key === data.layoutPresetKey);
|
|
7445
7524
|
if (preset) mutate((prev) => [...prev, makeLayoutRow(preset)]);
|
|
7525
|
+
} else if (data.contentType && typeof data.contentType === "string") {
|
|
7526
|
+
insertBlockFromLibrary(data.contentType);
|
|
7446
7527
|
}
|
|
7447
7528
|
} catch {
|
|
7448
7529
|
}
|
|
@@ -7483,6 +7564,21 @@ var ReactEmailEditor = forwardRef(
|
|
|
7483
7564
|
}
|
|
7484
7565
|
return base;
|
|
7485
7566
|
})(),
|
|
7567
|
+
onDragOver: (e) => {
|
|
7568
|
+
e.preventDefault();
|
|
7569
|
+
e.stopPropagation();
|
|
7570
|
+
},
|
|
7571
|
+
onDrop: (e) => {
|
|
7572
|
+
e.preventDefault();
|
|
7573
|
+
e.stopPropagation();
|
|
7574
|
+
try {
|
|
7575
|
+
const data = JSON.parse(e.dataTransfer.getData("application/json") || "{}");
|
|
7576
|
+
if (data.contentType && typeof data.contentType === "string") {
|
|
7577
|
+
insertBlockFromLibrary(data.contentType);
|
|
7578
|
+
}
|
|
7579
|
+
} catch {
|
|
7580
|
+
}
|
|
7581
|
+
},
|
|
7486
7582
|
children: [
|
|
7487
7583
|
rows.length === 0 && /* @__PURE__ */ jsxs9("div", { id: eid("canvas-empty"), style: { padding: "56px 20px", textAlign: "center", color: C.muted, border: `2px dashed ${C.border}`, borderRadius: 7 }, children: [
|
|
7488
7584
|
/* @__PURE__ */ jsx11("div", { style: { fontSize: 30, marginBottom: 10 }, children: "\u2709" }),
|
|
@@ -7694,43 +7790,7 @@ var ReactEmailEditor = forwardRef(
|
|
|
7694
7790
|
onDragStart: (e) => {
|
|
7695
7791
|
e.dataTransfer.setData("application/json", JSON.stringify({ contentType: bt.type }));
|
|
7696
7792
|
},
|
|
7697
|
-
onClick: () =>
|
|
7698
|
-
if (!rows.length) return;
|
|
7699
|
-
if (selContentMeta?.inner) {
|
|
7700
|
-
const { rowId, cellIdx, contentIdx, inner } = selContentMeta;
|
|
7701
|
-
dropContent(rowId, cellIdx, {
|
|
7702
|
-
kind: "new",
|
|
7703
|
-
contentType: bt.type,
|
|
7704
|
-
insertAt: null,
|
|
7705
|
-
nested: { parentBlockIdx: contentIdx, innerCellIdx: inner.cellIdx }
|
|
7706
|
-
});
|
|
7707
|
-
return;
|
|
7708
|
-
}
|
|
7709
|
-
if (selContentMeta?.rowId && typeof selContentMeta.cellIdx === "number" && selContentMeta.cellIdx >= 0) {
|
|
7710
|
-
const r = rows.find((x) => x.id === selContentMeta.rowId);
|
|
7711
|
-
if (r && selContentMeta.cellIdx < r.cells.length) {
|
|
7712
|
-
dropContent(selContentMeta.rowId, selContentMeta.cellIdx, {
|
|
7713
|
-
kind: "new",
|
|
7714
|
-
contentType: bt.type,
|
|
7715
|
-
insertAt: null
|
|
7716
|
-
});
|
|
7717
|
-
return;
|
|
7718
|
-
}
|
|
7719
|
-
}
|
|
7720
|
-
if (selectedRowId) {
|
|
7721
|
-
const targetRow = rows.find((r) => r.id === selectedRowId);
|
|
7722
|
-
if (targetRow) {
|
|
7723
|
-
dropContent(targetRow.id, 0, {
|
|
7724
|
-
kind: "new",
|
|
7725
|
-
contentType: bt.type,
|
|
7726
|
-
insertAt: null
|
|
7727
|
-
});
|
|
7728
|
-
return;
|
|
7729
|
-
}
|
|
7730
|
-
}
|
|
7731
|
-
const main = rows[0];
|
|
7732
|
-
dropContent(main.id, 0, { kind: "new", contentType: bt.type, insertAt: null });
|
|
7733
|
-
},
|
|
7793
|
+
onClick: () => insertBlockFromLibrary(bt.type),
|
|
7734
7794
|
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",
|
|
7735
7795
|
style: {
|
|
7736
7796
|
display: "flex",
|
|
@@ -8101,11 +8161,79 @@ var ReactEmailEditor = forwardRef(
|
|
|
8101
8161
|
);
|
|
8102
8162
|
}
|
|
8103
8163
|
);
|
|
8164
|
+
|
|
8165
|
+
// src/lib/htmlToEmailDesign.ts
|
|
8166
|
+
var pad = (n) => ({ top: n, right: n, bottom: n, left: n });
|
|
8167
|
+
function extractHtmlForDesign(html) {
|
|
8168
|
+
const t = String(html ?? "").trim();
|
|
8169
|
+
if (!t) return "";
|
|
8170
|
+
const head = t.slice(0, 800).toLowerCase();
|
|
8171
|
+
if (!head.includes("<html") && !head.includes("<!doctype")) {
|
|
8172
|
+
return normalizeRichHtmlForStorage(t);
|
|
8173
|
+
}
|
|
8174
|
+
try {
|
|
8175
|
+
const doc = new DOMParser().parseFromString(t, "text/html");
|
|
8176
|
+
const body = doc.body;
|
|
8177
|
+
if (!body) return normalizeRichHtmlForStorage(t);
|
|
8178
|
+
return normalizeRichHtmlForStorage(body.innerHTML);
|
|
8179
|
+
} catch {
|
|
8180
|
+
return normalizeRichHtmlForStorage(t);
|
|
8181
|
+
}
|
|
8182
|
+
}
|
|
8183
|
+
function htmlToEmailDesignTemplate(html) {
|
|
8184
|
+
const inner = extractHtmlForDesign(html);
|
|
8185
|
+
if (!inner) return null;
|
|
8186
|
+
const doc = {
|
|
8187
|
+
type: "email_document",
|
|
8188
|
+
settings: {
|
|
8189
|
+
width: 600,
|
|
8190
|
+
backgroundColor: "#f1f5f9",
|
|
8191
|
+
contentBackgroundColor: "#ffffff",
|
|
8192
|
+
fontFamily: "Arial, Helvetica, sans-serif",
|
|
8193
|
+
lineHeightBase: 1.6,
|
|
8194
|
+
color: "#111827",
|
|
8195
|
+
responsive: true,
|
|
8196
|
+
rtl: false
|
|
8197
|
+
},
|
|
8198
|
+
rows: [
|
|
8199
|
+
{
|
|
8200
|
+
id: "row_html_import",
|
|
8201
|
+
type: "row",
|
|
8202
|
+
layout: { columns: 1, gap: 0, stackOnMobile: true, align: "center" },
|
|
8203
|
+
styles: {
|
|
8204
|
+
backgroundColor: "#ffffff",
|
|
8205
|
+
backgroundRepeat: "no-repeat",
|
|
8206
|
+
backgroundSize: "cover",
|
|
8207
|
+
padding: pad(24),
|
|
8208
|
+
textAlign: "left"
|
|
8209
|
+
},
|
|
8210
|
+
columns: [
|
|
8211
|
+
{
|
|
8212
|
+
id: "col_html_import",
|
|
8213
|
+
layout: { width: "100%", verticalAlign: "top", mobileWidth: "100%" },
|
|
8214
|
+
styles: { padding: pad(0), backgroundColor: "" },
|
|
8215
|
+
blocks: [
|
|
8216
|
+
{
|
|
8217
|
+
id: "block_html_import",
|
|
8218
|
+
type: "html",
|
|
8219
|
+
content: { html: inner },
|
|
8220
|
+
styles: {}
|
|
8221
|
+
}
|
|
8222
|
+
]
|
|
8223
|
+
}
|
|
8224
|
+
]
|
|
8225
|
+
}
|
|
8226
|
+
]
|
|
8227
|
+
};
|
|
8228
|
+
return doc;
|
|
8229
|
+
}
|
|
8104
8230
|
export {
|
|
8105
8231
|
PreviewModal as EmailPreviewModal,
|
|
8106
8232
|
ReactEmailEditor,
|
|
8107
8233
|
base64ToUtf8,
|
|
8108
8234
|
DEVICES as emailPreviewDevices,
|
|
8235
|
+
extractHtmlForDesign,
|
|
8236
|
+
htmlToEmailDesignTemplate,
|
|
8109
8237
|
jsonToHtml,
|
|
8110
8238
|
utf8ToBase64
|
|
8111
8239
|
};
|