react-tailwind-email-editor 0.0.16 → 0.0.18
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/README.md +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +157 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +157 -2
- package/dist/index.mjs.map +1 -1
- package/dist/style.css +21 -0
- package/package.json +17 -8
package/README.md
CHANGED
|
@@ -154,6 +154,7 @@ function App() {
|
|
|
154
154
|
| `templates` | `EmailTemplate[]` | `[]` | Pre-defined templates |
|
|
155
155
|
| `callbacks` | `EditorCallbacks` | `{}` | Event handlers (onExport, onChange, etc.) |
|
|
156
156
|
| `initialState` | `string` | — | Serialized Craft.js state to restore |
|
|
157
|
+
| `initialHtml` | `string` | — | HTML string to parse and load into the editor |
|
|
157
158
|
| `defaultContent` | `ReactNode` | — | Default JSX content for the canvas |
|
|
158
159
|
| `title` | `string` | `'Email Editor'` | Toolbar title |
|
|
159
160
|
| `logo` | `ReactNode` | — | Custom logo element |
|
package/dist/index.d.cts
CHANGED
|
@@ -97,6 +97,8 @@ interface EmailEditorProps {
|
|
|
97
97
|
templates?: EmailTemplate[];
|
|
98
98
|
callbacks?: EditorCallbacks;
|
|
99
99
|
initialState?: string;
|
|
100
|
+
/** HTML string to parse and load into the editor on mount */
|
|
101
|
+
initialHtml?: string;
|
|
100
102
|
defaultContent?: React.ReactNode;
|
|
101
103
|
title?: string;
|
|
102
104
|
logo?: React.ReactNode;
|
package/dist/index.d.ts
CHANGED
|
@@ -97,6 +97,8 @@ interface EmailEditorProps {
|
|
|
97
97
|
templates?: EmailTemplate[];
|
|
98
98
|
callbacks?: EditorCallbacks;
|
|
99
99
|
initialState?: string;
|
|
100
|
+
/** HTML string to parse and load into the editor on mount */
|
|
101
|
+
initialHtml?: string;
|
|
100
102
|
defaultContent?: React.ReactNode;
|
|
101
103
|
title?: string;
|
|
102
104
|
logo?: React.ReactNode;
|
package/dist/index.js
CHANGED
|
@@ -4024,6 +4024,160 @@ var TabsContent = React9__namespace.forwardRef(({ className, ...props }, ref) =>
|
|
|
4024
4024
|
}
|
|
4025
4025
|
));
|
|
4026
4026
|
TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
|
|
4027
|
+
|
|
4028
|
+
// src/lib/htmlImporter.ts
|
|
4029
|
+
var nodeCounter = 0;
|
|
4030
|
+
var generateNodeId = () => {
|
|
4031
|
+
nodeCounter++;
|
|
4032
|
+
return `imported_${nodeCounter}_${Math.random().toString(36).slice(2, 8)}`;
|
|
4033
|
+
};
|
|
4034
|
+
var decodeProps = (encoded) => {
|
|
4035
|
+
try {
|
|
4036
|
+
const json = atob(encoded);
|
|
4037
|
+
const parsed = JSON.parse(json);
|
|
4038
|
+
const { _type, ...props } = parsed;
|
|
4039
|
+
return props;
|
|
4040
|
+
} catch (e) {
|
|
4041
|
+
return null;
|
|
4042
|
+
}
|
|
4043
|
+
};
|
|
4044
|
+
var importHtmlToState = (html) => {
|
|
4045
|
+
nodeCounter = 0;
|
|
4046
|
+
const parser = new DOMParser();
|
|
4047
|
+
const doc = parser.parseFromString(html, "text/html");
|
|
4048
|
+
const componentEls = doc.querySelectorAll("[data-component]");
|
|
4049
|
+
const nodes = {};
|
|
4050
|
+
const childNodeIds = [];
|
|
4051
|
+
const topLevelComponents = [];
|
|
4052
|
+
componentEls.forEach((el) => {
|
|
4053
|
+
let parent = el.parentElement;
|
|
4054
|
+
let isNested = false;
|
|
4055
|
+
while (parent) {
|
|
4056
|
+
if (parent.hasAttribute("data-component")) {
|
|
4057
|
+
isNested = true;
|
|
4058
|
+
break;
|
|
4059
|
+
}
|
|
4060
|
+
parent = parent.parentElement;
|
|
4061
|
+
}
|
|
4062
|
+
if (!isNested) {
|
|
4063
|
+
topLevelComponents.push(el);
|
|
4064
|
+
}
|
|
4065
|
+
});
|
|
4066
|
+
if (topLevelComponents.length === 0) {
|
|
4067
|
+
const rawNodeId = generateNodeId();
|
|
4068
|
+
nodes[rawNodeId] = {
|
|
4069
|
+
type: { resolvedName: "RawHtml" },
|
|
4070
|
+
isCanvas: false,
|
|
4071
|
+
props: { html, padding: 0 },
|
|
4072
|
+
displayName: "RawHtml",
|
|
4073
|
+
custom: {},
|
|
4074
|
+
hidden: false,
|
|
4075
|
+
nodes: [],
|
|
4076
|
+
linkedNodes: {},
|
|
4077
|
+
parent: "ROOT"
|
|
4078
|
+
};
|
|
4079
|
+
childNodeIds.push(rawNodeId);
|
|
4080
|
+
} else {
|
|
4081
|
+
for (const el of topLevelComponents) {
|
|
4082
|
+
const typeName = el.getAttribute("data-component") || "RawHtml";
|
|
4083
|
+
const encodedProps = el.getAttribute("data-props") || "";
|
|
4084
|
+
const props = decodeProps(encodedProps);
|
|
4085
|
+
if (!props) continue;
|
|
4086
|
+
const nodeId = generateNodeId();
|
|
4087
|
+
const isCanvas = typeName === "Container" || typeName === "Paper";
|
|
4088
|
+
const nestedChildren = [];
|
|
4089
|
+
const nestedLinkedNodes = {};
|
|
4090
|
+
if (typeName === "Container") {
|
|
4091
|
+
const nestedEls = el.querySelectorAll(":scope > div > [data-component], :scope [data-component]");
|
|
4092
|
+
nestedEls.forEach((nestedEl) => {
|
|
4093
|
+
let nestedParent = nestedEl.parentElement;
|
|
4094
|
+
let belongsToThis = false;
|
|
4095
|
+
while (nestedParent && nestedParent !== el) {
|
|
4096
|
+
if (nestedParent.hasAttribute("data-component") && nestedParent !== el) {
|
|
4097
|
+
break;
|
|
4098
|
+
}
|
|
4099
|
+
if (nestedParent === el) {
|
|
4100
|
+
belongsToThis = true;
|
|
4101
|
+
}
|
|
4102
|
+
nestedParent = nestedParent.parentElement;
|
|
4103
|
+
}
|
|
4104
|
+
if (nestedParent === el) belongsToThis = true;
|
|
4105
|
+
if (belongsToThis) {
|
|
4106
|
+
const nestedType = nestedEl.getAttribute("data-component") || "RawHtml";
|
|
4107
|
+
const nestedEncoded = nestedEl.getAttribute("data-props") || "";
|
|
4108
|
+
const nestedProps = decodeProps(nestedEncoded);
|
|
4109
|
+
if (nestedProps) {
|
|
4110
|
+
const childId = generateNodeId();
|
|
4111
|
+
nodes[childId] = {
|
|
4112
|
+
type: { resolvedName: nestedType },
|
|
4113
|
+
isCanvas: false,
|
|
4114
|
+
props: nestedProps,
|
|
4115
|
+
displayName: nestedType,
|
|
4116
|
+
custom: {},
|
|
4117
|
+
hidden: false,
|
|
4118
|
+
nodes: [],
|
|
4119
|
+
linkedNodes: {},
|
|
4120
|
+
parent: nodeId
|
|
4121
|
+
};
|
|
4122
|
+
nestedChildren.push(childId);
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
});
|
|
4126
|
+
}
|
|
4127
|
+
if (typeName === "TwoColumn") {
|
|
4128
|
+
const leftId = generateNodeId();
|
|
4129
|
+
const rightId = generateNodeId();
|
|
4130
|
+
nodes[leftId] = {
|
|
4131
|
+
type: { resolvedName: "Container" },
|
|
4132
|
+
isCanvas: true,
|
|
4133
|
+
props: { background: "#f9f9f9", padding: 10 },
|
|
4134
|
+
displayName: "Container",
|
|
4135
|
+
custom: {},
|
|
4136
|
+
hidden: false,
|
|
4137
|
+
nodes: [],
|
|
4138
|
+
linkedNodes: {},
|
|
4139
|
+
parent: nodeId
|
|
4140
|
+
};
|
|
4141
|
+
nodes[rightId] = {
|
|
4142
|
+
type: { resolvedName: "Container" },
|
|
4143
|
+
isCanvas: true,
|
|
4144
|
+
props: { background: "#f9f9f9", padding: 10 },
|
|
4145
|
+
displayName: "Container",
|
|
4146
|
+
custom: {},
|
|
4147
|
+
hidden: false,
|
|
4148
|
+
nodes: [],
|
|
4149
|
+
linkedNodes: {},
|
|
4150
|
+
parent: nodeId
|
|
4151
|
+
};
|
|
4152
|
+
nestedLinkedNodes["left-column"] = leftId;
|
|
4153
|
+
nestedLinkedNodes["right-column"] = rightId;
|
|
4154
|
+
}
|
|
4155
|
+
nodes[nodeId] = {
|
|
4156
|
+
type: { resolvedName: typeName },
|
|
4157
|
+
isCanvas,
|
|
4158
|
+
props,
|
|
4159
|
+
displayName: typeName,
|
|
4160
|
+
custom: {},
|
|
4161
|
+
hidden: false,
|
|
4162
|
+
nodes: nestedChildren,
|
|
4163
|
+
linkedNodes: nestedLinkedNodes,
|
|
4164
|
+
parent: "ROOT"
|
|
4165
|
+
};
|
|
4166
|
+
childNodeIds.push(nodeId);
|
|
4167
|
+
}
|
|
4168
|
+
}
|
|
4169
|
+
nodes["ROOT"] = {
|
|
4170
|
+
type: { resolvedName: "Paper" },
|
|
4171
|
+
isCanvas: true,
|
|
4172
|
+
props: { background: "#ffffff" },
|
|
4173
|
+
displayName: "Paper",
|
|
4174
|
+
custom: {},
|
|
4175
|
+
hidden: false,
|
|
4176
|
+
nodes: childNodeIds,
|
|
4177
|
+
linkedNodes: {}
|
|
4178
|
+
};
|
|
4179
|
+
return JSON.stringify(nodes);
|
|
4180
|
+
};
|
|
4027
4181
|
var Modal = ({
|
|
4028
4182
|
open,
|
|
4029
4183
|
onClose,
|
|
@@ -4725,7 +4879,8 @@ var EmailEditor = ({
|
|
|
4725
4879
|
showToolbox = true,
|
|
4726
4880
|
darkMode = true,
|
|
4727
4881
|
className,
|
|
4728
|
-
style
|
|
4882
|
+
style,
|
|
4883
|
+
initialHtml
|
|
4729
4884
|
}) => {
|
|
4730
4885
|
var _a, _b, _c, _d;
|
|
4731
4886
|
const mergedComponents = React9.useMemo(() => {
|
|
@@ -4843,7 +4998,7 @@ var EmailEditor = ({
|
|
|
4843
4998
|
onClick: () => {
|
|
4844
4999
|
setActiveTab("properties");
|
|
4845
5000
|
},
|
|
4846
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(core.Frame, { data: initialState, children: defaultEmailContent })
|
|
5001
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8", children: initialState ? /* @__PURE__ */ jsxRuntime.jsx(core.Frame, { data: initialState, children: defaultEmailContent }) : initialHtml ? /* @__PURE__ */ jsxRuntime.jsx(core.Frame, { data: importHtmlToState(initialHtml), children: defaultEmailContent }) : /* @__PURE__ */ jsxRuntime.jsx(core.Frame, { children: defaultContent || defaultEmailContent }) })
|
|
4847
5002
|
}
|
|
4848
5003
|
)
|
|
4849
5004
|
}
|