@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.js CHANGED
@@ -8,8 +8,9 @@ import { createTheme, alpha, lighten, darken } from '@mui/material/styles';
8
8
  import { I18nProvider, Trans } from '@lingui/react';
9
9
  import { MenuItem, Stack, ThemeProvider, CssBaseline, useTheme, Drawer, Box, Tabs, Tab, Typography, Tooltip, IconButton, TextField, InputAdornment, Chip, CircularProgress, Alert, ToggleButtonGroup, ToggleButton, Snackbar, Menu, ListItemIcon, ListItemText, Divider as Divider$1, Dialog, DialogTitle, DialogContent, Button as Button$1, DialogActions, List, ListItemButton, InputBase, AlertTitle, FormControlLabel, Switch, InputLabel, Slider, ButtonBase, Popper, Paper, Fade } from '@mui/material';
10
10
  import { i18n } from '@lingui/core';
11
- import { create } from 'zustand';
12
- import { AddOutlined, SearchOutlined, MonitorOutlined, PhoneIphoneOutlined, MoreVertOutlined, DriveFileRenameOutlineOutlined, ContentCopyOutlined, LibraryAddOutlined, FileUploadOutlined, FileDownloadOutlined, DeleteOutlined, InsertDriveFileOutlined, DescriptionOutlined, EditOutlined, PreviewOutlined, CodeOutlined, SubjectOutlined, DataObjectOutlined, LastPageOutlined, AppRegistrationOutlined, CloudUploadOutlined, SaveOutlined, SaveAsOutlined, ViewColumnSharp, ExpandMore, ChevronRight, KeyboardArrowUp, KeyboardArrowDown, FirstPageOutlined, MenuOutlined, GridOnOutlined, SquareOutlined, CheckOutlined, InputOutlined, DeleteOutline, RoundedCornerOutlined, AspectRatioOutlined, HeightOutlined, CollectionsOutlined, ErrorOutlineOutlined, VerticalAlignTopOutlined, VerticalAlignCenterOutlined, VerticalAlignBottomOutlined, SpaceBarOutlined, BusinessOutlined, ViewColumnOutlined, HtmlOutlined, Crop32Outlined, HorizontalRuleOutlined, ContactMailOutlined, AccountCircleOutlined, ImageOutlined, SmartButtonOutlined, NotesOutlined, HMobiledataOutlined, DashboardOutlined, CloseOutlined, AlignVerticalTopOutlined, AlignVerticalBottomOutlined, AlignHorizontalLeftOutlined, AlignHorizontalRightOutlined, FormatAlignLeftOutlined, FormatAlignCenterOutlined, FormatAlignRightOutlined, FormatLineSpacingOutlined, TextFieldsOutlined, FormatBoldOutlined, FormatItalicOutlined, LinkOutlined, ArrowUpwardOutlined, ArrowDownwardOutlined } from '@mui/icons-material';
11
+ import { create, useStore } from 'zustand';
12
+ import { temporal } from 'zundo';
13
+ import { AddOutlined, SearchOutlined, MonitorOutlined, PhoneIphoneOutlined, MoreVertOutlined, DriveFileRenameOutlineOutlined, ContentCopyOutlined, LibraryAddOutlined, FileUploadOutlined, FileDownloadOutlined, DeleteOutlined, InsertDriveFileOutlined, DescriptionOutlined, EditOutlined, PreviewOutlined, CodeOutlined, SubjectOutlined, DataObjectOutlined, UndoOutlined, RedoOutlined, LastPageOutlined, AppRegistrationOutlined, CloudUploadOutlined, SaveOutlined, SaveAsOutlined, ViewColumnSharp, ExpandMore, ChevronRight, KeyboardArrowUp, KeyboardArrowDown, FirstPageOutlined, MenuOutlined, GridOnOutlined, SquareOutlined, CheckOutlined, InputOutlined, DeleteOutline, RoundedCornerOutlined, AspectRatioOutlined, HeightOutlined, CollectionsOutlined, ErrorOutlineOutlined, VerticalAlignTopOutlined, VerticalAlignCenterOutlined, VerticalAlignBottomOutlined, SpaceBarOutlined, BusinessOutlined, ViewColumnOutlined, HtmlOutlined, Crop32Outlined, HorizontalRuleOutlined, ContactMailOutlined, AccountCircleOutlined, ImageOutlined, SmartButtonOutlined, NotesOutlined, HMobiledataOutlined, DashboardOutlined, CloseOutlined, AlignVerticalTopOutlined, AlignVerticalBottomOutlined, AlignHorizontalLeftOutlined, AlignHorizontalRightOutlined, FormatAlignLeftOutlined, FormatAlignCenterOutlined, FormatAlignRightOutlined, FormatLineSpacingOutlined, TextFieldsOutlined, FormatBoldOutlined, FormatItalicOutlined, LinkOutlined, ArrowUpwardOutlined, ArrowDownwardOutlined } from '@mui/icons-material';
13
14
  import { HexColorPicker, HexColorInput } from 'react-colorful';
14
15
  import hljs from 'highlight.js';
15
16
  import jsonHighlighter from 'highlight.js/lib/languages/json';
@@ -2004,13 +2005,13 @@ var THEME = createTheme(BASE_THEME, {
2004
2005
  var theme_default = THEME;
2005
2006
 
2006
2007
  // src/locales/en/messages.ts
2007
- 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"]}');
2008
+ 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"]}');
2008
2009
 
2009
2010
  // src/locales/fi/messages.ts
2010
- 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"]}');
2011
+ 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"]}');
2011
2012
 
2012
2013
  // src/locales/sv/messages.ts
2013
- 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"]}');
2014
+ 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"]}');
2014
2015
  var SUPPORTED_LOCALES = ["en", "sv", "fi"];
2015
2016
  var CATALOGS = {
2016
2017
  en: messages,
@@ -2045,20 +2046,48 @@ var EMPTY_DOCUMENT = {
2045
2046
  }
2046
2047
  }
2047
2048
  };
2048
- var editorStateStore = create(() => ({
2049
- document: EMPTY_DOCUMENT,
2050
- selectedBlockId: null,
2051
- selectedSidebarTab: "styles",
2052
- selectedMainTab: "editor",
2053
- selectedScreenSize: "desktop",
2054
- inspectorDrawerOpen: true,
2055
- samplesDrawerOpen: true,
2056
- persistenceEnabled: false,
2057
- lastFocusedEditable: null,
2058
- hoveredBlockId: null,
2059
- draggingBlock: null,
2060
- workspaceBackground: "checkerboard"
2061
- }));
2049
+ var COALESCE_MS = 300;
2050
+ function leadingThrottle(fn, wait) {
2051
+ let last = Number.NEGATIVE_INFINITY;
2052
+ return (...args) => {
2053
+ const now = Date.now();
2054
+ if (now - last >= wait) {
2055
+ last = now;
2056
+ fn(...args);
2057
+ }
2058
+ };
2059
+ }
2060
+ var editorStateStore = create()(
2061
+ temporal(
2062
+ () => ({
2063
+ document: EMPTY_DOCUMENT,
2064
+ selectedBlockId: null,
2065
+ selectedSidebarTab: "styles",
2066
+ selectedMainTab: "editor",
2067
+ selectedScreenSize: "desktop",
2068
+ inspectorDrawerOpen: true,
2069
+ samplesDrawerOpen: true,
2070
+ persistenceEnabled: false,
2071
+ lastFocusedEditable: null,
2072
+ hoveredBlockId: null,
2073
+ draggingBlock: null,
2074
+ workspaceBackground: "checkerboard"
2075
+ }),
2076
+ {
2077
+ limit: 100,
2078
+ // Only the document participates in history — selection, drawers, tabs
2079
+ // and other UI state are intentionally excluded.
2080
+ partialize: (state) => ({ document: state.document }),
2081
+ // Skip UI-only state changes: if the document reference is unchanged,
2082
+ // no history entry is recorded.
2083
+ equality: (a, b) => a.document === b.document,
2084
+ handleSet: (handleSet) => leadingThrottle(
2085
+ (pastState, replace, currentState) => handleSet(pastState, replace, currentState),
2086
+ COALESCE_MS
2087
+ )
2088
+ }
2089
+ )
2090
+ );
2062
2091
  function useDocument() {
2063
2092
  return editorStateStore((s) => s.document);
2064
2093
  }
@@ -2101,11 +2130,15 @@ function setSidebarTab(selectedSidebarTab) {
2101
2130
  return editorStateStore.setState({ selectedSidebarTab });
2102
2131
  }
2103
2132
  function resetDocument(document2) {
2104
- return editorStateStore.setState({
2133
+ const temporalApi = editorStateStore.temporal.getState();
2134
+ temporalApi.pause();
2135
+ editorStateStore.setState({
2105
2136
  document: document2,
2106
2137
  selectedSidebarTab: "styles",
2107
2138
  selectedBlockId: null
2108
2139
  });
2140
+ temporalApi.clear();
2141
+ temporalApi.resume();
2109
2142
  }
2110
2143
  function getDocument() {
2111
2144
  return editorStateStore.getState().document;
@@ -2116,6 +2149,9 @@ function setDocument(document2) {
2116
2149
  document: __spreadValues(__spreadValues({}, originalDocument), document2)
2117
2150
  });
2118
2151
  }
2152
+ function replaceDocument(document2) {
2153
+ editorStateStore.setState({ document: document2 });
2154
+ }
2119
2155
  function toggleInspectorDrawerOpen() {
2120
2156
  const inspectorDrawerOpen = !editorStateStore.getState().inspectorDrawerOpen;
2121
2157
  return editorStateStore.setState({ inspectorDrawerOpen });
@@ -2160,6 +2196,18 @@ function setWorkspaceBackground(workspaceBackground) {
2160
2196
  function setLastFocusedEditable(lastFocusedEditable) {
2161
2197
  return editorStateStore.setState({ lastFocusedEditable });
2162
2198
  }
2199
+ function undo() {
2200
+ editorStateStore.temporal.getState().undo();
2201
+ }
2202
+ function redo() {
2203
+ editorStateStore.temporal.getState().redo();
2204
+ }
2205
+ function useCanUndo() {
2206
+ return useStore(editorStateStore.temporal, (s) => s.pastStates.length > 0);
2207
+ }
2208
+ function useCanRedo() {
2209
+ return useStore(editorStateStore.temporal, (s) => s.futureStates.length > 0);
2210
+ }
2163
2211
 
2164
2212
  // src/app/save-payload.ts
2165
2213
  var ROOT_BLOCK_ID = "root";
@@ -2855,7 +2903,7 @@ function AvatarSidebarPanel({ data, setData }) {
2855
2903
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Avatar block" }, /* @__PURE__ */ React57.createElement(
2856
2904
  SliderInput,
2857
2905
  {
2858
- label: "Size",
2906
+ label: t("field.size", "Size"),
2859
2907
  iconLabel: /* @__PURE__ */ React57.createElement(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
2860
2908
  units: "px",
2861
2909
  step: 3,
@@ -2869,19 +2917,19 @@ function AvatarSidebarPanel({ data, setData }) {
2869
2917
  ), /* @__PURE__ */ React57.createElement(
2870
2918
  RadioGroupInput,
2871
2919
  {
2872
- label: "Shape",
2920
+ label: t("avatar.shape", "Shape"),
2873
2921
  defaultValue: shape,
2874
2922
  onChange: (shape2) => {
2875
2923
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { shape: shape2 }) }));
2876
2924
  }
2877
2925
  },
2878
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "circle" }, "Circle"),
2879
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "square" }, "Square"),
2880
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rounded" }, "Rounded")
2926
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "circle" }, t("signature.shape.circle", "Circle")),
2927
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "square" }, t("signature.shape.square", "Square")),
2928
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rounded" }, t("signature.shape.rounded", "Rounded"))
2881
2929
  ), /* @__PURE__ */ React57.createElement(
2882
2930
  TextInput,
2883
2931
  {
2884
- label: "Image URL",
2932
+ label: t("signature.image-url", "Image URL"),
2885
2933
  defaultValue: imageUrl,
2886
2934
  onChange: (imageUrl2) => {
2887
2935
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }));
@@ -2890,7 +2938,7 @@ function AvatarSidebarPanel({ data, setData }) {
2890
2938
  ), /* @__PURE__ */ React57.createElement(
2891
2939
  TextInput,
2892
2940
  {
2893
- label: "Alt text",
2941
+ label: t("image.alt-text", "Alt text"),
2894
2942
  defaultValue: alt,
2895
2943
  onChange: (alt2) => {
2896
2944
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt: alt2 }) }));
@@ -2927,58 +2975,58 @@ function ButtonSidebarPanel({ data, setData }) {
2927
2975
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Button block" }, /* @__PURE__ */ React57.createElement(
2928
2976
  TextInput,
2929
2977
  {
2930
- label: "Text",
2978
+ label: t("field.text", "Text"),
2931
2979
  defaultValue: text,
2932
2980
  onChange: (text2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text: text2 }) }))
2933
2981
  }
2934
2982
  ), /* @__PURE__ */ React57.createElement(
2935
2983
  TextInput,
2936
2984
  {
2937
- label: "Url",
2985
+ label: t("field.url", "Url"),
2938
2986
  defaultValue: url,
2939
2987
  onChange: (url2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: url2 }) }))
2940
2988
  }
2941
2989
  ), /* @__PURE__ */ React57.createElement(
2942
2990
  RadioGroupInput,
2943
2991
  {
2944
- label: "Width",
2992
+ label: t("field.width", "Width"),
2945
2993
  defaultValue: fullWidth ? "FULL_WIDTH" : "AUTO",
2946
2994
  onChange: (v) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { fullWidth: v === "FULL_WIDTH" }) }))
2947
2995
  },
2948
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "FULL_WIDTH" }, "Full"),
2949
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "AUTO" }, "Auto")
2996
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "FULL_WIDTH" }, t("button.width.full", "Full")),
2997
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "AUTO" }, t("button.width.auto", "Auto"))
2950
2998
  ), /* @__PURE__ */ React57.createElement(
2951
2999
  RadioGroupInput,
2952
3000
  {
2953
- label: "Size",
3001
+ label: t("field.size", "Size"),
2954
3002
  defaultValue: size,
2955
3003
  onChange: (size2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { size: size2 }) }))
2956
3004
  },
2957
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "x-small" }, "Xs"),
2958
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "small" }, "Sm"),
2959
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "medium" }, "Md"),
2960
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "large" }, "Lg")
3005
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "x-small" }, t("size.xs", "Xs")),
3006
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "small" }, t("size.sm", "Sm")),
3007
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "medium" }, t("size.md", "Md")),
3008
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "large" }, t("size.lg", "Lg"))
2961
3009
  ), /* @__PURE__ */ React57.createElement(
2962
3010
  RadioGroupInput,
2963
3011
  {
2964
- label: "Style",
3012
+ label: t("field.style", "Style"),
2965
3013
  defaultValue: buttonStyle,
2966
3014
  onChange: (buttonStyle2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonStyle: buttonStyle2 }) }))
2967
3015
  },
2968
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rectangle" }, "Rectangle"),
2969
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rounded" }, "Rounded"),
2970
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "pill" }, "Pill")
3016
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rectangle" }, t("button.style.rectangle", "Rectangle")),
3017
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rounded" }, t("button.style.rounded", "Rounded")),
3018
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "pill" }, t("button.style.pill", "Pill"))
2971
3019
  ), /* @__PURE__ */ React57.createElement(
2972
3020
  ColorInput2,
2973
3021
  {
2974
- label: "Text color",
3022
+ label: t("style.text-color", "Text color"),
2975
3023
  defaultValue: buttonTextColor,
2976
3024
  onChange: (buttonTextColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonTextColor: buttonTextColor2 }) }))
2977
3025
  }
2978
3026
  ), /* @__PURE__ */ React57.createElement(
2979
3027
  ColorInput2,
2980
3028
  {
2981
- label: "Button color",
3029
+ label: t("button.color", "Button color"),
2982
3030
  defaultValue: buttonBackgroundColor,
2983
3031
  onChange: (buttonBackgroundColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { buttonBackgroundColor: buttonBackgroundColor2 }) }))
2984
3032
  }
@@ -3098,7 +3146,7 @@ function ColumnsContainerPanel({ data, setData }) {
3098
3146
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Columns block" }, /* @__PURE__ */ React57.createElement(
3099
3147
  RadioGroupInput,
3100
3148
  {
3101
- label: "Number of columns",
3149
+ label: t("columns.count", "Number of columns"),
3102
3150
  defaultValue: ((_a = data.props) == null ? void 0 : _a.columnsCount) === 2 ? "2" : "3",
3103
3151
  onChange: (v) => {
3104
3152
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { columnsCount: v === "2" ? 2 : 3 }) }));
@@ -3117,7 +3165,7 @@ function ColumnsContainerPanel({ data, setData }) {
3117
3165
  ), /* @__PURE__ */ React57.createElement(
3118
3166
  SliderInput,
3119
3167
  {
3120
- label: "Columns gap",
3168
+ label: t("columns.gap", "Columns gap"),
3121
3169
  iconLabel: /* @__PURE__ */ React57.createElement(SpaceBarOutlined, { sx: { color: "text.secondary" } }),
3122
3170
  units: "px",
3123
3171
  step: 4,
@@ -3130,7 +3178,7 @@ function ColumnsContainerPanel({ data, setData }) {
3130
3178
  ), /* @__PURE__ */ React57.createElement(
3131
3179
  RadioGroupInput,
3132
3180
  {
3133
- label: "Alignment",
3181
+ label: t("style.alignment", "Alignment"),
3134
3182
  defaultValue: (_f = (_e = data.props) == null ? void 0 : _e.contentAlignment) != null ? _f : "middle",
3135
3183
  onChange: (contentAlignment) => {
3136
3184
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }));
@@ -3194,14 +3242,14 @@ function DividerSidebarPanel({ data, setData }) {
3194
3242
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Divider block" }, /* @__PURE__ */ React57.createElement(
3195
3243
  ColorInput2,
3196
3244
  {
3197
- label: "Color",
3245
+ label: t("divider.color", "Color"),
3198
3246
  defaultValue: lineColor,
3199
3247
  onChange: (lineColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { lineColor: lineColor2 }) }))
3200
3248
  }
3201
3249
  ), /* @__PURE__ */ React57.createElement(
3202
3250
  SliderInput,
3203
3251
  {
3204
- label: "Height",
3252
+ label: t("field.height", "Height"),
3205
3253
  iconLabel: /* @__PURE__ */ React57.createElement(HeightOutlined, { sx: { color: "text.secondary" } }),
3206
3254
  units: "px",
3207
3255
  step: 1,
@@ -3289,28 +3337,28 @@ function EmailLayoutSidebarFields({ data, setData }) {
3289
3337
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Global" }, /* @__PURE__ */ React57.createElement(
3290
3338
  BooleanInput,
3291
3339
  {
3292
- label: "Disable backdrop",
3340
+ label: t("global.disable-backdrop", "Disable backdrop"),
3293
3341
  defaultValue: backdropDisabled,
3294
3342
  onChange: (backdropDisabled2) => updateData(__spreadProps(__spreadValues({}, data), { backdropDisabled: backdropDisabled2 }))
3295
3343
  }
3296
3344
  ), !backdropDisabled && /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(
3297
3345
  ColorInput2,
3298
3346
  {
3299
- label: "Backdrop color",
3347
+ label: t("global.backdrop-color", "Backdrop color"),
3300
3348
  defaultValue: (_b = data.backdropColor) != null ? _b : "#F5F5F5",
3301
3349
  onChange: (backdropColor) => updateData(__spreadProps(__spreadValues({}, data), { backdropColor }))
3302
3350
  }
3303
3351
  ), /* @__PURE__ */ React57.createElement(
3304
3352
  ColorInput2,
3305
3353
  {
3306
- label: "Canvas color",
3354
+ label: t("global.canvas-color", "Canvas color"),
3307
3355
  defaultValue: (_c = data.canvasColor) != null ? _c : "#FFFFFF",
3308
3356
  onChange: (canvasColor) => updateData(__spreadProps(__spreadValues({}, data), { canvasColor }))
3309
3357
  }
3310
3358
  ), /* @__PURE__ */ React57.createElement(
3311
3359
  NullableColorInput,
3312
3360
  {
3313
- label: "Canvas border color",
3361
+ label: t("global.canvas-border-color", "Canvas border color"),
3314
3362
  defaultValue: (_d = data.borderColor) != null ? _d : null,
3315
3363
  onChange: (borderColor) => updateData(__spreadProps(__spreadValues({}, data), { borderColor }))
3316
3364
  }
@@ -3323,21 +3371,21 @@ function EmailLayoutSidebarFields({ data, setData }) {
3323
3371
  marks: true,
3324
3372
  min: 0,
3325
3373
  max: 48,
3326
- label: "Canvas border radius",
3374
+ label: t("global.canvas-border-radius", "Canvas border radius"),
3327
3375
  defaultValue: (_e = data.borderRadius) != null ? _e : 0,
3328
3376
  onChange: (borderRadius) => updateData(__spreadProps(__spreadValues({}, data), { borderRadius }))
3329
3377
  }
3330
3378
  )), /* @__PURE__ */ React57.createElement(
3331
3379
  NullableFontFamily,
3332
3380
  {
3333
- label: "Font family",
3381
+ label: t("style.font-family", "Font family"),
3334
3382
  defaultValue: "MODERN_SANS",
3335
3383
  onChange: (fontFamily) => updateData(__spreadProps(__spreadValues({}, data), { fontFamily }))
3336
3384
  }
3337
3385
  ), /* @__PURE__ */ React57.createElement(
3338
3386
  ColorInput2,
3339
3387
  {
3340
- label: "Text color",
3388
+ label: t("style.text-color", "Text color"),
3341
3389
  defaultValue: (_f = data.textColor) != null ? _f : "#262626",
3342
3390
  onChange: (textColor) => updateData(__spreadProps(__spreadValues({}, data), { textColor }))
3343
3391
  }
@@ -3358,7 +3406,7 @@ function HeadingSidebarPanel({ data, setData }) {
3358
3406
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Heading block" }, /* @__PURE__ */ React57.createElement(
3359
3407
  TextInput,
3360
3408
  {
3361
- label: "Content",
3409
+ label: t("field.content", "Content"),
3362
3410
  rows: 3,
3363
3411
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.text) != null ? _b : HeadingPropsDefaults.text,
3364
3412
  onChange: (text) => {
@@ -3368,7 +3416,7 @@ function HeadingSidebarPanel({ data, setData }) {
3368
3416
  ), /* @__PURE__ */ React57.createElement(
3369
3417
  RadioGroupInput,
3370
3418
  {
3371
- label: "Level",
3419
+ label: t("field.level", "Level"),
3372
3420
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.level) != null ? _d : HeadingPropsDefaults.level,
3373
3421
  onChange: (level) => {
3374
3422
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { level }) }));
@@ -3410,7 +3458,7 @@ function HtmlSidebarPanel({ data, setData }) {
3410
3458
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Html block" }, /* @__PURE__ */ React57.createElement(
3411
3459
  TextInput,
3412
3460
  {
3413
- label: "Content",
3461
+ label: t("field.content", "Content"),
3414
3462
  rows: 5,
3415
3463
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.contents) != null ? _b : "",
3416
3464
  onChange: (contents) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contents }) }))
@@ -3626,7 +3674,7 @@ function ImageSidebarPanel({ data, setData }) {
3626
3674
  return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
3627
3675
  }
3628
3676
  },
3629
- uploading ? "Uploading\u2026" : "Upload"
3677
+ uploading ? t("image.uploading", "Uploading\u2026") : t("image.upload", "Upload")
3630
3678
  ), /* @__PURE__ */ React57.createElement(
3631
3679
  "input",
3632
3680
  {
@@ -3650,28 +3698,28 @@ function ImageSidebarPanel({ data, setData }) {
3650
3698
  startIcon: /* @__PURE__ */ React57.createElement(CollectionsOutlined, { fontSize: "small" }),
3651
3699
  onClick: () => setLibraryOpen(true)
3652
3700
  },
3653
- "Library"
3701
+ t("image.library", "Library")
3654
3702
  )), uploadError && /* @__PURE__ */ React57.createElement(Alert, { severity: "error", onClose: () => setUploadError(null), sx: { mt: 1 } }, uploadError), /* @__PURE__ */ React57.createElement(
3655
3703
  TextInput,
3656
3704
  {
3657
- label: "Source URL",
3705
+ label: t("image.source-url", "Source URL"),
3658
3706
  defaultValue: url,
3659
3707
  onChange: (v) => {
3660
3708
  const next = v.trim().length === 0 ? null : v.trim();
3661
3709
  updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { url: next }) }));
3662
3710
  }
3663
3711
  }
3664
- ), showHttpWarning && /* @__PURE__ */ React57.createElement(Box, { sx: { mt: -1, mb: 1, display: "flex", alignItems: "flex-start", gap: 0.75 } }, /* @__PURE__ */ React57.createElement(ErrorOutlineOutlined, { fontSize: "small", sx: { color: "warning.main", mt: "2px" } }), /* @__PURE__ */ React57.createElement(Box, { sx: { fontSize: 12, color: "warning.dark" } }, "Non-HTTPS URL: Gmail and other clients strip mixed content. Use https:// for reliable delivery.")), /* @__PURE__ */ React57.createElement(
3712
+ ), showHttpWarning && /* @__PURE__ */ React57.createElement(Box, { sx: { mt: -1, mb: 1, display: "flex", alignItems: "flex-start", gap: 0.75 } }, /* @__PURE__ */ React57.createElement(ErrorOutlineOutlined, { fontSize: "small", sx: { color: "warning.main", mt: "2px" } }), /* @__PURE__ */ React57.createElement(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.createElement(
3665
3713
  TextInput,
3666
3714
  {
3667
- label: "Alt text",
3715
+ label: t("image.alt-text", "Alt text"),
3668
3716
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.alt) != null ? _d : "",
3669
3717
  onChange: (alt) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { alt }) }))
3670
3718
  }
3671
3719
  ), /* @__PURE__ */ React57.createElement(
3672
3720
  TextInput,
3673
3721
  {
3674
- label: "Click through URL",
3722
+ label: t("image.link-href", "Click through URL"),
3675
3723
  defaultValue: (_f = (_e = data.props) == null ? void 0 : _e.linkHref) != null ? _f : "",
3676
3724
  onChange: (v) => {
3677
3725
  const linkHref = v.trim().length === 0 ? null : v.trim();
@@ -3681,21 +3729,21 @@ function ImageSidebarPanel({ data, setData }) {
3681
3729
  ), /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57.createElement(
3682
3730
  TextDimensionInput,
3683
3731
  {
3684
- label: "Width",
3732
+ label: t("field.width", "Width"),
3685
3733
  defaultValue: (_g = data.props) == null ? void 0 : _g.width,
3686
3734
  onChange: (width) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { width }) }))
3687
3735
  }
3688
3736
  ), /* @__PURE__ */ React57.createElement(
3689
3737
  TextDimensionInput,
3690
3738
  {
3691
- label: "Height",
3739
+ label: t("field.height", "Height"),
3692
3740
  defaultValue: (_h = data.props) == null ? void 0 : _h.height,
3693
3741
  onChange: (height) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { height }) }))
3694
3742
  }
3695
3743
  )), /* @__PURE__ */ React57.createElement(
3696
3744
  RadioGroupInput,
3697
3745
  {
3698
- label: "Alignment",
3746
+ label: t("style.alignment", "Alignment"),
3699
3747
  defaultValue: (_j = (_i = data.props) == null ? void 0 : _i.contentAlignment) != null ? _j : "middle",
3700
3748
  onChange: (contentAlignment) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { contentAlignment }) }))
3701
3749
  },
@@ -3751,70 +3799,70 @@ function SignatureSidebarPanel({ data, setData }) {
3751
3799
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Signature block" }, /* @__PURE__ */ React57.createElement(
3752
3800
  TextInput,
3753
3801
  {
3754
- label: "Greeting",
3802
+ label: t("signature.greeting", "Greeting"),
3755
3803
  defaultValue: greeting,
3756
3804
  onChange: (greeting2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { greeting: greeting2 }) }))
3757
3805
  }
3758
3806
  ), /* @__PURE__ */ React57.createElement(
3759
3807
  TextInput,
3760
3808
  {
3761
- label: "Name",
3809
+ label: t("signature.name", "Name"),
3762
3810
  defaultValue: name,
3763
3811
  onChange: (name2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { name: name2 }) }))
3764
3812
  }
3765
3813
  ), /* @__PURE__ */ React57.createElement(
3766
3814
  TextInput,
3767
3815
  {
3768
- label: "Title",
3816
+ label: t("signature.title", "Title"),
3769
3817
  defaultValue: title,
3770
3818
  onChange: (title2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { title: title2 }) }))
3771
3819
  }
3772
3820
  ), /* @__PURE__ */ React57.createElement(
3773
3821
  TextInput,
3774
3822
  {
3775
- label: "Company",
3823
+ label: t("signature.company", "Company"),
3776
3824
  defaultValue: company,
3777
3825
  onChange: (company2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { company: company2 }) }))
3778
3826
  }
3779
3827
  ), /* @__PURE__ */ React57.createElement(
3780
3828
  TextInput,
3781
3829
  {
3782
- label: "Address",
3830
+ label: t("signature.address", "Address"),
3783
3831
  defaultValue: address,
3784
3832
  onChange: (address2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { address: address2 }) }))
3785
3833
  }
3786
3834
  ), /* @__PURE__ */ React57.createElement(
3787
3835
  TextInput,
3788
3836
  {
3789
- label: "Email",
3837
+ label: t("signature.email", "Email"),
3790
3838
  defaultValue: email,
3791
3839
  onChange: (email2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { email: email2 }) }))
3792
3840
  }
3793
3841
  ), /* @__PURE__ */ React57.createElement(
3794
3842
  TextInput,
3795
3843
  {
3796
- label: "Phone",
3844
+ label: t("signature.phone", "Phone"),
3797
3845
  defaultValue: phone,
3798
3846
  onChange: (phone2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { phone: phone2 }) }))
3799
3847
  }
3800
3848
  ), /* @__PURE__ */ React57.createElement(
3801
3849
  TextInput,
3802
3850
  {
3803
- label: "Website",
3851
+ label: t("signature.website", "Website"),
3804
3852
  defaultValue: website,
3805
3853
  onChange: (website2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { website: website2 }) }))
3806
3854
  }
3807
3855
  ), /* @__PURE__ */ React57.createElement(
3808
3856
  TextInput,
3809
3857
  {
3810
- label: "Image URL",
3858
+ label: t("signature.image-url", "Image URL"),
3811
3859
  defaultValue: imageUrl,
3812
3860
  onChange: (imageUrl2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageUrl: imageUrl2 }) }))
3813
3861
  }
3814
3862
  ), /* @__PURE__ */ React57.createElement(
3815
3863
  SliderInput,
3816
3864
  {
3817
- label: "Image size",
3865
+ label: t("signature.image-size", "Image size"),
3818
3866
  iconLabel: /* @__PURE__ */ React57.createElement(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
3819
3867
  units: "px",
3820
3868
  step: 4,
@@ -3826,40 +3874,40 @@ function SignatureSidebarPanel({ data, setData }) {
3826
3874
  ), /* @__PURE__ */ React57.createElement(
3827
3875
  RadioGroupInput,
3828
3876
  {
3829
- label: "Image shape",
3877
+ label: t("signature.image-shape", "Image shape"),
3830
3878
  defaultValue: imageShape,
3831
3879
  onChange: (imageShape2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { imageShape: imageShape2 }) }))
3832
3880
  },
3833
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "circle" }, "Circle"),
3834
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "square" }, "Square"),
3835
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rounded" }, "Rounded")
3881
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "circle" }, t("signature.shape.circle", "Circle")),
3882
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "square" }, t("signature.shape.square", "Square")),
3883
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "rounded" }, t("signature.shape.rounded", "Rounded"))
3836
3884
  ), /* @__PURE__ */ React57.createElement(
3837
3885
  RadioGroupInput,
3838
3886
  {
3839
- label: "Layout",
3887
+ label: t("signature.layout", "Layout"),
3840
3888
  defaultValue: layout,
3841
3889
  onChange: (layout2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { layout: layout2 }) }))
3842
3890
  },
3843
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "horizontal" }, "Horizontal"),
3844
- /* @__PURE__ */ React57.createElement(ToggleButton, { value: "vertical" }, "Vertical")
3891
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "horizontal" }, t("signature.layout.horizontal", "Horizontal")),
3892
+ /* @__PURE__ */ React57.createElement(ToggleButton, { value: "vertical" }, t("signature.layout.vertical", "Vertical"))
3845
3893
  ), /* @__PURE__ */ React57.createElement(
3846
3894
  ColorInput2,
3847
3895
  {
3848
- label: "Name color",
3896
+ label: t("signature.name-color", "Name color"),
3849
3897
  defaultValue: nameColor,
3850
3898
  onChange: (nameColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { nameColor: nameColor2 }) }))
3851
3899
  }
3852
3900
  ), /* @__PURE__ */ React57.createElement(
3853
3901
  ColorInput2,
3854
3902
  {
3855
- label: "Text color",
3903
+ label: t("style.text-color", "Text color"),
3856
3904
  defaultValue: textColor,
3857
3905
  onChange: (textColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { textColor: textColor2 }) }))
3858
3906
  }
3859
3907
  ), /* @__PURE__ */ React57.createElement(
3860
3908
  ColorInput2,
3861
3909
  {
3862
- label: "Link color",
3910
+ label: t("signature.link-color", "Link color"),
3863
3911
  defaultValue: linkColor,
3864
3912
  onChange: (linkColor2) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { linkColor: linkColor2 }) }))
3865
3913
  }
@@ -3887,7 +3935,7 @@ function SpacerSidebarPanel({ data, setData }) {
3887
3935
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Spacer block" }, /* @__PURE__ */ React57.createElement(
3888
3936
  SliderInput,
3889
3937
  {
3890
- label: "Height",
3938
+ label: t("field.height", "Height"),
3891
3939
  iconLabel: /* @__PURE__ */ React57.createElement(HeightOutlined, { sx: { color: "text.secondary" } }),
3892
3940
  units: "px",
3893
3941
  step: 4,
@@ -3913,7 +3961,7 @@ function TextSidebarPanel({ data, setData }) {
3913
3961
  return /* @__PURE__ */ React57.createElement(BaseSidebarPanel, { title: "Text block" }, /* @__PURE__ */ React57.createElement(
3914
3962
  TextInput,
3915
3963
  {
3916
- label: "Content",
3964
+ label: t("field.content", "Content"),
3917
3965
  rows: 5,
3918
3966
  defaultValue: (_b = (_a = data.props) == null ? void 0 : _a.text) != null ? _b : "",
3919
3967
  onChange: (text) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { text }) }))
@@ -3921,7 +3969,7 @@ function TextSidebarPanel({ data, setData }) {
3921
3969
  ), /* @__PURE__ */ React57.createElement(
3922
3970
  BooleanInput,
3923
3971
  {
3924
- label: "Markdown",
3972
+ label: t("field.markdown", "Markdown"),
3925
3973
  defaultValue: (_d = (_c = data.props) == null ? void 0 : _c.markdown) != null ? _d : false,
3926
3974
  onChange: (markdown) => updateData(__spreadProps(__spreadValues({}, data), { props: __spreadProps(__spreadValues({}, data.props), { markdown }) }))
3927
3975
  }
@@ -4698,10 +4746,10 @@ function InspectorDrawer({
4698
4746
  variant: "fullWidth",
4699
4747
  sx: { "& .MuiTab-root": { minWidth: 0, px: 1, fontSize: 13 } }
4700
4748
  },
4701
- /* @__PURE__ */ React57.createElement(Tab, { value: "styles", label: "Styles" }),
4702
- /* @__PURE__ */ React57.createElement(Tab, { value: "block-configuration", label: "Inspect" }),
4703
- /* @__PURE__ */ React57.createElement(Tab, { value: "variables", label: "Variables" }),
4704
- /* @__PURE__ */ React57.createElement(Tab, { value: "template-settings", label: "Settings" })
4749
+ /* @__PURE__ */ React57.createElement(Tab, { value: "styles", label: t("inspector.tab.styles", "Styles") }),
4750
+ /* @__PURE__ */ React57.createElement(Tab, { value: "block-configuration", label: t("inspector.tab.inspect", "Inspect") }),
4751
+ /* @__PURE__ */ React57.createElement(Tab, { value: "variables", label: t("inspector.tab.variables", "Variables") }),
4752
+ /* @__PURE__ */ React57.createElement(Tab, { value: "template-settings", label: t("inspector.tab.settings", "Settings") })
4705
4753
  ))),
4706
4754
  /* @__PURE__ */ React57.createElement(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" } }, renderCurrentSidebarPanel())
4707
4755
  );
@@ -4747,17 +4795,17 @@ function relativeTime(iso) {
4747
4795
  if (Number.isNaN(date)) return null;
4748
4796
  const diffMs = Date.now() - date;
4749
4797
  const diffSec = Math.round(diffMs / 1e3);
4750
- if (diffSec < 60) return "just now";
4798
+ if (diffSec < 60) return t("time.just-now", "just now");
4751
4799
  const diffMin = Math.round(diffSec / 60);
4752
- if (diffMin < 60) return `${diffMin}m ago`;
4800
+ if (diffMin < 60) return `${diffMin}${t("time.minutes-short", "m ago")}`;
4753
4801
  const diffHr = Math.round(diffMin / 60);
4754
- if (diffHr < 24) return `${diffHr}h ago`;
4802
+ if (diffHr < 24) return `${diffHr}${t("time.hours-short", "h ago")}`;
4755
4803
  const diffDay = Math.round(diffHr / 24);
4756
- if (diffDay < 30) return `${diffDay}d ago`;
4804
+ if (diffDay < 30) return `${diffDay}${t("time.days-short", "d ago")}`;
4757
4805
  const diffMo = Math.round(diffDay / 30);
4758
- if (diffMo < 12) return `${diffMo}mo ago`;
4806
+ if (diffMo < 12) return `${diffMo}${t("time.months-short", "mo ago")}`;
4759
4807
  const diffYr = Math.round(diffMo / 12);
4760
- return `${diffYr}y ago`;
4808
+ return `${diffYr}${t("time.years-short", "y ago")}`;
4761
4809
  }
4762
4810
  function TemplateRow({
4763
4811
  template,
@@ -4871,12 +4919,12 @@ function TemplateRow({
4871
4919
  sx: { height: 18, fontSize: "0.65rem", "& .MuiChip-label": { px: 0.75 } }
4872
4920
  }
4873
4921
  ))))),
4874
- hasActions && /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(Tooltip, { title: "More" }, /* @__PURE__ */ React57.createElement(
4922
+ hasActions && /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(Tooltip, { title: t("row.more", "More") }, /* @__PURE__ */ React57.createElement(
4875
4923
  IconButton,
4876
4924
  {
4877
4925
  size: "small",
4878
4926
  onClick: openMenu,
4879
- "aria-label": "Row actions",
4927
+ "aria-label": t("row.actions", "Row actions"),
4880
4928
  "aria-haspopup": "menu",
4881
4929
  "aria-expanded": Boolean(menuAnchor) || void 0,
4882
4930
  sx: {
@@ -4899,14 +4947,14 @@ function TemplateRow({
4899
4947
  transformOrigin: { vertical: "top", horizontal: "right" },
4900
4948
  slotProps: { paper: { sx: { minWidth: 200 } } }
4901
4949
  },
4902
- onRename && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onRename) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(DriveFileRenameOutlineOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, "Edit name & tags\u2026")),
4903
- onDuplicate && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onDuplicate) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(ContentCopyOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, "Duplicate")),
4904
- onDuplicateAsTemplate && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onDuplicateAsTemplate) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(LibraryAddOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, "Duplicate as template")),
4905
- onPromote && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onPromote) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(FileUploadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, "Promote to sample")),
4906
- onDemote && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onDemote) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(FileDownloadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, "Demote to template")),
4950
+ onRename && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onRename) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(DriveFileRenameOutlineOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, t("row.edit-details", "Edit name & tags\u2026"))),
4951
+ onDuplicate && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onDuplicate) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(ContentCopyOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, t("row.duplicate", "Duplicate"))),
4952
+ onDuplicateAsTemplate && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onDuplicateAsTemplate) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(LibraryAddOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, t("row.duplicate-as-template", "Duplicate as template"))),
4953
+ onPromote && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onPromote) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(FileUploadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, t("row.promote", "Promote to sample"))),
4954
+ onDemote && /* @__PURE__ */ React57.createElement(MenuItem, { onClick: runAction(onDemote) }, /* @__PURE__ */ React57.createElement(ListItemIcon, null, /* @__PURE__ */ React57.createElement(FileDownloadOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, t("row.demote", "Demote to template"))),
4907
4955
  onDelete && [
4908
4956
  /* @__PURE__ */ React57.createElement(Divider$1, { key: "divider" }),
4909
- /* @__PURE__ */ React57.createElement(MenuItem, { key: "delete", onClick: runAction(onDelete), sx: { color: "error.main" } }, /* @__PURE__ */ React57.createElement(ListItemIcon, { sx: { color: "error.main" } }, /* @__PURE__ */ React57.createElement(DeleteOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, "Delete"))
4957
+ /* @__PURE__ */ React57.createElement(MenuItem, { key: "delete", onClick: runAction(onDelete), sx: { color: "error.main" } }, /* @__PURE__ */ React57.createElement(ListItemIcon, { sx: { color: "error.main" } }, /* @__PURE__ */ React57.createElement(DeleteOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(ListItemText, null, t("tune.delete", "Delete")))
4910
4958
  ]
4911
4959
  ))
4912
4960
  );
@@ -5463,7 +5511,7 @@ function NewTemplatePickerDialog({
5463
5511
  const [busy, setBusy] = useState(false);
5464
5512
  useEffect(() => {
5465
5513
  if (open) {
5466
- setName(defaultName != null ? defaultName : kind === "sample" ? "New sample" : "New template");
5514
+ setName(defaultName != null ? defaultName : t(kind === "sample" ? "drawer.new-sample" : "drawer.new-template", kind === "sample" ? "New sample" : "New template"));
5467
5515
  setSelectedStarter(null);
5468
5516
  setError(null);
5469
5517
  setBusy(false);
@@ -5471,9 +5519,9 @@ function NewTemplatePickerDialog({
5471
5519
  }, [open, defaultName, kind]);
5472
5520
  const validate = () => {
5473
5521
  const trimmed = name.trim();
5474
- if (!trimmed) return "Name is required";
5522
+ if (!trimmed) return t("picker.error-name-required", "Name is required");
5475
5523
  if (existingSlugs.some((s) => s.toLowerCase() === trimmed.toLowerCase())) {
5476
- return kind === "sample" ? "A sample with this name already exists" : "A template with this name already exists";
5524
+ 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");
5477
5525
  }
5478
5526
  return null;
5479
5527
  };
@@ -5492,7 +5540,7 @@ function NewTemplatePickerDialog({
5492
5540
  }
5493
5541
  });
5494
5542
  const pickable = samples.filter((s) => s.id !== "empty-email");
5495
- return /* @__PURE__ */ React57.createElement(Dialog, { open, onClose: busy ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57.createElement(DialogTitle, null, kind === "sample" ? "New sample" : "New template"), /* @__PURE__ */ React57.createElement(DialogContent, { dividers: true }, /* @__PURE__ */ React57.createElement(Typography, { variant: "subtitle2", sx: { mb: 1 } }, "Start from"), /* @__PURE__ */ React57.createElement(
5543
+ return /* @__PURE__ */ React57.createElement(Dialog, { open, onClose: busy ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57.createElement(DialogTitle, null, kind === "sample" ? t("picker.title-sample", "New sample") : t("picker.title-template", "New template")), /* @__PURE__ */ React57.createElement(DialogContent, { dividers: true }, /* @__PURE__ */ React57.createElement(Typography, { variant: "subtitle2", sx: { mb: 1 } }, t("picker.start-from", "Start from")), /* @__PURE__ */ React57.createElement(
5496
5544
  List,
5497
5545
  {
5498
5546
  dense: true,
@@ -5512,7 +5560,7 @@ function NewTemplatePickerDialog({
5512
5560
  selected: selectedStarter === null,
5513
5561
  onClick: () => setSelectedStarter(null)
5514
5562
  },
5515
- /* @__PURE__ */ React57.createElement(Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1 } }, /* @__PURE__ */ React57.createElement(InsertDriveFileOutlined, { fontSize: "small", sx: { color: "text.secondary" } }), /* @__PURE__ */ React57.createElement(ListItemText, { primary: "Blank", secondary: "Start from an empty email" }))
5563
+ /* @__PURE__ */ React57.createElement(Box, { sx: { display: "flex", alignItems: "center", gap: 1.5, flex: 1 } }, /* @__PURE__ */ React57.createElement(InsertDriveFileOutlined, { fontSize: "small", sx: { color: "text.secondary" } }), /* @__PURE__ */ React57.createElement(ListItemText, { primary: t("picker.blank-title", "Blank"), secondary: t("picker.blank-desc", "Start from an empty email") }))
5516
5564
  ),
5517
5565
  pickable.map((s) => /* @__PURE__ */ React57.createElement(
5518
5566
  ListItemButton,
@@ -5529,8 +5577,9 @@ function NewTemplatePickerDialog({
5529
5577
  autoFocus: true,
5530
5578
  fullWidth: true,
5531
5579
  size: "small",
5532
- label: "Name",
5580
+ label: t("rename.name-label", "Name"),
5533
5581
  value: name,
5582
+ onFocus: (e) => e.currentTarget.select(),
5534
5583
  onChange: (e) => {
5535
5584
  setName(e.target.value);
5536
5585
  if (error) setError(null);
@@ -5542,7 +5591,7 @@ function NewTemplatePickerDialog({
5542
5591
  helperText: error != null ? error : " ",
5543
5592
  disabled: busy
5544
5593
  }
5545
- )), /* @__PURE__ */ React57.createElement(DialogActions, null, /* @__PURE__ */ React57.createElement(Button$1, { onClick: onClose, disabled: busy }, "Cancel"), /* @__PURE__ */ React57.createElement(Button$1, { variant: "contained", onClick: handleCreate, disabled: busy }, busy ? "Creating\u2026" : `Create ${kind}`)));
5594
+ )), /* @__PURE__ */ React57.createElement(DialogActions, null, /* @__PURE__ */ React57.createElement(Button$1, { onClick: onClose, disabled: busy }, t("common.cancel", "Cancel")), /* @__PURE__ */ React57.createElement(Button$1, { 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"))));
5546
5595
  }
5547
5596
  function RenameDialog({
5548
5597
  open,
@@ -5581,12 +5630,12 @@ function RenameDialog({
5581
5630
  const handleSubmit = () => __async(null, null, function* () {
5582
5631
  const trimmedSlug = slug.trim();
5583
5632
  if (!trimmedSlug) {
5584
- setError("Please enter a name");
5633
+ setError(t("rename.error-empty", "Please enter a name"));
5585
5634
  return;
5586
5635
  }
5587
5636
  const slugChanged = trimmedSlug !== currentSlug;
5588
5637
  if (slugChanged && existingSlugs.some((s) => s.toLowerCase() === trimmedSlug.toLowerCase())) {
5589
- setError("A template with this name already exists");
5638
+ setError(t("rename.error-taken", "A template with this name already exists"));
5590
5639
  return;
5591
5640
  }
5592
5641
  if (!slugChanged && tagsUnchanged) {
@@ -5599,17 +5648,17 @@ function RenameDialog({
5599
5648
  onClose();
5600
5649
  } catch (e) {
5601
5650
  console.error("Error updating template details:", e);
5602
- setError("Failed to update template details");
5651
+ setError(t("rename.error-generic", "Failed to update template details"));
5603
5652
  } finally {
5604
5653
  setSubmitting(false);
5605
5654
  }
5606
5655
  });
5607
- return /* @__PURE__ */ React57.createElement(Dialog, { open, onClose: submitting ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57.createElement(DialogTitle, null, "Edit details"), /* @__PURE__ */ React57.createElement(DialogContent, null, /* @__PURE__ */ React57.createElement(
5656
+ return /* @__PURE__ */ React57.createElement(Dialog, { open, onClose: submitting ? void 0 : onClose, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ React57.createElement(DialogTitle, null, t("rename.title", "Edit details")), /* @__PURE__ */ React57.createElement(DialogContent, null, /* @__PURE__ */ React57.createElement(
5608
5657
  TextField,
5609
5658
  {
5610
5659
  autoFocus: true,
5611
5660
  margin: "dense",
5612
- label: "Name",
5661
+ label: t("rename.name-label", "Name"),
5613
5662
  fullWidth: true,
5614
5663
  variant: "outlined",
5615
5664
  value: slug,
@@ -5624,7 +5673,7 @@ function RenameDialog({
5624
5673
  if (e.key === "Enter" && !submitting) handleSubmit();
5625
5674
  }
5626
5675
  }
5627
- ), /* @__PURE__ */ React57.createElement(Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 1, mb: 0.5 } }, "Tags"), tags.length > 0 ? /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 0.5, sx: { flexWrap: "wrap", gap: 0.5, mb: 1 } }, tags.map((tag) => /* @__PURE__ */ React57.createElement(
5676
+ ), /* @__PURE__ */ React57.createElement(Typography, { variant: "caption", sx: { color: "text.secondary", display: "block", mt: 1, mb: 0.5 } }, t("rename.tags", "Tags")), tags.length > 0 ? /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 0.5, sx: { flexWrap: "wrap", gap: 0.5, mb: 1 } }, tags.map((tag) => /* @__PURE__ */ React57.createElement(
5628
5677
  Chip,
5629
5678
  {
5630
5679
  key: tag,
@@ -5632,12 +5681,12 @@ function RenameDialog({
5632
5681
  size: "small",
5633
5682
  onDelete: submitting ? void 0 : () => removeTag(tag)
5634
5683
  }
5635
- ))) : /* @__PURE__ */ React57.createElement(Typography, { variant: "caption", sx: { color: "text.disabled", display: "block", mb: 1 } }, "No tags yet. Suggested: ", /* @__PURE__ */ React57.createElement("i", null, "transactional"), ", ", /* @__PURE__ */ React57.createElement("i", null, "marketing"), "."), /* @__PURE__ */ React57.createElement(
5684
+ ))) : /* @__PURE__ */ React57.createElement(Typography, { variant: "caption", sx: { color: "text.disabled", display: "block", mb: 1 } }, t("rename.no-tags", "No tags yet.")), /* @__PURE__ */ React57.createElement(
5636
5685
  TextField,
5637
5686
  {
5638
5687
  size: "small",
5639
5688
  fullWidth: true,
5640
- placeholder: "Add a tag and press Enter",
5689
+ placeholder: t("rename.tag-placeholder", "Add a tag and press Enter"),
5641
5690
  value: tagInput,
5642
5691
  onChange: (e) => setTagInput(e.target.value),
5643
5692
  disabled: submitting,
@@ -5660,18 +5709,18 @@ function RenameDialog({
5660
5709
  startIcon: /* @__PURE__ */ React57.createElement(AddOutlined, { fontSize: "small" }),
5661
5710
  sx: { textTransform: "none" }
5662
5711
  },
5663
- "Add"
5712
+ t("common.add", "Add")
5664
5713
  ))
5665
5714
  }
5666
5715
  }
5667
- ), /* @__PURE__ */ React57.createElement(Box, { sx: { minHeight: 8 } })), /* @__PURE__ */ React57.createElement(DialogActions, null, /* @__PURE__ */ React57.createElement(Button$1, { onClick: onClose, disabled: submitting }, "Cancel"), /* @__PURE__ */ React57.createElement(
5716
+ ), /* @__PURE__ */ React57.createElement(Box, { sx: { minHeight: 8 } })), /* @__PURE__ */ React57.createElement(DialogActions, null, /* @__PURE__ */ React57.createElement(Button$1, { onClick: onClose, disabled: submitting }, t("common.cancel", "Cancel")), /* @__PURE__ */ React57.createElement(
5668
5717
  Button$1,
5669
5718
  {
5670
5719
  onClick: handleSubmit,
5671
5720
  variant: "contained",
5672
5721
  disabled: !slug.trim() || submitting
5673
5722
  },
5674
- submitting ? "Saving\u2026" : "Save"
5723
+ submitting ? t("common.saving", "Saving\u2026") : t("common.save", "Save")
5675
5724
  )));
5676
5725
  }
5677
5726
  function SaveTemplateDialog({
@@ -5680,7 +5729,8 @@ function SaveTemplateDialog({
5680
5729
  onSave,
5681
5730
  onNameChange,
5682
5731
  defaultName = "",
5683
- error: externalError = null
5732
+ error: externalError = null,
5733
+ mode = "save-as"
5684
5734
  }) {
5685
5735
  const [templateName, setTemplateName] = useState(defaultName);
5686
5736
  const [internalError, setInternalError] = useState("");
@@ -5704,7 +5754,7 @@ function SaveTemplateDialog({
5704
5754
  };
5705
5755
  const handleSave = () => __async(null, null, function* () {
5706
5756
  if (!templateName.trim()) {
5707
- setInternalError("Please enter a template name");
5757
+ setInternalError(t("save-dialog.error-empty-name", "Please enter a template name"));
5708
5758
  return;
5709
5759
  }
5710
5760
  setIsSubmitting(true);
@@ -5741,19 +5791,20 @@ function SaveTemplateDialog({
5741
5791
  maxWidth: "sm",
5742
5792
  fullWidth: true
5743
5793
  },
5744
- /* @__PURE__ */ React57.createElement(DialogTitle, null, "Save Email Template"),
5794
+ /* @__PURE__ */ React57.createElement(DialogTitle, null, mode === "new" ? t("save-dialog.title-new", "Create a new template") : t("save-dialog.title", "Save as a new template")),
5745
5795
  /* @__PURE__ */ React57.createElement(DialogContent, null, /* @__PURE__ */ React57.createElement(Box, { sx: { pt: 1 } }, /* @__PURE__ */ React57.createElement(
5746
5796
  TextField,
5747
5797
  {
5748
5798
  autoFocus: true,
5749
5799
  margin: "dense",
5750
5800
  id: "template-name",
5751
- label: "Template Name",
5801
+ label: t("save-dialog.name-label", "Template Name"),
5752
5802
  type: "text",
5753
5803
  fullWidth: true,
5754
5804
  variant: "outlined",
5755
5805
  value: templateName,
5756
5806
  onChange: handleNameChange,
5807
+ onFocus: (e) => e.currentTarget.select(),
5757
5808
  error: !!displayError,
5758
5809
  helperText: displayError,
5759
5810
  onKeyPress: (e) => {
@@ -5764,7 +5815,7 @@ function SaveTemplateDialog({
5764
5815
  disabled: isSubmitting
5765
5816
  }
5766
5817
  ))),
5767
- /* @__PURE__ */ React57.createElement(DialogActions, null, /* @__PURE__ */ React57.createElement(Button$1, { onClick: handleCancel, disabled: isSubmitting }, "Cancel"), /* @__PURE__ */ React57.createElement(
5818
+ /* @__PURE__ */ React57.createElement(DialogActions, null, /* @__PURE__ */ React57.createElement(Button$1, { onClick: handleCancel, disabled: isSubmitting }, t("common.cancel", "Cancel")), /* @__PURE__ */ React57.createElement(
5768
5819
  Button$1,
5769
5820
  {
5770
5821
  onClick: handleSave,
@@ -5772,7 +5823,7 @@ function SaveTemplateDialog({
5772
5823
  color: "primary",
5773
5824
  disabled: !templateName.trim() || !!displayError || isSubmitting
5774
5825
  },
5775
- isSubmitting ? "Saving..." : "Save Template"
5826
+ isSubmitting ? t("save-dialog.saving", "Saving...") : mode === "new" ? t("save-dialog.create", "Create") : t("save-dialog.save", "Save")
5776
5827
  ))
5777
5828
  );
5778
5829
  }
@@ -5794,12 +5845,12 @@ var empty_email_message_default = EMPTY_EMAIL_MESSAGE;
5794
5845
 
5795
5846
  // src/app/templates-drawer/index.tsx
5796
5847
  var SAMPLES_DRAWER_WIDTH = 320;
5797
- var EMPTY_TEMPLATE = {
5848
+ var buildEmptyTemplate = () => ({
5798
5849
  id: "empty-email",
5799
- slug: "Empty email",
5850
+ slug: t("empty.slug", "Empty email"),
5800
5851
  kind: "sample",
5801
- description: "A blank email template to start from scratch"
5802
- };
5852
+ description: t("empty.description", "A blank email template to start from scratch")
5853
+ });
5803
5854
  var SORT_OPTIONS = [
5804
5855
  { value: "updatedAt", labelKey: "sort.last-updated", fallback: "Last updated" },
5805
5856
  { value: "createdAt", labelKey: "sort.recently-created", fallback: "Recently created" },
@@ -5834,7 +5885,7 @@ function SamplesDrawer({
5834
5885
  const samplesDrawerOpen = useSamplesDrawerOpen();
5835
5886
  const { setCurrentTemplate, loadTemplate: ctxLoadTemplate } = useEmailEditor();
5836
5887
  const { showMessage } = useSnackbar();
5837
- const [samples, setSamples] = useState([EMPTY_TEMPLATE]);
5888
+ const [samples, setSamples] = useState([buildEmptyTemplate()]);
5838
5889
  const [templates, setTemplates] = useState([]);
5839
5890
  const [loadingSamples, setLoadingSamples] = useState(false);
5840
5891
  const [loadingTemplates, setLoadingTemplates] = useState(false);
@@ -5863,10 +5914,10 @@ function SamplesDrawer({
5863
5914
  loadSamples().then((results) => {
5864
5915
  const normalized = withKind(results, "sample");
5865
5916
  const existingEmpty = normalized.find((s) => s.id === "empty-email");
5866
- setSamples(existingEmpty ? normalized : [EMPTY_TEMPLATE, ...normalized]);
5917
+ setSamples(existingEmpty ? normalized : [buildEmptyTemplate(), ...normalized]);
5867
5918
  }).catch((error) => {
5868
5919
  console.error("Failed to load samples:", error);
5869
- setSamples([EMPTY_TEMPLATE]);
5920
+ setSamples([buildEmptyTemplate()]);
5870
5921
  }).finally(() => setLoadingSamples(false));
5871
5922
  }, [enabled, samplesDrawerOpen, loadSamples]);
5872
5923
  const refreshTemplates = () => __async(null, null, function* () {
@@ -6852,7 +6903,7 @@ function EmailLayoutEditor(props) {
6852
6903
  }
6853
6904
  }
6854
6905
  delete nDocument[selectedBlockId];
6855
- resetDocument(nDocument);
6906
+ replaceDocument(nDocument);
6856
6907
  }, [selectedBlockId, document2]);
6857
6908
  const handleCopy = useCallback((e) => {
6858
6909
  if (!(e.metaKey || e.ctrlKey) || e.key !== "c") return;
@@ -6895,7 +6946,7 @@ function EmailLayoutEditor(props) {
6895
6946
  childrenIds: currentChildrenIds
6896
6947
  })
6897
6948
  };
6898
- resetDocument(doc);
6949
+ replaceDocument(doc);
6899
6950
  setSelectedBlockId(newRootId);
6900
6951
  }), [document2, childrenIds, selectedBlockId, currentBlockId]);
6901
6952
  useEffect(() => {
@@ -6936,7 +6987,6 @@ function EmailLayoutEditor(props) {
6936
6987
  }
6937
6988
  }
6938
6989
  );
6939
- const WORKSPACE_BG = "#e7e8ec";
6940
6990
  const CARD_MAX_WIDTH = 664;
6941
6991
  const cardStyle = {
6942
6992
  maxWidth: CARD_MAX_WIDTH,
@@ -6952,7 +7002,6 @@ function EmailLayoutEditor(props) {
6952
7002
  setSelectedBlockId(null);
6953
7003
  },
6954
7004
  style: __spreadProps(__spreadValues({}, baseStyle), {
6955
- backgroundColor: WORKSPACE_BG,
6956
7005
  padding: "32px",
6957
7006
  width: "100%",
6958
7007
  minHeight: "100%"
@@ -6977,7 +7026,6 @@ function EmailLayoutEditor(props) {
6977
7026
  setSelectedBlockId(null);
6978
7027
  },
6979
7028
  style: __spreadProps(__spreadValues({}, baseStyle), {
6980
- backgroundColor: WORKSPACE_BG,
6981
7029
  padding: "32px 16px",
6982
7030
  width: "100%",
6983
7031
  minHeight: "100%"
@@ -8446,31 +8494,31 @@ function MainTabsGroup() {
8446
8494
  Tab,
8447
8495
  {
8448
8496
  value: "editor",
8449
- label: /* @__PURE__ */ React57.createElement(Tooltip, { title: "Edit" }, /* @__PURE__ */ React57.createElement(EditOutlined, { fontSize: "small" }))
8497
+ label: /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tab.edit", "Edit") }, /* @__PURE__ */ React57.createElement(EditOutlined, { fontSize: "small" }))
8450
8498
  }
8451
8499
  ), /* @__PURE__ */ React57.createElement(
8452
8500
  Tab,
8453
8501
  {
8454
8502
  value: "preview",
8455
- label: /* @__PURE__ */ React57.createElement(Tooltip, { title: "Preview" }, /* @__PURE__ */ React57.createElement(PreviewOutlined, { fontSize: "small" }))
8503
+ label: /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tab.preview", "Preview") }, /* @__PURE__ */ React57.createElement(PreviewOutlined, { fontSize: "small" }))
8456
8504
  }
8457
8505
  ), /* @__PURE__ */ React57.createElement(
8458
8506
  Tab,
8459
8507
  {
8460
8508
  value: "html",
8461
- label: /* @__PURE__ */ React57.createElement(Tooltip, { title: "HTML output" }, /* @__PURE__ */ React57.createElement(CodeOutlined, { fontSize: "small" }))
8509
+ label: /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tab.html-output", "HTML output") }, /* @__PURE__ */ React57.createElement(CodeOutlined, { fontSize: "small" }))
8462
8510
  }
8463
8511
  ), /* @__PURE__ */ React57.createElement(
8464
8512
  Tab,
8465
8513
  {
8466
8514
  value: "text",
8467
- label: /* @__PURE__ */ React57.createElement(Tooltip, { title: "Plain text output" }, /* @__PURE__ */ React57.createElement(SubjectOutlined, { fontSize: "small" }))
8515
+ label: /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tab.text-output", "Plain text output") }, /* @__PURE__ */ React57.createElement(SubjectOutlined, { fontSize: "small" }))
8468
8516
  }
8469
8517
  ), /* @__PURE__ */ React57.createElement(
8470
8518
  Tab,
8471
8519
  {
8472
8520
  value: "json",
8473
- label: /* @__PURE__ */ React57.createElement(Tooltip, { title: "JSON output" }, /* @__PURE__ */ React57.createElement(DataObjectOutlined, { fontSize: "small" }))
8521
+ label: /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tab.json-output", "JSON output") }, /* @__PURE__ */ React57.createElement(DataObjectOutlined, { fontSize: "small" }))
8474
8522
  }
8475
8523
  ));
8476
8524
  }
@@ -8615,6 +8663,7 @@ function SaveBar({ loadTemplates, saveAs }) {
8615
8663
  SaveTemplateDialog,
8616
8664
  {
8617
8665
  open: dialogMode !== null,
8666
+ mode: dialogMode === "new-blank" ? "new" : "save-as",
8618
8667
  onClose: () => {
8619
8668
  setDialogMode(null);
8620
8669
  setNameError(null);
@@ -8626,6 +8675,64 @@ function SaveBar({ loadTemplates, saveAs }) {
8626
8675
  }
8627
8676
  ));
8628
8677
  }
8678
+ function isMac() {
8679
+ if (typeof navigator === "undefined") return false;
8680
+ const platform = (navigator.platform || "").toLowerCase();
8681
+ if (platform.includes("mac")) return true;
8682
+ const ua = (navigator.userAgent || "").toLowerCase();
8683
+ return ua.includes("mac") && !ua.includes("windows");
8684
+ }
8685
+ function isEditableTarget(target) {
8686
+ if (!(target instanceof HTMLElement)) return false;
8687
+ const tag = target.tagName;
8688
+ if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return true;
8689
+ if (target.isContentEditable) return true;
8690
+ return false;
8691
+ }
8692
+ function UndoRedoButtons() {
8693
+ const canUndo = useCanUndo();
8694
+ const canRedo = useCanRedo();
8695
+ const mac = isMac();
8696
+ const modKey = mac ? "\u2318" : "Ctrl";
8697
+ const undoHint = `${modKey}+Z`;
8698
+ const redoHint = mac ? `${modKey}+\u21E7+Z` : `${modKey}+Shift+Z / ${modKey}+Y`;
8699
+ useEffect(() => {
8700
+ const onKeyDown = (e) => {
8701
+ const mod = mac ? e.metaKey : e.ctrlKey;
8702
+ if (!mod) return;
8703
+ if (isEditableTarget(e.target)) return;
8704
+ const key = e.key.toLowerCase();
8705
+ if (key === "z" && !e.shiftKey) {
8706
+ e.preventDefault();
8707
+ undo();
8708
+ } else if (key === "z" && e.shiftKey || key === "y" && !mac) {
8709
+ e.preventDefault();
8710
+ redo();
8711
+ }
8712
+ };
8713
+ window.addEventListener("keydown", onKeyDown);
8714
+ return () => window.removeEventListener("keydown", onKeyDown);
8715
+ }, [mac]);
8716
+ return /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 0.5, alignItems: "center" }, /* @__PURE__ */ React57.createElement(Tooltip, { title: `${t("undo.tooltip", "Undo")} (${undoHint})` }, /* @__PURE__ */ React57.createElement("span", null, /* @__PURE__ */ React57.createElement(
8717
+ IconButton,
8718
+ {
8719
+ size: "small",
8720
+ onClick: undo,
8721
+ disabled: !canUndo,
8722
+ "aria-label": t("undo.label", "Undo")
8723
+ },
8724
+ /* @__PURE__ */ React57.createElement(UndoOutlined, { fontSize: "small" })
8725
+ ))), /* @__PURE__ */ React57.createElement(Tooltip, { title: `${t("redo.tooltip", "Redo")} (${redoHint})` }, /* @__PURE__ */ React57.createElement("span", null, /* @__PURE__ */ React57.createElement(
8726
+ IconButton,
8727
+ {
8728
+ size: "small",
8729
+ onClick: redo,
8730
+ disabled: !canRedo,
8731
+ "aria-label": t("redo.label", "Redo")
8732
+ },
8733
+ /* @__PURE__ */ React57.createElement(RedoOutlined, { fontSize: "small" })
8734
+ ))));
8735
+ }
8629
8736
  function SubjectInput() {
8630
8737
  var _a;
8631
8738
  const document2 = useDocument();
@@ -8854,7 +8961,7 @@ function ImageDropPasteHandler({ enabled, children }) {
8854
8961
 
8855
8962
  // src/app/email-canvas/index.tsx
8856
8963
  var WORKSPACE_SOLID = "#e7e8ec";
8857
- var WORKSPACE_CHECKERBOARD = "repeating-conic-gradient(#eceef2 0% 25%, #dfe1e6 0% 50%) 50% / 24px 24px";
8964
+ var WORKSPACE_CHECKERBOARD = "repeating-conic-gradient(#eceef2 0% 25%, #dfe1e6 0% 50%) 50% / 12px 12px";
8858
8965
  function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true }) {
8859
8966
  const document2 = useDocument();
8860
8967
  const selectedMainTab = useSelectedMainTab();
@@ -8924,7 +9031,7 @@ function TemplatePanel2({ loadTemplates, saveAs, samplesDrawerEnabled = true })
8924
9031
  alignItems: "center"
8925
9032
  },
8926
9033
  samplesDrawerEnabled && /* @__PURE__ */ React57.createElement(ToggleSamplesPanelButton, null),
8927
- /* @__PURE__ */ React57.createElement(Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57.createElement(MainTabsGroup, null)), /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57.createElement(ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React57.createElement(ToggleButton, { value: "desktop" }, /* @__PURE__ */ React57.createElement(Tooltip, { title: "Desktop view" }, /* @__PURE__ */ React57.createElement(MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(ToggleButton, { value: "mobile" }, /* @__PURE__ */ React57.createElement(Tooltip, { title: "Mobile view" }, /* @__PURE__ */ React57.createElement(PhoneIphoneOutlined, { fontSize: "small" })))))),
9034
+ /* @__PURE__ */ React57.createElement(Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center" }, /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 2 }, /* @__PURE__ */ React57.createElement(MainTabsGroup, null)), /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 2, alignItems: "center" }, selectedMainTab === "editor" && /* @__PURE__ */ React57.createElement(UndoRedoButtons, null), /* @__PURE__ */ React57.createElement(ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange }, /* @__PURE__ */ React57.createElement(ToggleButton, { value: "desktop" }, /* @__PURE__ */ React57.createElement(Tooltip, { title: t("canvas.desktop-view", "Desktop view") }, /* @__PURE__ */ React57.createElement(MonitorOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(ToggleButton, { value: "mobile" }, /* @__PURE__ */ React57.createElement(Tooltip, { title: t("canvas.mobile-view", "Mobile view") }, /* @__PURE__ */ React57.createElement(PhoneIphoneOutlined, { fontSize: "small" })))))),
8928
9035
  /* @__PURE__ */ React57.createElement(ToggleInspectorPanelButton, null)
8929
9036
  ), selectedMainTab === "editor" && /* @__PURE__ */ React57.createElement(SubjectInput, null), selectedMainTab === "preview" && /* @__PURE__ */ React57.createElement(SubjectPreview, null), /* @__PURE__ */ React57.createElement(ImageDropPasteHandler, { enabled: selectedMainTab === "editor" }, /* @__PURE__ */ React57.createElement(
8930
9037
  Box,