@standhigher/react-email-editor 0.3.0 → 0.4.1
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 +35 -0
- package/README.md +24 -131
- package/README.zh-CN.md +24 -131
- package/dist/index.d.ts +355 -37
- package/dist/index.js +378 -298
- package/docs/advanced-examples.md +265 -0
- package/docs/advanced-examples.zh-CN.md +265 -0
- package/docs/api.md +275 -0
- package/docs/api.zh-CN.md +275 -0
- package/docs/assets/architecture.png +0 -0
- package/docs/assets/architecture.svg +84 -0
- package/docs/assets/architecture.zh-CN.png +0 -0
- package/docs/assets/architecture.zh-CN.svg +84 -0
- package/docs/basic-examples.md +113 -0
- package/docs/basic-examples.zh-CN.md +113 -0
- package/docs/custom-blocks.md +27 -31
- package/docs/custom-blocks.zh-CN.md +26 -30
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -31,9 +31,6 @@ var __objRest = (source, exclude) => {
|
|
|
31
31
|
return target;
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
// src/EmailEditor.tsx
|
|
35
|
-
import { forwardRef as forwardRef3 } from "react";
|
|
36
|
-
|
|
37
34
|
// src/plugins/editor-context.ts
|
|
38
35
|
import { createContext, useContext } from "react";
|
|
39
36
|
var RichTextFocusContext = createContext({ active: null, activate: () => {
|
|
@@ -47,7 +44,7 @@ function usePluginEditor() {
|
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
// src/shell/EmailEditorShell.tsx
|
|
50
|
-
import {
|
|
47
|
+
import { useState as useState18 } from "react";
|
|
51
48
|
|
|
52
49
|
// src/editor-dnd/EditorDnd.tsx
|
|
53
50
|
import { useLayoutEffect as useLayoutEffect5, useMemo, useRef as useRef7, useState as useState7 } from "react";
|
|
@@ -2730,13 +2727,13 @@ function bindPluginComponent(Component2) {
|
|
|
2730
2727
|
// src/plugins/controls.ts
|
|
2731
2728
|
import { createElement as createElement2 } from "react";
|
|
2732
2729
|
|
|
2733
|
-
// src/
|
|
2730
|
+
// src/utils/snapshot.ts
|
|
2734
2731
|
import { isValidElement } from "react";
|
|
2735
|
-
function
|
|
2736
|
-
if (Array.isArray(value)) return Object.freeze(value.map((item) =>
|
|
2732
|
+
function snapshotValue(value) {
|
|
2733
|
+
if (Array.isArray(value)) return Object.freeze(value.map((item) => snapshotValue(item)));
|
|
2737
2734
|
if (!value || typeof value !== "object" || isValidElement(value)) return value;
|
|
2738
2735
|
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return value;
|
|
2739
|
-
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key,
|
|
2736
|
+
return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, snapshotValue(item)])));
|
|
2740
2737
|
}
|
|
2741
2738
|
|
|
2742
2739
|
// src/plugins/control-validation.ts
|
|
@@ -2761,10 +2758,10 @@ function controlConstraintError(kind, options, value) {
|
|
|
2761
2758
|
// src/plugins/controls.ts
|
|
2762
2759
|
function buildControl(kind, options, fallback, parse) {
|
|
2763
2760
|
var _b;
|
|
2764
|
-
const _a =
|
|
2761
|
+
const _a = snapshotValue(options), { component: Component2, validate } = _a, config = __objRest(_a, ["component", "validate"]);
|
|
2765
2762
|
const defaultValue = structuredClone((_b = config.defaultValue) != null ? _b : fallback);
|
|
2766
2763
|
const read = (value) => value === void 0 ? structuredClone(defaultValue) : parse(value);
|
|
2767
|
-
return
|
|
2764
|
+
return snapshotValue(__spreadProps(__spreadValues({}, config), {
|
|
2768
2765
|
kind,
|
|
2769
2766
|
defaultValue,
|
|
2770
2767
|
read,
|
|
@@ -2799,8 +2796,8 @@ var EmailControls = {
|
|
|
2799
2796
|
}),
|
|
2800
2797
|
list(options) {
|
|
2801
2798
|
const _a = options, { controls } = _a, config = __objRest(_a, ["controls"]);
|
|
2802
|
-
const schema =
|
|
2803
|
-
return
|
|
2799
|
+
const schema = snapshotValue(controls);
|
|
2800
|
+
return snapshotValue(__spreadProps(__spreadValues({}, buildControl("list", config, [], (value) => Array.isArray(value) ? value.map((item) => readControlValues(schema, item && typeof item === "object" ? item : {})) : [])), { itemControls: schema }));
|
|
2804
2801
|
},
|
|
2805
2802
|
custom(options) {
|
|
2806
2803
|
const _a = options, { read } = _a, config = __objRest(_a, ["read"]);
|
|
@@ -2811,7 +2808,7 @@ var EmailControls = {
|
|
|
2811
2808
|
// src/plugins/define-block.ts
|
|
2812
2809
|
function defineBlock(input) {
|
|
2813
2810
|
var _a, _b, _c;
|
|
2814
|
-
const options =
|
|
2811
|
+
const options = snapshotValue(input);
|
|
2815
2812
|
if (!options.type.trim() || !options.title.trim()) throw new Error("Block type and title are required.");
|
|
2816
2813
|
const schema = (_a = options.controls) != null ? _a : {};
|
|
2817
2814
|
const readControls = (source) => {
|
|
@@ -2824,7 +2821,7 @@ function defineBlock(input) {
|
|
|
2824
2821
|
for (const item of (_b = options.styleControls) != null ? _b : []) styles.set(item.id, item);
|
|
2825
2822
|
const inline = Object.entries(schema).filter(([, spec]) => spec.kind === "richText" && spec.inline);
|
|
2826
2823
|
if (inline.length > 1 && !options.Canvas) throw new Error(`${options.type}: multiple inline controls require a Canvas component.`);
|
|
2827
|
-
return
|
|
2824
|
+
return snapshotValue({
|
|
2828
2825
|
type: options.type,
|
|
2829
2826
|
title: options.title,
|
|
2830
2827
|
description: options.description,
|
|
@@ -4638,8 +4635,10 @@ function renderTemplatePreview(html, defaultData) {
|
|
|
4638
4635
|
}
|
|
4639
4636
|
|
|
4640
4637
|
// src/render/block-html.ts
|
|
4641
|
-
function
|
|
4642
|
-
|
|
4638
|
+
function assertBlockRenderOptions(options) {
|
|
4639
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) {
|
|
4640
|
+
throw new TypeError("Block render options must be an object.");
|
|
4641
|
+
}
|
|
4643
4642
|
}
|
|
4644
4643
|
function renderPreparedBlock(context, definition) {
|
|
4645
4644
|
try {
|
|
@@ -4712,23 +4711,23 @@ function mergeTemplateData(variables, defaultData) {
|
|
|
4712
4711
|
}
|
|
4713
4712
|
function renderBlockContent(node, definitions = DEFAULT_BLOCKS, mode = "email", options = {}) {
|
|
4714
4713
|
var _a;
|
|
4715
|
-
|
|
4714
|
+
assertBlockRenderOptions(options);
|
|
4716
4715
|
const rendered = renderBlock(
|
|
4717
4716
|
node,
|
|
4718
4717
|
definitions,
|
|
4719
4718
|
mode,
|
|
4720
|
-
(_a =
|
|
4719
|
+
(_a = options.body) != null ? _a : DEFAULT_EMAIL_BODY
|
|
4721
4720
|
);
|
|
4722
|
-
return resolveBlockContent(rendered, node,
|
|
4721
|
+
return resolveBlockContent(rendered, node, options);
|
|
4723
4722
|
}
|
|
4724
|
-
function resolveBlockContent(rendered, node,
|
|
4723
|
+
function resolveBlockContent(rendered, node, options) {
|
|
4725
4724
|
var _a, _b;
|
|
4726
|
-
if (!
|
|
4727
|
-
return applyListedVariableDots(rendered, (_a =
|
|
4725
|
+
if (!options.resolveHtmlTemplate) {
|
|
4726
|
+
return applyListedVariableDots(rendered, (_a = options.variables) != null ? _a : []);
|
|
4728
4727
|
}
|
|
4729
4728
|
return renderTemplatePreview(
|
|
4730
4729
|
rendered,
|
|
4731
|
-
(_b =
|
|
4730
|
+
(_b = options.templateData) != null ? _b : node.defaultData
|
|
4732
4731
|
);
|
|
4733
4732
|
}
|
|
4734
4733
|
function renderBlock(node, definitions = DEFAULT_BLOCKS, mode = "email", body = DEFAULT_EMAIL_BODY) {
|
|
@@ -4742,10 +4741,10 @@ function renderBlock(node, definitions = DEFAULT_BLOCKS, mode = "email", body =
|
|
|
4742
4741
|
}
|
|
4743
4742
|
function blockToHtml(node, definitions = DEFAULT_BLOCKS, mode = "email", options = {}) {
|
|
4744
4743
|
var _a, _b, _c;
|
|
4745
|
-
|
|
4746
|
-
const body = (_a =
|
|
4744
|
+
assertBlockRenderOptions(options);
|
|
4745
|
+
const body = (_a = options.body) != null ? _a : DEFAULT_EMAIL_BODY;
|
|
4747
4746
|
const style = resolveBlockStyle(node.style, getBlockDefinition(node.type, definitions));
|
|
4748
|
-
const inner = renderBlockContent(node, definitions, mode, __spreadProps(__spreadValues({},
|
|
4747
|
+
const inner = renderBlockContent(node, definitions, mode, __spreadProps(__spreadValues({}, options), {
|
|
4749
4748
|
body
|
|
4750
4749
|
}));
|
|
4751
4750
|
const height = cssPx((_b = style.dimension) == null ? void 0 : _b.height);
|
|
@@ -4785,8 +4784,8 @@ function HtmlCanvas({ html, baseCss = "", onSelect }) {
|
|
|
4785
4784
|
const frame = frameRef.current;
|
|
4786
4785
|
const document = frame == null ? void 0 : frame.contentDocument;
|
|
4787
4786
|
if (!container || !frame || !(document == null ? void 0 : document.body)) return;
|
|
4788
|
-
const
|
|
4789
|
-
if (!
|
|
4787
|
+
const window2 = document.defaultView;
|
|
4788
|
+
if (!window2) return;
|
|
4790
4789
|
let animationFrame = 0;
|
|
4791
4790
|
const fit = () => {
|
|
4792
4791
|
const availableWidth = container.clientWidth;
|
|
@@ -4798,12 +4797,12 @@ function HtmlCanvas({ html, baseCss = "", onSelect }) {
|
|
|
4798
4797
|
container.style.height = `${contentHeight}px`;
|
|
4799
4798
|
};
|
|
4800
4799
|
const scheduleFit = () => {
|
|
4801
|
-
|
|
4802
|
-
animationFrame =
|
|
4800
|
+
window2.cancelAnimationFrame(animationFrame);
|
|
4801
|
+
animationFrame = window2.requestAnimationFrame(fit);
|
|
4803
4802
|
};
|
|
4804
|
-
const observer = new
|
|
4803
|
+
const observer = new window2.ResizeObserver(scheduleFit);
|
|
4805
4804
|
let previousWidth = container.clientWidth;
|
|
4806
|
-
const containerObserver = new
|
|
4805
|
+
const containerObserver = new window2.ResizeObserver(() => {
|
|
4807
4806
|
if (container.clientWidth === previousWidth) return;
|
|
4808
4807
|
previousWidth = container.clientWidth;
|
|
4809
4808
|
scheduleFit();
|
|
@@ -4816,7 +4815,7 @@ function HtmlCanvas({ html, baseCss = "", onSelect }) {
|
|
|
4816
4815
|
observer.disconnect();
|
|
4817
4816
|
containerObserver.disconnect();
|
|
4818
4817
|
document.removeEventListener("load", scheduleFit, true);
|
|
4819
|
-
|
|
4818
|
+
window2.cancelAnimationFrame(animationFrame);
|
|
4820
4819
|
};
|
|
4821
4820
|
}, []);
|
|
4822
4821
|
useEffect6(() => () => {
|
|
@@ -5420,13 +5419,13 @@ function Stage({
|
|
|
5420
5419
|
] });
|
|
5421
5420
|
}
|
|
5422
5421
|
|
|
5422
|
+
// src/shell/SubjectBar.tsx
|
|
5423
|
+
import { useId as useId13, useRef as useRef15 } from "react";
|
|
5424
|
+
|
|
5423
5425
|
// src/shell/constants.ts
|
|
5424
5426
|
var EMPTY_VARIABLES = [];
|
|
5425
5427
|
var PERSONALIZATION_HINT = "Personalization fields will appear blank if no data is available.";
|
|
5426
5428
|
|
|
5427
|
-
// src/shell/SubjectBar.tsx
|
|
5428
|
-
import { useId as useId13, useRef as useRef15 } from "react";
|
|
5429
|
-
|
|
5430
5429
|
// src/shell/PersonalizationMenu.tsx
|
|
5431
5430
|
import { useEffect as useEffect8, useRef as useRef14, useState as useState16 } from "react";
|
|
5432
5431
|
import { jsx as jsx56, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
@@ -5488,6 +5487,7 @@ function SubjectBar({
|
|
|
5488
5487
|
onSubjectChange
|
|
5489
5488
|
}) {
|
|
5490
5489
|
const inputRef = useRef15(null);
|
|
5490
|
+
const subjectId = useId13();
|
|
5491
5491
|
const countId = useId13();
|
|
5492
5492
|
const insertVariable = (token) => {
|
|
5493
5493
|
var _a, _b;
|
|
@@ -5507,12 +5507,12 @@ function SubjectBar({
|
|
|
5507
5507
|
});
|
|
5508
5508
|
};
|
|
5509
5509
|
return /* @__PURE__ */ jsxs44("div", { className: "ree-subject-bar", children: [
|
|
5510
|
-
/* @__PURE__ */ jsx57("label", { className: "ree-subject-label", htmlFor:
|
|
5510
|
+
/* @__PURE__ */ jsx57("label", { className: "ree-subject-label", htmlFor: subjectId, children: "Email subject" }),
|
|
5511
5511
|
/* @__PURE__ */ jsxs44("div", { className: "ree-subject-field", children: [
|
|
5512
5512
|
/* @__PURE__ */ jsx57(
|
|
5513
5513
|
TextInput,
|
|
5514
5514
|
{
|
|
5515
|
-
id:
|
|
5515
|
+
id: subjectId,
|
|
5516
5516
|
ref: inputRef,
|
|
5517
5517
|
className: "ree-subject-input",
|
|
5518
5518
|
value: subject,
|
|
@@ -5534,6 +5534,9 @@ function SubjectBar({
|
|
|
5534
5534
|
] });
|
|
5535
5535
|
}
|
|
5536
5536
|
|
|
5537
|
+
// src/shell/useEditorSession.ts
|
|
5538
|
+
import { useCallback as useCallback3, useState as useState17, useSyncExternalStore } from "react";
|
|
5539
|
+
|
|
5537
5540
|
// src/utils/id.ts
|
|
5538
5541
|
function generateId(prefix = "block") {
|
|
5539
5542
|
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
@@ -5542,62 +5545,6 @@ function generateId(prefix = "block") {
|
|
|
5542
5545
|
return `${prefix}-${Math.random().toString(36).slice(2, 10)}`;
|
|
5543
5546
|
}
|
|
5544
5547
|
|
|
5545
|
-
// src/document/create-block.ts
|
|
5546
|
-
function createBlockNode(type, definitions) {
|
|
5547
|
-
var _a, _b;
|
|
5548
|
-
const definition = getBlockDefinition(type, definitions);
|
|
5549
|
-
if (!definition) return null;
|
|
5550
|
-
const controls = structuredClone(definition.readControls({}));
|
|
5551
|
-
let style = resolveBlockStyle(definition.defaultStyle, definition);
|
|
5552
|
-
for (const control of (_a = definition.styleControls) != null ? _a : []) {
|
|
5553
|
-
const [group, key] = control.id.split(".");
|
|
5554
|
-
const stored = (_b = definition.defaultStyle) == null ? void 0 : _b[group];
|
|
5555
|
-
if (control.defaultValue !== void 0 && (!stored || !(key in stored))) style = writeStyleValue(style, control.id, control.defaultValue);
|
|
5556
|
-
}
|
|
5557
|
-
return {
|
|
5558
|
-
id: generateId(type),
|
|
5559
|
-
type,
|
|
5560
|
-
controls,
|
|
5561
|
-
style,
|
|
5562
|
-
defaultData: definition.defaultData ? structuredClone(definition.defaultData) : void 0
|
|
5563
|
-
};
|
|
5564
|
-
}
|
|
5565
|
-
|
|
5566
|
-
// src/plugins/config.ts
|
|
5567
|
-
function createEmailEditorConfig(options = {}) {
|
|
5568
|
-
var _a, _b, _c;
|
|
5569
|
-
const definitions = new Map(DEFAULT_BLOCKS.map((block) => [block.type, block]));
|
|
5570
|
-
const customTypes = /* @__PURE__ */ new Set();
|
|
5571
|
-
for (const plugin of (_a = options.plugins) != null ? _a : []) {
|
|
5572
|
-
if (customTypes.has(plugin.type)) throw new Error(`Duplicate block plugin: ${plugin.type}`);
|
|
5573
|
-
if (definitions.has(plugin.type) && !plugin.override) throw new Error(`Block ${plugin.type} already exists. Set override: true to replace it.`);
|
|
5574
|
-
customTypes.add(plugin.type);
|
|
5575
|
-
definitions.set(plugin.type, plugin);
|
|
5576
|
-
}
|
|
5577
|
-
const builtinTypes = new Set(DEFAULT_BLOCKS.map((block) => block.type));
|
|
5578
|
-
const visibleBuiltins = options.builtins === false ? [] : (_b = options.builtins) != null ? _b : [...builtinTypes];
|
|
5579
|
-
if (new Set(visibleBuiltins).size !== visibleBuiltins.length) throw new Error("Duplicate builtin in library order.");
|
|
5580
|
-
for (const type of visibleBuiltins) if (!builtinTypes.has(type)) throw new Error(`Unknown builtin block: ${type}`);
|
|
5581
|
-
const all = Object.freeze([...definitions.values()].map((plugin) => snapshotConfig(plugin)));
|
|
5582
|
-
const registered = new Map(all.map((plugin) => [plugin.type, plugin]));
|
|
5583
|
-
return Object.freeze({
|
|
5584
|
-
definitions: all,
|
|
5585
|
-
library: Object.freeze([...visibleBuiltins.map((type) => registered.get(type)), ...((_c = options.plugins) != null ? _c : []).filter((plugin) => !builtinTypes.has(plugin.type)).map((plugin) => registered.get(plugin.type))]),
|
|
5586
|
-
pickImage: options.pickImage,
|
|
5587
|
-
createBlock: (type) => {
|
|
5588
|
-
const block = createBlockNode(type, all);
|
|
5589
|
-
if (!block) throw new Error(`Unknown block plugin: ${type}`);
|
|
5590
|
-
return block;
|
|
5591
|
-
},
|
|
5592
|
-
toHtml: (document, htmlOptions) => documentToHtml(document, all, htmlOptions),
|
|
5593
|
-
validate: (document) => validateDocument(document, all)
|
|
5594
|
-
});
|
|
5595
|
-
}
|
|
5596
|
-
var DEFAULT_EDITOR_CONFIG = createEmailEditorConfig();
|
|
5597
|
-
|
|
5598
|
-
// src/shell/useEditorSession.ts
|
|
5599
|
-
import { useCallback as useCallback3, useEffect as useEffect9, useLayoutEffect as useLayoutEffect8, useMemo as useMemo5, useRef as useRef16, useState as useState17 } from "react";
|
|
5600
|
-
|
|
5601
5548
|
// src/document/mutations.ts
|
|
5602
5549
|
function moveItem(items, from, to) {
|
|
5603
5550
|
const next = items.slice();
|
|
@@ -5666,68 +5613,215 @@ function updateBodySettings(document, patch) {
|
|
|
5666
5613
|
});
|
|
5667
5614
|
}
|
|
5668
5615
|
|
|
5616
|
+
// src/document/create-block.ts
|
|
5617
|
+
function createBlockNode(type, definitions) {
|
|
5618
|
+
var _a, _b;
|
|
5619
|
+
const definition = getBlockDefinition(type, definitions);
|
|
5620
|
+
if (!definition) return null;
|
|
5621
|
+
const controls = structuredClone(definition.readControls({}));
|
|
5622
|
+
let style = resolveBlockStyle(definition.defaultStyle, definition);
|
|
5623
|
+
for (const control of (_a = definition.styleControls) != null ? _a : []) {
|
|
5624
|
+
const [group, key] = control.id.split(".");
|
|
5625
|
+
const stored = (_b = definition.defaultStyle) == null ? void 0 : _b[group];
|
|
5626
|
+
if (control.defaultValue !== void 0 && (!stored || !(key in stored))) style = writeStyleValue(style, control.id, control.defaultValue);
|
|
5627
|
+
}
|
|
5628
|
+
return {
|
|
5629
|
+
id: generateId(type),
|
|
5630
|
+
type,
|
|
5631
|
+
controls,
|
|
5632
|
+
style,
|
|
5633
|
+
defaultData: definition.defaultData ? structuredClone(definition.defaultData) : void 0
|
|
5634
|
+
};
|
|
5635
|
+
}
|
|
5636
|
+
|
|
5637
|
+
// src/plugins/config.ts
|
|
5638
|
+
function buildEmailEditorConfig(options = {}) {
|
|
5639
|
+
var _a, _b, _c;
|
|
5640
|
+
const definitions = new Map(DEFAULT_BLOCKS.map((block) => [block.type, block]));
|
|
5641
|
+
const customTypes = /* @__PURE__ */ new Set();
|
|
5642
|
+
for (const plugin of (_a = options.plugins) != null ? _a : []) {
|
|
5643
|
+
if (customTypes.has(plugin.type)) throw new Error(`Duplicate block plugin: ${plugin.type}`);
|
|
5644
|
+
if (definitions.has(plugin.type) && !plugin.override) throw new Error(`Block ${plugin.type} already exists. Set override: true to replace it.`);
|
|
5645
|
+
customTypes.add(plugin.type);
|
|
5646
|
+
definitions.set(plugin.type, plugin);
|
|
5647
|
+
}
|
|
5648
|
+
const builtinTypes = new Set(DEFAULT_BLOCKS.map((block) => block.type));
|
|
5649
|
+
const visibleBuiltins = options.builtins === false ? [] : (_b = options.builtins) != null ? _b : [...builtinTypes];
|
|
5650
|
+
if (new Set(visibleBuiltins).size !== visibleBuiltins.length) throw new Error("Duplicate builtin in library order.");
|
|
5651
|
+
for (const type of visibleBuiltins) if (!builtinTypes.has(type)) throw new Error(`Unknown builtin block: ${type}`);
|
|
5652
|
+
const all = Object.freeze([...definitions.values()].map((plugin) => snapshotValue(plugin)));
|
|
5653
|
+
const registered = new Map(all.map((plugin) => [plugin.type, plugin]));
|
|
5654
|
+
return Object.freeze({
|
|
5655
|
+
definitions: all,
|
|
5656
|
+
library: Object.freeze([...visibleBuiltins.map((type) => registered.get(type)), ...((_c = options.plugins) != null ? _c : []).filter((plugin) => !builtinTypes.has(plugin.type)).map((plugin) => registered.get(plugin.type))]),
|
|
5657
|
+
pickImage: options.pickImage,
|
|
5658
|
+
createBlock: (type) => {
|
|
5659
|
+
const block = createBlockNode(type, all);
|
|
5660
|
+
if (!block) throw new Error(`Unknown block plugin: ${type}`);
|
|
5661
|
+
return block;
|
|
5662
|
+
},
|
|
5663
|
+
toHtml: (document, htmlOptions) => documentToHtml(document, all, htmlOptions),
|
|
5664
|
+
validate: (document) => validateDocument(document, all)
|
|
5665
|
+
});
|
|
5666
|
+
}
|
|
5667
|
+
var DEFAULT_EDITOR_CONFIG = buildEmailEditorConfig();
|
|
5668
|
+
|
|
5669
|
+
// src/shell/editor-store.ts
|
|
5670
|
+
var stores = /* @__PURE__ */ new WeakMap();
|
|
5671
|
+
function copyDocument(document) {
|
|
5672
|
+
return ensureEmailDocument(structuredClone(document));
|
|
5673
|
+
}
|
|
5674
|
+
function getEditorStore(editor) {
|
|
5675
|
+
const store = stores.get(editor);
|
|
5676
|
+
if (!store) throw new Error("EmailEditor requires an instance returned by useEmailEditor().");
|
|
5677
|
+
return store;
|
|
5678
|
+
}
|
|
5679
|
+
function createEditorStore(options) {
|
|
5680
|
+
var _a, _b, _c, _d;
|
|
5681
|
+
let callbacks = options;
|
|
5682
|
+
const base = copyDocument((_a = options.initialDocument) != null ? _a : createEmptyDocument());
|
|
5683
|
+
const initial = options.body === void 0 ? base : __spreadProps(__spreadValues({}, base), { body: mergeEmailBody(base.body, options.body) });
|
|
5684
|
+
let snapshot = {
|
|
5685
|
+
document: initial,
|
|
5686
|
+
config: (_b = options.config) != null ? _b : DEFAULT_EDITOR_CONFIG,
|
|
5687
|
+
variables: structuredClone((_c = options.variables) != null ? _c : EMPTY_VARIABLES),
|
|
5688
|
+
resetKey: generateId("session")
|
|
5689
|
+
};
|
|
5690
|
+
let state = snapshotValue({ document: copyDocument(initial) });
|
|
5691
|
+
let bodyKey = JSON.stringify(options.body);
|
|
5692
|
+
let variablesKey = JSON.stringify((_d = options.variables) != null ? _d : EMPTY_VARIABLES);
|
|
5693
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
5694
|
+
const notify = () => listeners.forEach((listener) => listener());
|
|
5695
|
+
let optionsChanged = false;
|
|
5696
|
+
let pendingBodyDocument;
|
|
5697
|
+
const setSnapshot = (next) => {
|
|
5698
|
+
if (next.document !== snapshot.document) state = snapshotValue({ document: copyDocument(next.document) });
|
|
5699
|
+
snapshot = next;
|
|
5700
|
+
};
|
|
5701
|
+
const flushOptions = () => {
|
|
5702
|
+
const shouldNotify = optionsChanged;
|
|
5703
|
+
const document = pendingBodyDocument;
|
|
5704
|
+
const onChange = callbacks.onChange;
|
|
5705
|
+
optionsChanged = false;
|
|
5706
|
+
pendingBodyDocument = void 0;
|
|
5707
|
+
if (shouldNotify) notify();
|
|
5708
|
+
if (document) onChange == null ? void 0 : onChange(copyDocument(document));
|
|
5709
|
+
};
|
|
5710
|
+
const publish = (next) => {
|
|
5711
|
+
setSnapshot(next);
|
|
5712
|
+
notify();
|
|
5713
|
+
};
|
|
5714
|
+
const commit = (document, bodyChange = false) => {
|
|
5715
|
+
var _a2, _b2;
|
|
5716
|
+
flushOptions();
|
|
5717
|
+
if (document === snapshot.document) return;
|
|
5718
|
+
const next = copyDocument(document);
|
|
5719
|
+
publish(__spreadProps(__spreadValues({}, snapshot), { document: next }));
|
|
5720
|
+
(_a2 = callbacks.onChange) == null ? void 0 : _a2.call(callbacks, copyDocument(next));
|
|
5721
|
+
if (bodyChange) (_b2 = callbacks.onBodyChange) == null ? void 0 : _b2.call(callbacks, structuredClone(next.body));
|
|
5722
|
+
};
|
|
5723
|
+
const replace = (document) => {
|
|
5724
|
+
var _a2;
|
|
5725
|
+
flushOptions();
|
|
5726
|
+
const next = copyDocument(document);
|
|
5727
|
+
publish(__spreadProps(__spreadValues({}, snapshot), { document: next, resetKey: generateId("session") }));
|
|
5728
|
+
(_a2 = callbacks.onChange) == null ? void 0 : _a2.call(callbacks, copyDocument(next));
|
|
5729
|
+
};
|
|
5730
|
+
const getDocument = () => copyDocument(snapshot.document);
|
|
5731
|
+
const editor = Object.freeze({
|
|
5732
|
+
getDocument,
|
|
5733
|
+
getJson: () => JSON.stringify(getDocument(), null, 2),
|
|
5734
|
+
getHtml: () => snapshot.config.toHtml(getDocument(), { variables: structuredClone(snapshot.variables) }),
|
|
5735
|
+
getRenderedHtml: () => snapshot.config.toHtml(getDocument(), { variables: structuredClone(snapshot.variables), resolveHtmlTemplates: true }),
|
|
5736
|
+
getData: () => {
|
|
5737
|
+
const document = getDocument();
|
|
5738
|
+
const { config } = snapshot;
|
|
5739
|
+
const variables = structuredClone(snapshot.variables);
|
|
5740
|
+
return {
|
|
5741
|
+
document,
|
|
5742
|
+
json: JSON.stringify(document, null, 2),
|
|
5743
|
+
html: config.toHtml(document, { variables }),
|
|
5744
|
+
renderedHtml: config.toHtml(document, { variables, resolveHtmlTemplates: true })
|
|
5745
|
+
};
|
|
5746
|
+
},
|
|
5747
|
+
setDocument: replace,
|
|
5748
|
+
reset: () => replace(initial),
|
|
5749
|
+
validate: () => snapshot.config.validate(getDocument())
|
|
5750
|
+
});
|
|
5751
|
+
const store = {
|
|
5752
|
+
editor,
|
|
5753
|
+
subscribe: (listener) => {
|
|
5754
|
+
listeners.add(listener);
|
|
5755
|
+
return () => {
|
|
5756
|
+
listeners.delete(listener);
|
|
5757
|
+
};
|
|
5758
|
+
},
|
|
5759
|
+
getSnapshot: () => snapshot,
|
|
5760
|
+
getState: () => state,
|
|
5761
|
+
commit,
|
|
5762
|
+
flushOptions,
|
|
5763
|
+
updateOptions: (nextOptions) => {
|
|
5764
|
+
var _a2, _b2, _c2;
|
|
5765
|
+
callbacks = nextOptions;
|
|
5766
|
+
const nextVariablesKey = JSON.stringify((_a2 = nextOptions.variables) != null ? _a2 : EMPTY_VARIABLES);
|
|
5767
|
+
const nextBodyKey = JSON.stringify(nextOptions.body);
|
|
5768
|
+
let next = snapshot;
|
|
5769
|
+
const config = (_b2 = nextOptions.config) != null ? _b2 : DEFAULT_EDITOR_CONFIG;
|
|
5770
|
+
if (config !== next.config || nextVariablesKey !== variablesKey) {
|
|
5771
|
+
next = __spreadProps(__spreadValues({}, next), { config, variables: structuredClone((_c2 = nextOptions.variables) != null ? _c2 : EMPTY_VARIABLES) });
|
|
5772
|
+
}
|
|
5773
|
+
variablesKey = nextVariablesKey;
|
|
5774
|
+
let bodyChanged = false;
|
|
5775
|
+
if (bodyKey !== nextBodyKey && nextOptions.body !== void 0) {
|
|
5776
|
+
const body = mergeEmailBody(next.document.body, nextOptions.body);
|
|
5777
|
+
bodyChanged = !sameEmailBody(next.document.body, body);
|
|
5778
|
+
if (bodyChanged) next = __spreadProps(__spreadValues({}, next), { document: __spreadProps(__spreadValues({}, next.document), { body }) });
|
|
5779
|
+
}
|
|
5780
|
+
bodyKey = nextBodyKey;
|
|
5781
|
+
if (next !== snapshot) {
|
|
5782
|
+
setSnapshot(next);
|
|
5783
|
+
optionsChanged = true;
|
|
5784
|
+
}
|
|
5785
|
+
if (bodyChanged) pendingBodyDocument = next.document;
|
|
5786
|
+
}
|
|
5787
|
+
};
|
|
5788
|
+
stores.set(editor, store);
|
|
5789
|
+
return store;
|
|
5790
|
+
}
|
|
5791
|
+
|
|
5669
5792
|
// src/shell/useEditorSession.ts
|
|
5670
|
-
function useEditorSession({
|
|
5671
|
-
initialDocument,
|
|
5672
|
-
body,
|
|
5673
|
-
config = DEFAULT_EDITOR_CONFIG,
|
|
5674
|
-
variables = EMPTY_VARIABLES,
|
|
5675
|
-
onChange,
|
|
5676
|
-
onBodyChange
|
|
5677
|
-
}) {
|
|
5793
|
+
function useEditorSession(editor) {
|
|
5678
5794
|
var _a;
|
|
5795
|
+
const store = getEditorStore(editor);
|
|
5796
|
+
const { document, config, variables, resetKey } = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
5679
5797
|
const definitions = config.definitions;
|
|
5680
|
-
const [document, setDocument] = useState17(() => {
|
|
5681
|
-
const base = ensureEmailDocument(
|
|
5682
|
-
structuredClone(initialDocument != null ? initialDocument : createEmptyDocument())
|
|
5683
|
-
);
|
|
5684
|
-
if (body === void 0) return base;
|
|
5685
|
-
return __spreadProps(__spreadValues({}, base), { body: mergeEmailBody(base.body, body) });
|
|
5686
|
-
});
|
|
5687
5798
|
const [selectedId, setSelectedId] = useState17(null);
|
|
5688
|
-
const
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
documentRef.current = next;
|
|
5695
|
-
setDocument(next);
|
|
5696
|
-
onChange == null ? void 0 : onChange(structuredClone(next));
|
|
5697
|
-
},
|
|
5698
|
-
[onChange]
|
|
5699
|
-
);
|
|
5700
|
-
useEffect9(() => {
|
|
5701
|
-
if (body === void 0) return;
|
|
5702
|
-
const current = documentRef.current;
|
|
5703
|
-
const nextBody = mergeEmailBody(current.body, body);
|
|
5704
|
-
if (sameEmailBody(resolveEmailBody(current.body), nextBody)) return;
|
|
5705
|
-
commit(__spreadProps(__spreadValues({}, current), { body: nextBody }));
|
|
5706
|
-
}, [body, commit]);
|
|
5707
|
-
const getDocument = useCallback3(
|
|
5708
|
-
() => ensureEmailDocument(structuredClone(documentRef.current)),
|
|
5709
|
-
[]
|
|
5710
|
-
);
|
|
5799
|
+
const [previousReset, setPreviousReset] = useState17({ editor, resetKey });
|
|
5800
|
+
if (previousReset.editor !== editor || previousReset.resetKey !== resetKey) {
|
|
5801
|
+
setPreviousReset({ editor, resetKey });
|
|
5802
|
+
setSelectedId(null);
|
|
5803
|
+
}
|
|
5804
|
+
const commit = store.commit;
|
|
5711
5805
|
const selectBlock = useCallback3((id) => {
|
|
5712
5806
|
setSelectedId(id);
|
|
5713
5807
|
}, []);
|
|
5714
5808
|
const insertBlock = useCallback3(
|
|
5715
5809
|
(type, index) => {
|
|
5716
|
-
const node =
|
|
5810
|
+
const node = definitions.some((definition) => definition.type === type) ? config.createBlock(type) : null;
|
|
5717
5811
|
if (!node) return false;
|
|
5718
|
-
commit(insertBlockNode(
|
|
5812
|
+
commit(insertBlockNode(store.getSnapshot().document, node, index));
|
|
5719
5813
|
setSelectedId(node.id);
|
|
5720
5814
|
return true;
|
|
5721
5815
|
},
|
|
5722
|
-
[commit, definitions]
|
|
5816
|
+
[commit, definitions, config, store]
|
|
5723
5817
|
);
|
|
5724
5818
|
const updateControls = useCallback3(
|
|
5725
5819
|
(id, patch) => {
|
|
5726
|
-
const current =
|
|
5820
|
+
const current = store.getSnapshot().document;
|
|
5727
5821
|
const next = updateBlockControls(current, id, patch);
|
|
5728
5822
|
if (next !== current) commit(next);
|
|
5729
5823
|
},
|
|
5730
|
-
[commit]
|
|
5824
|
+
[commit, store]
|
|
5731
5825
|
);
|
|
5732
5826
|
const updateControl = useCallback3(
|
|
5733
5827
|
(id, name, value) => updateControls(id, { [name]: value }),
|
|
@@ -5735,58 +5829,56 @@ function useEditorSession({
|
|
|
5735
5829
|
);
|
|
5736
5830
|
const updateStyle = useCallback3(
|
|
5737
5831
|
(id, styleId, value) => {
|
|
5738
|
-
commit(updateBlockStyle(
|
|
5832
|
+
commit(updateBlockStyle(store.getSnapshot().document, id, styleId, value));
|
|
5739
5833
|
},
|
|
5740
|
-
[commit]
|
|
5834
|
+
[commit, store]
|
|
5741
5835
|
);
|
|
5742
5836
|
const updateBody = useCallback3(
|
|
5743
5837
|
(patch) => {
|
|
5744
|
-
const next = updateBodySettings(
|
|
5745
|
-
commit(next);
|
|
5746
|
-
onBodyChange == null ? void 0 : onBodyChange(structuredClone(next.body));
|
|
5838
|
+
const next = updateBodySettings(store.getSnapshot().document, patch);
|
|
5839
|
+
store.commit(next, true);
|
|
5747
5840
|
},
|
|
5748
|
-
[
|
|
5841
|
+
[store]
|
|
5749
5842
|
);
|
|
5750
5843
|
const moveBlock = useCallback3(
|
|
5751
5844
|
(id, direction) => {
|
|
5752
|
-
commit(moveBlockBy(
|
|
5845
|
+
commit(moveBlockBy(store.getSnapshot().document, id, direction));
|
|
5753
5846
|
},
|
|
5754
|
-
[commit]
|
|
5847
|
+
[commit, store]
|
|
5755
5848
|
);
|
|
5756
5849
|
const duplicateBlock = useCallback3(
|
|
5757
5850
|
(id) => {
|
|
5758
|
-
commit(duplicateBlockNode(
|
|
5851
|
+
commit(duplicateBlockNode(store.getSnapshot().document, id));
|
|
5759
5852
|
},
|
|
5760
|
-
[commit]
|
|
5853
|
+
[commit, store]
|
|
5761
5854
|
);
|
|
5762
5855
|
const removeBlock = useCallback3(
|
|
5763
5856
|
(id) => {
|
|
5764
|
-
commit(removeBlockNode(
|
|
5857
|
+
commit(removeBlockNode(store.getSnapshot().document, id));
|
|
5765
5858
|
setSelectedId((current) => current === id ? null : current);
|
|
5766
5859
|
},
|
|
5767
|
-
[commit]
|
|
5860
|
+
[commit, store]
|
|
5768
5861
|
);
|
|
5769
5862
|
const reorderBlocks = useCallback3(
|
|
5770
5863
|
(activeId, overId) => {
|
|
5771
|
-
commit(reorderBlockNodes(
|
|
5864
|
+
commit(reorderBlockNodes(store.getSnapshot().document, activeId, overId));
|
|
5772
5865
|
},
|
|
5773
|
-
[commit]
|
|
5866
|
+
[commit, store]
|
|
5774
5867
|
);
|
|
5775
5868
|
const setSubject = useCallback3(
|
|
5776
5869
|
(subject) => {
|
|
5777
|
-
commit(withSubject(
|
|
5870
|
+
commit(withSubject(store.getSnapshot().document, subject.slice(0, SUBJECT_MAX_LENGTH)));
|
|
5778
5871
|
},
|
|
5779
|
-
[commit]
|
|
5872
|
+
[commit, store]
|
|
5780
5873
|
);
|
|
5781
|
-
const
|
|
5782
|
-
const selectedBlock = (_a = resolvedDocument.blocks.find((block) => block.id === selectedId)) != null ? _a : null;
|
|
5874
|
+
const selectedBlock = (_a = document.blocks.find((block) => block.id === selectedId)) != null ? _a : null;
|
|
5783
5875
|
const selectedDefinition = selectedBlock ? getBlockDefinition(selectedBlock.type, definitions) : void 0;
|
|
5784
|
-
return {
|
|
5785
|
-
document
|
|
5786
|
-
getDocument,
|
|
5876
|
+
return __spreadProps(__spreadValues({}, editor), {
|
|
5877
|
+
document,
|
|
5787
5878
|
definitions,
|
|
5788
5879
|
config,
|
|
5789
5880
|
variables,
|
|
5881
|
+
resetKey,
|
|
5790
5882
|
selectedId,
|
|
5791
5883
|
selectedBlock,
|
|
5792
5884
|
selectedDefinition,
|
|
@@ -5801,158 +5893,144 @@ function useEditorSession({
|
|
|
5801
5893
|
removeBlock,
|
|
5802
5894
|
reorderBlocks,
|
|
5803
5895
|
setSubject
|
|
5804
|
-
};
|
|
5805
|
-
}
|
|
5806
|
-
|
|
5807
|
-
// src/shell/useEditorHandle.ts
|
|
5808
|
-
import { useImperativeHandle } from "react";
|
|
5809
|
-
function useEditorHandle(ref, { getDocument, definitions, variables }) {
|
|
5810
|
-
useImperativeHandle(ref, () => ({
|
|
5811
|
-
getData: () => {
|
|
5812
|
-
const document = getDocument();
|
|
5813
|
-
return {
|
|
5814
|
-
document,
|
|
5815
|
-
json: JSON.stringify(document, null, 2),
|
|
5816
|
-
html: documentToHtml(document, definitions, { variables }),
|
|
5817
|
-
renderedHtml: documentToHtml(document, definitions, {
|
|
5818
|
-
resolveHtmlTemplates: true,
|
|
5819
|
-
variables
|
|
5820
|
-
})
|
|
5821
|
-
};
|
|
5822
|
-
},
|
|
5823
|
-
getDocument,
|
|
5824
|
-
getJson: () => JSON.stringify(getDocument(), null, 2),
|
|
5825
|
-
getHtml: () => documentToHtml(getDocument(), definitions, { variables }),
|
|
5826
|
-
getRenderedHtml: () => documentToHtml(getDocument(), definitions, {
|
|
5827
|
-
resolveHtmlTemplates: true,
|
|
5828
|
-
variables
|
|
5829
|
-
})
|
|
5830
|
-
}), [getDocument, definitions, variables]);
|
|
5896
|
+
});
|
|
5831
5897
|
}
|
|
5832
5898
|
|
|
5833
5899
|
// src/shell/EmailEditorShell.tsx
|
|
5834
5900
|
import { jsx as jsx58, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
|
|
5858
|
-
|
|
5859
|
-
const [previousSelectedId, setPreviousSelectedId] = useState18(session.selectedId);
|
|
5860
|
-
if (previousSelectedId !== session.selectedId) {
|
|
5861
|
-
setPreviousSelectedId(session.selectedId);
|
|
5862
|
-
if (!session.selectedId) setInspectorPanel("body");
|
|
5901
|
+
function EmailEditorShell({ editor, height = "100%" }) {
|
|
5902
|
+
var _a;
|
|
5903
|
+
const session = useEditorSession(editor);
|
|
5904
|
+
const [activeRichText, setActiveRichText] = useState18(null);
|
|
5905
|
+
const [viewMode, setViewMode] = useState18("edit");
|
|
5906
|
+
const [device, setDevice] = useState18("desktop");
|
|
5907
|
+
const [inspectorPanel, setInspectorPanel] = useState18("body");
|
|
5908
|
+
const [previousReset, setPreviousReset] = useState18({ editor, key: session.resetKey });
|
|
5909
|
+
if (previousReset.editor !== editor || previousReset.key !== session.resetKey) {
|
|
5910
|
+
setPreviousReset({ editor, key: session.resetKey });
|
|
5911
|
+
setActiveRichText(null);
|
|
5912
|
+
setInspectorPanel("body");
|
|
5913
|
+
}
|
|
5914
|
+
const [previousSelectedId, setPreviousSelectedId] = useState18(session.selectedId);
|
|
5915
|
+
if (previousSelectedId !== session.selectedId) {
|
|
5916
|
+
setPreviousSelectedId(session.selectedId);
|
|
5917
|
+
if (!session.selectedId) setInspectorPanel("body");
|
|
5918
|
+
}
|
|
5919
|
+
const selectBlock = (id) => {
|
|
5920
|
+
const hadSelection = session.selectedId !== null;
|
|
5921
|
+
session.selectBlock(id);
|
|
5922
|
+
if (!id) {
|
|
5923
|
+
setInspectorPanel("body");
|
|
5924
|
+
return;
|
|
5863
5925
|
}
|
|
5864
|
-
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
}
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5926
|
+
if (!hadSelection) setInspectorPanel("block");
|
|
5927
|
+
};
|
|
5928
|
+
const handleKeyDown = (event) => {
|
|
5929
|
+
if (event.key !== "Escape") return;
|
|
5930
|
+
const target = event.target;
|
|
5931
|
+
const tag = target == null ? void 0 : target.tagName;
|
|
5932
|
+
if ((target == null ? void 0 : target.isContentEditable) || tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") {
|
|
5933
|
+
return;
|
|
5934
|
+
}
|
|
5935
|
+
selectBlock(null);
|
|
5936
|
+
};
|
|
5937
|
+
const showCanvas = () => setViewMode("edit");
|
|
5938
|
+
return /* @__PURE__ */ jsx58(EditorConfigContext.Provider, { value: session.config, children: /* @__PURE__ */ jsx58(RichTextFocusContext.Provider, { value: { active: activeRichText, activate: setActiveRichText }, children: /* @__PURE__ */ jsxs45("div", { className: "ree-root", style: { height }, onKeyDown: handleKeyDown, children: [
|
|
5939
|
+
/* @__PURE__ */ jsx58(
|
|
5940
|
+
SubjectBar,
|
|
5941
|
+
{
|
|
5942
|
+
subject: (_a = session.document.subject) != null ? _a : "",
|
|
5943
|
+
variables: session.variables,
|
|
5944
|
+
onSubjectChange: session.setSubject
|
|
5879
5945
|
}
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5946
|
+
),
|
|
5947
|
+
/* @__PURE__ */ jsxs45("div", { className: "ree-body", children: [
|
|
5948
|
+
/* @__PURE__ */ jsxs45(
|
|
5949
|
+
EditorDnd,
|
|
5950
|
+
{
|
|
5951
|
+
blocks: session.document.blocks,
|
|
5952
|
+
definitions: session.definitions,
|
|
5953
|
+
onInsertBlock: (type, index) => {
|
|
5954
|
+
showCanvas();
|
|
5955
|
+
if (session.insertBlock(type, index)) setInspectorPanel("block");
|
|
5956
|
+
},
|
|
5957
|
+
onReorder: session.reorderBlocks,
|
|
5958
|
+
onLibraryDragStart: showCanvas,
|
|
5959
|
+
children: [
|
|
5960
|
+
/* @__PURE__ */ jsx58(
|
|
5961
|
+
BlockLibrary,
|
|
5962
|
+
{
|
|
5963
|
+
definitions: session.config.library,
|
|
5964
|
+
onAdd: (type) => {
|
|
5965
|
+
showCanvas();
|
|
5966
|
+
if (session.insertBlock(type)) setInspectorPanel("block");
|
|
5967
|
+
}
|
|
5968
|
+
}
|
|
5969
|
+
),
|
|
5970
|
+
/* @__PURE__ */ jsx58(
|
|
5971
|
+
Stage,
|
|
5972
|
+
{
|
|
5973
|
+
session,
|
|
5974
|
+
viewMode,
|
|
5975
|
+
device,
|
|
5976
|
+
onViewModeChange: setViewMode,
|
|
5977
|
+
onDeviceChange: setDevice,
|
|
5978
|
+
onSelectBlock: selectBlock
|
|
5979
|
+
}
|
|
5980
|
+
)
|
|
5981
|
+
]
|
|
5982
|
+
}
|
|
5983
|
+
),
|
|
5884
5984
|
/* @__PURE__ */ jsx58(
|
|
5885
|
-
|
|
5985
|
+
Inspector,
|
|
5886
5986
|
{
|
|
5887
|
-
|
|
5987
|
+
panel: inspectorPanel,
|
|
5988
|
+
body: session.document.body,
|
|
5989
|
+
block: session.selectedBlock,
|
|
5990
|
+
definition: session.selectedDefinition,
|
|
5888
5991
|
variables: session.variables,
|
|
5889
|
-
|
|
5992
|
+
onPanelChange: setInspectorPanel,
|
|
5993
|
+
onCommitBody: session.updateBody,
|
|
5994
|
+
onCommitControl: session.updateControl,
|
|
5995
|
+
onCommitControls: session.updateControls,
|
|
5996
|
+
onCommitStyle: session.updateStyle
|
|
5890
5997
|
}
|
|
5891
|
-
)
|
|
5892
|
-
|
|
5893
|
-
|
|
5894
|
-
|
|
5895
|
-
{
|
|
5896
|
-
blocks: session.document.blocks,
|
|
5897
|
-
definitions: session.definitions,
|
|
5898
|
-
onInsertBlock: (type, index) => {
|
|
5899
|
-
showCanvas();
|
|
5900
|
-
if (session.insertBlock(type, index)) setInspectorPanel("block");
|
|
5901
|
-
},
|
|
5902
|
-
onReorder: session.reorderBlocks,
|
|
5903
|
-
onLibraryDragStart: showCanvas,
|
|
5904
|
-
children: [
|
|
5905
|
-
/* @__PURE__ */ jsx58(
|
|
5906
|
-
BlockLibrary,
|
|
5907
|
-
{
|
|
5908
|
-
definitions: session.config.library,
|
|
5909
|
-
onAdd: (type) => {
|
|
5910
|
-
showCanvas();
|
|
5911
|
-
if (session.insertBlock(type)) setInspectorPanel("block");
|
|
5912
|
-
}
|
|
5913
|
-
}
|
|
5914
|
-
),
|
|
5915
|
-
/* @__PURE__ */ jsx58(
|
|
5916
|
-
Stage,
|
|
5917
|
-
{
|
|
5918
|
-
session,
|
|
5919
|
-
viewMode,
|
|
5920
|
-
device,
|
|
5921
|
-
onViewModeChange: setViewMode,
|
|
5922
|
-
onDeviceChange: setDevice,
|
|
5923
|
-
onSelectBlock: selectBlock
|
|
5924
|
-
}
|
|
5925
|
-
)
|
|
5926
|
-
]
|
|
5927
|
-
}
|
|
5928
|
-
),
|
|
5929
|
-
/* @__PURE__ */ jsx58(
|
|
5930
|
-
Inspector,
|
|
5931
|
-
{
|
|
5932
|
-
panel: inspectorPanel,
|
|
5933
|
-
body: session.document.body,
|
|
5934
|
-
block: session.selectedBlock,
|
|
5935
|
-
definition: session.selectedDefinition,
|
|
5936
|
-
variables: session.variables,
|
|
5937
|
-
onPanelChange: setInspectorPanel,
|
|
5938
|
-
onCommitBody: session.updateBody,
|
|
5939
|
-
onCommitControl: session.updateControl,
|
|
5940
|
-
onCommitControls: session.updateControls,
|
|
5941
|
-
onCommitStyle: session.updateStyle
|
|
5942
|
-
}
|
|
5943
|
-
)
|
|
5944
|
-
] })
|
|
5945
|
-
] }) }) });
|
|
5946
|
-
}
|
|
5947
|
-
);
|
|
5998
|
+
)
|
|
5999
|
+
] })
|
|
6000
|
+
] }, session.resetKey) }) });
|
|
6001
|
+
}
|
|
5948
6002
|
|
|
5949
6003
|
// src/EmailEditor.tsx
|
|
5950
6004
|
import { jsx as jsx59 } from "react/jsx-runtime";
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
6005
|
+
function EmailEditor(props) {
|
|
6006
|
+
return /* @__PURE__ */ jsx59(EmailEditorShell, __spreadValues({}, props));
|
|
6007
|
+
}
|
|
6008
|
+
|
|
6009
|
+
// src/plugins/useEmailEditorConfig.ts
|
|
6010
|
+
import { useMemo as useMemo5 } from "react";
|
|
6011
|
+
function useEmailEditorConfig(options = {}) {
|
|
6012
|
+
const { plugins, builtins, pickImage } = options;
|
|
6013
|
+
return useMemo5(() => buildEmailEditorConfig({ plugins, builtins, pickImage }), [plugins, builtins, pickImage]);
|
|
6014
|
+
}
|
|
6015
|
+
|
|
6016
|
+
// src/shell/useEmailEditor.ts
|
|
6017
|
+
import { useEffect as useEffect9, useInsertionEffect, useLayoutEffect as useLayoutEffect8, useState as useState19 } from "react";
|
|
6018
|
+
var useOptionsEffect = typeof window === "undefined" ? useEffect9 : useLayoutEffect8;
|
|
6019
|
+
function useEmailEditor(options = {}) {
|
|
6020
|
+
const [store] = useState19(() => createEditorStore(options));
|
|
6021
|
+
useInsertionEffect(() => {
|
|
6022
|
+
store.updateOptions(options);
|
|
6023
|
+
});
|
|
6024
|
+
useOptionsEffect(store.flushOptions);
|
|
6025
|
+
return store.editor;
|
|
6026
|
+
}
|
|
6027
|
+
|
|
6028
|
+
// src/shell/useEmailEditorState.ts
|
|
6029
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
6030
|
+
function useEmailEditorState(editor) {
|
|
6031
|
+
const store = getEditorStore(editor);
|
|
6032
|
+
return useSyncExternalStore2(store.subscribe, store.getState, store.getState);
|
|
6033
|
+
}
|
|
5956
6034
|
|
|
5957
6035
|
// src/plugins/components/ControlEditor.tsx
|
|
5958
6036
|
import { jsx as jsx60 } from "react/jsx-runtime";
|
|
@@ -5991,7 +6069,6 @@ export {
|
|
|
5991
6069
|
createDecorationControls,
|
|
5992
6070
|
createDimensionControls,
|
|
5993
6071
|
createEmailDocument,
|
|
5994
|
-
createEmailEditorConfig,
|
|
5995
6072
|
createTypographyControls,
|
|
5996
6073
|
defineBlock,
|
|
5997
6074
|
documentToHtml,
|
|
@@ -6002,5 +6079,8 @@ export {
|
|
|
6002
6079
|
renderBlockContent,
|
|
6003
6080
|
renderTemplatePreview,
|
|
6004
6081
|
resolveEmailBody,
|
|
6082
|
+
useEmailEditor,
|
|
6083
|
+
useEmailEditorConfig,
|
|
6084
|
+
useEmailEditorState,
|
|
6005
6085
|
variablesToTemplateData
|
|
6006
6086
|
};
|