react-tailwind-email-editor 0.0.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/README.md +236 -0
- package/dist/index.d.cts +694 -0
- package/dist/index.d.ts +694 -0
- package/dist/index.js +4679 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4626 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +108 -0
package/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# React Email Editor
|
|
2
|
+
|
|
3
|
+
A professional, fully customizable drag-and-drop email template editor built with React, Craft.js, Tailwind CSS, and shadcn/ui.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🎨 **Dark mode** by default with `dark:` class support
|
|
8
|
+
- 🧩 **16+ built-in components** — Header, Footer, Text, Image, Button, Invoice Table, Countdown, Promo Code, Testimonial, and more
|
|
9
|
+
- 🔌 **Props-based component registry** — add custom blocks via props
|
|
10
|
+
- 🎛️ **Full slot system** — override toolbar, toolbox, settings panel, export/preview dialogs
|
|
11
|
+
- 🎨 **Built-in color customizer** — users can change the primary color at runtime
|
|
12
|
+
- 📱 **Responsive preview** — desktop and mobile preview modes
|
|
13
|
+
- 📤 **HTML export** — generates email-client-compatible HTML with table-based layouts
|
|
14
|
+
- 🏗️ **Single sidebar layout** — components + properties in one left panel via tabs
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# Copy the src/components/editor directory into your project
|
|
20
|
+
cp -r src/components/editor your-project/src/components/editor
|
|
21
|
+
cp src/lib/htmlExporter.ts your-project/src/lib/htmlExporter.ts
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Peer Dependencies
|
|
25
|
+
|
|
26
|
+
Ensure your project has these installed:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install @craftjs/core react react-dom lucide-react tailwindcss tailwind-merge clsx class-variance-authority
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Also requires [shadcn/ui](https://ui.shadcn.com/) components: `button`, `scroll-area`, `tabs`, `accordion`, `dialog`, `dropdown-menu`, `popover`, `label`, `separator`.
|
|
33
|
+
|
|
34
|
+
### Tailwind Config
|
|
35
|
+
|
|
36
|
+
Make sure your `tailwind.config.ts` has `darkMode: ["class"]` and includes the editor path in `content`:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
export default {
|
|
40
|
+
darkMode: ["class"],
|
|
41
|
+
content: [
|
|
42
|
+
"./src/**/*.{ts,tsx}",
|
|
43
|
+
// Include the editor component path
|
|
44
|
+
],
|
|
45
|
+
// ...
|
|
46
|
+
};
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
### Basic
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { EmailEditor } from "@/components/editor";
|
|
55
|
+
|
|
56
|
+
function App() {
|
|
57
|
+
return <EmailEditor />;
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### With Custom Components
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { EmailEditor } from "@/components/editor";
|
|
65
|
+
import { MyCustomBlock } from "./MyCustomBlock";
|
|
66
|
+
import { Puzzle } from "lucide-react";
|
|
67
|
+
|
|
68
|
+
function App() {
|
|
69
|
+
return (
|
|
70
|
+
<EmailEditor
|
|
71
|
+
components={{
|
|
72
|
+
MyCustomBlock: {
|
|
73
|
+
component: MyCustomBlock,
|
|
74
|
+
label: "Custom Block",
|
|
75
|
+
description: "A custom email block",
|
|
76
|
+
icon: Puzzle,
|
|
77
|
+
category: "Custom",
|
|
78
|
+
},
|
|
79
|
+
}}
|
|
80
|
+
/>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Full Customization
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { EmailEditor } from "@/components/editor";
|
|
89
|
+
|
|
90
|
+
function App() {
|
|
91
|
+
return (
|
|
92
|
+
<EmailEditor
|
|
93
|
+
title="Invoice Builder"
|
|
94
|
+
darkMode={true}
|
|
95
|
+
theme={{
|
|
96
|
+
paperWidth: 600,
|
|
97
|
+
paperMinHeight: 800,
|
|
98
|
+
paperBackground: "#ffffff",
|
|
99
|
+
}}
|
|
100
|
+
callbacks={{
|
|
101
|
+
onExport: (html) => console.log("Exported:", html),
|
|
102
|
+
onChange: (state) => localStorage.setItem("draft", state),
|
|
103
|
+
onColorChange: (hsl) => console.log("Primary color:", hsl),
|
|
104
|
+
}}
|
|
105
|
+
templates={[
|
|
106
|
+
{
|
|
107
|
+
id: "welcome",
|
|
108
|
+
name: "Welcome Email",
|
|
109
|
+
description: "Onboarding template",
|
|
110
|
+
data: "{ ... }", // Serialized Craft.js JSON
|
|
111
|
+
},
|
|
112
|
+
]}
|
|
113
|
+
htmlRenderers={{
|
|
114
|
+
MyCustomBlock: (name, props, children) => {
|
|
115
|
+
return `<td style="padding:20px">${children}</td>`;
|
|
116
|
+
},
|
|
117
|
+
}}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Props API
|
|
124
|
+
|
|
125
|
+
| Prop | Type | Default | Description |
|
|
126
|
+
| ----------------- | ------------------------------ | ---------------- | -------------------------------------------------- |
|
|
127
|
+
| `components` | `ComponentRegistry` | `{}` | Additional components merged with built-ins |
|
|
128
|
+
| `replaceBuiltins` | `boolean` | `false` | Replace all built-in components |
|
|
129
|
+
| `theme` | `EditorTheme` | `{}` | Paper width, height, background |
|
|
130
|
+
| `slots` | `EditorSlots` | `{}` | Override toolbar, toolbox, settings panel, dialogs |
|
|
131
|
+
| `templates` | `EmailTemplate[]` | `[]` | Pre-defined templates |
|
|
132
|
+
| `callbacks` | `EditorCallbacks` | `{}` | Event handlers (onExport, onChange, etc.) |
|
|
133
|
+
| `initialState` | `string` | — | Serialized Craft.js state to restore |
|
|
134
|
+
| `defaultContent` | `ReactNode` | — | Default JSX content for the canvas |
|
|
135
|
+
| `title` | `string` | `'Email Editor'` | Toolbar title |
|
|
136
|
+
| `logo` | `ReactNode` | — | Custom logo element |
|
|
137
|
+
| `htmlRenderers` | `Record<string, HtmlRenderer>` | `{}` | Custom HTML renderers for export |
|
|
138
|
+
| `showToolbar` | `boolean` | `true` | Show/hide top toolbar |
|
|
139
|
+
| `showToolbox` | `boolean` | `true` | Show/hide left sidebar |
|
|
140
|
+
| `darkMode` | `boolean` | `true` | Enable dark mode |
|
|
141
|
+
| `className` | `string` | — | Additional CSS class |
|
|
142
|
+
| `style` | `CSSProperties` | — | Inline styles |
|
|
143
|
+
|
|
144
|
+
### Slot Overrides
|
|
145
|
+
|
|
146
|
+
Override any UI section with your own component:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
<EmailEditor
|
|
150
|
+
slots={{
|
|
151
|
+
toolbar: MyToolbar, // Full toolbar replacement
|
|
152
|
+
toolbox: MyToolbox, // Component list replacement
|
|
153
|
+
settingsPanel: MySettings, // Properties panel replacement
|
|
154
|
+
exportDialog: MyExport, // Export dialog content
|
|
155
|
+
previewDialog: MyPreview, // Preview dialog content
|
|
156
|
+
renderNode: MyNodeWrapper, // Custom node wrapper
|
|
157
|
+
}}
|
|
158
|
+
/>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Creating Custom Components
|
|
162
|
+
|
|
163
|
+
Custom components need a `craft` static property for Craft.js:
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import { useNode } from "@craftjs/core";
|
|
167
|
+
|
|
168
|
+
const MyBlock = ({ text = "Hello" }) => {
|
|
169
|
+
const {
|
|
170
|
+
connectors: { connect, drag },
|
|
171
|
+
} = useNode();
|
|
172
|
+
return (
|
|
173
|
+
<div ref={(ref) => connect(drag(ref!))}>
|
|
174
|
+
<p>{text}</p>
|
|
175
|
+
</div>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
const MyBlockSettings = () => {
|
|
180
|
+
const {
|
|
181
|
+
actions: { setProp },
|
|
182
|
+
text,
|
|
183
|
+
} = useNode((node) => ({
|
|
184
|
+
text: node.data.props.text,
|
|
185
|
+
}));
|
|
186
|
+
return (
|
|
187
|
+
<input
|
|
188
|
+
value={text}
|
|
189
|
+
onChange={(e) => setProp((props: any) => (props.text = e.target.value))}
|
|
190
|
+
/>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
MyBlock.craft = {
|
|
195
|
+
props: { text: "Hello" },
|
|
196
|
+
related: { settings: MyBlockSettings },
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Architecture
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
src/components/editor/
|
|
204
|
+
├── EmailEditor.tsx # Main entry point with layout + toolbar
|
|
205
|
+
├── types.ts # All TypeScript interfaces
|
|
206
|
+
├── context.tsx # React context for editor config
|
|
207
|
+
├── defaultComponents.tsx # Built-in component registry
|
|
208
|
+
├── Paper.tsx # Canvas wrapper component
|
|
209
|
+
├── Toolbox.tsx # Component palette (left sidebar)
|
|
210
|
+
├── SettingsPanel.tsx # Properties editor (left sidebar tab)
|
|
211
|
+
├── RenderNode.tsx # Node selection overlay
|
|
212
|
+
├── components/ # All built-in email components
|
|
213
|
+
│ ├── Container.tsx
|
|
214
|
+
│ ├── EmailHeader.tsx
|
|
215
|
+
│ ├── EmailFooter.tsx
|
|
216
|
+
│ ├── TextBlock.tsx
|
|
217
|
+
│ ├── ImageBlock.tsx
|
|
218
|
+
│ ├── EmailButton.tsx
|
|
219
|
+
│ ├── Divider.tsx
|
|
220
|
+
│ ├── Spacer.tsx
|
|
221
|
+
│ ├── TwoColumn.tsx
|
|
222
|
+
│ ├── InvoiceTable.tsx
|
|
223
|
+
│ ├── SocialLinks.tsx
|
|
224
|
+
│ ├── Countdown.tsx
|
|
225
|
+
│ ├── PromoCode.tsx
|
|
226
|
+
│ ├── Testimonial.tsx
|
|
227
|
+
│ ├── VideoPlaceholder.tsx
|
|
228
|
+
│ ├── VariableText.tsx
|
|
229
|
+
│ ├── IconList.tsx
|
|
230
|
+
│ └── index.ts
|
|
231
|
+
└── index.ts # Public barrel export
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
MIT
|