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 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