@kontakto/email-template-editor 2.4.0 → 2.5.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.d.cts CHANGED
@@ -4797,6 +4797,9 @@ declare function EmailLayoutReader(props: EmailLayoutProps): React.JSX.Element;
4797
4797
 
4798
4798
  declare const THEME: _mui_material_styles.Theme;
4799
4799
 
4800
+ declare const SUPPORTED_LOCALES: readonly ["en", "sv", "fi"];
4801
+ type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
4802
+
4800
4803
  declare const EditorBlockSchema: z.ZodEffects<z.ZodDiscriminatedUnion<"type", any>, BlockConfiguration<{
4801
4804
  Avatar: z.ZodObject<{
4802
4805
  style: z.ZodNullable<z.ZodOptional<z.ZodObject<{
@@ -6131,7 +6134,13 @@ interface EmailEditorProps {
6131
6134
  * This allows for easy styling without requiring a separate ThemeProvider.
6132
6135
  */
6133
6136
  theme?: Theme;
6137
+ /**
6138
+ * UI language. One of "en", "sv", or "fi". Unknown values fall back to "en"
6139
+ * with a console.warn. Defaults to "en". Applies to editor chrome only —
6140
+ * email content and user data are never translated.
6141
+ */
6142
+ locale?: SupportedLocale | string;
6134
6143
  }
6135
6144
  declare const EmailEditor: React.ForwardRefExoticComponent<EmailEditorProps & React.RefAttributes<EmailEditorRef>>;
6136
6145
 
6137
- export { Avatar, AvatarProps, AvatarPropsDefaults, AvatarPropsSchema, BlockConfiguration, Button, ButtonProps, ButtonPropsDefaults, ButtonPropsSchema, ColumnsContainer, ColumnsContainerProps$1 as ColumnsContainerProps, ColumnsContainerPropsSchema$1 as ColumnsContainerPropsSchema, ColumnsContainerReader, Container, ContainerProps$1 as ContainerProps, ContainerPropsSchema$1 as ContainerPropsSchema, ContainerReader, Divider, DividerProps, DividerPropsDefaults, DividerPropsSchema, DocumentBlocksDictionary, EmailEditor, type EmailEditorContextType, type EmailEditorProps, EmailEditorProvider, type EmailEditorProviderProps, type EmailEditorRef, EmailLayoutPropsSchema, EmailLayoutReader, EmailMarkdown, type HandlebarsContext, Heading, HeadingProps, HeadingPropsDefaults, HeadingPropsSchema, Html, HtmlProps, HtmlPropsSchema, Image, type ImageCallbacks, ImageProps, ImagePropsSchema, type LibraryImage, Reader, ReaderBlock, ReaderBlockSchema, ReaderDocumentSchema, type SavePayload, Signature, SignatureProps, SignaturePropsDefaults, SignaturePropsSchema, Spacer, SpacerProps, SpacerPropsDefaults, SpacerPropsSchema, type TReaderBlock, type TReaderBlockProps, type TReaderDocument, type TReaderProps, type TemplateKind, type TemplateListItem, TemplateVariableSchema, Text, TextProps, TextPropsDefaults, TextPropsSchema, type UploadedImage, buildBlockComponent, buildBlockConfigurationDictionary, buildBlockConfigurationSchema, editorHandlebars, evaluateHandlebars, htmlToEditorConfig, renderToStaticMarkup, renderToText, THEME as theme, useEmailEditor };
6146
+ export { Avatar, AvatarProps, AvatarPropsDefaults, AvatarPropsSchema, BlockConfiguration, Button, ButtonProps, ButtonPropsDefaults, ButtonPropsSchema, ColumnsContainer, ColumnsContainerProps$1 as ColumnsContainerProps, ColumnsContainerPropsSchema$1 as ColumnsContainerPropsSchema, ColumnsContainerReader, Container, ContainerProps$1 as ContainerProps, ContainerPropsSchema$1 as ContainerPropsSchema, ContainerReader, Divider, DividerProps, DividerPropsDefaults, DividerPropsSchema, DocumentBlocksDictionary, EmailEditor, type EmailEditorContextType, type EmailEditorProps, EmailEditorProvider, type EmailEditorProviderProps, type EmailEditorRef, EmailLayoutPropsSchema, EmailLayoutReader, EmailMarkdown, type HandlebarsContext, Heading, HeadingProps, HeadingPropsDefaults, HeadingPropsSchema, Html, HtmlProps, HtmlPropsSchema, Image, type ImageCallbacks, ImageProps, ImagePropsSchema, type LibraryImage, Reader, ReaderBlock, ReaderBlockSchema, ReaderDocumentSchema, SUPPORTED_LOCALES, type SavePayload, Signature, SignatureProps, SignaturePropsDefaults, SignaturePropsSchema, Spacer, SpacerProps, SpacerPropsDefaults, SpacerPropsSchema, type SupportedLocale, type TReaderBlock, type TReaderBlockProps, type TReaderDocument, type TReaderProps, type TemplateKind, type TemplateListItem, TemplateVariableSchema, Text, TextProps, TextPropsDefaults, TextPropsSchema, type UploadedImage, buildBlockComponent, buildBlockConfigurationDictionary, buildBlockConfigurationSchema, editorHandlebars, evaluateHandlebars, htmlToEditorConfig, renderToStaticMarkup, renderToText, THEME as theme, useEmailEditor };
package/dist/index.d.ts CHANGED
@@ -4797,6 +4797,9 @@ declare function EmailLayoutReader(props: EmailLayoutProps): React.JSX.Element;
4797
4797
 
4798
4798
  declare const THEME: _mui_material_styles.Theme;
4799
4799
 
4800
+ declare const SUPPORTED_LOCALES: readonly ["en", "sv", "fi"];
4801
+ type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
4802
+
4800
4803
  declare const EditorBlockSchema: z.ZodEffects<z.ZodDiscriminatedUnion<"type", any>, BlockConfiguration<{
4801
4804
  Avatar: z.ZodObject<{
4802
4805
  style: z.ZodNullable<z.ZodOptional<z.ZodObject<{
@@ -6131,7 +6134,13 @@ interface EmailEditorProps {
6131
6134
  * This allows for easy styling without requiring a separate ThemeProvider.
6132
6135
  */
6133
6136
  theme?: Theme;
6137
+ /**
6138
+ * UI language. One of "en", "sv", or "fi". Unknown values fall back to "en"
6139
+ * with a console.warn. Defaults to "en". Applies to editor chrome only —
6140
+ * email content and user data are never translated.
6141
+ */
6142
+ locale?: SupportedLocale | string;
6134
6143
  }
6135
6144
  declare const EmailEditor: React.ForwardRefExoticComponent<EmailEditorProps & React.RefAttributes<EmailEditorRef>>;
6136
6145
 
6137
- export { Avatar, AvatarProps, AvatarPropsDefaults, AvatarPropsSchema, BlockConfiguration, Button, ButtonProps, ButtonPropsDefaults, ButtonPropsSchema, ColumnsContainer, ColumnsContainerProps$1 as ColumnsContainerProps, ColumnsContainerPropsSchema$1 as ColumnsContainerPropsSchema, ColumnsContainerReader, Container, ContainerProps$1 as ContainerProps, ContainerPropsSchema$1 as ContainerPropsSchema, ContainerReader, Divider, DividerProps, DividerPropsDefaults, DividerPropsSchema, DocumentBlocksDictionary, EmailEditor, type EmailEditorContextType, type EmailEditorProps, EmailEditorProvider, type EmailEditorProviderProps, type EmailEditorRef, EmailLayoutPropsSchema, EmailLayoutReader, EmailMarkdown, type HandlebarsContext, Heading, HeadingProps, HeadingPropsDefaults, HeadingPropsSchema, Html, HtmlProps, HtmlPropsSchema, Image, type ImageCallbacks, ImageProps, ImagePropsSchema, type LibraryImage, Reader, ReaderBlock, ReaderBlockSchema, ReaderDocumentSchema, type SavePayload, Signature, SignatureProps, SignaturePropsDefaults, SignaturePropsSchema, Spacer, SpacerProps, SpacerPropsDefaults, SpacerPropsSchema, type TReaderBlock, type TReaderBlockProps, type TReaderDocument, type TReaderProps, type TemplateKind, type TemplateListItem, TemplateVariableSchema, Text, TextProps, TextPropsDefaults, TextPropsSchema, type UploadedImage, buildBlockComponent, buildBlockConfigurationDictionary, buildBlockConfigurationSchema, editorHandlebars, evaluateHandlebars, htmlToEditorConfig, renderToStaticMarkup, renderToText, THEME as theme, useEmailEditor };
6146
+ export { Avatar, AvatarProps, AvatarPropsDefaults, AvatarPropsSchema, BlockConfiguration, Button, ButtonProps, ButtonPropsDefaults, ButtonPropsSchema, ColumnsContainer, ColumnsContainerProps$1 as ColumnsContainerProps, ColumnsContainerPropsSchema$1 as ColumnsContainerPropsSchema, ColumnsContainerReader, Container, ContainerProps$1 as ContainerProps, ContainerPropsSchema$1 as ContainerPropsSchema, ContainerReader, Divider, DividerProps, DividerPropsDefaults, DividerPropsSchema, DocumentBlocksDictionary, EmailEditor, type EmailEditorContextType, type EmailEditorProps, EmailEditorProvider, type EmailEditorProviderProps, type EmailEditorRef, EmailLayoutPropsSchema, EmailLayoutReader, EmailMarkdown, type HandlebarsContext, Heading, HeadingProps, HeadingPropsDefaults, HeadingPropsSchema, Html, HtmlProps, HtmlPropsSchema, Image, type ImageCallbacks, ImageProps, ImagePropsSchema, type LibraryImage, Reader, ReaderBlock, ReaderBlockSchema, ReaderDocumentSchema, SUPPORTED_LOCALES, type SavePayload, Signature, SignatureProps, SignaturePropsDefaults, SignaturePropsSchema, Spacer, SpacerProps, SpacerPropsDefaults, SpacerPropsSchema, type SupportedLocale, type TReaderBlock, type TReaderBlockProps, type TReaderDocument, type TReaderProps, type TemplateKind, type TemplateListItem, TemplateVariableSchema, Text, TextProps, TextPropsDefaults, TextPropsSchema, type UploadedImage, buildBlockComponent, buildBlockConfigurationDictionary, buildBlockConfigurationSchema, editorHandlebars, evaluateHandlebars, htmlToEditorConfig, renderToStaticMarkup, renderToText, THEME as theme, useEmailEditor };
package/dist/index.js CHANGED
@@ -5,7 +5,9 @@ import { z } from 'zod';
5
5
  import { renderToStaticMarkup as renderToStaticMarkup$1 } from 'react-dom/server';
6
6
  import Handlebars from 'handlebars';
7
7
  import { createTheme, alpha, lighten, darken } from '@mui/material/styles';
8
+ import { I18nProvider, Trans } from '@lingui/react';
8
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
+ import { i18n } from '@lingui/core';
9
11
  import { create } from 'zustand';
10
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
13
  import { HexColorPicker, HexColorInput } from 'react-colorful';
@@ -2000,6 +2002,37 @@ var THEME = createTheme(BASE_THEME, {
2000
2002
  ]
2001
2003
  });
2002
2004
  var theme_default = THEME;
2005
+
2006
+ // 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
+
2009
+ // 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
+
2012
+ // 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 SUPPORTED_LOCALES = ["en", "sv", "fi"];
2015
+ var CATALOGS = {
2016
+ en: messages,
2017
+ sv: messages3,
2018
+ fi: messages2
2019
+ };
2020
+ var loaded = false;
2021
+ function activateLocale(locale) {
2022
+ const resolved = SUPPORTED_LOCALES.includes(locale != null ? locale : "") ? locale : "en";
2023
+ if (locale && resolved !== locale) {
2024
+ console.warn(`[email-template-editor] Unsupported locale "${locale}", falling back to "en".`);
2025
+ }
2026
+ if (!loaded) {
2027
+ i18n.load({ en: CATALOGS.en, sv: CATALOGS.sv, fi: CATALOGS.fi });
2028
+ loaded = true;
2029
+ }
2030
+ i18n.activate(resolved);
2031
+ return resolved;
2032
+ }
2033
+ function t(id, fallback) {
2034
+ return i18n._(id, {}, { message: fallback != null ? fallback : id });
2035
+ }
2003
2036
  var EMPTY_DOCUMENT = {
2004
2037
  root: {
2005
2038
  type: "EmailLayout",
@@ -2236,8 +2269,27 @@ function ImageCallbacksProvider({
2236
2269
  function useImageCallbacks() {
2237
2270
  return useContext(ImageCallbacksContext);
2238
2271
  }
2272
+ var TITLE_KEYS = {
2273
+ "Editor appearance": "panel.editor-appearance",
2274
+ Template: "panel.template",
2275
+ Export: "panel.export",
2276
+ Global: "panel.global",
2277
+ "Text block": "panel.text-block",
2278
+ "Heading block": "panel.heading-block",
2279
+ "Button block": "panel.button-block",
2280
+ "Image block": "panel.image-block",
2281
+ "Avatar block": "panel.avatar-block",
2282
+ "Signature block": "panel.signature-block",
2283
+ "Spacer block": "panel.spacer-block",
2284
+ "Divider block": "panel.divider-block",
2285
+ "Columns block": "panel.columns-block",
2286
+ "Container block": "panel.container-block",
2287
+ "Html block": "panel.html-block"
2288
+ };
2239
2289
  function BaseSidebarPanel({ title, children }) {
2240
- return /* @__PURE__ */ React57.createElement(Box, { p: 2 }, /* @__PURE__ */ React57.createElement(Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 } }, title), /* @__PURE__ */ React57.createElement(Stack, { spacing: 5, mb: 3 }, children));
2290
+ const key = TITLE_KEYS[title];
2291
+ const displayTitle = key ? t(key, title) : title;
2292
+ return /* @__PURE__ */ React57.createElement(Box, { p: 2 }, /* @__PURE__ */ React57.createElement(Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 } }, displayTitle), /* @__PURE__ */ React57.createElement(Stack, { spacing: 5, mb: 3 }, children));
2241
2293
  }
2242
2294
  function RadioGroupInput({ label, children, defaultValue, onChange }) {
2243
2295
  const [value, setValue] = useState(defaultValue);
@@ -2741,9 +2793,9 @@ function SingleStylePropertyPanel({ name, value, onChange }) {
2741
2793
  };
2742
2794
  switch (name) {
2743
2795
  case "backgroundColor":
2744
- return /* @__PURE__ */ React57.createElement(NullableColorInput, { label: "Background color", defaultValue, onChange: handleChange });
2796
+ return /* @__PURE__ */ React57.createElement(NullableColorInput, { label: t("style.background-color", "Background color"), defaultValue, onChange: handleChange });
2745
2797
  case "borderColor":
2746
- return /* @__PURE__ */ React57.createElement(NullableColorInput, { label: "Border color", defaultValue, onChange: handleChange });
2798
+ return /* @__PURE__ */ React57.createElement(NullableColorInput, { label: t("style.border-color", "Border color"), defaultValue, onChange: handleChange });
2747
2799
  case "borderRadius":
2748
2800
  return /* @__PURE__ */ React57.createElement(
2749
2801
  SliderInput,
@@ -2754,27 +2806,27 @@ function SingleStylePropertyPanel({ name, value, onChange }) {
2754
2806
  marks: true,
2755
2807
  min: 0,
2756
2808
  max: 48,
2757
- label: "Border radius",
2809
+ label: t("style.border-radius", "Border radius"),
2758
2810
  defaultValue,
2759
2811
  onChange: handleChange
2760
2812
  }
2761
2813
  );
2762
2814
  case "color":
2763
- return /* @__PURE__ */ React57.createElement(NullableColorInput, { label: "Text color", defaultValue, onChange: handleChange });
2815
+ return /* @__PURE__ */ React57.createElement(NullableColorInput, { label: t("style.text-color", "Text color"), defaultValue, onChange: handleChange });
2764
2816
  case "fontFamily":
2765
- return /* @__PURE__ */ React57.createElement(NullableFontFamily, { label: "Font family", defaultValue, onChange: handleChange });
2817
+ return /* @__PURE__ */ React57.createElement(NullableFontFamily, { label: t("style.font-family", "Font family"), defaultValue, onChange: handleChange });
2766
2818
  case "fontSize":
2767
- return /* @__PURE__ */ React57.createElement(FontSizeInput, { label: "Font size", defaultValue, onChange: handleChange });
2819
+ return /* @__PURE__ */ React57.createElement(FontSizeInput, { label: t("style.font-size", "Font size"), defaultValue, onChange: handleChange });
2768
2820
  case "fontWeight":
2769
- return /* @__PURE__ */ React57.createElement(FontWeightInput, { label: "Font weight", defaultValue, onChange: handleChange });
2821
+ return /* @__PURE__ */ React57.createElement(FontWeightInput, { label: t("style.font-weight", "Font weight"), defaultValue, onChange: handleChange });
2770
2822
  case "lineHeight":
2771
- return /* @__PURE__ */ React57.createElement(LineHeightInput, { label: "Line height", defaultValue, onChange: handleChange });
2823
+ return /* @__PURE__ */ React57.createElement(LineHeightInput, { label: t("style.line-height", "Line height"), defaultValue, onChange: handleChange });
2772
2824
  case "letterSpacing":
2773
- return /* @__PURE__ */ React57.createElement(LetterSpacingInput, { label: "Letter spacing", defaultValue, onChange: handleChange });
2825
+ return /* @__PURE__ */ React57.createElement(LetterSpacingInput, { label: t("style.letter-spacing", "Letter spacing"), defaultValue, onChange: handleChange });
2774
2826
  case "textAlign":
2775
- return /* @__PURE__ */ React57.createElement(TextAlignInput, { label: "Alignment", defaultValue, onChange: handleChange });
2827
+ return /* @__PURE__ */ React57.createElement(TextAlignInput, { label: t("style.alignment", "Alignment"), defaultValue, onChange: handleChange });
2776
2828
  case "padding":
2777
- return /* @__PURE__ */ React57.createElement(PaddingInput, { label: "Padding", defaultValue, onChange: handleChange });
2829
+ return /* @__PURE__ */ React57.createElement(PaddingInput, { label: t("style.padding", "Padding"), defaultValue, onChange: handleChange });
2778
2830
  }
2779
2831
  }
2780
2832
 
@@ -4081,15 +4133,15 @@ function DetailsEditor({ templateId, currentName, currentTags, canEdit, onSave }
4081
4133
  const addTag = () => {
4082
4134
  const trimmed = tagInput.trim();
4083
4135
  if (!trimmed) return;
4084
- if (tags.some((t) => t.toLowerCase() === trimmed.toLowerCase())) {
4136
+ if (tags.some((t2) => t2.toLowerCase() === trimmed.toLowerCase())) {
4085
4137
  setTagInput("");
4086
4138
  return;
4087
4139
  }
4088
4140
  setTags([...tags, trimmed]);
4089
4141
  setTagInput("");
4090
4142
  };
4091
- const removeTag = (tag) => setTags(tags.filter((t) => t !== tag));
4092
- const dirty = name !== currentName || tags.length !== currentTags.length || tags.some((t, i) => t !== currentTags[i]);
4143
+ const removeTag = (tag) => setTags(tags.filter((t2) => t2 !== tag));
4144
+ const dirty = name !== currentName || tags.length !== currentTags.length || tags.some((t2, i) => t2 !== currentTags[i]);
4093
4145
  const handleSave = () => __async(null, null, function* () {
4094
4146
  if (!canEdit || !dirty || !name.trim()) return;
4095
4147
  setSaving(true);
@@ -5517,15 +5569,15 @@ function RenameDialog({
5517
5569
  const addTag = () => {
5518
5570
  const trimmed = tagInput.trim();
5519
5571
  if (!trimmed) return;
5520
- if (tags.some((t) => t.toLowerCase() === trimmed.toLowerCase())) {
5572
+ if (tags.some((t2) => t2.toLowerCase() === trimmed.toLowerCase())) {
5521
5573
  setTagInput("");
5522
5574
  return;
5523
5575
  }
5524
5576
  setTags([...tags, trimmed]);
5525
5577
  setTagInput("");
5526
5578
  };
5527
- const removeTag = (tag) => setTags(tags.filter((t) => t !== tag));
5528
- const tagsUnchanged = tags.length === currentTags.length && tags.every((t, i) => t === currentTags[i]);
5579
+ const removeTag = (tag) => setTags(tags.filter((t2) => t2 !== tag));
5580
+ const tagsUnchanged = tags.length === currentTags.length && tags.every((t2, i) => t2 === currentTags[i]);
5529
5581
  const handleSubmit = () => __async(null, null, function* () {
5530
5582
  const trimmedSlug = slug.trim();
5531
5583
  if (!trimmedSlug) {
@@ -5749,9 +5801,9 @@ var EMPTY_TEMPLATE = {
5749
5801
  description: "A blank email template to start from scratch"
5750
5802
  };
5751
5803
  var SORT_OPTIONS = [
5752
- { value: "updatedAt", label: "Last updated" },
5753
- { value: "createdAt", label: "Recently created" },
5754
- { value: "slug", label: "Name (A\u2013Z)" }
5804
+ { value: "updatedAt", labelKey: "sort.last-updated", fallback: "Last updated" },
5805
+ { value: "createdAt", labelKey: "sort.recently-created", fallback: "Recently created" },
5806
+ { value: "slug", labelKey: "sort.name", fallback: "Name (A\u2013Z)" }
5755
5807
  ];
5756
5808
  function compareTemplates(a, b, key) {
5757
5809
  if (key === "slug") {
@@ -5835,9 +5887,9 @@ function SamplesDrawer({
5835
5887
  const now = (/* @__PURE__ */ new Date()).toISOString();
5836
5888
  const row = { id, slug, kind, tags, createdAt: now, updatedAt: now };
5837
5889
  if (kind === "sample") {
5838
- setSamples((prev) => prev.some((t) => t.id === id) ? prev : [...prev, row]);
5890
+ setSamples((prev) => prev.some((t2) => t2.id === id) ? prev : [...prev, row]);
5839
5891
  } else {
5840
- setTemplates((prev) => prev.some((t) => t.id === id) ? prev : [...prev, row]);
5892
+ setTemplates((prev) => prev.some((t2) => t2.id === id) ? prev : [...prev, row]);
5841
5893
  }
5842
5894
  };
5843
5895
  useEffect(() => {
@@ -5855,30 +5907,30 @@ function SamplesDrawer({
5855
5907
  const { templateRows, sampleRows } = useMemo(() => {
5856
5908
  const byId = /* @__PURE__ */ new Map();
5857
5909
  for (const s of samples) byId.set(s.id, s);
5858
- for (const t of templates) byId.set(t.id, t);
5910
+ for (const t2 of templates) byId.set(t2.id, t2);
5859
5911
  const all = Array.from(byId.values());
5860
5912
  return {
5861
- templateRows: all.filter((t) => t.kind === "template"),
5862
- sampleRows: all.filter((t) => t.kind === "sample")
5913
+ templateRows: all.filter((t2) => t2.kind === "template"),
5914
+ sampleRows: all.filter((t2) => t2.kind === "sample")
5863
5915
  };
5864
5916
  }, [samples, templates]);
5865
5917
  const allTags = useMemo(() => {
5866
5918
  var _a2, _b2;
5867
5919
  const set = /* @__PURE__ */ new Set();
5868
- for (const t of templateRows) (_a2 = t.tags) == null ? void 0 : _a2.forEach((tag) => set.add(tag));
5920
+ for (const t2 of templateRows) (_a2 = t2.tags) == null ? void 0 : _a2.forEach((tag) => set.add(tag));
5869
5921
  for (const s of sampleRows) (_b2 = s.tags) == null ? void 0 : _b2.forEach((tag) => set.add(tag));
5870
5922
  return Array.from(set).sort();
5871
5923
  }, [templateRows, sampleRows]);
5872
5924
  const matchesSearchAndTags = useMemo(() => {
5873
5925
  const term = search.trim().toLowerCase();
5874
- return (t) => {
5926
+ return (t2) => {
5875
5927
  if (term) {
5876
- const haystack = [t.slug, t.description, t.subject].filter(Boolean).join(" ").toLowerCase();
5928
+ const haystack = [t2.slug, t2.description, t2.subject].filter(Boolean).join(" ").toLowerCase();
5877
5929
  if (!haystack.includes(term)) return false;
5878
5930
  }
5879
5931
  if (activeTags.length > 0) {
5880
- if (!t.tags || t.tags.length === 0) return false;
5881
- if (!activeTags.every((tag) => t.tags.includes(tag))) return false;
5932
+ if (!t2.tags || t2.tags.length === 0) return false;
5933
+ if (!activeTags.every((tag) => t2.tags.includes(tag))) return false;
5882
5934
  }
5883
5935
  return true;
5884
5936
  };
@@ -5892,7 +5944,7 @@ function SamplesDrawer({
5892
5944
  [sampleRows, matchesSearchAndTags, sortKey]
5893
5945
  );
5894
5946
  const toggleTag = (tag) => {
5895
- setActiveTags((prev) => prev.includes(tag) ? prev.filter((t) => t !== tag) : [...prev, tag]);
5947
+ setActiveTags((prev) => prev.includes(tag) ? prev.filter((t2) => t2 !== tag) : [...prev, tag]);
5896
5948
  };
5897
5949
  const handleDuplicate = (template) => {
5898
5950
  if (!copyTemplate) return;
@@ -5922,7 +5974,7 @@ function SamplesDrawer({
5922
5974
  if (!renameTarget || !renameTemplate) return;
5923
5975
  yield renameTemplate(renameTarget.id, newSlug, opts);
5924
5976
  const newTags = (_b2 = (_a2 = opts == null ? void 0 : opts.tags) != null ? _a2 : renameTarget.tags) != null ? _b2 : [];
5925
- const patch = (t) => t.id === renameTarget.id ? __spreadProps(__spreadValues({}, t), { slug: newSlug, tags: newTags }) : t;
5977
+ const patch = (t2) => t2.id === renameTarget.id ? __spreadProps(__spreadValues({}, t2), { slug: newSlug, tags: newTags }) : t2;
5926
5978
  setTemplates((prev) => prev.map(patch));
5927
5979
  setSamples((prev) => prev.map(patch));
5928
5980
  if (currentTemplateId === renameTarget.id) {
@@ -5931,8 +5983,8 @@ function SamplesDrawer({
5931
5983
  showMessage("Details saved");
5932
5984
  });
5933
5985
  const flipKindLocally = (id, kind) => {
5934
- setTemplates((prev) => prev.map((t) => t.id === id ? __spreadProps(__spreadValues({}, t), { kind }) : t));
5935
- setSamples((prev) => prev.map((t) => t.id === id ? __spreadProps(__spreadValues({}, t), { kind }) : t));
5986
+ setTemplates((prev) => prev.map((t2) => t2.id === id ? __spreadProps(__spreadValues({}, t2), { kind }) : t2));
5987
+ setSamples((prev) => prev.map((t2) => t2.id === id ? __spreadProps(__spreadValues({}, t2), { kind }) : t2));
5936
5988
  };
5937
5989
  const handleSetKind = (template, kind) => {
5938
5990
  if (!setTemplateKind) return;
@@ -5969,7 +6021,7 @@ function SamplesDrawer({
5969
6021
  };
5970
6022
  const handleSaveAsSubmit = (templateName) => __async(null, null, function* () {
5971
6023
  if (!saveAs || !pendingSaveAs) return false;
5972
- const taken = templateRows.some((t) => t.slug.toLowerCase() === templateName.toLowerCase());
6024
+ const taken = templateRows.some((t2) => t2.slug.toLowerCase() === templateName.toLowerCase());
5973
6025
  if (taken) {
5974
6026
  setNewError("A template with this name already exists");
5975
6027
  return false;
@@ -6032,7 +6084,7 @@ function SamplesDrawer({
6032
6084
  if (!enabled) {
6033
6085
  return null;
6034
6086
  }
6035
- const existingSlugs = templates.map((t) => t.slug);
6087
+ const existingSlugs = templates.map((t2) => t2.slug);
6036
6088
  return /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(
6037
6089
  Drawer,
6038
6090
  {
@@ -6058,12 +6110,12 @@ function SamplesDrawer({
6058
6110
  spacing: 1.5,
6059
6111
  sx: { overflowY: "auto" }
6060
6112
  },
6061
- /* @__PURE__ */ React57.createElement(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { pt: 1 } }, /* @__PURE__ */ React57.createElement(Typography, { variant: "h6", component: "h1" }, "Library"), saveAs && (activeLeftTab === "templates" || activeLeftTab === "samples") && /* @__PURE__ */ React57.createElement(Tooltip, { title: activeLeftTab === "samples" ? "New sample" : "New template" }, /* @__PURE__ */ React57.createElement(
6113
+ /* @__PURE__ */ React57.createElement(Stack, { direction: "row", alignItems: "center", justifyContent: "space-between", sx: { pt: 1 } }, /* @__PURE__ */ React57.createElement(Typography, { variant: "h6", component: "h1" }, /* @__PURE__ */ React57.createElement(Trans, { id: "drawer.library" }, "Library")), saveAs && (activeLeftTab === "templates" || activeLeftTab === "samples") && /* @__PURE__ */ React57.createElement(Tooltip, { title: activeLeftTab === "samples" ? t("drawer.new-sample", "New sample") : t("drawer.new-template", "New template") }, /* @__PURE__ */ React57.createElement(
6062
6114
  IconButton,
6063
6115
  {
6064
6116
  size: "small",
6065
6117
  onClick: () => openNewPicker(activeLeftTab === "samples" ? "sample" : "template"),
6066
- "aria-label": activeLeftTab === "samples" ? "New sample" : "New template"
6118
+ "aria-label": activeLeftTab === "samples" ? t("drawer.new-sample", "New sample") : t("drawer.new-template", "New template")
6067
6119
  },
6068
6120
  /* @__PURE__ */ React57.createElement(AddOutlined, { fontSize: "small" })
6069
6121
  ))),
@@ -6075,15 +6127,15 @@ function SamplesDrawer({
6075
6127
  variant: "fullWidth",
6076
6128
  sx: { minHeight: 36, "& .MuiTab-root": { minHeight: 36, minWidth: 0, px: 1, fontSize: 13 } }
6077
6129
  },
6078
- /* @__PURE__ */ React57.createElement(Tab, { value: "templates", label: "Templates", disabled: !loadTemplates }),
6079
- /* @__PURE__ */ React57.createElement(Tab, { value: "samples", label: "Samples" }),
6080
- /* @__PURE__ */ React57.createElement(Tab, { value: "outline", label: "Outline" })
6130
+ /* @__PURE__ */ React57.createElement(Tab, { value: "templates", label: t("drawer.tab.templates", "Templates"), disabled: !loadTemplates }),
6131
+ /* @__PURE__ */ React57.createElement(Tab, { value: "samples", label: t("drawer.tab.samples", "Samples") }),
6132
+ /* @__PURE__ */ React57.createElement(Tab, { value: "outline", label: t("drawer.tab.outline", "Outline") })
6081
6133
  ),
6082
6134
  activeLeftTab === "outline" ? /* @__PURE__ */ React57.createElement(OutlinePanel, null) : /* @__PURE__ */ React57.createElement(React57.Fragment, null, /* @__PURE__ */ React57.createElement(
6083
6135
  TextField,
6084
6136
  {
6085
6137
  size: "small",
6086
- placeholder: activeLeftTab === "templates" ? "Search templates" : "Search samples",
6138
+ placeholder: activeLeftTab === "templates" ? t("drawer.search-templates", "Search templates") : t("drawer.search-samples", "Search samples"),
6087
6139
  value: search,
6088
6140
  onChange: (e) => setSearch(e.target.value),
6089
6141
  InputProps: {
@@ -6095,15 +6147,15 @@ function SamplesDrawer({
6095
6147
  {
6096
6148
  select: true,
6097
6149
  size: "small",
6098
- label: "Sort by",
6150
+ label: t("drawer.sort-by", "Sort by"),
6099
6151
  value: sortKey,
6100
6152
  onChange: (e) => setSortKey(e.target.value)
6101
6153
  },
6102
- SORT_OPTIONS.map((opt) => /* @__PURE__ */ React57.createElement(MenuItem, { key: opt.value, value: opt.value }, opt.label))
6154
+ SORT_OPTIONS.map((opt) => /* @__PURE__ */ React57.createElement(MenuItem, { key: opt.value, value: opt.value }, t(opt.labelKey, opt.fallback)))
6103
6155
  ), allTags.length > 0 && /* @__PURE__ */ React57.createElement(Stack, { direction: "row", sx: { flexWrap: "wrap", gap: 0.5 } }, /* @__PURE__ */ React57.createElement(
6104
6156
  Chip,
6105
6157
  {
6106
- label: "All",
6158
+ label: t("drawer.tag.all", "All"),
6107
6159
  size: "small",
6108
6160
  clickable: true,
6109
6161
  color: activeTags.length === 0 ? "primary" : "default",
@@ -6133,7 +6185,7 @@ function SamplesDrawer({
6133
6185
  onDelete: deleteTemplate ? () => handleDelete(template) : void 0,
6134
6186
  onPromote: setTemplateKind ? () => handleSetKind(template, "sample") : void 0
6135
6187
  }
6136
- ))) : /* @__PURE__ */ React57.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, templateRows.length === 0 ? "No saved templates yet" : "No templates match your filters")) : /* @__PURE__ */ React57.createElement(Box, null, loadingSamples ? /* @__PURE__ */ React57.createElement(Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React57.createElement(CircularProgress, { size: 24 })) : filteredSamples.length > 0 ? /* @__PURE__ */ React57.createElement(Stack, { spacing: 0.25, sx: { width: "100%" } }, filteredSamples.map((sample) => /* @__PURE__ */ React57.createElement(
6188
+ ))) : /* @__PURE__ */ React57.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, templateRows.length === 0 ? t("drawer.no-templates", "No saved templates yet") : t("drawer.no-templates-match", "No templates match your filters"))) : /* @__PURE__ */ React57.createElement(Box, null, loadingSamples ? /* @__PURE__ */ React57.createElement(Stack, { alignItems: "center", width: "100%", py: 2 }, /* @__PURE__ */ React57.createElement(CircularProgress, { size: 24 })) : filteredSamples.length > 0 ? /* @__PURE__ */ React57.createElement(Stack, { spacing: 0.25, sx: { width: "100%" } }, filteredSamples.map((sample) => /* @__PURE__ */ React57.createElement(
6137
6189
  TemplateRow,
6138
6190
  {
6139
6191
  key: sample.id,
@@ -6145,7 +6197,7 @@ function SamplesDrawer({
6145
6197
  onDelete: deleteTemplate ? () => handleDelete(sample) : void 0,
6146
6198
  onDemote: setTemplateKind ? () => handleSetKind(sample, "template") : void 0
6147
6199
  }
6148
- ))) : /* @__PURE__ */ React57.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, sampleRows.length === 0 ? "No samples available" : "No samples match your filters")))
6200
+ ))) : /* @__PURE__ */ React57.createElement(Typography, { variant: "body2", sx: { color: "text.secondary", py: 1 } }, sampleRows.length === 0 ? t("drawer.no-samples", "No samples available") : t("drawer.no-samples-match", "No samples match your filters"))))
6149
6201
  )
6150
6202
  ), renameTarget && /* @__PURE__ */ React57.createElement(
6151
6203
  RenameDialog,
@@ -6176,7 +6228,7 @@ function SamplesDrawer({
6176
6228
  open: pickerKind !== null,
6177
6229
  kind: pickerKind != null ? pickerKind : "template",
6178
6230
  samples: sampleRows,
6179
- existingSlugs: pickerKind === "sample" ? sampleRows.map((s) => s.slug) : templateRows.map((t) => t.slug),
6231
+ existingSlugs: pickerKind === "sample" ? sampleRows.map((s) => s.slug) : templateRows.map((t2) => t2.slug),
6180
6232
  onClose: () => setPickerKind(null),
6181
6233
  onCreate: handleCreateFromPicker
6182
6234
  }
@@ -7123,7 +7175,7 @@ function TuneMenu({ blockId }) {
7123
7175
  resetDocument(nDocument);
7124
7176
  setSelectedBlockId(blockId);
7125
7177
  };
7126
- return /* @__PURE__ */ React57.createElement(Paper, { sx, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React57.createElement(Stack, null, /* @__PURE__ */ React57.createElement(Tooltip, { title: "Move up", placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { onClick: () => handleMoveClick("up"), sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(ArrowUpwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(Tooltip, { title: "Move down", placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { onClick: () => handleMoveClick("down"), sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(ArrowDownwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(Tooltip, { title: "Copy block", placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { onClick: handleCopyClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(ContentCopyOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(Tooltip, { title: "Delete", placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { onClick: handleDeleteClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(DeleteOutlined, { fontSize: "small" })))));
7178
+ return /* @__PURE__ */ React57.createElement(Paper, { sx, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React57.createElement(Stack, null, /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tune.move-up", "Move up"), placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { "aria-label": t("tune.move-up", "Move up"), onClick: () => handleMoveClick("up"), sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(ArrowUpwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tune.move-down", "Move down"), placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { "aria-label": t("tune.move-down", "Move down"), onClick: () => handleMoveClick("down"), sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(ArrowDownwardOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tune.copy", "Copy block"), placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { "aria-label": t("tune.copy", "Copy block"), onClick: handleCopyClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(ContentCopyOutlined, { fontSize: "small" }))), /* @__PURE__ */ React57.createElement(Tooltip, { title: t("tune.delete", "Delete"), placement: "left-start" }, /* @__PURE__ */ React57.createElement(IconButton, { "aria-label": t("tune.delete", "Delete"), onClick: handleDeleteClick, sx: { color: "text.primary" } }, /* @__PURE__ */ React57.createElement(DeleteOutlined, { fontSize: "small" })))));
7127
7179
  }
7128
7180
 
7129
7181
  // src/editor/blocks/helpers/block-wrappers/editor-block-wrapper.tsx
@@ -7486,7 +7538,7 @@ function InlineFormattingToolbar({
7486
7538
  },
7487
7539
  sx: { width: 220 }
7488
7540
  }
7489
- )) : /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 0.25 }, /* @__PURE__ */ React57.createElement(IconButton, { size: "small", onClick: onBold, title: "Bold (Cmd+B)", "aria-label": "Bold" }, /* @__PURE__ */ React57.createElement(FormatBoldOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(IconButton, { size: "small", onClick: onItalic, title: "Italic (Cmd+I)", "aria-label": "Italic" }, /* @__PURE__ */ React57.createElement(FormatItalicOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(IconButton, { size: "small", onClick: onLinkRequest, title: "Link (Cmd+K)", "aria-label": "Link" }, /* @__PURE__ */ React57.createElement(LinkOutlined, { fontSize: "small" })))));
7541
+ )) : /* @__PURE__ */ React57.createElement(Stack, { direction: "row", spacing: 0.25 }, /* @__PURE__ */ React57.createElement(IconButton, { size: "small", onClick: onBold, title: t("toolbar.bold-shortcut", "Bold (Cmd+B)"), "aria-label": t("toolbar.bold", "Bold") }, /* @__PURE__ */ React57.createElement(FormatBoldOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(IconButton, { size: "small", onClick: onItalic, title: t("toolbar.italic-shortcut", "Italic (Cmd+I)"), "aria-label": t("toolbar.italic", "Italic") }, /* @__PURE__ */ React57.createElement(FormatItalicOutlined, { fontSize: "small" })), /* @__PURE__ */ React57.createElement(IconButton, { size: "small", onClick: onLinkRequest, title: t("toolbar.link-shortcut", "Link (Cmd+K)"), "aria-label": t("toolbar.link", "Link") }, /* @__PURE__ */ React57.createElement(LinkOutlined, { fontSize: "small" })))));
7490
7542
  }
7491
7543
 
7492
7544
  // src/editor/blocks/heading/heading-editor.tsx
@@ -8437,7 +8489,7 @@ function SaveBar({ loadTemplates, saveAs }) {
8437
8489
  const [nameError, setNameError] = useState(null);
8438
8490
  const hasOpenRow = Boolean(currentTemplateId);
8439
8491
  const isSample = currentTemplateKind === "sample";
8440
- const primaryLabel = hasOpenRow ? "Save" : "Save as new\u2026";
8492
+ const primaryLabel = hasOpenRow ? t("savebar.save", "Save") : t("savebar.save-as-new", "Save as new\u2026");
8441
8493
  const handlePrimary = () => __async(null, null, function* () {
8442
8494
  try {
8443
8495
  if (!hasOpenRow) {
@@ -8446,11 +8498,11 @@ function SaveBar({ loadTemplates, saveAs }) {
8446
8498
  return;
8447
8499
  }
8448
8500
  saveTemplate();
8449
- showMessage(isSample ? "Sample saved" : "Template saved");
8501
+ showMessage(isSample ? t("savebar.sample-saved", "Sample saved") : t("savebar.template-saved", "Template saved"));
8450
8502
  if (loadTemplates) yield loadTemplates();
8451
8503
  } catch (e) {
8452
8504
  console.error("Error saving:", e);
8453
- showMessage("Error saving");
8505
+ showMessage(t("savebar.error-saving", "Error saving"));
8454
8506
  }
8455
8507
  });
8456
8508
  const handleSaveAs = (name) => __async(null, null, function* () {
@@ -8462,12 +8514,14 @@ function SaveBar({ loadTemplates, saveAs }) {
8462
8514
  setCurrentTemplate(id, slug, "template");
8463
8515
  ctxLoadTemplate(starterContent, id, slug, "template");
8464
8516
  if (loadTemplates) yield loadTemplates();
8465
- showMessage(dialogMode === "new-blank" ? "New template created" : "Template saved");
8517
+ showMessage(
8518
+ dialogMode === "new-blank" ? t("savebar.new-template-created", "New template created") : t("savebar.template-saved", "Template saved")
8519
+ );
8466
8520
  window.location.hash = `#template/${id}`;
8467
8521
  return true;
8468
8522
  } catch (e) {
8469
8523
  console.error("Error in saveAs:", e);
8470
- showMessage("Error saving");
8524
+ showMessage(t("savebar.error-saving", "Error saving"));
8471
8525
  return false;
8472
8526
  }
8473
8527
  });
@@ -8514,10 +8568,10 @@ function SaveBar({ loadTemplates, saveAs }) {
8514
8568
  },
8515
8569
  title: currentTemplateName
8516
8570
  },
8517
- isSample ? "Sample \xB7 " : "",
8571
+ isSample ? `${t("savebar.sample-prefix", "Sample")} \xB7 ` : "",
8518
8572
  /* @__PURE__ */ React57.createElement(Box, { component: "span", sx: { color: "text.primary", fontWeight: 600 } }, currentTemplateName)
8519
8573
  ),
8520
- /* @__PURE__ */ React57.createElement(Tooltip, { title: hasOpenRow ? `Save changes${isSample ? " to this sample" : ""}` : "Save as a new template" }, /* @__PURE__ */ React57.createElement(
8574
+ /* @__PURE__ */ React57.createElement(Tooltip, { title: hasOpenRow ? isSample ? t("savebar.save-changes-to-sample", "Save changes to this sample") : t("savebar.save-changes", "Save changes") : t("savebar.save-as-new-template", "Save as a new template") }, /* @__PURE__ */ React57.createElement(
8521
8575
  Button$1,
8522
8576
  {
8523
8577
  variant: "contained",
@@ -8528,7 +8582,7 @@ function SaveBar({ loadTemplates, saveAs }) {
8528
8582
  },
8529
8583
  primaryLabel
8530
8584
  )),
8531
- hasOpenRow && saveAs && /* @__PURE__ */ React57.createElement(Tooltip, { title: "Save as a new template" }, /* @__PURE__ */ React57.createElement(
8585
+ hasOpenRow && saveAs && /* @__PURE__ */ React57.createElement(Tooltip, { title: t("savebar.save-as-new-template", "Save as a new template") }, /* @__PURE__ */ React57.createElement(
8532
8586
  Button$1,
8533
8587
  {
8534
8588
  variant: "outlined",
@@ -8540,9 +8594,9 @@ function SaveBar({ loadTemplates, saveAs }) {
8540
8594
  },
8541
8595
  sx: { borderRadius: 999, textTransform: "none", px: 2, fontSize: 14 }
8542
8596
  },
8543
- "Save as\u2026"
8597
+ t("savebar.save-as", "Save as\u2026")
8544
8598
  )),
8545
- saveAs && /* @__PURE__ */ React57.createElement(Tooltip, { title: "Start a fresh template" }, /* @__PURE__ */ React57.createElement(
8599
+ saveAs && /* @__PURE__ */ React57.createElement(Tooltip, { title: t("savebar.start-fresh", "Start a fresh template") }, /* @__PURE__ */ React57.createElement(
8546
8600
  Button$1,
8547
8601
  {
8548
8602
  variant: "text",
@@ -8554,7 +8608,7 @@ function SaveBar({ loadTemplates, saveAs }) {
8554
8608
  },
8555
8609
  sx: { borderRadius: 999, textTransform: "none", px: 2, fontSize: 14, color: "text.secondary" }
8556
8610
  },
8557
- "New"
8611
+ t("savebar.new", "New")
8558
8612
  ))
8559
8613
  )
8560
8614
  ), /* @__PURE__ */ React57.createElement(
@@ -9031,8 +9085,10 @@ var EmailEditor = forwardRef((props, ref) => {
9031
9085
  uploadImage,
9032
9086
  loadImages,
9033
9087
  deleteImage,
9034
- theme
9088
+ theme,
9089
+ locale
9035
9090
  } = props;
9091
+ activateLocale(locale);
9036
9092
  const resolvedTemplate = useMemo(
9037
9093
  () => typeof initialTemplateProp === "string" ? htmlToEditorConfig(initialTemplateProp) : initialTemplateProp,
9038
9094
  [initialTemplateProp]
@@ -9049,7 +9105,7 @@ var EmailEditor = forwardRef((props, ref) => {
9049
9105
  () => ({ uploadImage, loadImages, deleteImage }),
9050
9106
  [uploadImage, loadImages, deleteImage]
9051
9107
  );
9052
- return /* @__PURE__ */ React57.createElement(ThemeProvider, { theme: theme || theme_default }, /* @__PURE__ */ React57.createElement(CssBaseline, null), /* @__PURE__ */ React57.createElement("div", { style: { height: "100%", overflow: "auto" } }, /* @__PURE__ */ React57.createElement(SnackbarProvider, null, /* @__PURE__ */ React57.createElement(ImageCallbacksProvider, { callbacks: imageCallbacks }, /* @__PURE__ */ React57.createElement(
9108
+ return /* @__PURE__ */ React57.createElement(I18nProvider, { i18n }, /* @__PURE__ */ React57.createElement(ThemeProvider, { theme: theme || theme_default }, /* @__PURE__ */ React57.createElement(CssBaseline, null), /* @__PURE__ */ React57.createElement("div", { style: { height: "100%", overflow: "auto" } }, /* @__PURE__ */ React57.createElement(SnackbarProvider, null, /* @__PURE__ */ React57.createElement(ImageCallbacksProvider, { callbacks: imageCallbacks }, /* @__PURE__ */ React57.createElement(
9053
9109
  EmailEditorProvider,
9054
9110
  {
9055
9111
  initialTemplate: resolvedTemplate,
@@ -9077,11 +9133,11 @@ var EmailEditor = forwardRef((props, ref) => {
9077
9133
  onChange
9078
9134
  }
9079
9135
  )
9080
- )))));
9136
+ ))))));
9081
9137
  });
9082
9138
  EmailEditor.displayName = "EmailEditor";
9083
9139
  EmailEditorInternal.displayName = "EmailEditorInternal";
9084
9140
 
9085
- export { avatar_default as Avatar, AvatarProps, AvatarPropsDefaults, AvatarPropsSchema, BlockConfiguration, button_default as Button, ButtonProps, ButtonPropsDefaults, ButtonPropsSchema, columns_container_default as ColumnsContainer, ColumnsContainerProps, ColumnsContainerPropsSchema, ColumnsContainerReader, container_default as Container, ContainerProps, ContainerPropsSchema, ContainerReader, divider_default as Divider, DividerProps, DividerPropsDefaults, DividerPropsSchema, DocumentBlocksDictionary, EmailEditor, EmailEditorProvider, EmailLayoutPropsSchema, EmailLayoutReader, EmailMarkdown, heading_default as Heading, HeadingProps, HeadingPropsDefaults, HeadingPropsSchema, html_default as Html, HtmlProps, HtmlPropsSchema, image_default as Image, ImageProps, ImagePropsSchema, Reader, ReaderBlock, ReaderBlockSchema, ReaderDocumentSchema, signature_default as Signature, SignatureProps, SignaturePropsDefaults, SignaturePropsSchema, spacer_default as Spacer, SpacerProps, SpacerPropsDefaults, SpacerPropsSchema, TemplateVariableSchema, Text, TextProps, TextPropsDefaults, TextPropsSchema, buildBlockComponent, buildBlockConfigurationDictionary, buildBlockConfigurationSchema, editorHandlebars, evaluateHandlebars, htmlToEditorConfig, renderToStaticMarkup, renderToText, theme_default as theme, useEmailEditor };
9141
+ export { avatar_default as Avatar, AvatarProps, AvatarPropsDefaults, AvatarPropsSchema, BlockConfiguration, button_default as Button, ButtonProps, ButtonPropsDefaults, ButtonPropsSchema, columns_container_default as ColumnsContainer, ColumnsContainerProps, ColumnsContainerPropsSchema, ColumnsContainerReader, container_default as Container, ContainerProps, ContainerPropsSchema, ContainerReader, divider_default as Divider, DividerProps, DividerPropsDefaults, DividerPropsSchema, DocumentBlocksDictionary, EmailEditor, EmailEditorProvider, EmailLayoutPropsSchema, EmailLayoutReader, EmailMarkdown, heading_default as Heading, HeadingProps, HeadingPropsDefaults, HeadingPropsSchema, html_default as Html, HtmlProps, HtmlPropsSchema, image_default as Image, ImageProps, ImagePropsSchema, Reader, ReaderBlock, ReaderBlockSchema, ReaderDocumentSchema, SUPPORTED_LOCALES, signature_default as Signature, SignatureProps, SignaturePropsDefaults, SignaturePropsSchema, spacer_default as Spacer, SpacerProps, SpacerPropsDefaults, SpacerPropsSchema, TemplateVariableSchema, Text, TextProps, TextPropsDefaults, TextPropsSchema, buildBlockComponent, buildBlockConfigurationDictionary, buildBlockConfigurationSchema, editorHandlebars, evaluateHandlebars, htmlToEditorConfig, renderToStaticMarkup, renderToText, theme_default as theme, useEmailEditor };
9086
9142
  //# sourceMappingURL=index.js.map
9087
9143
  //# sourceMappingURL=index.js.map