@seliseblocks/mailcraft 0.2.14 → 0.2.16

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.
Files changed (57) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/DOCS.md +5 -4
  3. package/README.md +2 -1
  4. package/README.md.txt +2 -1
  5. package/dist/mailcraft-editor.bundle.js +71 -71
  6. package/dist/mailcraft-editor.bundle.js.map +3 -3
  7. package/examples/templates/back-in-stock.html +1 -8
  8. package/examples/templates/cart-left-behind.html +1 -8
  9. package/examples/templates/meet-nova-launch.html +5 -0
  10. package/examples/templates/rate-your-headphones.html +1 -8
  11. package/examples/templates/the-sunday-brief.html +5 -0
  12. package/examples/templates/your-order-shipped.html +1 -0
  13. package/examples/vanilla.html +14 -24
  14. package/package.json +1 -1
  15. package/src/core/i18n/ar.js +2 -1
  16. package/src/core/i18n/bg.js +2 -1
  17. package/src/core/i18n/bn.js +2 -1
  18. package/src/core/i18n/ca.js +2 -1
  19. package/src/core/i18n/cs.js +2 -1
  20. package/src/core/i18n/da.js +2 -1
  21. package/src/core/i18n/de-CH.js +2 -1
  22. package/src/core/i18n/de.js +2 -1
  23. package/src/core/i18n/dz.js +2 -1
  24. package/src/core/i18n/el.js +2 -1
  25. package/src/core/i18n/en.js +2 -1
  26. package/src/core/i18n/es.js +2 -1
  27. package/src/core/i18n/et.js +2 -1
  28. package/src/core/i18n/fi.js +2 -1
  29. package/src/core/i18n/fr.js +2 -1
  30. package/src/core/i18n/hr.js +2 -1
  31. package/src/core/i18n/hu.js +2 -1
  32. package/src/core/i18n/index.js +83 -83
  33. package/src/core/i18n/it.js +2 -1
  34. package/src/core/i18n/lt.js +2 -1
  35. package/src/core/i18n/lv.js +2 -1
  36. package/src/core/i18n/nb.js +2 -1
  37. package/src/core/i18n/nl.js +2 -1
  38. package/src/core/i18n/pl.js +2 -1
  39. package/src/core/i18n/pt.js +2 -1
  40. package/src/core/i18n/ro.js +2 -1
  41. package/src/core/i18n/ru.js +2 -1
  42. package/src/core/i18n/sk.js +2 -1
  43. package/src/core/i18n/sl.js +2 -1
  44. package/src/core/i18n/sv.js +2 -1
  45. package/src/core/i18n/tr.js +2 -1
  46. package/src/core/i18n/uk.js +2 -1
  47. package/src/core/ids.js +1 -1
  48. package/src/core/layout-style.js +100 -100
  49. package/src/core/parse.js +10 -10
  50. package/src/core/placeholder.js +15 -15
  51. package/src/core/variables.js +11 -11
  52. package/src/mailcraft-editor.js +26 -10
  53. package/src/render/focus-preserve.js +158 -158
  54. package/src/render/screenshot.js +95 -7
  55. package/src/render/story.js +541 -415
  56. package/src/render/style.js +1 -1
  57. package/types/index.d.ts +22 -7
package/CHANGELOG.md CHANGED
@@ -4,6 +4,23 @@ All notable changes to `@seliseblocks/mailcraft` are documented here.
4
4
 
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.2.16] — 2026-09-05
8
+
9
+ ### Fixed
10
+ - **The screenshot viewer opens and slides smoothly.** Three sources of jank, all on the main thread at once: the capture's heavy bursts (render, layout, serialize, rasterize, encode) started inside the entrance animation and stuttered it — the skeleton now goes up immediately and the capture waits for the chrome to finish arriving; the skeleton's shimmer animated `background-position`, a full-card repaint per frame exactly while that work ran — it sweeps on a composited `transform` now; and the tall capture image wasn't pinned to its own compositor layer, so a slide could re-rasterize megapixels mid-transition — `will-change: transform` keeps it promoted, and the image is fully decoded off-screen before it fades in.
11
+ - **Faster reopen on photo-heavy templates.** Every capture re-fetched and re-inlined each external image; the inlined bytes are now cached per URL for the session (a failed fetch is evicted, so a transient network error is not pinned).
12
+ - **The viewer no longer reads as a modal stacked on the export dialog.** Opened from the dialog's Screenshot button, the dialog is parked while the viewer is up and restored when it closes; the backdrop also dims deeper (0.86 → 0.94), so bright chrome underneath stops bleeding through the viewer's own header.
13
+
14
+ ## [0.2.15] — 2026-09-05
15
+
16
+ ### Added
17
+ - **Compressed screenshots.** `screenshotPng(options)` takes `{ format: 'png' | 'jpeg' | 'webp', quality: 0–1, scale }`, so a long template can be captured as a JPG or WebP at a fraction of the PNG's size (PNG stays the lossless default). The capture itself is still one lossless render; a lossy pick re-encodes it at download time against the template's page colour, and never captures twice. `downloadScreenshot(blob?, options?)` passes the options through and names the file by the format that was actually encoded (a browser without a WebP encoder falls back to PNG, per spec). Copy still hands the clipboard a PNG — it accepts nothing else.
18
+ - **The screenshot viewer's actions are one floating control bar now.** Play/pause and Copy sit as quiet segments beside a segmented **PNG | JPG | WEBP** picker (all three visible, the active one lit) and a solid Download button that renames itself with the chosen format. The capture's dimensions and screen position moved up under the Screenshot kicker, where a full header line keeps them from truncating; on narrow cards Copy folds to its icon so Download keeps its label.
19
+ - **The demo templates have product and hero imagery now.** Six of the example templates (back in stock, cart left behind, rate your headphones, meet Nova, The Sunday Brief, your order shipped) were shipping with no images at all — colour tiles stood in where a product shot or hero belongs. Each now carries flat SVG illustrations as self-contained `data:` URIs, so the gallery keeps working from `file://`, offline, and inside the screenshot capture's no-network rule. All six still converge as save round-trip fixed points.
20
+
21
+ ### Changed
22
+ - The `action.downloadPng` message key is retired in favour of `story.download` (`'Download {fmt}'`) and the new `story.format` hint, in all 31 locales. A host override table using the old key should move to the new ones.
23
+
7
24
  ## [0.2.14] — 2026-09-03
8
25
 
9
26
  ### Fixed
package/DOCS.md CHANGED
@@ -542,9 +542,9 @@ template, not to your app.
542
542
  | `importHtml(html)` | number of rows produced |
543
543
  | `loadTemplate({ name, html })` | — |
544
544
  | `undo()` / `redo()` | — |
545
- | `screenshotPng()` | full template as a PNG `Blob` |
546
- | `previewScreenshot()` | opens the story-style viewer |
547
- | `downloadScreenshot(blob?)` / `copyScreenshot(blob?)` | save / clipboard — captures first if no blob is passed |
545
+ | `screenshotPng(options?)` | full template as an image `Blob`. PNG by default (lossless); `{ format: 'jpeg' \| 'webp', quality: 0–1 }` compresses it to a fraction of the size, and `scale` (default 2) trades resolution for bytes. Read the returned `blob.type` — a browser without a WebP encoder hands back PNG |
546
+ | `previewScreenshot()` | opens the story-style viewer, with its own PNG / JPG / WebP download toggle |
547
+ | `downloadScreenshot(blob?, options?)` / `copyScreenshot(blob?)` | save / clipboard — captures first (with `options`) if no blob is passed; the filename extension follows the blob's actual type |
548
548
 
549
549
  ### Events
550
550
 
@@ -580,7 +580,6 @@ The complete catalog of UI strings that `.messages` accepts — every key the ed
580
580
  | `action.codeHint` | Edit the raw HTML with a live preview |
581
581
  | `action.deleteHint` | Delete — ⌫ |
582
582
  | `action.download` | Download |
583
- | `action.downloadPng` | Download PNG |
584
583
  | `action.duplicateHint` | Duplicate — ⌘D |
585
584
  | `action.export` | Export |
586
585
  | `action.exportHint` | Export your email |
@@ -707,8 +706,10 @@ The complete catalog of UI strings that `.messages` accepts — every key the ed
707
706
  | `storage.loading` | Loading files… |
708
707
  | `storage.uploading` | Uploading {count}… |
709
708
  | `story.copy` | Copy |
709
+ | `story.download` | Download {fmt} |
710
710
  | `story.failed` | Screenshot failed |
711
711
  | `story.failedHint` | An image in the template could not be loaded for capture. |
712
+ | `story.format` | Image format — PNG is lossless, JPG and WebP are smaller files |
712
713
  | `story.kicker` | Screenshot |
713
714
  | `story.meta` | {w}×{h} · screen {i} of {n} |
714
715
  | `story.pause` | Pause |
package/README.md CHANGED
@@ -101,7 +101,8 @@ ATTRS variables="a,b,c" | locale="de" | theme="dark" | dir="rtl"
101
101
  PROPS .variables .toolbar .footer .uiFont .accent .messages .aiProvider .iconProvider
102
102
  .storageProvider .storageLimits
103
103
  METHODS exportHtml() importHtml(html) loadTemplate(tpl) undo() redo()
104
- screenshotPng() previewScreenshot() downloadScreenshot() copyScreenshot()
104
+ screenshotPng({format:'png'|'jpeg'|'webp', quality, scale}?)
105
+ previewScreenshot() downloadScreenshot() copyScreenshot()
105
106
 
106
107
  KEYS Bound on window, so they survive toolbar="none":
107
108
  Esc (leave field / deselect + close), Ctrl/Cmd+Z, Shift+Ctrl/Cmd+Z,
package/README.md.txt CHANGED
@@ -101,7 +101,8 @@ ATTRS variables="a,b,c" | locale="de" | theme="dark" | dir="rtl"
101
101
  PROPS .variables .toolbar .footer .uiFont .accent .messages .aiProvider .iconProvider
102
102
  .storageProvider .storageLimits
103
103
  METHODS exportHtml() importHtml(html) loadTemplate(tpl) undo() redo()
104
- screenshotPng() previewScreenshot() downloadScreenshot() copyScreenshot()
104
+ screenshotPng({format:'png'|'jpeg'|'webp', quality, scale}?)
105
+ previewScreenshot() downloadScreenshot() copyScreenshot()
105
106
 
106
107
  KEYS Bound on window, so they survive toolbar="none":
107
108
  Esc (leave field / deselect + close), Ctrl/Cmd+Z, Shift+Ctrl/Cmd+Z,