react-visual-email-editor
v2.0.0
Published
Visual React email editor: JSON design in/out; HTML for preview.
Maintainers
Readme
react-visual-email-editor
Visual drag-and-drop email editor for React. Edit a JSON document (rows + settings), preview in the UI, and turn the same JSON into HTML for sending or archiving.
Install
npm install react-visual-email-editorPeer dependencies
The editor expects these in your app (they are not bundled):
| Package | Version |
|--------|---------|
| react | ^18 or ^19 |
| react-dom | ^18 or ^19 |
| lucide-react | ≥ 0.4 |
| @tiptap/react | ^3 |
| @tiptap/starter-kit | ^3 |
| @tiptap/core | ^3 |
| @tiptap/extension-link | ^3 |
| @tiptap/extension-placeholder | ^3 |
| @tiptap/extension-text-align | ^3 |
| @tiptap/extension-text-style | ^3 |
| @tiptap/extension-underline | ^3 |
Example one-liner after installing the main package:
npm install lucide-react @tiptap/react @tiptap/starter-kit @tiptap/core @tiptap/extension-link @tiptap/extension-placeholder @tiptap/extension-text-align @tiptap/extension-text-style @tiptap/extension-underlineQuick start
import { useRef } from "react";
import {
ReactEmailEditor,
type ReactEmailEditorRef,
} from "react-visual-email-editor";
export function App() {
const editorRef = useRef<ReactEmailEditorRef>(null);
return (
<>
<button
type="button"
onClick={() =>
editorRef.current?.exportJson((json) => {
console.log(json);
})
}
>
Export JSON
</button>
<ReactEmailEditor ref={editorRef} minHeight="100vh" />
</>
);
}Imperative API (ref)
Use ReactEmailEditorRef for JSON in/out only. HTML — use jsonToHtml (see below). Preview is opened from the editor toolbar, not the ref.
| Method | Description |
|--------|-------------|
| loadJson(input) | Load a design from a JSON string or object ({ rows, settings } or supported mail-page JSON). |
| exportJson(callback, pretty?) | Calls callback with the JSON string ({ rows, settings }). |
onLoad and onReady receive the same API instance once the editor has mounted.
HTML from JSON
import { jsonToHtml } from "react-visual-email-editor";
// From a design object or a JSON string (e.g. from `exportJson` / storage)
const htmlDoc = jsonToHtml(designOrJsonString, options);ReactEmailEditor props
| Prop | Type | Description |
|------|------|-------------|
| ref | ReactEmailEditorRef | Imperative API (see above). |
| minHeight | string | CSS min-height of the shell (default "100vh"). |
| editorId | string | Prefix for DOM ids (default "email-editor"). |
| style | CSSProperties | Extra styles on the root element. |
| options | object | See Options below. |
| templates | Template[] | Optional list for the templates drawer. |
| hideTemplates | boolean | Hide templates UI entirely. |
| onLoad | (api) => void | Fires when the editor mounts. |
| onReady | (api) => void | Fires when ready (same timing as onLoad in practice). |
| onUpload | (file: File) => Promise<string> | Image upload handler; return a public URL. |
Template: { name: string; design: { rows: unknown[]; settings?: object }; thumbnail?: string }
Options (options prop)
| Key | Purpose |
|-----|---------|
| appearance.theme | "light" | "dark" (and deprecated aliases). |
| appearance.colors | Partial override of theme tokens (borders, accent, etc.). |
| appearance.customThemes | Extra named palettes merged into the theme map. |
| locale | UI language key, e.g. "en", "fr", "de", "es". |
| mergeTags | { name: string; value: string }[] for merge-tag inserts. |
| features.autoSave | { enabled?: boolean; interval?: number } — shows a short “auto-saved” hint. |
| tools | Per-block toggles, e.g. { image: { enabled: false } } to hide a block from the palette. |
| fonts | { name: string }[] — listed under Settings. |
| blockLibrary.groupHeadings.blocks | Optional title above block groups in the sidebar. |
| blockLibrary.paletteGroupLabels | Override group labels (text, structure, media, actions, widgets). |
Example:
<ReactEmailEditor
ref={editorRef}
options={{
appearance: { theme: "light" },
locale: "en",
features: { autoSave: { enabled: true, interval: 3000 } },
}}
templates={[
{
name: "Welcome",
thumbnail: "https://example.com/thumb.png",
design: { rows: [/* ... */], settings: { contentWidth: 600 } },
},
]}
onUpload={async (file) => {
const url = await uploadToYourBackend(file);
return url;
}}
/>Other exports
jsonToHtml— design object or JSON string → HTML documentutf8ToBase64/base64ToUtf8— UTF-8 ↔ base64 (e.g. custom tooling around the HTML design comment)emailEditorThemes,emailPreviewDevicesEmailPreviewModal— standalone preview component- Types:
ReactEmailEditorProps,ReactEmailEditorRef, etc. (seeindex.d.ts)
License
MIT
