@kontakto/email-template-editor 2.5.0 → 2.7.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/dist/index.cjs CHANGED
@@ -11,6 +11,7 @@ var react = require('@lingui/react');
11
11
  var material = require('@mui/material');
12
12
  var core = require('@lingui/core');
13
13
  var zustand = require('zustand');
14
+ var zundo = require('zundo');
14
15
  var iconsMaterial = require('@mui/icons-material');
15
16
  var reactColorful = require('react-colorful');
16
17
  var hljs = require('highlight.js');
@@ -2015,13 +2016,13 @@ var THEME = styles.createTheme(BASE_THEME, {
2015
2016
  var theme_default = THEME;
2016
2017
 
2017
2018
  // src/locales/en/messages.ts
2018
- var messages = JSON.parse('{"drawer.library":["Library"],"drawer.new-sample":["New sample"],"drawer.new-template":["New template"],"drawer.no-samples":["No samples available"],"drawer.no-samples-match":["No samples match your filters"],"drawer.no-templates":["No saved templates yet"],"drawer.no-templates-match":["No templates match your filters"],"drawer.search-samples":["Search samples"],"drawer.search-templates":["Search templates"],"drawer.sort-by":["Sort by"],"drawer.tab.outline":["Outline"],"drawer.tab.samples":["Samples"],"drawer.tab.templates":["Templates"],"drawer.tag.all":["All"],"panel.avatar-block":["Avatar block"],"panel.button-block":["Button block"],"panel.columns-block":["Columns block"],"panel.container-block":["Container block"],"panel.divider-block":["Divider block"],"panel.editor-appearance":["Editor appearance"],"panel.export":["Export"],"panel.global":["Global"],"panel.heading-block":["Heading block"],"panel.html-block":["HTML block"],"panel.image-block":["Image block"],"panel.signature-block":["Signature block"],"panel.spacer-block":["Spacer block"],"panel.template":["Template"],"panel.text-block":["Text block"],"savebar.error-saving":["Error saving"],"savebar.new":["New"],"savebar.new-template-created":["New template created"],"savebar.sample-prefix":["Sample"],"savebar.sample-saved":["Sample saved"],"savebar.save":["Save"],"savebar.save-as":["Save as\u2026"],"savebar.save-as-new":["Save as new\u2026"],"savebar.save-as-new-template":["Save as a new template"],"savebar.save-changes":["Save changes"],"savebar.save-changes-to-sample":["Save changes to this sample"],"savebar.start-fresh":["Start a fresh template"],"savebar.template-saved":["Template saved"],"sort.last-updated":["Last updated"],"sort.name":["Name (A\u2013Z)"],"sort.recently-created":["Recently created"],"style.alignment":["Alignment"],"style.background-color":["Background color"],"style.border-color":["Border color"],"style.border-radius":["Border radius"],"style.font-family":["Font family"],"style.font-size":["Font size"],"style.font-weight":["Font weight"],"style.letter-spacing":["Letter spacing"],"style.line-height":["Line height"],"style.padding":["Padding"],"style.text-color":["Text color"],"toolbar.bold":["Bold"],"toolbar.bold-shortcut":["Bold (Cmd+B)"],"toolbar.italic":["Italic"],"toolbar.italic-shortcut":["Italic (Cmd+I)"],"toolbar.link":["Link"],"toolbar.link-shortcut":["Link (Cmd+K)"],"tune.copy":["Copy block"],"tune.delete":["Delete"],"tune.move-down":["Move down"],"tune.move-up":["Move up"]}');
2019
+ var messages = JSON.parse('{"avatar.shape":["Shape"],"button.color":["Button color"],"button.style.pill":["Pill"],"button.style.rectangle":["Rectangle"],"button.style.rounded":["Rounded"],"button.width.auto":["Auto"],"button.width.full":["Full"],"canvas.desktop-view":["Desktop view"],"canvas.mobile-view":["Mobile view"],"columns.count":["Number of columns"],"columns.gap":["Columns gap"],"common.add":["Add"],"common.cancel":["Cancel"],"common.save":["Save"],"common.saving":["Saving\u2026"],"divider.color":["Color"],"drawer.library":["Library"],"drawer.new-sample":["New sample"],"drawer.new-template":["New template"],"drawer.no-samples":["No samples available"],"drawer.no-samples-match":["No samples match your filters"],"drawer.no-templates":["No saved templates yet"],"drawer.no-templates-match":["No templates match your filters"],"drawer.search-samples":["Search samples"],"drawer.search-templates":["Search templates"],"drawer.sort-by":["Sort by"],"drawer.tab.outline":["Outline"],"drawer.tab.samples":["Samples"],"drawer.tab.templates":["Templates"],"drawer.tag.all":["All"],"empty.description":["A blank email template to start from scratch"],"empty.slug":["Empty email"],"field.content":["Content"],"field.height":["Height"],"field.level":["Level"],"field.markdown":["Markdown"],"field.size":["Size"],"field.style":["Style"],"field.text":["Text"],"field.url":["Url"],"field.width":["Width"],"global.backdrop-color":["Backdrop color"],"global.canvas-border-color":["Canvas border color"],"global.canvas-border-radius":["Canvas border radius"],"global.canvas-color":["Canvas color"],"global.disable-backdrop":["Disable backdrop"],"image.alt-text":["Alt text"],"image.http-warning":["Non-HTTPS URL: Gmail and other clients strip mixed content. Use https:// for reliable delivery."],"image.library":["Library"],"image.link-href":["Click through URL"],"image.source-url":["Source URL"],"image.upload":["Upload"],"image.uploading":["Uploading\u2026"],"inspector.tab.inspect":["Inspect"],"inspector.tab.settings":["Settings"],"inspector.tab.styles":["Styles"],"inspector.tab.variables":["Variables"],"panel.avatar-block":["Avatar block"],"panel.button-block":["Button block"],"panel.columns-block":["Columns block"],"panel.container-block":["Container block"],"panel.divider-block":["Divider block"],"panel.editor-appearance":["Editor appearance"],"panel.export":["Export"],"panel.global":["Global"],"panel.heading-block":["Heading block"],"panel.html-block":["HTML block"],"panel.image-block":["Image block"],"panel.signature-block":["Signature block"],"panel.spacer-block":["Spacer block"],"panel.template":["Template"],"panel.text-block":["Text block"],"picker.blank-desc":["Start from an empty email"],"picker.blank-title":["Blank"],"picker.create-sample":["Create sample"],"picker.create-template":["Create template"],"picker.creating":["Creating\u2026"],"picker.error-name-required":["Name is required"],"picker.error-sample-taken":["A sample with this name already exists"],"picker.error-template-taken":["A template with this name already exists"],"picker.start-from":["Start from"],"picker.title-sample":["New sample"],"picker.title-template":["New template"],"rename.error-empty":["Please enter a name"],"rename.error-generic":["Failed to update template details"],"rename.error-taken":["A template with this name already exists"],"rename.name-label":["Name"],"rename.no-tags":["No tags yet."],"rename.tag-placeholder":["Add a tag and press Enter"],"rename.tags":["Tags"],"rename.title":["Edit details"],"row.actions":["Row actions"],"row.demote":["Demote to template"],"row.duplicate":["Duplicate"],"row.duplicate-as-template":["Duplicate as template"],"row.edit-details":["Edit name & tags\u2026"],"row.more":["More"],"row.promote":["Promote to sample"],"save-dialog.create":["Create"],"save-dialog.error-empty-name":["Please enter a template name"],"save-dialog.name-label":["Template Name"],"save-dialog.save":["Save"],"save-dialog.saving":["Saving..."],"save-dialog.title":["Save as a new template"],"save-dialog.title-new":["Create a new template"],"savebar.error-saving":["Error saving"],"savebar.new":["New"],"savebar.new-template-created":["New template created"],"savebar.sample-prefix":["Sample"],"savebar.sample-saved":["Sample saved"],"savebar.save":["Save"],"savebar.save-as":["Save as\u2026"],"savebar.save-as-new":["Save as new\u2026"],"savebar.save-as-new-template":["Save as a new template"],"savebar.save-changes":["Save changes"],"savebar.save-changes-to-sample":["Save changes to this sample"],"savebar.start-fresh":["Start a fresh template"],"savebar.template-saved":["Template saved"],"signature.address":["Address"],"signature.company":["Company"],"signature.email":["Email"],"signature.greeting":["Greeting"],"signature.image-shape":["Image shape"],"signature.image-size":["Image size"],"signature.image-url":["Image URL"],"signature.layout":["Layout"],"signature.layout.horizontal":["Horizontal"],"signature.layout.vertical":["Vertical"],"signature.link-color":["Link color"],"signature.name":["Name"],"signature.name-color":["Name color"],"signature.phone":["Phone"],"signature.shape.circle":["Circle"],"signature.shape.rounded":["Rounded"],"signature.shape.square":["Square"],"signature.title":["Title"],"signature.website":["Website"],"size.lg":["Lg"],"size.md":["Md"],"size.sm":["Sm"],"size.xs":["Xs"],"sort.last-updated":["Last updated"],"sort.name":["Name (A\u2013Z)"],"sort.recently-created":["Recently created"],"style.alignment":["Alignment"],"style.background-color":["Background color"],"style.border-color":["Border color"],"style.border-radius":["Border radius"],"style.font-family":["Font family"],"style.font-size":["Font size"],"style.font-weight":["Font weight"],"style.letter-spacing":["Letter spacing"],"style.line-height":["Line height"],"style.padding":["Padding"],"style.text-color":["Text color"],"tab.edit":["Edit"],"tab.html-output":["HTML output"],"tab.json-output":["JSON output"],"tab.preview":["Preview"],"tab.text-output":["Plain text output"],"time.days-short":["d ago"],"time.hours-short":["h ago"],"time.just-now":["just now"],"time.minutes-short":["m ago"],"time.months-short":["mo ago"],"time.years-short":["y ago"],"toolbar.bold":["Bold"],"toolbar.bold-shortcut":["Bold (Cmd+B)"],"toolbar.italic":["Italic"],"toolbar.italic-shortcut":["Italic (Cmd+I)"],"toolbar.link":["Link"],"toolbar.link-shortcut":["Link (Cmd+K)"],"tune.copy":["Copy block"],"tune.delete":["Delete"],"tune.move-down":["Move down"],"tune.move-up":["Move up"]}');
2019
2020
 
2020
2021
  // src/locales/fi/messages.ts
2021
- var messages2 = JSON.parse('{"drawer.library":["Kirjasto"],"drawer.new-sample":["Uusi malli"],"drawer.new-template":["Uusi pohja"],"drawer.no-samples":["Ei malleja saatavilla"],"drawer.no-samples-match":["Mik\xE4\xE4n malli ei vastaa hakua"],"drawer.no-templates":["Ei tallennettuja pohjia"],"drawer.no-templates-match":["Mik\xE4\xE4n pohja ei vastaa hakua"],"drawer.search-samples":["Etsi malleja"],"drawer.search-templates":["Etsi pohjia"],"drawer.sort-by":["J\xE4rjestys"],"drawer.tab.outline":["Rakenne"],"drawer.tab.samples":["Mallit"],"drawer.tab.templates":["Pohjat"],"drawer.tag.all":["Kaikki"],"panel.avatar-block":["Avatarlohko"],"panel.button-block":["Painikelohko"],"panel.columns-block":["Sarakkeet"],"panel.container-block":["S\xE4ili\xF6lohko"],"panel.divider-block":["Erotin"],"panel.editor-appearance":["Editorin ulkoasu"],"panel.export":["Vienti"],"panel.global":["Yleiset"],"panel.heading-block":["Otsikkolohko"],"panel.html-block":["HTML-lohko"],"panel.image-block":["Kuvalohko"],"panel.signature-block":["Allekirjoituslohko"],"panel.spacer-block":["V\xE4lilohko"],"panel.template":["Pohja"],"panel.text-block":["Tekstilohko"],"savebar.error-saving":["Tallennus ep\xE4onnistui"],"savebar.new":["Uusi"],"savebar.new-template-created":["Uusi pohja luotu"],"savebar.sample-prefix":["Malli"],"savebar.sample-saved":["Malli tallennettu"],"savebar.save":["Tallenna"],"savebar.save-as":["Tallenna nimell\xE4\u2026"],"savebar.save-as-new":["Tallenna uutena\u2026"],"savebar.save-as-new-template":["Tallenna uutena pohjana"],"savebar.save-changes":["Tallenna muutokset"],"savebar.save-changes-to-sample":["Tallenna muutokset t\xE4h\xE4n malliin"],"savebar.start-fresh":["Aloita tyhj\xE4st\xE4 pohjasta"],"savebar.template-saved":["Pohja tallennettu"],"sort.last-updated":["Viimeksi p\xE4ivitetty"],"sort.name":["Nimi (A\u2013\xD6)"],"sort.recently-created":["\xC4skett\xE4in luotu"],"style.alignment":["Tasaus"],"style.background-color":["Taustav\xE4ri"],"style.border-color":["Reunan v\xE4ri"],"style.border-radius":["Reunan py\xF6ristys"],"style.font-family":["Fontti"],"style.font-size":["Fonttikoko"],"style.font-weight":["Fontin paksuus"],"style.letter-spacing":["Kirjainv\xE4li"],"style.line-height":["Rivikorkeus"],"style.padding":["T\xE4yte"],"style.text-color":["Tekstin v\xE4ri"],"toolbar.bold":["Lihavointi"],"toolbar.bold-shortcut":["Lihavointi (Cmd+B)"],"toolbar.italic":["Kursivointi"],"toolbar.italic-shortcut":["Kursivointi (Cmd+I)"],"toolbar.link":["Linkki"],"toolbar.link-shortcut":["Linkki (Cmd+K)"],"tune.copy":["Kopioi lohko"],"tune.delete":["Poista"],"tune.move-down":["Siirr\xE4 alas"],"tune.move-up":["Siirr\xE4 yl\xF6s"]}');
2022
+ var messages2 = JSON.parse('{"avatar.shape":["Muoto"],"button.color":["Painikkeen v\xE4ri"],"button.style.pill":["Pilleri"],"button.style.rectangle":["Suorakaide"],"button.style.rounded":["Py\xF6ristetty"],"button.width.auto":["Automaattinen"],"button.width.full":["T\xE4ysi"],"canvas.desktop-view":["Ty\xF6p\xF6yt\xE4n\xE4kym\xE4"],"canvas.mobile-view":["Mobiilin\xE4kym\xE4"],"columns.count":["Sarakkeiden m\xE4\xE4r\xE4"],"columns.gap":["Sarakev\xE4li"],"common.add":["Lis\xE4\xE4"],"common.cancel":["Peruuta"],"common.save":["Tallenna"],"common.saving":["Tallennetaan\u2026"],"divider.color":["V\xE4ri"],"drawer.library":["Kirjasto"],"drawer.new-sample":["Uusi malli"],"drawer.new-template":["Uusi pohja"],"drawer.no-samples":["Ei malleja saatavilla"],"drawer.no-samples-match":["Mik\xE4\xE4n malli ei vastaa hakua"],"drawer.no-templates":["Ei tallennettuja pohjia"],"drawer.no-templates-match":["Mik\xE4\xE4n pohja ei vastaa hakua"],"drawer.search-samples":["Etsi malleja"],"drawer.search-templates":["Etsi pohjia"],"drawer.sort-by":["J\xE4rjestys"],"drawer.tab.outline":["Rakenne"],"drawer.tab.samples":["Mallit"],"drawer.tab.templates":["Pohjat"],"drawer.tag.all":["Kaikki"],"empty.description":["Tyhj\xE4 s\xE4hk\xF6postipohja, aloita tyhj\xE4lt\xE4 p\xF6yd\xE4lt\xE4"],"empty.slug":["Tyhj\xE4 s\xE4hk\xF6posti"],"field.content":["Sis\xE4lt\xF6"],"field.height":["Korkeus"],"field.level":["Taso"],"field.markdown":["Markdown"],"field.size":["Koko"],"field.style":["Tyyli"],"field.text":["Teksti"],"field.url":["Osoite"],"field.width":["Leveys"],"global.backdrop-color":["Taustav\xE4ri"],"global.canvas-border-color":["Kankaan reunan v\xE4ri"],"global.canvas-border-radius":["Kankaan reunan py\xF6ristys"],"global.canvas-color":["Kankaan v\xE4ri"],"global.disable-backdrop":["Piilota taustav\xE4ri"],"image.alt-text":["Vaihtoehtoinen teksti"],"image.http-warning":["Ei-HTTPS-osoite: Gmail ja muut asiakasohjelmat poistavat sekoitetun sis\xE4ll\xF6n. K\xE4yt\xE4 https:// varmaa toimitusta varten."],"image.library":["Kirjasto"],"image.link-href":["Linkin osoite"],"image.source-url":["L\xE4hdeosoite"],"image.upload":["Lataa"],"image.uploading":["Ladataan\u2026"],"inspector.tab.inspect":["Tarkastele"],"inspector.tab.settings":["Asetukset"],"inspector.tab.styles":["Tyylit"],"inspector.tab.variables":["Muuttujat"],"panel.avatar-block":["Avatarlohko"],"panel.button-block":["Painikelohko"],"panel.columns-block":["Sarakkeet"],"panel.container-block":["S\xE4ili\xF6lohko"],"panel.divider-block":["Erotin"],"panel.editor-appearance":["Editorin ulkoasu"],"panel.export":["Vienti"],"panel.global":["Yleiset"],"panel.heading-block":["Otsikkolohko"],"panel.html-block":["HTML-lohko"],"panel.image-block":["Kuvalohko"],"panel.signature-block":["Allekirjoituslohko"],"panel.spacer-block":["V\xE4lilohko"],"panel.template":["Pohja"],"panel.text-block":["Tekstilohko"],"picker.blank-desc":["Aloita tyhj\xE4st\xE4 s\xE4hk\xF6postista"],"picker.blank-title":["Tyhj\xE4"],"picker.create-sample":["Luo malli"],"picker.create-template":["Luo pohja"],"picker.creating":["Luodaan\u2026"],"picker.error-name-required":["Nimi vaaditaan"],"picker.error-sample-taken":["Samanniminen malli on jo olemassa"],"picker.error-template-taken":["Samanniminen pohja on jo olemassa"],"picker.start-from":["Aloitetaan pohjasta"],"picker.title-sample":["Uusi malli"],"picker.title-template":["Uusi pohja"],"rename.error-empty":["Anna nimi"],"rename.error-generic":["Tietojen p\xE4ivitys ep\xE4onnistui"],"rename.error-taken":["Samanniminen pohja on jo olemassa"],"rename.name-label":["Nimi"],"rename.no-tags":["Ei tunnisteita."],"rename.tag-placeholder":["Lis\xE4\xE4 tunniste ja paina Enter"],"rename.tags":["Tunnisteet"],"rename.title":["Muokkaa tietoja"],"row.actions":["Rivin toiminnot"],"row.demote":["Alenna pohjaksi"],"row.duplicate":["Monista"],"row.duplicate-as-template":["Monista pohjaksi"],"row.edit-details":["Muokkaa nime\xE4 ja tunnisteita\u2026"],"row.more":["Lis\xE4\xE4"],"row.promote":["Ylenn\xE4 malliksi"],"save-dialog.create":["Luo"],"save-dialog.error-empty-name":["Anna pohjalle nimi"],"save-dialog.name-label":["Pohjan nimi"],"save-dialog.save":["Tallenna"],"save-dialog.saving":["Tallennetaan..."],"save-dialog.title":["Tallenna uutena pohjana"],"save-dialog.title-new":["Luo uusi pohja"],"savebar.error-saving":["Tallennus ep\xE4onnistui"],"savebar.new":["Uusi"],"savebar.new-template-created":["Uusi pohja luotu"],"savebar.sample-prefix":["Malli"],"savebar.sample-saved":["Malli tallennettu"],"savebar.save":["Tallenna"],"savebar.save-as":["Tallenna nimell\xE4\u2026"],"savebar.save-as-new":["Tallenna uutena\u2026"],"savebar.save-as-new-template":["Tallenna uutena pohjana"],"savebar.save-changes":["Tallenna muutokset"],"savebar.save-changes-to-sample":["Tallenna muutokset t\xE4h\xE4n malliin"],"savebar.start-fresh":["Aloita tyhj\xE4st\xE4 pohjasta"],"savebar.template-saved":["Pohja tallennettu"],"signature.address":["Osoite"],"signature.company":["Yritys"],"signature.email":["S\xE4hk\xF6posti"],"signature.greeting":["Tervehdys"],"signature.image-shape":["Kuvan muoto"],"signature.image-size":["Kuvan koko"],"signature.image-url":["Kuvan osoite"],"signature.layout":["Asettelu"],"signature.layout.horizontal":["Vaakasuora"],"signature.layout.vertical":["Pystysuora"],"signature.link-color":["Linkin v\xE4ri"],"signature.name":["Nimi"],"signature.name-color":["Nimen v\xE4ri"],"signature.phone":["Puhelin"],"signature.shape.circle":["Ympyr\xE4"],"signature.shape.rounded":["Py\xF6ristetty"],"signature.shape.square":["Neli\xF6"],"signature.title":["Titteli"],"signature.website":["Verkkosivusto"],"size.lg":["Lg"],"size.md":["Md"],"size.sm":["Sm"],"size.xs":["Xs"],"sort.last-updated":["Viimeksi p\xE4ivitetty"],"sort.name":["Nimi (A\u2013\xD6)"],"sort.recently-created":["\xC4skett\xE4in luotu"],"style.alignment":["Tasaus"],"style.background-color":["Taustav\xE4ri"],"style.border-color":["Reunan v\xE4ri"],"style.border-radius":["Reunan py\xF6ristys"],"style.font-family":["Fontti"],"style.font-size":["Fonttikoko"],"style.font-weight":["Fontin paksuus"],"style.letter-spacing":["Kirjainv\xE4li"],"style.line-height":["Rivikorkeus"],"style.padding":["T\xE4yte"],"style.text-color":["Tekstin v\xE4ri"],"tab.edit":["Muokkaa"],"tab.html-output":["HTML-tuloste"],"tab.json-output":["JSON-tuloste"],"tab.preview":["Esikatselu"],"tab.text-output":["Tekstituloste"],"time.days-short":[" pv sitten"],"time.hours-short":[" h sitten"],"time.just-now":["juuri nyt"],"time.minutes-short":[" min sitten"],"time.months-short":[" kk sitten"],"time.years-short":[" v sitten"],"toolbar.bold":["Lihavointi"],"toolbar.bold-shortcut":["Lihavointi (Cmd+B)"],"toolbar.italic":["Kursivointi"],"toolbar.italic-shortcut":["Kursivointi (Cmd+I)"],"toolbar.link":["Linkki"],"toolbar.link-shortcut":["Linkki (Cmd+K)"],"tune.copy":["Kopioi lohko"],"tune.delete":["Poista"],"tune.move-down":["Siirr\xE4 alas"],"tune.move-up":["Siirr\xE4 yl\xF6s"]}');
2022
2023
 
2023
2024
  // src/locales/sv/messages.ts
2024
- var messages3 = JSON.parse('{"drawer.library":["Bibliotek"],"drawer.new-sample":["Ny mall"],"drawer.new-template":["Ny e-postmall"],"drawer.no-samples":["Inga exempel tillg\xE4ngliga"],"drawer.no-samples-match":["Inga exempel matchar dina filter"],"drawer.no-templates":["Inga sparade mallar \xE4nnu"],"drawer.no-templates-match":["Inga mallar matchar dina filter"],"drawer.search-samples":["S\xF6k exempel"],"drawer.search-templates":["S\xF6k mallar"],"drawer.sort-by":["Sortera efter"],"drawer.tab.outline":["Struktur"],"drawer.tab.samples":["Exempel"],"drawer.tab.templates":["Mallar"],"drawer.tag.all":["Alla"],"panel.avatar-block":["Avatarblock"],"panel.button-block":["Knappblock"],"panel.columns-block":["Kolumner"],"panel.container-block":["Beh\xE5llarblock"],"panel.divider-block":["Avgr\xE4nsare"],"panel.editor-appearance":["Editorns utseende"],"panel.export":["Exportera"],"panel.global":["Allm\xE4nt"],"panel.heading-block":["Rubrikblock"],"panel.html-block":["HTML-block"],"panel.image-block":["Bildblock"],"panel.signature-block":["Signaturblock"],"panel.spacer-block":["Mellanrumsblock"],"panel.template":["Mall"],"panel.text-block":["Textblock"],"savebar.error-saving":["Fel vid sparande"],"savebar.new":["Ny"],"savebar.new-template-created":["Ny mall skapad"],"savebar.sample-prefix":["Exempel"],"savebar.sample-saved":["Exempel sparat"],"savebar.save":["Spara"],"savebar.save-as":["Spara som\u2026"],"savebar.save-as-new":["Spara som ny\u2026"],"savebar.save-as-new-template":["Spara som en ny mall"],"savebar.save-changes":["Spara \xE4ndringar"],"savebar.save-changes-to-sample":["Spara \xE4ndringar till detta exempel"],"savebar.start-fresh":["Starta en ny mall"],"savebar.template-saved":["Mall sparad"],"sort.last-updated":["Senast uppdaterad"],"sort.name":["Namn (A\u2013\xD6)"],"sort.recently-created":["Nyligen skapad"],"style.alignment":["Justering"],"style.background-color":["Bakgrundsf\xE4rg"],"style.border-color":["Kantf\xE4rg"],"style.border-radius":["Kantradie"],"style.font-family":["Typsnitt"],"style.font-size":["Typsnittsstorlek"],"style.font-weight":["Typsnittsvikt"],"style.letter-spacing":["Teckenavst\xE5nd"],"style.line-height":["Radh\xF6jd"],"style.padding":["Utrymme"],"style.text-color":["Textf\xE4rg"],"toolbar.bold":["Fet"],"toolbar.bold-shortcut":["Fet (Cmd+B)"],"toolbar.italic":["Kursiv"],"toolbar.italic-shortcut":["Kursiv (Cmd+I)"],"toolbar.link":["L\xE4nk"],"toolbar.link-shortcut":["L\xE4nk (Cmd+K)"],"tune.copy":["Kopiera block"],"tune.delete":["Ta bort"],"tune.move-down":["Flytta ner"],"tune.move-up":["Flytta upp"]}');
2025
+ var messages3 = JSON.parse('{"avatar.shape":["Form"],"button.color":["Knappf\xE4rg"],"button.style.pill":["Piller"],"button.style.rectangle":["Rektangel"],"button.style.rounded":["Rundad"],"button.width.auto":["Auto"],"button.width.full":["Full"],"canvas.desktop-view":["Skrivbordsvy"],"canvas.mobile-view":["Mobilvy"],"columns.count":["Antal kolumner"],"columns.gap":["Kolumnmellanrum"],"common.add":["L\xE4gg till"],"common.cancel":["Avbryt"],"common.save":["Spara"],"common.saving":["Sparar\u2026"],"divider.color":["F\xE4rg"],"drawer.library":["Bibliotek"],"drawer.new-sample":["Ny mall"],"drawer.new-template":["Ny e-postmall"],"drawer.no-samples":["Inga exempel tillg\xE4ngliga"],"drawer.no-samples-match":["Inga exempel matchar dina filter"],"drawer.no-templates":["Inga sparade mallar \xE4nnu"],"drawer.no-templates-match":["Inga mallar matchar dina filter"],"drawer.search-samples":["S\xF6k exempel"],"drawer.search-templates":["S\xF6k mallar"],"drawer.sort-by":["Sortera efter"],"drawer.tab.outline":["Struktur"],"drawer.tab.samples":["Exempel"],"drawer.tab.templates":["Mallar"],"drawer.tag.all":["Alla"],"empty.description":["En tom e-postmall att utg\xE5 fr\xE5n"],"empty.slug":["Tomt e-postmeddelande"],"field.content":["Inneh\xE5ll"],"field.height":["H\xF6jd"],"field.level":["Niv\xE5"],"field.markdown":["Markdown"],"field.size":["Storlek"],"field.style":["Stil"],"field.text":["Text"],"field.url":["Adress"],"field.width":["Bredd"],"global.backdrop-color":["Bakgrundsf\xE4rg"],"global.canvas-border-color":["Canvaskantf\xE4rg"],"global.canvas-border-radius":["Canvaskantradie"],"global.canvas-color":["Canvasf\xE4rg"],"global.disable-backdrop":["D\xF6lj bakgrund"],"image.alt-text":["Alternativ text"],"image.http-warning":["Icke-HTTPS-URL: Gmail och andra klienter tar bort blandat inneh\xE5ll. Anv\xE4nd https:// f\xF6r p\xE5litlig leverans."],"image.library":["Bibliotek"],"image.link-href":["Klickl\xE4nk"],"image.source-url":["K\xE4lladress"],"image.upload":["Ladda upp"],"image.uploading":["Laddar upp\u2026"],"inspector.tab.inspect":["Inspektera"],"inspector.tab.settings":["Inst\xE4llningar"],"inspector.tab.styles":["Stilar"],"inspector.tab.variables":["Variabler"],"panel.avatar-block":["Avatarblock"],"panel.button-block":["Knappblock"],"panel.columns-block":["Kolumner"],"panel.container-block":["Beh\xE5llarblock"],"panel.divider-block":["Avgr\xE4nsare"],"panel.editor-appearance":["Editorns utseende"],"panel.export":["Exportera"],"panel.global":["Allm\xE4nt"],"panel.heading-block":["Rubrikblock"],"panel.html-block":["HTML-block"],"panel.image-block":["Bildblock"],"panel.signature-block":["Signaturblock"],"panel.spacer-block":["Mellanrumsblock"],"panel.template":["Mall"],"panel.text-block":["Textblock"],"picker.blank-desc":["Starta fr\xE5n ett tomt e-postmeddelande"],"picker.blank-title":["Tomt"],"picker.create-sample":["Skapa exempel"],"picker.create-template":["Skapa mall"],"picker.creating":["Skapar\u2026"],"picker.error-name-required":["Namn kr\xE4vs"],"picker.error-sample-taken":["Ett exempel med detta namn finns redan"],"picker.error-template-taken":["En mall med detta namn finns redan"],"picker.start-from":["Utg\xE5 fr\xE5n"],"picker.title-sample":["Nytt exempel"],"picker.title-template":["Ny mall"],"rename.error-empty":["Ange ett namn"],"rename.error-generic":["Kunde inte uppdatera malldetaljer"],"rename.error-taken":["En mall med detta namn finns redan"],"rename.name-label":["Namn"],"rename.no-tags":["Inga etiketter \xE4nnu."],"rename.tag-placeholder":["L\xE4gg till en etikett och tryck Enter"],"rename.tags":["Etiketter"],"rename.title":["Redigera detaljer"],"row.actions":["Rad\xE5tg\xE4rder"],"row.demote":["Degradera till mall"],"row.duplicate":["Duplicera"],"row.duplicate-as-template":["Duplicera som mall"],"row.edit-details":["Redigera namn och etiketter\u2026"],"row.more":["Mer"],"row.promote":["Befordra till exempel"],"save-dialog.create":["Skapa"],"save-dialog.error-empty-name":["Ange ett mallnamn"],"save-dialog.name-label":["Mallnamn"],"save-dialog.save":["Spara"],"save-dialog.saving":["Sparar..."],"save-dialog.title":["Spara som en ny mall"],"save-dialog.title-new":["Skapa en ny mall"],"savebar.error-saving":["Fel vid sparande"],"savebar.new":["Ny"],"savebar.new-template-created":["Ny mall skapad"],"savebar.sample-prefix":["Exempel"],"savebar.sample-saved":["Exempel sparat"],"savebar.save":["Spara"],"savebar.save-as":["Spara som\u2026"],"savebar.save-as-new":["Spara som ny\u2026"],"savebar.save-as-new-template":["Spara som en ny mall"],"savebar.save-changes":["Spara \xE4ndringar"],"savebar.save-changes-to-sample":["Spara \xE4ndringar till detta exempel"],"savebar.start-fresh":["Starta en ny mall"],"savebar.template-saved":["Mall sparad"],"signature.address":["Adress"],"signature.company":["F\xF6retag"],"signature.email":["E-post"],"signature.greeting":["H\xE4lsning"],"signature.image-shape":["Bildform"],"signature.image-size":["Bildstorlek"],"signature.image-url":["Bildadress"],"signature.layout":["Layout"],"signature.layout.horizontal":["Horisontell"],"signature.layout.vertical":["Vertikal"],"signature.link-color":["L\xE4nkf\xE4rg"],"signature.name":["Namn"],"signature.name-color":["Namnf\xE4rg"],"signature.phone":["Telefon"],"signature.shape.circle":["Cirkel"],"signature.shape.rounded":["Rundad"],"signature.shape.square":["Kvadrat"],"signature.title":["Titel"],"signature.website":["Webbplats"],"size.lg":["Lg"],"size.md":["Md"],"size.sm":["Sm"],"size.xs":["Xs"],"sort.last-updated":["Senast uppdaterad"],"sort.name":["Namn (A\u2013\xD6)"],"sort.recently-created":["Nyligen skapad"],"style.alignment":["Justering"],"style.background-color":["Bakgrundsf\xE4rg"],"style.border-color":["Kantf\xE4rg"],"style.border-radius":["Kantradie"],"style.font-family":["Typsnitt"],"style.font-size":["Typsnittsstorlek"],"style.font-weight":["Typsnittsvikt"],"style.letter-spacing":["Teckenavst\xE5nd"],"style.line-height":["Radh\xF6jd"],"style.padding":["Utrymme"],"style.text-color":["Textf\xE4rg"],"tab.edit":["Redigera"],"tab.html-output":["HTML-utdata"],"tab.json-output":["JSON-utdata"],"tab.preview":["F\xF6rhandsgranska"],"tab.text-output":["Textutdata"],"time.days-short":[" d sedan"],"time.hours-short":[" tim sedan"],"time.just-now":["just nu"],"time.minutes-short":[" min sedan"],"time.months-short":[" m\xE5n sedan"],"time.years-short":[" \xE5r sedan"],"toolbar.bold":["Fet"],"toolbar.bold-shortcut":["Fet (Cmd+B)"],"toolbar.italic":["Kursiv"],"toolbar.italic-shortcut":["Kursiv (Cmd+I)"],"toolbar.link":["L\xE4nk"],"toolbar.link-shortcut":["L\xE4nk (Cmd+K)"],"tune.copy":["Kopiera block"],"tune.delete":["Ta bort"],"tune.move-down":["Flytta ner"],"tune.move-up":["Flytta upp"]}');
2025
2026
  var SUPPORTED_LOCALES = ["en", "sv", "fi"];
2026
2027
  var CATALOGS = {
2027
2028
  en: messages,
@@ -2056,20 +2057,48 @@ var EMPTY_DOCUMENT = {
2056
2057
  }
2057
2058
  }
2058
2059
  };
2059
- var editorStateStore = zustand.create(() => ({
2060
- document: EMPTY_DOCUMENT,
2061
- selectedBlockId: null,
2062
- selectedSidebarTab: "styles",
2063
- selectedMainTab: "editor",
2064
- selectedScreenSize: "desktop",
2065
- inspectorDrawerOpen: true,
2066
- samplesDrawerOpen: true,
2067
- persistenceEnabled: false,
2068
- lastFocusedEditable: null,
2069
- hoveredBlockId: null,
2070
- draggingBlock: null,
2071
- workspaceBackground: "checkerboard"
2072
- }));
2060
+ var COALESCE_MS = 300;
2061
+ function leadingThrottle(fn, wait) {
2062
+ let last = Number.NEGATIVE_INFINITY;
2063
+ return (...args) => {
2064
+ const now = Date.now();
2065
+ if (now - last >= wait) {
2066
+ last = now;
2067
+ fn(...args);
2068
+ }
2069
+ };
2070
+ }
2071
+ var editorStateStore = zustand.create()(
2072
+ zundo.temporal(
2073
+ () => ({
2074
+ document: EMPTY_DOCUMENT,
2075
+ selectedBlockId: null,
2076
+ selectedSidebarTab: "styles",
2077
+ selectedMainTab: "editor",
2078
+ selectedScreenSize: "desktop",
2079
+ inspectorDrawerOpen: true,
2080
+ samplesDrawerOpen: true,
2081
+ persistenceEnabled: false,
2082
+ lastFocusedEditable: null,
2083
+ hoveredBlockId: null,
2084
+ draggingBlock: null,
2085
+ workspaceBackground: "checkerboard"
2086
+ }),
2087
+ {
2088
+ limit: 100,
2089
+ // Only the document participates in history — selection, drawers, tabs
2090
+ // and other UI state are intentionally excluded.
2091
+ partialize: (state) => ({ document: state.document }),
2092
+ // Skip UI-only state changes: if the document reference is unchanged,
2093
+ // no history entry is recorded.
2094
+ equality: (a, b) => a.document === b.document,
2095
+ handleSet: (handleSet) => leadingThrottle(
2096
+ (pastState, replace, currentState) => handleSet(pastState, replace, currentState),
2097
+ COALESCE_MS
2098
+ )
2099
+ }
2100
+ )
2101
+ );
2073
2102
  function useDocument() {
2074
2103
  return editorStateStore((s) => s.document);
2075
2104
  }
@@ -2112,11 +2141,15 @@ function setSidebarTab(selectedSidebarTab) {
2112
2141
  return editorStateStore.setState({ selectedSidebarTab });
2113
2142
  }
2114
2143
  function resetDocument(document2) {
2115
- return editorStateStore.setState({
2144
+ const temporalApi = editorStateStore.temporal.getState();
2145
+ temporalApi.pause();
2146
+ editorStateStore.setState({
2116
2147
  document: document2,
2117
2148
  selectedSidebarTab: "styles",
2118
2149
  selectedBlockId: null
2119
2150
  });
2151
+ temporalApi.clear();
2152
+ temporalApi.resume();
2120
2153
  }
2121
2154
  function getDocument() {
2122
2155
  return editorStateStore.getState().document;
@@ -2127,6 +2160,9 @@ function setDocument(document2) {
2127
2160
  document: __spreadValues(__spreadValues({}, originalDocument), document2)
2128
2161
  });
2129
2162
  }
2163
+ function replaceDocument(document2) {
2164
+ editorStateStore.setState({ document: document2 });
2165
+ }
2130
2166
  function toggleInspectorDrawerOpen() {
2131
2167
  const inspectorDrawerOpen = !editorStateStore.getState().inspectorDrawerOpen;
2132
2168
  return editorStateStore.setState({ inspectorDrawerOpen });
@@ -2171,6 +2207,18 @@ function setWorkspaceBackground(workspaceBackground) {
2171
2207
  function setLastFocusedEditable(lastFocusedEditable) {
2172
2208
  return editorStateStore.setState({ lastFocusedEditable });
2173
2209
  }
2210
+ function undo() {
2211
+ editorStateStore.temporal.getState().undo();
2212
+ }
2213
+ function redo() {
2214
+ editorStateStore.temporal.getState().redo();
2215
+ }
2216
+ function useCanUndo() {
2217
+ return zustand.useStore(editorStateStore.temporal, (s) => s.pastStates.length > 0);
2218
+ }
2219
+ function useCanRedo() {
2220
+ return zustand.useStore(editorStateStore.temporal, (s) => s.futureStates.length > 0);
2221
+ }
2174
2222
 
2175
2223
  // src/app/save-payload.ts
2176
2224
  var ROOT_BLOCK_ID = "root";
@@ -2866,7 +2914,7 @@ function AvatarSidebarPanel({ data, setData }) {
2866
2914
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Avatar block" }, /* @__PURE__ */ React57__default.default.createElement(
2867
2915
  SliderInput,
2868
2916
  {
2869
- label: "Size",
2917
+ label: t("field.size", "Size"),
2870
2918
  iconLabel: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.AspectRatioOutlined, { sx: { color: "text.secondary" } }),
2871
2919
  units: "px",
2872
2920
  step: 3,
@@ -2880,19 +2928,19 @@ function AvatarSidebarPanel({ data, setData }) {
2880
2928
  ), /* @__PURE__ */ React57__default.default.createElement(
2881
2929
  RadioGroupInput,
2882
2930
  {
2883
- label: "Shape",
2931
+ label: t("avatar.shape", "Shape"),
2884
2932
  defaultValue: shape,
2885
2933
  onChange: (shape2) => {
2886
2934
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { shape: shape2 }) }));
2887
2935
  }
2888
2936
  },
2889
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "circle" }, "Circle"),
2890
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "square" }, "Square"),
2891
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded")
2937
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "circle" }, t("signature.shape.circle", "Circle")),
2938
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "square" }, t("signature.shape.square", "Square")),
2939
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rounded" }, t("signature.shape.rounded", "Rounded"))
2892
2940
  ), /* @__PURE__ */ React57__default.default.createElement(
2893
2941
  TextInput,
2894
2942
  {
2895
- label: "Image URL",
2943
+ label: t("signature.image-url", "Image URL"),
2896
2944
  defaultValue: imageUrl,
2897
2945
  onChange: (imageUrl2) => {
2898
2946
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }));
@@ -2901,7 +2949,7 @@ function AvatarSidebarPanel({ data, setData }) {
2901
2949
  ), /* @__PURE__ */ React57__default.default.createElement(
2902
2950
  TextInput,
2903
2951
  {
2904
- label: "Alt text",
2952
+ label: t("image.alt-text", "Alt text"),
2905
2953
  defaultValue: alt,
2906
2954
  onChange: (alt2) => {
2907
2955
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt: alt2 }) }));
@@ -2938,58 +2986,58 @@ function ButtonSidebarPanel({ data, setData }) {
2938
2986
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Button block" }, /* @__PURE__ */ React57__default.default.createElement(
2939
2987
  TextInput,
2940
2988
  {
2941
- label: "Text",
2989
+ label: t("field.text", "Text"),
2942
2990
  defaultValue: text,
2943
2991
  onChange: (text2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text: text2 }) }))
2944
2992
  }
2945
2993
  ), /* @__PURE__ */ React57__default.default.createElement(
2946
2994
  TextInput,
2947
2995
  {
2948
- label: "Url",
2996
+ label: t("field.url", "Url"),
2949
2997
  defaultValue: url,
2950
2998
  onChange: (url2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: url2 }) }))
2951
2999
  }
2952
3000
  ), /* @__PURE__ */ React57__default.default.createElement(
2953
3001
  RadioGroupInput,
2954
3002
  {
2955
- label: "Width",
3003
+ label: t("field.width", "Width"),
2956
3004
  defaultValue: fullWidth ? "FULL_WIDTH" : "AUTO",
2957
3005
  onChange: (v) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { fullWidth: v === "FULL_WIDTH" }) }))
2958
3006
  },
2959
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "FULL_WIDTH" }, "Full"),
2960
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "AUTO" }, "Auto")
3007
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "FULL_WIDTH" }, t("button.width.full", "Full")),
3008
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "AUTO" }, t("button.width.auto", "Auto"))
2961
3009
  ), /* @__PURE__ */ React57__default.default.createElement(
2962
3010
  RadioGroupInput,
2963
3011
  {
2964
- label: "Size",
3012
+ label: t("field.size", "Size"),
2965
3013
  defaultValue: size,
2966
3014
  onChange: (size2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { size: size2 }) }))
2967
3015
  },
2968
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "x-small" }, "Xs"),
2969
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "small" }, "Sm"),
2970
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "medium" }, "Md"),
2971
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "large" }, "Lg")
3016
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "x-small" }, t("size.xs", "Xs")),
3017
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "small" }, t("size.sm", "Sm")),
3018
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "medium" }, t("size.md", "Md")),
3019
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "large" }, t("size.lg", "Lg"))
2972
3020
  ), /* @__PURE__ */ React57__default.default.createElement(
2973
3021
  RadioGroupInput,
2974
3022
  {
2975
- label: "Style",
3023
+ label: t("field.style", "Style"),
2976
3024
  defaultValue: buttonStyle,
2977
3025
  onChange: (buttonStyle2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonStyle: buttonStyle2 }) }))
2978
3026
  },
2979
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rectangle" }, "Rectangle"),
2980
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded"),
2981
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "pill" }, "Pill")
3027
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rectangle" }, t("button.style.rectangle", "Rectangle")),
3028
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rounded" }, t("button.style.rounded", "Rounded")),
3029
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "pill" }, t("button.style.pill", "Pill"))
2982
3030
  ), /* @__PURE__ */ React57__default.default.createElement(
2983
3031
  ColorInput2,
2984
3032
  {
2985
- label: "Text color",
3033
+ label: t("style.text-color", "Text color"),
2986
3034
  defaultValue: buttonTextColor,
2987
3035
  onChange: (buttonTextColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonTextColor: buttonTextColor2 }) }))
2988
3036
  }
2989
3037
  ), /* @__PURE__ */ React57__default.default.createElement(
2990
3038
  ColorInput2,
2991
3039
  {
2992
- label: "Button color",
3040
+ label: t("button.color", "Button color"),
2993
3041
  defaultValue: buttonBackgroundColor,
2994
3042
  onChange: (buttonBackgroundColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonBackgroundColor: buttonBackgroundColor2 }) }))
2995
3043
  }
@@ -3109,7 +3157,7 @@ function ColumnsContainerPanel({ data, setData }) {
3109
3157
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Columns block" }, /* @__PURE__ */ React57__default.default.createElement(
3110
3158
  RadioGroupInput,
3111
3159
  {
3112
- label: "Number of columns",
3160
+ label: t("columns.count", "Number of columns"),
3113
3161
  defaultValue: ((_a = data.props) == null ? void 0 : _a.columnsCount) === 2 ? "2" : "3",
3114
3162
  onChange: (v) => {
3115
3163
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { columnsCount: v === "2" ? 2 : 3 }) }));
@@ -3128,7 +3176,7 @@ function ColumnsContainerPanel({ data, setData }) {
3128
3176
  ), /* @__PURE__ */ React57__default.default.createElement(
3129
3177
  SliderInput,
3130
3178
  {
3131
- label: "Columns gap",
3179
+ label: t("columns.gap", "Columns gap"),
3132
3180
  iconLabel: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.SpaceBarOutlined, { sx: { color: "text.secondary" } }),
3133
3181
  units: "px",
3134
3182
  step: 4,
@@ -3141,7 +3189,7 @@ function ColumnsContainerPanel({ data, setData }) {
3141
3189
  ), /* @__PURE__ */ React57__default.default.createElement(
3142
3190
  RadioGroupInput,
3143
3191
  {
3144
- label: "Alignment",
3192
+ label: t("style.alignment", "Alignment"),
3145
3193
  defaultValue: (_f = (_e = data.props) == null ? void 0 : _e.contentAlignment) != null ? _f : "middle",
3146
3194
  onChange: (contentAlignment) => {
3147
3195
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }));
@@ -3205,14 +3253,14 @@ function DividerSidebarPanel({ data, setData }) {
3205
3253
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Divider block" }, /* @__PURE__ */ React57__default.default.createElement(
3206
3254
  ColorInput2,
3207
3255
  {
3208
- label: "Color",
3256
+ label: t("divider.color", "Color"),
3209
3257
  defaultValue: lineColor,
3210
3258
  onChange: (lineColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { lineColor: lineColor2 }) }))
3211
3259
  }
3212
3260
  ), /* @__PURE__ */ React57__default.default.createElement(
3213
3261
  SliderInput,
3214
3262
  {
3215
- label: "Height",
3263
+ label: t("field.height", "Height"),
3216
3264
  iconLabel: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.HeightOutlined, { sx: { color: "text.secondary" } }),
3217
3265
  units: "px",
3218
3266
  step: 1,
@@ -3300,28 +3348,28 @@ function EmailLayoutSidebarFields({ data, setData }) {
3300
3348
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Global" }, /* @__PURE__ */ React57__default.default.createElement(
3301
3349
  BooleanInput,
3302
3350
  {
3303
- label: "Disable backdrop",
3351
+ label: t("global.disable-backdrop", "Disable backdrop"),
3304
3352
  defaultValue: backdropDisabled,
3305
3353
  onChange: (backdropDisabled2) => updateData(__spreadProps(__spreadValues({}, data), { backdropDisabled: backdropDisabled2 }))
3306
3354
  }
3307
3355
  ), !backdropDisabled && /* @__PURE__ */ React57__default.default.createElement(React57__default.default.Fragment, null, /* @__PURE__ */ React57__default.default.createElement(
3308
3356
  ColorInput2,
3309
3357
  {
3310
- label: "Backdrop color",
3358
+ label: t("global.backdrop-color", "Backdrop color"),
3311
3359
  defaultValue: (_b = data.backdropColor) != null ? _b : "#F5F5F5",
3312
3360
  onChange: (backdropColor) => updateData(__spreadProps(__spreadValues({}, data), { backdropColor }))
3313
3361
  }
3314
3362
  ), /* @__PURE__ */ React57__default.default.createElement(
3315
3363
  ColorInput2,
3316
3364
  {
3317
- label: "Canvas color",
3365
+ label: t("global.canvas-color", "Canvas color"),
3318
3366
  defaultValue: (_c = data.canvasColor) != null ? _c : "#FFFFFF",
3319
3367
  onChange: (canvasColor) => updateData(__spreadProps(__spreadValues({}, data), { canvasColor }))
3320
3368
  }
3321
3369
  ), /* @__PURE__ */ React57__default.default.createElement(
3322
3370
  NullableColorInput,
3323
3371
  {
3324
- label: "Canvas border color",
3372
+ label: t("global.canvas-border-color", "Canvas border color"),
3325
3373
  defaultValue: (_d = data.borderColor) != null ? _d : null,
3326
3374
  onChange: (borderColor) => updateData(__spreadProps(__spreadValues({}, data), { borderColor }))
3327
3375
  }
@@ -3334,21 +3382,21 @@ function EmailLayoutSidebarFields({ data, setData }) {
3334
3382
  marks: true,
3335
3383
  min: 0,
3336
3384
  max: 48,
3337
- label: "Canvas border radius",
3385
+ label: t("global.canvas-border-radius", "Canvas border radius"),
3338
3386
  defaultValue: (_e = data.borderRadius) != null ? _e : 0,
3339
3387
  onChange: (borderRadius) => updateData(__spreadProps(__spreadValues({}, data), { borderRadius }))
3340
3388
  }
3341
3389
  )), /* @__PURE__ */ React57__default.default.createElement(
3342
3390
  NullableFontFamily,
3343
3391
  {
3344
- label: "Font family",
3392
+ label: t("style.font-family", "Font family"),
3345
3393
  defaultValue: "MODERN_SANS",
3346
3394
  onChange: (fontFamily) => updateData(__spreadProps(__spreadValues({}, data), { fontFamily }))
3347
3395
  }
3348
3396
  ), /* @__PURE__ */ React57__default.default.createElement(
3349
3397
  ColorInput2,
3350
3398
  {
3351
- label: "Text color",
3399
+ label: t("style.text-color", "Text color"),
3352
3400
  defaultValue: (_f = data.textColor) != null ? _f : "#262626",
3353
3401
  onChange: (textColor) => updateData(__spreadProps(__spreadValues({}, data), { textColor }))
3354
3402
  }
@@ -3369,7 +3417,7 @@ function HeadingSidebarPanel({ data, setData }) {
3369
3417
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Heading block" }, /* @__PURE__ */ React57__default.default.createElement(
3370
3418
  TextInput,
3371
3419
  {
3372
- label: "Content",
3420
+ label: t("field.content", "Content"),
3373
3421
  rows: 3,
3374
3422
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.text) != null ? _b : HeadingPropsDefaults.text,
3375
3423
  onChange: (text) => {
@@ -3379,7 +3427,7 @@ function HeadingSidebarPanel({ data, setData }) {
3379
3427
  ), /* @__PURE__ */ React57__default.default.createElement(
3380
3428
  RadioGroupInput,
3381
3429
  {
3382
- label: "Level",
3430
+ label: t("field.level", "Level"),
3383
3431
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.level) != null ? _d : HeadingPropsDefaults.level,
3384
3432
  onChange: (level) => {
3385
3433
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { level }) }));
@@ -3421,7 +3469,7 @@ function HtmlSidebarPanel({ data, setData }) {
3421
3469
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Html block" }, /* @__PURE__ */ React57__default.default.createElement(
3422
3470
  TextInput,
3423
3471
  {
3424
- label: "Content",
3472
+ label: t("field.content", "Content"),
3425
3473
  rows: 5,
3426
3474
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.contents) != null ? _b : "",
3427
3475
  onChange: (contents) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contents }) }))
@@ -3637,7 +3685,7 @@ function ImageSidebarPanel({ data, setData }) {
3637
3685
  return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
3638
3686
  }
3639
3687
  },
3640
- uploading ? "Uploading\u2026" : "Upload"
3688
+ uploading ? t("image.uploading", "Uploading\u2026") : t("image.upload", "Upload")
3641
3689
  ), /* @__PURE__ */ React57__default.default.createElement(
3642
3690
  "input",
3643
3691
  {
@@ -3661,28 +3709,28 @@ function ImageSidebarPanel({ data, setData }) {
3661
3709
  startIcon: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.CollectionsOutlined, { fontSize: "small" }),
3662
3710
  onClick: () => setLibraryOpen(true)
3663
3711
  },
3664
- "Library"
3712
+ t("image.library", "Library")
3665
3713
  )), uploadError && /* @__PURE__ */ React57__default.default.createElement(material.Alert, { severity: "error", onClose: () => setUploadError(null), sx: { mt: 1 } }, uploadError), /* @__PURE__ */ React57__default.default.createElement(
3666
3714
  TextInput,
3667
3715
  {
3668
- label: "Source URL",
3716
+ label: t("image.source-url", "Source URL"),
3669
3717
  defaultValue: url,
3670
3718
  onChange: (v) => {
3671
3719
  const next = v.trim().length === 0 ? null : v.trim();
3672
3720
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: next }) }));
3673
3721
  }
3674
3722
  }
3675
- ), showHttpWarning && /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { mt: -1, mb: 1, display: "flex", alignItems: "flex-start", gap: 0.75 } }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.ErrorOutlineOutlined, { fontSize: "small", sx: { color: "warning.main", mt: "2px" } }), /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { fontSize: 12, color: "warning.dark" } }, "Non-HTTPS URL: Gmail and other clients strip mixed content. Use https:// for reliable delivery.")), /* @__PURE__ */ React57__default.default.createElement(
3723
+ ), showHttpWarning && /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { mt: -1, mb: 1, display: "flex", alignItems: "flex-start", gap: 0.75 } }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.ErrorOutlineOutlined, { fontSize: "small", sx: { color: "warning.main", mt: "2px" } }), /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { fontSize: 12, color: "warning.dark" } }, t("image.http-warning", "Non-HTTPS URL: Gmail and other clients strip mixed content. Use https:// for reliable delivery."))), /* @__PURE__ */ React57__default.default.createElement(
3676
3724
  TextInput,
3677
3725
  {
3678
- label: "Alt text",
3726
+ label: t("image.alt-text", "Alt text"),
3679
3727
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.alt) != null ? _d : "",
3680
3728
  onChange: (alt) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt }) }))
3681
3729
  }
3682
3730
  ), /* @__PURE__ */ React57__default.default.createElement(
3683
3731
  TextInput,
3684
3732
  {
3685
- label: "Click through URL",
3733
+ label: t("image.link-href", "Click through URL"),
3686
3734
  defaultValue: (_f = (_e = data.props) == null ? void 0 : _e.linkHref) != null ? _f : "",
3687
3735
  onChange: (v) => {
3688
3736
  const linkHref = v.trim().length === 0 ? null : v.trim();
@@ -3692,21 +3740,21 @@ function ImageSidebarPanel({ data, setData }) {
3692
3740
  ), /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57__default.default.createElement(
3693
3741
  TextDimensionInput,
3694
3742
  {
3695
- label: "Width",
3743
+ label: t("field.width", "Width"),
3696
3744
  defaultValue: (_g = data.props) == null ? void 0 : _g.width,
3697
3745
  onChange: (width) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { width }) }))
3698
3746
  }
3699
3747
  ), /* @__PURE__ */ React57__default.default.createElement(
3700
3748
  TextDimensionInput,
3701
3749
  {
3702
- label: "Height",
3750
+ label: t("field.height", "Height"),
3703
3751
  defaultValue: (_h = data.props) == null ? void 0 : _h.height,
3704
3752
  onChange: (height) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { height }) }))
3705
3753
  }
3706
3754
  )), /* @__PURE__ */ React57__default.default.createElement(
3707
3755
  RadioGroupInput,
3708
3756
  {
3709
- label: "Alignment",
3757
+ label: t("style.alignment", "Alignment"),
3710
3758
  defaultValue: (_j = (_i = data.props) == null ? void 0 : _i.contentAlignment) != null ? _j : "middle",
3711
3759
  onChange: (contentAlignment) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }))
3712
3760
  },
@@ -3762,70 +3810,70 @@ function SignatureSidebarPanel({ data, setData }) {
3762
3810
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Signature block" }, /* @__PURE__ */ React57__default.default.createElement(
3763
3811
  TextInput,
3764
3812
  {
3765
- label: "Greeting",
3813
+ label: t("signature.greeting", "Greeting"),
3766
3814
  defaultValue: greeting,
3767
3815
  onChange: (greeting2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { greeting: greeting2 }) }))
3768
3816
  }
3769
3817
  ), /* @__PURE__ */ React57__default.default.createElement(
3770
3818
  TextInput,
3771
3819
  {
3772
- label: "Name",
3820
+ label: t("signature.name", "Name"),
3773
3821
  defaultValue: name,
3774
3822
  onChange: (name2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { name: name2 }) }))
3775
3823
  }
3776
3824
  ), /* @__PURE__ */ React57__default.default.createElement(
3777
3825
  TextInput,
3778
3826
  {
3779
- label: "Title",
3827
+ label: t("signature.title", "Title"),
3780
3828
  defaultValue: title,
3781
3829
  onChange: (title2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { title: title2 }) }))
3782
3830
  }
3783
3831
  ), /* @__PURE__ */ React57__default.default.createElement(
3784
3832
  TextInput,
3785
3833
  {
3786
- label: "Company",
3834
+ label: t("signature.company", "Company"),
3787
3835
  defaultValue: company,
3788
3836
  onChange: (company2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { company: company2 }) }))
3789
3837
  }
3790
3838
  ), /* @__PURE__ */ React57__default.default.createElement(
3791
3839
  TextInput,
3792
3840
  {
3793
- label: "Address",
3841
+ label: t("signature.address", "Address"),
3794
3842
  defaultValue: address,
3795
3843
  onChange: (address2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { address: address2 }) }))
3796
3844
  }
3797
3845
  ), /* @__PURE__ */ React57__default.default.createElement(
3798
3846
  TextInput,
3799
3847
  {
3800
- label: "Email",
3848
+ label: t("signature.email", "Email"),
3801
3849
  defaultValue: email,
3802
3850
  onChange: (email2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { email: email2 }) }))
3803
3851
  }
3804
3852
  ), /* @__PURE__ */ React57__default.default.createElement(
3805
3853
  TextInput,
3806
3854
  {
3807
- label: "Phone",
3855
+ label: t("signature.phone", "Phone"),
3808
3856
  defaultValue: phone,
3809
3857
  onChange: (phone2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { phone: phone2 }) }))
3810
3858
  }
3811
3859
  ), /* @__PURE__ */ React57__default.default.createElement(
3812
3860
  TextInput,
3813
3861
  {
3814
- label: "Website",
3862
+ label: t("signature.website", "Website"),
3815
3863
  defaultValue: website,
3816
3864
  onChange: (website2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { website: website2 }) }))
3817
3865
  }
3818
3866
  ), /* @__PURE__ */ React57__default.default.createElement(
3819
3867
  TextInput,
3820
3868
  {
3821
- label: "Image URL",
3869
+ label: t("signature.image-url", "Image URL"),
3822
3870
  defaultValue: imageUrl,
3823
3871
  onChange: (imageUrl2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }))
3824
3872
  }
3825
3873
  ), /* @__PURE__ */ React57__default.default.createElement(
3826
3874
  SliderInput,
3827
3875
  {
3828
- label: "Image size",
3876
+ label: t("signature.image-size", "Image size"),
3829
3877
  iconLabel: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.AspectRatioOutlined, { sx: { color: "text.secondary" } }),
3830
3878
  units: "px",
3831
3879
  step: 4,
@@ -3837,40 +3885,40 @@ function SignatureSidebarPanel({ data, setData }) {
3837
3885
  ), /* @__PURE__ */ React57__default.default.createElement(
3838
3886
  RadioGroupInput,
3839
3887
  {
3840
- label: "Image shape",
3888
+ label: t("signature.image-shape", "Image shape"),
3841
3889
  defaultValue: imageShape,
3842
3890
  onChange: (imageShape2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageShape: imageShape2 }) }))
3843
3891
  },
3844
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "circle" }, "Circle"),
3845
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "square" }, "Square"),
3846
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rounded" }, "Rounded")
3892
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "circle" }, t("signature.shape.circle", "Circle")),
3893
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "square" }, t("signature.shape.square", "Square")),
3894
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "rounded" }, t("signature.shape.rounded", "Rounded"))
3847
3895
  ), /* @__PURE__ */ React57__default.default.createElement(
3848
3896
  RadioGroupInput,
3849
3897
  {
3850
- label: "Layout",
3898
+ label: t("signature.layout", "Layout"),
3851
3899
  defaultValue: layout,
3852
3900
  onChange: (layout2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { layout: layout2 }) }))
3853
3901
  },
3854
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "horizontal" }, "Horizontal"),
3855
- /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "vertical" }, "Vertical")
3902
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "horizontal" }, t("signature.layout.horizontal", "Horizontal")),
3903
+ /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "vertical" }, t("signature.layout.vertical", "Vertical"))
3856
3904
  ), /* @__PURE__ */ React57__default.default.createElement(
3857
3905
  ColorInput2,
3858
3906
  {
3859
- label: "Name color",
3907
+ label: t("signature.name-color", "Name color"),
3860
3908
  defaultValue: nameColor,
3861
3909
  onChange: (nameColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { nameColor: nameColor2 }) }))
3862
3910
  }
3863
3911
  ), /* @__PURE__ */ React57__default.default.createElement(
3864
3912
  ColorInput2,
3865
3913
  {
3866
- label: "Text color",
3914
+ label: t("style.text-color", "Text color"),
3867
3915
  defaultValue: textColor,
3868
3916
  onChange: (textColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { textColor: textColor2 }) }))
3869
3917
  }
3870
3918
  ), /* @__PURE__ */ React57__default.default.createElement(
3871
3919
  ColorInput2,
3872
3920
  {
3873
- label: "Link color",
3921
+ label: t("signature.link-color", "Link color"),
3874
3922
  defaultValue: linkColor,
3875
3923
  onChange: (linkColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { linkColor: linkColor2 }) }))
3876
3924
  }
@@ -3898,7 +3946,7 @@ function SpacerSidebarPanel({ data, setData }) {
3898
3946
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Spacer block" }, /* @__PURE__ */ React57__default.default.createElement(
3899
3947
  SliderInput,
3900
3948
  {
3901
- label: "Height",
3949
+ label: t("field.height", "Height"),
3902
3950
  iconLabel: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.HeightOutlined, { sx: { color: "text.secondary" } }),
3903
3951
  units: "px",
3904
3952
  step: 4,
@@ -3924,7 +3972,7 @@ function TextSidebarPanel({ data, setData }) {
3924
3972
  return /* @__PURE__ */ React57__default.default.createElement(BaseSidebarPanel, { title: "Text block" }, /* @__PURE__ */ React57__default.default.createElement(
3925
3973
  TextInput,
3926
3974
  {
3927
- label: "Content",
3975
+ label: t("field.content", "Content"),
3928
3976
  rows: 5,
3929
3977
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.text) != null ? _b : "",
3930
3978
  onChange: (text) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text }) }))
@@ -3932,7 +3980,7 @@ function TextSidebarPanel({ data, setData }) {
3932
3980
  ), /* @__PURE__ */ React57__default.default.createElement(
3933
3981
  BooleanInput,
3934
3982
  {
3935
- label: "Markdown",
3983
+ label: t("field.markdown", "Markdown"),
3936
3984
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.markdown) != null ? _d : false,
3937
3985
  onChange: (markdown) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { markdown }) }))
3938
3986
  }
@@ -4709,10 +4757,10 @@ function InspectorDrawer({
4709
4757
  variant: "fullWidth",
4710
4758
  sx: { "& .MuiTab-root": { minWidth: 0, px: 1, fontSize: 13 } }
4711
4759
  },
4712
- /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "styles", label: "Styles" }),
4713
- /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "block-configuration", label: "Inspect" }),
4714
- /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "variables", label: "Variables" }),
4715
- /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "template-settings", label: "Settings" })
4760
+ /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "styles", label: t("inspector.tab.styles", "Styles") }),
4761
+ /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "block-configuration", label: t("inspector.tab.inspect", "Inspect") }),
4762
+ /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "variables", label: t("inspector.tab.variables", "Variables") }),
4763
+ /* @__PURE__ */ React57__default.default.createElement(material.Tab, { value: "template-settings", label: t("inspector.tab.settings", "Settings") })
4716
4764
  ))),
4717
4765
  /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" } }, renderCurrentSidebarPanel())
4718
4766
  );
@@ -4758,17 +4806,17 @@ function relativeTime(iso) {
4758
4806
  if (Number.isNaN(date)) return null;
4759
4807
  const diffMs = Date.now() - date;
4760
4808
  const diffSec = Math.round(diffMs / 1e3);
4761
- if (diffSec < 60) return "just now";
4809
+ if (diffSec < 60) return t("time.just-now", "just now");
4762
4810
  const diffMin = Math.round(diffSec / 60);
4763
- if (diffMin < 60) return `${diffMin}m ago`;
4811
+ if (diffMin < 60) return `${diffMin}${t("time.minutes-short", "m ago")}`;
4764
4812
  const diffHr = Math.round(diffMin / 60);
4765
- if (diffHr < 24) return `${diffHr}h ago`;
4813
+ if (diffHr < 24) return `${diffHr}${t("time.hours-short", "h ago")}`;
4766
4814
  const diffDay = Math.round(diffHr / 24);
4767
- if (diffDay < 30) return `${diffDay}d ago`;
4815
+ if (diffDay < 30) return `${diffDay}${t("time.days-short", "d ago")}`;
4768
4816
  const diffMo = Math.round(diffDay / 30);
4769
- if (diffMo < 12) return `${diffMo}mo ago`;
4817
+ if (diffMo < 12) return `${diffMo}${t("time.months-short", "mo ago")}`;
4770
4818
  const diffYr = Math.round(diffMo / 12);
4771
- return `${diffYr}y ago`;
4819
+ return `${diffYr}${t("time.years-short", "y ago")}`;
4772
4820
  }
4773
4821
  function TemplateRow({
4774
4822
  template,
@@ -4882,12 +4930,12 @@ function TemplateRow({
4882
4930
  sx: { height: 18, fontSize: "0.65rem", "& .MuiChip-label": { px: 0.75 } }
4883
4931
  }
4884
4932
  ))))),
4885
- hasActions && /* @__PURE__ */ React57__default.default.createElement(React57__default.default.Fragment, null, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "More" }, /* @__PURE__ */ React57__default.default.createElement(
4933
+ hasActions && /* @__PURE__ */ React57__default.default.createElement(React57__default.default.Fragment, null, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("row.more", "More") }, /* @__PURE__ */ React57__default.default.createElement(
4886
4934
  material.IconButton,
4887
4935
  {
4888
4936
  size: "small",
4889
4937
  onClick: openMenu,
4890
- "aria-label": "Row actions",
4938
+ "aria-label": t("row.actions", "Row actions"),
4891
4939
  "aria-haspopup": "menu",
4892
4940
  "aria-expanded": Boolean(menuAnchor) || void 0,
4893
4941
  sx: {
@@ -4910,14 +4958,14 @@ function TemplateRow({
4910
4958
  transformOrigin: { vertical: "top", horizontal: "right" },
4911
4959
  slotProps: { paper: { sx: { minWidth: 200 } } }
4912
4960
  },
4913
- onRename && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onRename) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.DriveFileRenameOutlineOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, "Edit name & tags\u2026")),
4914
- onDuplicate && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onDuplicate) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, "Duplicate")),
4915
- onDuplicateAsTemplate && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onDuplicateAsTemplate) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.LibraryAddOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, "Duplicate as template")),
4916
- onPromote && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onPromote) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.FileUploadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, "Promote to sample")),
4917
- onDemote && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onDemote) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.FileDownloadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, "Demote to template")),
4961
+ onRename && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onRename) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.DriveFileRenameOutlineOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, t("row.edit-details", "Edit name & tags\u2026"))),
4962
+ onDuplicate && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onDuplicate) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.ContentCopyOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, t("row.duplicate", "Duplicate"))),
4963
+ onDuplicateAsTemplate && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onDuplicateAsTemplate) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.LibraryAddOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, t("row.duplicate-as-template", "Duplicate as template"))),
4964
+ onPromote && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onPromote) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.FileUploadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, t("row.promote", "Promote to sample"))),
4965
+ onDemote && /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { onClick: runAction(onDemote) }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, null, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.FileDownloadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, t("row.demote", "Demote to template"))),
4918
4966
  onDelete && [
4919
4967
  /* @__PURE__ */ React57__default.default.createElement(material.Divider, { key: "divider" }),
4920
- /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { key: "delete", onClick: runAction(onDelete), sx: { color: "error.main" } }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, { sx: { color: "error.main" } }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.DeleteOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, "Delete"))
4968
+ /* @__PURE__ */ React57__default.default.createElement(material.MenuItem, { key: "delete", onClick: runAction(onDelete), sx: { color: "error.main" } }, /* @__PURE__ */ React57__default.default.createElement(material.ListItemIcon, { sx: { color: "error.main" } }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.DeleteOutlined, { fontSize: "small" })), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, null, t("tune.delete", "Delete")))
4921
4969
  ]
4922
4970
  ))
4923
4971
  );
@@ -5474,7 +5522,7 @@ function NewTemplatePickerDialog({
5474
5522
  const [busy, setBusy] = React57.useState(false);
5475
5523
  React57.useEffect(() => {
5476
5524
  if (open) {
5477
- setName(defaultName != null ? defaultName : kind === "sample" ? "New sample" : "New template");
5525
+ setName(defaultName != null ? defaultName : t(kind === "sample" ? "drawer.new-sample" : "drawer.new-template", kind === "sample" ? "New sample" : "New template"));
5478
5526
  setSelectedStarter(null);
5479
5527
  setError(null);
5480
5528
  setBusy(false);
@@ -5482,9 +5530,9 @@ function NewTemplatePickerDialog({
5482
5530
  }, [open, defaultName, kind]);
5483
5531
  const validate = () => {
5484
5532
  const trimmed = name.trim();
5485
- if (!trimmed) return "Name is required";
5533
+ if (!trimmed) return t("picker.error-name-required", "Name is required");
5486
5534
  if (existingSlugs.some((s) => s.toLowerCase() === trimmed.toLowerCase())) {
5487
- return kind === "sample" ? "A sample with this name already exists" : "A template with this name already exists";
5535
+ return kind === "sample" ? t("picker.error-sample-taken", "A sample with this name already exists") : t("picker.error-template-taken", "A template with this name already exists");
5488
5536
  }
5489
5537
  return null;
5490
5538
  };
@@ -5503,7 +5551,7 @@ function NewTemplatePickerDialog({
5503
5551
  }
5504
5552
  });
5505
5553
  const pickable = samples.filter((s) => s.id !== "empty-email");
5506
- return /* @__PURE__ */ React57__default.default.createElement(material.Dialog, { open, onClose: busy ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57__default.default.createElement(material.DialogTitle, null, kind === "sample" ? "New sample" : "New template"), /* @__PURE__ */ React57__default.default.createElement(material.DialogContent, { dividers: true }, /* @__PURE__ */ React57__default.default.createElement(material.Typography, { variant: "subtitle2", sx: { mb: 1 } }, "Start from"), /* @__PURE__ */ React57__default.default.createElement(
5554
+ return /* @__PURE__ */ React57__default.default.createElement(material.Dialog, { open, onClose: busy ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57__default.default.createElement(material.DialogTitle, null, kind === "sample" ? t("picker.title-sample", "New sample") : t("picker.title-template", "New template")), /* @__PURE__ */ React57__default.default.createElement(material.DialogContent, { dividers: true }, /* @__PURE__ */ React57__default.default.createElement(material.Typography, { variant: "subtitle2", sx: { mb: 1 } }, t("picker.start-from", "Start from")), /* @__PURE__ */ React57__default.default.createElement(
5507
5555
  material.List,
5508
5556
  {
5509
5557
  dense: true,
@@ -5523,7 +5571,7 @@ function NewTemplatePickerDialog({
5523
5571
  selected: selectedStarter === null,
5524
5572
  onClick: () => setSelectedStarter(null)
5525
5573
  },
5526
- /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1 } }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.InsertDriveFileOutlined, { fontSize: "small", sx: { color: "text.secondary" } }), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, { primary: "Blank", secondary: "Start from an empty email" }))
5574
+ /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1 } }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.InsertDriveFileOutlined, { fontSize: "small", sx: { color: "text.secondary" } }), /* @__PURE__ */ React57__default.default.createElement(material.ListItemText, { primary: t("picker.blank-title", "Blank"), secondary: t("picker.blank-desc", "Start from an empty email") }))
5527
5575
  ),
5528
5576
  pickable.map((s) => /* @__PURE__ */ React57__default.default.createElement(
5529
5577
  material.ListItemButton,
@@ -5540,8 +5588,9 @@ function NewTemplatePickerDialog({
5540
5588
  autoFocus: true,
5541
5589
  fullWidth: true,
5542
5590
  size: "small",
5543
- label: "Name",
5591
+ label: t("rename.name-label", "Name"),
5544
5592
  value: name,
5593
+ onFocus: (e) => e.currentTarget.select(),
5545
5594
  onChange: (e) => {
5546
5595
  setName(e.target.value);
5547
5596
  if (error) setError(null);
@@ -5553,7 +5602,7 @@ function NewTemplatePickerDialog({
5553
5602
  helperText: error != null ? error : " ",
5554
5603
  disabled: busy
5555
5604
  }
5556
- )), /* @__PURE__ */ React57__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React57__default.default.createElement(material.Button, { onClick: onClose, disabled: busy }, "Cancel"), /* @__PURE__ */ React57__default.default.createElement(material.Button, { variant: "contained", onClick: handleCreate, disabled: busy }, busy ? "Creating\u2026" : `Create ${kind}`)));
5605
+ )), /* @__PURE__ */ React57__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React57__default.default.createElement(material.Button, { onClick: onClose, disabled: busy }, t("common.cancel", "Cancel")), /* @__PURE__ */ React57__default.default.createElement(material.Button, { variant: "contained", onClick: handleCreate, disabled: busy }, busy ? t("picker.creating", "Creating\u2026") : kind === "sample" ? t("picker.create-sample", "Create sample") : t("picker.create-template", "Create template"))));
5557
5606
  }
5558
5607
  function RenameDialog({
5559
5608
  open,
@@ -5592,12 +5641,12 @@ function RenameDialog({
5592
5641
  const handleSubmit = () => __async(null, null, function* () {
5593
5642
  const trimmedSlug = slug.trim();
5594
5643
  if (!trimmedSlug) {
5595
- setError("Please enter a name");
5644
+ setError(t("rename.error-empty", "Please enter a name"));
5596
5645
  return;
5597
5646
  }
5598
5647
  const slugChanged = trimmedSlug !== currentSlug;
5599
5648
  if (slugChanged && existingSlugs.some((s) => s.toLowerCase() === trimmedSlug.toLowerCase())) {
5600
- setError("A template with this name already exists");
5649
+ setError(t("rename.error-taken", "A template with this name already exists"));
5601
5650
  return;
5602
5651
  }
5603
5652
  if (!slugChanged && tagsUnchanged) {
@@ -5610,17 +5659,17 @@ function RenameDialog({
5610
5659
  onClose();
5611
5660
  } catch (e) {
5612
5661
  console.error("Error updating template details:", e);
5613
- setError("Failed to update template details");
5662
+ setError(t("rename.error-generic", "Failed to update template details"));
5614
5663
  } finally {
5615
5664
  setSubmitting(false);
5616
5665
  }
5617
5666
  });
5618
- return /* @__PURE__ */ React57__default.default.createElement(material.Dialog, { open, onClose: submitting ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57__default.default.createElement(material.DialogTitle, null, "Edit details"), /* @__PURE__ */ React57__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React57__default.default.createElement(
5667
+ return /* @__PURE__ */ React57__default.default.createElement(material.Dialog, { open, onClose: submitting ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57__default.default.createElement(material.DialogTitle, null, t("rename.title", "Edit details")), /* @__PURE__ */ React57__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React57__default.default.createElement(
5619
5668
  material.TextField,
5620
5669
  {
5621
5670
  autoFocus: true,
5622
5671
  margin: "dense",
5623
- label: "Name",
5672
+ label: t("rename.name-label", "Name"),
5624
5673
  fullWidth: true,
5625
5674
  variant: "outlined",
5626
5675
  value: slug,
@@ -5635,7 +5684,7 @@ function RenameDialog({
5635
5684
  if (e.key === "Enter" && !submitting) handleSubmit();
5636
5685
  }
5637
5686
  }
5638
- ), /* @__PURE__ */ React57__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 1, mb: 0.5 } }, "Tags"), tags.length > 0 ? /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, sx: { flexWrap: "wrap", gap: 0.5, mb: 1 } }, tags.map((tag) => /* @__PURE__ */ React57__default.default.createElement(
5687
+ ), /* @__PURE__ */ React57__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 1, mb: 0.5 } }, t("rename.tags", "Tags")), tags.length > 0 ? /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, sx: { flexWrap: "wrap", gap: 0.5, mb: 1 } }, tags.map((tag) => /* @__PURE__ */ React57__default.default.createElement(
5639
5688
  material.Chip,
5640
5689
  {
5641
5690
  key: tag,
@@ -5643,12 +5692,12 @@ function RenameDialog({
5643
5692
  size: "small",
5644
5693
  onDelete: submitting ? void 0 : () => removeTag(tag)
5645
5694
  }
5646
- ))) : /* @__PURE__ */ React57__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.disabled", display: "block", mb: 1 } }, "No tags yet. Suggested: ", /* @__PURE__ */ React57__default.default.createElement("i", null, "transactional"), ", ", /* @__PURE__ */ React57__default.default.createElement("i", null, "marketing"), "."), /* @__PURE__ */ React57__default.default.createElement(
5695
+ ))) : /* @__PURE__ */ React57__default.default.createElement(material.Typography, { variant: "caption", sx: { color: "text.disabled", display: "block", mb: 1 } }, t("rename.no-tags", "No tags yet.")), /* @__PURE__ */ React57__default.default.createElement(
5647
5696
  material.TextField,
5648
5697
  {
5649
5698
  size: "small",
5650
5699
  fullWidth: true,
5651
- placeholder: "Add a tag and press Enter",
5700
+ placeholder: t("rename.tag-placeholder", "Add a tag and press Enter"),
5652
5701
  value: tagInput,
5653
5702
  onChange: (e) => setTagInput(e.target.value),
5654
5703
  disabled: submitting,
@@ -5671,18 +5720,18 @@ function RenameDialog({
5671
5720
  startIcon: /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.AddOutlined, { fontSize: "small" }),
5672
5721
  sx: { textTransform: "none" }
5673
5722
  },
5674
- "Add"
5723
+ t("common.add", "Add")
5675
5724
  ))
5676
5725
  }
5677
5726
  }
5678
- ), /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { minHeight: 8 } })), /* @__PURE__ */ React57__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React57__default.default.createElement(material.Button, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ React57__default.default.createElement(
5727
+ ), /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { minHeight: 8 } })), /* @__PURE__ */ React57__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React57__default.default.createElement(material.Button, { onClick: onClose, disabled: submitting }, t("common.cancel", "Cancel")), /* @__PURE__ */ React57__default.default.createElement(
5679
5728
  material.Button,
5680
5729
  {
5681
5730
  onClick: handleSubmit,
5682
5731
  variant: "contained",
5683
5732
  disabled: !slug.trim() || submitting
5684
5733
  },
5685
- submitting ? "Saving\u2026" : "Save"
5734
+ submitting ? t("common.saving", "Saving\u2026") : t("common.save", "Save")
5686
5735
  )));
5687
5736
  }
5688
5737
  function SaveTemplateDialog({
@@ -5691,7 +5740,8 @@ function SaveTemplateDialog({
5691
5740
  onSave,
5692
5741
  onNameChange,
5693
5742
  defaultName = "",
5694
- error: externalError = null
5743
+ error: externalError = null,
5744
+ mode = "save-as"
5695
5745
  }) {
5696
5746
  const [templateName, setTemplateName] = React57.useState(defaultName);
5697
5747
  const [internalError, setInternalError] = React57.useState("");
@@ -5715,7 +5765,7 @@ function SaveTemplateDialog({
5715
5765
  };
5716
5766
  const handleSave = () => __async(null, null, function* () {
5717
5767
  if (!templateName.trim()) {
5718
- setInternalError("Please enter a template name");
5768
+ setInternalError(t("save-dialog.error-empty-name", "Please enter a template name"));
5719
5769
  return;
5720
5770
  }
5721
5771
  setIsSubmitting(true);
@@ -5752,19 +5802,20 @@ function SaveTemplateDialog({
5752
5802
  maxWidth: "sm",
5753
5803
  fullWidth: true
5754
5804
  },
5755
- /* @__PURE__ */ React57__default.default.createElement(material.DialogTitle, null, "Save Email Template"),
5805
+ /* @__PURE__ */ React57__default.default.createElement(material.DialogTitle, null, mode === "new" ? t("save-dialog.title-new", "Create a new template") : t("save-dialog.title", "Save as a new template")),
5756
5806
  /* @__PURE__ */ React57__default.default.createElement(material.DialogContent, null, /* @__PURE__ */ React57__default.default.createElement(material.Box, { sx: { pt: 1 } }, /* @__PURE__ */ React57__default.default.createElement(
5757
5807
  material.TextField,
5758
5808
  {
5759
5809
  autoFocus: true,
5760
5810
  margin: "dense",
5761
5811
  id: "template-name",
5762
- label: "Template Name",
5812
+ label: t("save-dialog.name-label", "Template Name"),
5763
5813
  type: "text",
5764
5814
  fullWidth: true,
5765
5815
  variant: "outlined",
5766
5816
  value: templateName,
5767
5817
  onChange: handleNameChange,
5818
+ onFocus: (e) => e.currentTarget.select(),
5768
5819
  error: !!displayError,
5769
5820
  helperText: displayError,
5770
5821
  onKeyPress: (e) => {
@@ -5775,7 +5826,7 @@ function SaveTemplateDialog({
5775
5826
  disabled: isSubmitting
5776
5827
  }
5777
5828
  ))),
5778
- /* @__PURE__ */ React57__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React57__default.default.createElement(material.Button, { onClick: handleCancel, disabled: isSubmitting }, "Cancel"), /* @__PURE__ */ React57__default.default.createElement(
5829
+ /* @__PURE__ */ React57__default.default.createElement(material.DialogActions, null, /* @__PURE__ */ React57__default.default.createElement(material.Button, { onClick: handleCancel, disabled: isSubmitting }, t("common.cancel", "Cancel")), /* @__PURE__ */ React57__default.default.createElement(
5779
5830
  material.Button,
5780
5831
  {
5781
5832
  onClick: handleSave,
@@ -5783,7 +5834,7 @@ function SaveTemplateDialog({
5783
5834
  color: "primary",
5784
5835
  disabled: !templateName.trim() || !!displayError || isSubmitting
5785
5836
  },
5786
- isSubmitting ? "Saving..." : "Save Template"
5837
+ isSubmitting ? t("save-dialog.saving", "Saving...") : mode === "new" ? t("save-dialog.create", "Create") : t("save-dialog.save", "Save")
5787
5838
  ))
5788
5839
  );
5789
5840
  }
@@ -5805,12 +5856,12 @@ var empty_email_message_default = EMPTY_EMAIL_MESSAGE;
5805
5856
 
5806
5857
  // src/app/templates-drawer/index.tsx
5807
5858
  var SAMPLES_DRAWER_WIDTH = 320;
5808
- var EMPTY_TEMPLATE = {
5859
+ var buildEmptyTemplate = () => ({
5809
5860
  id: "empty-email",
5810
- slug: "Empty email",
5861
+ slug: t("empty.slug", "Empty email"),
5811
5862
  kind: "sample",
5812
- description: "A blank email template to start from scratch"
5813
- };
5863
+ description: t("empty.description", "A blank email template to start from scratch")
5864
+ });
5814
5865
  var SORT_OPTIONS = [
5815
5866
  { value: "updatedAt", labelKey: "sort.last-updated", fallback: "Last updated" },
5816
5867
  { value: "createdAt", labelKey: "sort.recently-created", fallback: "Recently created" },
@@ -5845,7 +5896,7 @@ function SamplesDrawer({
5845
5896
  const samplesDrawerOpen = useSamplesDrawerOpen();
5846
5897
  const { setCurrentTemplate, loadTemplate: ctxLoadTemplate } = useEmailEditor();
5847
5898
  const { showMessage } = useSnackbar();
5848
- const [samples, setSamples] = React57.useState([EMPTY_TEMPLATE]);
5899
+ const [samples, setSamples] = React57.useState([buildEmptyTemplate()]);
5849
5900
  const [templates, setTemplates] = React57.useState([]);
5850
5901
  const [loadingSamples, setLoadingSamples] = React57.useState(false);
5851
5902
  const [loadingTemplates, setLoadingTemplates] = React57.useState(false);
@@ -5874,10 +5925,10 @@ function SamplesDrawer({
5874
5925
  loadSamples().then((results) => {
5875
5926
  const normalized = withKind(results, "sample");
5876
5927
  const existingEmpty = normalized.find((s) => s.id === "empty-email");
5877
- setSamples(existingEmpty ? normalized : [EMPTY_TEMPLATE, ...normalized]);
5928
+ setSamples(existingEmpty ? normalized : [buildEmptyTemplate(), ...normalized]);
5878
5929
  }).catch((error) => {
5879
5930
  console.error("Failed to load samples:", error);
5880
- setSamples([EMPTY_TEMPLATE]);
5931
+ setSamples([buildEmptyTemplate()]);
5881
5932
  }).finally(() => setLoadingSamples(false));
5882
5933
  }, [enabled, samplesDrawerOpen, loadSamples]);
5883
5934
  const refreshTemplates = () => __async(null, null, function* () {
@@ -6863,7 +6914,7 @@ function EmailLayoutEditor(props) {
6863
6914
  }
6864
6915
  }
6865
6916
  delete nDocument[selectedBlockId];
6866
- resetDocument(nDocument);
6917
+ replaceDocument(nDocument);
6867
6918
  }, [selectedBlockId, document2]);
6868
6919
  const handleCopy = React57.useCallback((e) => {
6869
6920
  if (!(e.metaKey || e.ctrlKey) || e.key !== "c") return;
@@ -6906,7 +6957,7 @@ function EmailLayoutEditor(props) {
6906
6957
  childrenIds: currentChildrenIds
6907
6958
  })
6908
6959
  };
6909
- resetDocument(doc);
6960
+ replaceDocument(doc);
6910
6961
  setSelectedBlockId(newRootId);
6911
6962
  }), [document2, childrenIds, selectedBlockId, currentBlockId]);
6912
6963
  React57.useEffect(() => {
@@ -6947,7 +6998,6 @@ function EmailLayoutEditor(props) {
6947
6998
  }
6948
6999
  }
6949
7000
  );
6950
- const WORKSPACE_BG = "#e7e8ec";
6951
7001
  const CARD_MAX_WIDTH = 664;
6952
7002
  const cardStyle = {
6953
7003
  maxWidth: CARD_MAX_WIDTH,
@@ -6963,7 +7013,6 @@ function EmailLayoutEditor(props) {
6963
7013
  setSelectedBlockId(null);
6964
7014
  },
6965
7015
  style: __spreadProps(__spreadValues({}, baseStyle), {
6966
- backgroundColor: WORKSPACE_BG,
6967
7016
  padding: "32px",
6968
7017
  width: "100%",
6969
7018
  minHeight: "100%"
@@ -6988,7 +7037,6 @@ function EmailLayoutEditor(props) {
6988
7037
  setSelectedBlockId(null);
6989
7038
  },
6990
7039
  style: __spreadProps(__spreadValues({}, baseStyle), {
6991
- backgroundColor: WORKSPACE_BG,
6992
7040
  padding: "32px 16px",
6993
7041
  width: "100%",
6994
7042
  minHeight: "100%"
@@ -8457,31 +8505,31 @@ function MainTabsGroup() {
8457
8505
  material.Tab,
8458
8506
  {
8459
8507
  value: "editor",
8460
- label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "Edit" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.EditOutlined, { fontSize: "small" }))
8508
+ label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("tab.edit", "Edit") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.EditOutlined, { fontSize: "small" }))
8461
8509
  }
8462
8510
  ), /* @__PURE__ */ React57__default.default.createElement(
8463
8511
  material.Tab,
8464
8512
  {
8465
8513
  value: "preview",
8466
- label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "Preview" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.PreviewOutlined, { fontSize: "small" }))
8514
+ label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("tab.preview", "Preview") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.PreviewOutlined, { fontSize: "small" }))
8467
8515
  }
8468
8516
  ), /* @__PURE__ */ React57__default.default.createElement(
8469
8517
  material.Tab,
8470
8518
  {
8471
8519
  value: "html",
8472
- label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "HTML output" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.CodeOutlined, { fontSize: "small" }))
8520
+ label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("tab.html-output", "HTML output") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.CodeOutlined, { fontSize: "small" }))
8473
8521
  }
8474
8522
  ), /* @__PURE__ */ React57__default.default.createElement(
8475
8523
  material.Tab,
8476
8524
  {
8477
8525
  value: "text",
8478
- label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "Plain text output" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.SubjectOutlined, { fontSize: "small" }))
8526
+ label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("tab.text-output", "Plain text output") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.SubjectOutlined, { fontSize: "small" }))
8479
8527
  }
8480
8528
  ), /* @__PURE__ */ React57__default.default.createElement(
8481
8529
  material.Tab,
8482
8530
  {
8483
8531
  value: "json",
8484
- label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "JSON output" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.DataObjectOutlined, { fontSize: "small" }))
8532
+ label: /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("tab.json-output", "JSON output") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.DataObjectOutlined, { fontSize: "small" }))
8485
8533
  }
8486
8534
  ));
8487
8535
  }
@@ -8626,6 +8674,7 @@ function SaveBar({ loadTemplates, saveAs }) {
8626
8674
  SaveTemplateDialog,
8627
8675
  {
8628
8676
  open: dialogMode !== null,
8677
+ mode: dialogMode === "new-blank" ? "new" : "save-as",
8629
8678
  onClose: () => {
8630
8679
  setDialogMode(null);
8631
8680
  setNameError(null);
@@ -8637,6 +8686,64 @@ function SaveBar({ loadTemplates, saveAs }) {
8637
8686
  }
8638
8687
  ));
8639
8688
  }
8689
+ function isMac() {
8690
+ if (typeof navigator === "undefined") return false;
8691
+ const platform = (navigator.platform || "").toLowerCase();
8692
+ if (platform.includes("mac")) return true;
8693
+ const ua = (navigator.userAgent || "").toLowerCase();
8694
+ return ua.includes("mac") && !ua.includes("windows");
8695
+ }
8696
+ function isEditableTarget(target) {
8697
+ if (!(target instanceof HTMLElement)) return false;
8698
+ const tag = target.tagName;
8699
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
8700
+ if (target.isContentEditable) return true;
8701
+ return false;
8702
+ }
8703
+ function UndoRedoButtons() {
8704
+ const canUndo = useCanUndo();
8705
+ const canRedo = useCanRedo();
8706
+ const mac = isMac();
8707
+ const modKey = mac ? "\u2318" : "Ctrl";
8708
+ const undoHint = `${modKey}+Z`;
8709
+ const redoHint = mac ? `${modKey}+\u21E7+Z` : `${modKey}+Shift+Z / ${modKey}+Y`;
8710
+ React57.useEffect(() => {
8711
+ const onKeyDown = (e) => {
8712
+ const mod = mac ? e.metaKey : e.ctrlKey;
8713
+ if (!mod) return;
8714
+ if (isEditableTarget(e.target)) return;
8715
+ const key = e.key.toLowerCase();
8716
+ if (key === "z" && !e.shiftKey) {
8717
+ e.preventDefault();
8718
+ undo();
8719
+ } else if (key === "z" && e.shiftKey || key === "y" && !mac) {
8720
+ e.preventDefault();
8721
+ redo();
8722
+ }
8723
+ };
8724
+ window.addEventListener("keydown", onKeyDown);
8725
+ return () => window.removeEventListener("keydown", onKeyDown);
8726
+ }, [mac]);
8727
+ return /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 0.5, alignItems: "center" }, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: `${t("undo.tooltip", "Undo")} (${undoHint})` }, /* @__PURE__ */ React57__default.default.createElement("span", null, /* @__PURE__ */ React57__default.default.createElement(
8728
+ material.IconButton,
8729
+ {
8730
+ size: "small",
8731
+ onClick: undo,
8732
+ disabled: !canUndo,
8733
+ "aria-label": t("undo.label", "Undo")
8734
+ },
8735
+ /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.UndoOutlined, { fontSize: "small" })
8736
+ ))), /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: `${t("redo.tooltip", "Redo")} (${redoHint})` }, /* @__PURE__ */ React57__default.default.createElement("span", null, /* @__PURE__ */ React57__default.default.createElement(
8737
+ material.IconButton,
8738
+ {
8739
+ size: "small",
8740
+ onClick: redo,
8741
+ disabled: !canRedo,
8742
+ "aria-label": t("redo.label", "Redo")
8743
+ },
8744
+ /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.RedoOutlined, { fontSize: "small" })
8745
+ ))));
8746
+ }
8640
8747
  function SubjectInput() {
8641
8748
  var _a;
8642
8749
  const document2 = useDocument();
@@ -8865,7 +8972,7 @@ function ImageDropPasteHandler({ enabled, children }) {
8865
8972
 
8866
8973
  // src/app/email-canvas/index.tsx
8867
8974
  var WORKSPACE_SOLID = "#e7e8ec";
8868
- var WORKSPACE_CHECKERBOARD = "repeating-conic-gradient(#eceef2 0% 25%, #dfe1e6 0% 50%) 50% / 24px 24px";
8975
+ var WORKSPACE_CHECKERBOARD = "repeating-conic-gradient(#eceef2 0% 25%, #dfe1e6 0% 50%) 50% / 12px 12px";
8869
8976
  function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true }) {
8870
8977
  const document2 = useDocument();
8871
8978
  const selectedMainTab = useSelectedMainTab();
@@ -8935,7 +9042,7 @@ function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true })
8935
9042
  alignItems: "center"
8936
9043
  },
8937
9044
  samplesDrawerEnabled && /* @__PURE__ */ React57__default.default.createElement(ToggleSamplesPanelButton, null),
8938
- /* @__PURE__ */ React57__default.default.createElement(material.Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57__default.default.createElement(MainTabsGroup, null)), /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57__default.default.createElement(material.ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "desktop" }, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "Desktop view" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "mobile" }, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: "Mobile view" }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.PhoneIphoneOutlined, { fontSize: "small" })))))),
9045
+ /* @__PURE__ */ React57__default.default.createElement(material.Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57__default.default.createElement(MainTabsGroup, null)), /* @__PURE__ */ React57__default.default.createElement(material.Stack, { direction: "row", spacing: 2, alignItems: "center" }, selectedMainTab === "editor" && /* @__PURE__ */ React57__default.default.createElement(UndoRedoButtons, null), /* @__PURE__ */ React57__default.default.createElement(material.ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "desktop" }, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("canvas.desktop-view", "Desktop view") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57__default.default.createElement(material.ToggleButton, { value: "mobile" }, /* @__PURE__ */ React57__default.default.createElement(material.Tooltip, { title: t("canvas.mobile-view", "Mobile view") }, /* @__PURE__ */ React57__default.default.createElement(iconsMaterial.PhoneIphoneOutlined, { fontSize: "small" })))))),
8939
9046
  /* @__PURE__ */ React57__default.default.createElement(ToggleInspectorPanelButton, null)
8940
9047
  ), selectedMainTab === "editor" && /* @__PURE__ */ React57__default.default.createElement(SubjectInput, null), selectedMainTab === "preview" && /* @__PURE__ */ React57__default.default.createElement(SubjectPreview, null), /* @__PURE__ */ React57__default.default.createElement(ImageDropPasteHandler, { enabled: selectedMainTab === "editor" }, /* @__PURE__ */ React57__default.default.createElement(
8941
9048
  material.Box,