react-email-studio 3.3.1 → 3.8.0

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/CHANGELOG.md CHANGED
@@ -5,12 +5,90 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [3.8.0] - 2026-05-15
9
+
10
+ ### Changed
11
+
12
+ - **Export shape (restored)**: `exportJson` / `designToEmailDocument` again emit **`rows[]`** with **`columns[].blocks[]`** — the LMS / studio interchange format. Each row includes **`styles`**, block **`props`**, and **`_reactEmailStudio.row`** (preset, ratios, column props).
13
+ - **Settings export**: writes **`settings._reactEmailStudio`** (`contentPadding`, `contentBorderRadius`, `editorSettings` snapshot) plus top-level **`contentPadding`** / **`contentBorderRadius`**.
14
+ - **New blocks from palette**: content blocks are added as **new root sections** (one row each), not dropped into the first layout column.
15
+
16
+ ### Added
17
+
18
+ - **`loadJson(design, { mode: 'replace' | 'append' })`** — append merges imported rows/blocks onto the canvas.
19
+ - **`canonicalizeEmailDocument(input)`** — normalize any supported input to export-shaped `email_document` JSON.
20
+ - **Section reorder**: left **⋮⋮** drag handle, larger row drop zones, and **Move section up/down** in the row inspector.
21
+
22
+ ### Fixed
23
+
24
+ - **Root section order**: row drag-and-drop and move actions update canvas order (and exported `rows[]` order).
25
+ - **Rich HTML**: text color in the toolbar; bullet/numbered lists in canvas, preview, and exported HTML (`email-rich-html-content` styles).
26
+
27
+ ### Notes for integrators
28
+
29
+ - **Import**: still accepts **`blocks[]`**, legacy **`rows[]`**, **`styles`**, and **`_reactEmailStudio`**.
30
+ - If you briefly integrated against **3.7.0** `blocks[]`-only export, use **`rows[]`** + **`_reactEmailStudio`** again — that is the primary export in **3.8.0**.
31
+
32
+ ## [3.7.0] - 2026-05-15
33
+
34
+ ### Changed
35
+
36
+ - **Export shape**: `exportJson` / `designToEmailDocument` emit a flat root **`blocks[]`** instead of **`rows[]`**. Each canvas row becomes a root **`layout`** block; a row with a single content block exports that block directly at the root.
37
+ - **Settings**: **`contentPadding`** and **`contentBorderRadius`** are top-level `settings` fields. **`_reactEmailStudio` is no longer written** on export (including `settings._reactEmailStudio` and `editorSettings` snapshots).
38
+ - **`loadJson`**: optional second argument `{ mode: 'replace' | 'append' }` — append merges blocks/rows onto the canvas. Accepts `{ "blocks": [...] }` fragments and raw block arrays.
39
+
40
+ ### Notes for integrators
41
+
42
+ - **Import**: legacy JSON with **`rows[]`**, **`styles`**, and **`_reactEmailStudio`** still loads.
43
+ - **Breaking**: consumers reading **`rows`** or **`_reactEmailStudio`** from export must switch to **`blocks`** and top-level **`settings`**.
44
+
45
+ ## [3.6.0] - 2026-05-15
46
+
47
+ ### Changed
48
+
49
+ - **Column layout**: per-column surface styling uses **`columns: [{ props }]`** instead of **`columnStyles`** maps (rows, nested layouts, and `email_document` columns). Legacy `columnStyles` / column `styles` still import via `columnProps` helpers.
50
+
51
+ ### Notes for integrators
52
+
53
+ - **Row export**: **`exportJson` / `designToEmailDocument`** no longer write **`_reactEmailStudio.row`** on each row. Row shell uses **`props`** (editor field names: `bgColor`, `padding`, …), not **`styles`**. Column surfaces use **`columns[].props`**. Optional **`layout.preset`** / **`layout.ratios`**. Legacy **`styles`** / **`_reactEmailStudio.row`** still import.
54
+
55
+ ## [3.5.0] - 2026-05-15
56
+
57
+ ### Added
58
+
59
+ - **`htmlToJson(html, pretty?)`**: convert an HTML fragment or full page document into an `email_document` JSON string (one row, one column, single **html** block) — suitable for `loadJson` or storage.
60
+ - **`htmlToEmailDesignTemplate(html)`** and **`extractHtmlForDesign(html)`**: object and extraction helpers used by `htmlToJson`.
61
+ - **`ReactEmailEditor.htmlToJson`**: static method on the component (same implementation as the standalone export).
62
+
63
+ ### Changed
64
+
65
+ - **Rich HTML blocks (`type: "html"`)**: body markup lives on the block root as a **string** `content` field; typography and chrome stay in **`props`** (not `props.content` in exported JSON).
66
+ - **`exportJson` / `designToEmailDocument`**: styling is carried in **`props`** only (blocks, rows, columns) — no **`styles`** on export. Legacy **`styles`** still import.
67
+ - **`BlockBase.content`**: typed as `Record<string, unknown> | string` so `html` blocks can use a plain string at the root.
68
+
69
+ ### Notes for integrators
70
+
71
+ - **Export shape (blocks)**: `{ id, type, content?, props }` — no block `styles`. Example **html** block: `"content": "<p>…</p>"` plus `props` for `fontSize`, `padding`, backgrounds, etc.
72
+ - **Import**: legacy JSON with block `content` objects and/or `styles` still loads; `props` wins when present.
73
+ - **HTML → editor**: `loadJson(htmlToJson(paste))` or `loadJson(htmlToEmailDesignTemplate(paste))`.
74
+ - **HTML ← editor**: `jsonToHtml(exportJson)` unchanged.
75
+
76
+ ## [3.4.0] - 2026-05-08
77
+
78
+ ### Added
79
+
80
+ - **`ReactEmailEditor.jsonToHtml(json, opts?)`**: static method on the component for converting a saved design (object or JSON string) to a full HTML email document — same implementation as the standalone `jsonToHtml` export, no extra setup needed.
81
+
82
+ ### Changed
83
+
84
+ - **Empty cell drop affordance**: the "Drop here" strip is now a fixed **45px** tall row (top-level + nested columns) instead of a tall column, making compact layouts easier to scan and drop into.
85
+
8
86
  ## [3.1.1] - 2026-04-30
9
87
 
10
88
  ### Added
11
89
 
12
90
  - **Loading state for `loadJson`**: `ReactEmailEditor` shows a full-workspace overlay (spinner + localized “Loading design…”) while a design JSON is applied, including invalid-parse early exit.
13
- - **Lossless studio JSON**: document `settings._reactEmailStudio.editorSettings` stores a snapshot of editor settings; each row may include `_reactEmailStudio.row` (row fields without `cells`) for presets, ratios, `columnStyles`, etc.
91
+ - **Lossless studio JSON**: document `settings._reactEmailStudio.editorSettings` stores a snapshot of editor settings. Row layout metadata is carried on **`layout`** (`preset`, `ratios`, …); legacy imports may still supply **`_reactEmailStudio.row`**.
14
92
  - **i18n**: `loadingDesign` string in `en`, `fr`, `de`, `es`.
15
93
 
16
94
  ### Fixed
@@ -23,5 +101,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
101
 
24
102
  ### Notes for integrators
25
103
 
26
- - Prefer **`loadJson` / `exportJson`** (or `designToEmailDocument` + `normalizeEmailDesignInput`) for full fidelity; blocks may include a `props` object alongside `content` / `styles` for editor-only fields.
104
+ - Prefer **`loadJson` / `exportJson`** (or `designToEmailDocument` + `normalizeEmailDesignInput`) for full fidelity. As of **3.5.0**, exported blocks use **`props`** for styling (block `styles` are not written on export); **`html`** blocks use a root-level string **`content`**.
27
105
  - **`jsonToHtml`** nested layouts already receive `columnStyles` when present on hydrated blocks.
package/README.md CHANGED
@@ -7,6 +7,8 @@
7
7
 
8
8
  ## Release notes
9
9
 
10
+ **Latest: 3.8.0** — export uses **`rows[]`** + **`_reactEmailStudio`** (LMS shape); palette blocks add as root sections; section reorder via drag handle or inspector.
11
+
10
12
  Version history and migration hints: **[CHANGELOG.md](./CHANGELOG.md)** (also included in the published npm tarball under `node_modules/react-email-studio/CHANGELOG.md`).
11
13
 
12
14
  ---
@@ -49,6 +51,7 @@ import {
49
51
  ReactEmailEditor,
50
52
  type ReactEmailEditorRef,
51
53
  jsonToHtml,
54
+ htmlToJson,
52
55
  } from "react-email-studio";
53
56
 
54
57
  export function App() {
@@ -88,6 +91,10 @@ export function App() {
88
91
  const html = jsonToHtml(savedDesignJson, {
89
92
  customCSS: `/* optional extra styles */`,
90
93
  });
94
+
95
+ // Import existing HTML into the editor (fragment or full document)
96
+ const designJson = htmlToJson("<p>Hello from HTML</p>", true);
97
+ editorRef.current?.loadJson(designJson);
91
98
  ```
92
99
 
93
100
  Implement **`onUpload`** so image/video uploads return URLs your recipients can load (HTTPS recommended).
@@ -102,6 +109,11 @@ Implement **`onUpload`** so image/video uploads return URLs your recipients can
102
109
  | `ReactEmailEditorProps` | Component props type. |
103
110
  | `ReactEmailEditorRef` | Imperative API: `loadJson`, `exportJson`. |
104
111
  | `jsonToHtml` | `(design, opts?) => string` — full HTML email document. |
112
+ | `htmlToJson` | `(html, pretty?) => string` — HTML fragment/page → `email_document` JSON. |
113
+ | `htmlToEmailDesignTemplate` | `(html) => EmailDocument \| null` — same conversion as object. |
114
+ | `canonicalizeEmailDocument` | `(input) => EmailDocument \| null` — normalize import/export JSON. |
115
+ | `extractHtmlForDesign` | `(html) => string` — pull body/fragment from a full HTML document. |
116
+ | `ReactEmailEditor.jsonToHtml` / `.htmlToJson` | Static helpers on the component. |
105
117
  | `utf8ToBase64`, `base64ToUtf8` | Encoding helpers. |
106
118
  | `EmailPreviewModal` | Standalone responsive preview modal. |
107
119
  | `emailPreviewDevices` | Device presets for preview. |
package/TUTORIAL.md CHANGED
@@ -11,6 +11,7 @@ This document is for **npm users**: wiring **react-email-studio** into an app, p
11
11
  | **`ReactEmailEditor`** | Full-screen (or sized) visual editor: rows, columns, blocks, settings. |
12
12
  | **Design JSON** | Canonical storage format: `email_document` schema (see exported types). |
13
13
  | **`jsonToHtml`** | Turns saved JSON into a **full HTML document** for preview iframes or your ESP. |
14
+ | **`htmlToJson`** | Wraps pasted HTML in `email_document` JSON for **`loadJson`**. |
14
15
  | **`onUpload`** | Your code uploads assets and returns **HTTPS URLs** referenced in the HTML. |
15
16
 
16
17
  The package does **not** send mail, host files, or provide a backend—you connect those.
@@ -188,6 +189,34 @@ Use the returned string as the **email body HTML** with your provider (SendGrid,
188
189
 
189
190
  ---
190
191
 
192
+ ## 7b. `htmlToJson` — HTML into the editor
193
+
194
+ ```ts
195
+ import {
196
+ htmlToJson,
197
+ htmlToEmailDesignTemplate,
198
+ extractHtmlForDesign,
199
+ } from "react-email-studio";
200
+
201
+ const json = htmlToJson("<p>Welcome</p>", true); // pretty-print optional
202
+ editorRef.current?.loadJson(json);
203
+
204
+ // Or as an object:
205
+ const doc = htmlToEmailDesignTemplate(fullPageHtml);
206
+ if (doc) editorRef.current?.loadJson(doc);
207
+ ```
208
+
209
+ | Export | Description |
210
+ |--------|-------------|
211
+ | `htmlToJson(html, pretty?)` | `email_document` JSON string; `""` if HTML is empty after normalization. |
212
+ | `htmlToEmailDesignTemplate(html)` | Same design as an `EmailDocument` object, or `null`. |
213
+ | `extractHtmlForDesign(html)` | Body/fragment only (strips `<html>` wrapper when present). |
214
+ | `ReactEmailEditor.htmlToJson` | Static method — same as `htmlToJson`. |
215
+
216
+ Creates one row, one column, and a single **html** block with default typography `props`.
217
+
218
+ ---
219
+
191
220
  ## 8. Optional: `EmailPreviewModal` & `emailPreviewDevices`
192
221
 
193
222
  For a **standalone** responsive preview (outside the built-in toolbar preview), the package exports:
@@ -239,8 +268,33 @@ import type {
239
268
  Persist **`exportJson`** output as your source of truth. Top-level shape:
240
269
 
241
270
  - `type: "email_document"`
242
- - `settings` — global email / content shell options
243
- - `rows` — layout rows columns blocks
271
+ - `settings` — global shell (`width`, `backgroundColor`, `contentBackgroundColor`, `contentPadding`, `contentBorderRadius`, `fontFamily`, `rtl`, …) plus **`settings._reactEmailStudio`** (`editorSettings` snapshot).
272
+ - `rows` — **primary export**: each canvas section is a **`type: "row"`** with `layout`, `styles`, `columns[].blocks[]`, and **`_reactEmailStudio.row`** (preset, ratios, column props).
273
+
274
+ **Import** also accepts **`blocks[]`**, legacy **`styles`**, and partial fragments.
275
+
276
+ ### Row / block fields (export, 3.8+)
277
+
278
+ | Level | Fields |
279
+ |-------|--------|
280
+ | Row | `id`, `type: "row"`, `layout`, `styles`, `props`, `columns`, `_reactEmailStudio.row` |
281
+ | Column | `id`, `layout`, `styles`, `props`, `blocks[]` |
282
+ | Block | `id`, `type`, `content`, `styles`, `props`, optional `behavior` |
283
+
284
+ Blocks use **`props`** for editor fields; **`styles`** mirror the document schema for ESP compatibility. Rich **`html`** blocks use `content.html` (and `props.content`).
285
+
286
+ ### Optional `blocks[]` (import)
287
+
288
+ A flat **`blocks[]`** root (layout or content blocks) still loads; the editor wraps standalone blocks in rows. **Export** uses **`rows[]`**, not `blocks[]`.
289
+
290
+ ### `loadJson` append
291
+
292
+ ```ts
293
+ editorRef.current?.loadJson({ rows: [/* … */] }, { mode: "append" });
294
+ // or { blocks: […] } / a raw array — coerced before merge
295
+ ```
296
+
297
+ Use **`canonicalizeEmailDocument(input)`** to normalize saved JSON to the export shape without opening the editor.
244
298
 
245
299
  Use exported **`EmailDocument`** when typing API payloads or DB columns.
246
300
 
package/USER_README.md CHANGED
@@ -17,6 +17,23 @@ For **step-by-step integration** (Next.js, APIs, TypeScript), see **`TUTORIAL.md
17
17
  - **`ref.loadJson` / `ref.exportJson`** — load or save design JSON.
18
18
  - **`onUpload`** — return a public **HTTPS** URL for uploaded images.
19
19
  - **`jsonToHtml`** — design JSON → full HTML for sending.
20
+ - **`htmlToJson`** — paste HTML (fragment or page) → `email_document` JSON for `loadJson`.
21
+
22
+ ### Block JSON (3.5+)
23
+
24
+ Exported blocks use **`props`** for styling (no block-level **`styles`**). Rich **html** blocks store markup as a root-level **`content`** string; other block types keep structured `content` objects where applicable.
25
+
26
+ ### Column layout (3.6+)
27
+
28
+ Per-column backgrounds, padding, and radius use **`columns: [{ props }]`** on rows and nested layouts (not **`columnStyles`**). Legacy maps still import.
29
+
30
+ ### Export shape (3.8+)
31
+
32
+ **`exportJson`** writes **`rows[]`** (each section = `type: "row"` with `columns[].blocks[]`), plus **`settings._reactEmailStudio`** and per-row **`_reactEmailStudio.row`** for editor round-trip. **`blocks[]`** is still accepted on **import** only.
33
+
34
+ **Reorder sections**: drag the **⋮⋮** handle on the left of a row, or select the row and use **Move section up/down** in the right panel.
35
+
36
+ **Append designs**: `loadJson(fragment, { mode: "append" })`.
20
37
 
21
38
  ## Troubleshooting
22
39