npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-visual-email-editor

v2.0.0

Published

Visual React email editor: JSON design in/out; HTML for preview.

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

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

Quick 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 document
  • utf8ToBase64 / base64ToUtf8 — UTF-8 ↔ base64 (e.g. custom tooling around the HTML design comment)
  • emailEditorThemes, emailPreviewDevices
  • EmailPreviewModal — standalone preview component
  • Types: ReactEmailEditorProps, ReactEmailEditorRef, etc. (see index.d.ts)

License

MIT