monto-email-builder 1.0.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.
Files changed (181) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +169 -0
  3. package/dist/App/InspectorDrawer/ConfigurationPanel/index.d.ts +3 -0
  4. package/dist/App/InspectorDrawer/ConfigurationPanel/index.d.ts.map +1 -0
  5. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/AvatarSidebarPanel.d.ts +9 -0
  6. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/AvatarSidebarPanel.d.ts.map +1 -0
  7. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ButtonSidebarPanel.d.ts +9 -0
  8. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ButtonSidebarPanel.d.ts.map +1 -0
  9. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ColumnsContainerSidebarPanel.d.ts +9 -0
  10. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ColumnsContainerSidebarPanel.d.ts.map +1 -0
  11. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ContainerSidebarPanel.d.ts +9 -0
  12. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ContainerSidebarPanel.d.ts.map +1 -0
  13. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/DividerSidebarPanel.d.ts +9 -0
  14. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/DividerSidebarPanel.d.ts.map +1 -0
  15. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/EmailLayoutSidebarPanel.d.ts +9 -0
  16. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/EmailLayoutSidebarPanel.d.ts.map +1 -0
  17. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/HeadingSidebarPanel.d.ts +9 -0
  18. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/HeadingSidebarPanel.d.ts.map +1 -0
  19. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/HtmlSidebarPanel.d.ts +9 -0
  20. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/HtmlSidebarPanel.d.ts.map +1 -0
  21. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ImageSidebarPanel.d.ts +9 -0
  22. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/ImageSidebarPanel.d.ts.map +1 -0
  23. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/SpacerSidebarPanel.d.ts +9 -0
  24. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/SpacerSidebarPanel.d.ts.map +1 -0
  25. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/TextSidebarPanel.d.ts +9 -0
  26. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/TextSidebarPanel.d.ts.map +1 -0
  27. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/BaseSidebarPanel.d.ts +8 -0
  28. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/BaseSidebarPanel.d.ts.map +1 -0
  29. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/BooleanInput.d.ts +9 -0
  30. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/BooleanInput.d.ts.map +1 -0
  31. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/BaseColorInput.d.ts +15 -0
  32. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/BaseColorInput.d.ts.map +1 -0
  33. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/Picker.d.ts +8 -0
  34. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/Picker.d.ts.map +1 -0
  35. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/Swatch.d.ts +9 -0
  36. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/Swatch.d.ts.map +1 -0
  37. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/index.d.ts +15 -0
  38. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColorInput/index.d.ts.map +1 -0
  39. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColumnWidthsInput.d.ts +15 -0
  40. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/ColumnWidthsInput.d.ts.map +1 -0
  41. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/FontFamily.d.ts +9 -0
  42. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/FontFamily.d.ts.map +1 -0
  43. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/FontSizeInput.d.ts +9 -0
  44. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/FontSizeInput.d.ts.map +1 -0
  45. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/FontWeightInput.d.ts +9 -0
  46. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/FontWeightInput.d.ts.map +1 -0
  47. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/PaddingInput.d.ts +15 -0
  48. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/PaddingInput.d.ts.map +1 -0
  49. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/RadioGroupInput.d.ts +10 -0
  50. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/RadioGroupInput.d.ts.map +1 -0
  51. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/SliderInput.d.ts +15 -0
  52. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/SliderInput.d.ts.map +1 -0
  53. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/TextAlignInput.d.ts +9 -0
  54. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/TextAlignInput.d.ts.map +1 -0
  55. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/TextDimensionInput.d.ts +9 -0
  56. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/TextDimensionInput.d.ts.map +1 -0
  57. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/TextInput.d.ts +14 -0
  58. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/TextInput.d.ts.map +1 -0
  59. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/raw/RawSliderInput.d.ts +14 -0
  60. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/inputs/raw/RawSliderInput.d.ts.map +1 -0
  61. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/style-inputs/MultiStylePropertyPanel.d.ts +10 -0
  62. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/style-inputs/MultiStylePropertyPanel.d.ts.map +1 -0
  63. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/style-inputs/SingleStylePropertyPanel.d.ts +10 -0
  64. package/dist/App/InspectorDrawer/ConfigurationPanel/input-panels/helpers/style-inputs/SingleStylePropertyPanel.d.ts.map +1 -0
  65. package/dist/App/InspectorDrawer/StylesPanel.d.ts +3 -0
  66. package/dist/App/InspectorDrawer/StylesPanel.d.ts.map +1 -0
  67. package/dist/App/InspectorDrawer/ToggleInspectorPanelButton.d.ts +3 -0
  68. package/dist/App/InspectorDrawer/ToggleInspectorPanelButton.d.ts.map +1 -0
  69. package/dist/App/InspectorDrawer/index.d.ts +4 -0
  70. package/dist/App/InspectorDrawer/index.d.ts.map +1 -0
  71. package/dist/App/LanguageSwitcher/index.d.ts +3 -0
  72. package/dist/App/LanguageSwitcher/index.d.ts.map +1 -0
  73. package/dist/App/SamplesDrawer/SidebarButton.d.ts +6 -0
  74. package/dist/App/SamplesDrawer/SidebarButton.d.ts.map +1 -0
  75. package/dist/App/SamplesDrawer/ToggleSamplesPanelButton.d.ts +3 -0
  76. package/dist/App/SamplesDrawer/ToggleSamplesPanelButton.d.ts.map +1 -0
  77. package/dist/App/SamplesDrawer/index.d.ts +4 -0
  78. package/dist/App/SamplesDrawer/index.d.ts.map +1 -0
  79. package/dist/App/TemplatePanel/DownloadJson/index.d.ts +3 -0
  80. package/dist/App/TemplatePanel/DownloadJson/index.d.ts.map +1 -0
  81. package/dist/App/TemplatePanel/HtmlPanel.d.ts +3 -0
  82. package/dist/App/TemplatePanel/HtmlPanel.d.ts.map +1 -0
  83. package/dist/App/TemplatePanel/ImportJson/ImportJsonDialog.d.ts +7 -0
  84. package/dist/App/TemplatePanel/ImportJson/ImportJsonDialog.d.ts.map +1 -0
  85. package/dist/App/TemplatePanel/ImportJson/index.d.ts +3 -0
  86. package/dist/App/TemplatePanel/ImportJson/index.d.ts.map +1 -0
  87. package/dist/App/TemplatePanel/ImportJson/validateJsonStringValue.d.ts +11 -0
  88. package/dist/App/TemplatePanel/ImportJson/validateJsonStringValue.d.ts.map +1 -0
  89. package/dist/App/TemplatePanel/JsonPanel.d.ts +3 -0
  90. package/dist/App/TemplatePanel/JsonPanel.d.ts.map +1 -0
  91. package/dist/App/TemplatePanel/MainTabsGroup.d.ts +3 -0
  92. package/dist/App/TemplatePanel/MainTabsGroup.d.ts.map +1 -0
  93. package/dist/App/TemplatePanel/ShareButton.d.ts +3 -0
  94. package/dist/App/TemplatePanel/ShareButton.d.ts.map +1 -0
  95. package/dist/App/TemplatePanel/helper/HighlightedCodePanel.d.ts +8 -0
  96. package/dist/App/TemplatePanel/helper/HighlightedCodePanel.d.ts.map +1 -0
  97. package/dist/App/TemplatePanel/helper/highlighters.d.ts +3 -0
  98. package/dist/App/TemplatePanel/helper/highlighters.d.ts.map +1 -0
  99. package/dist/App/TemplatePanel/index.d.ts +3 -0
  100. package/dist/App/TemplatePanel/index.d.ts.map +1 -0
  101. package/dist/App/index.d.ts +3 -0
  102. package/dist/App/index.d.ts.map +1 -0
  103. package/dist/EmailBuilder/index.d.ts +68 -0
  104. package/dist/EmailBuilder/index.d.ts.map +1 -0
  105. package/dist/documents/blocks/ColumnsContainer/ColumnsContainerEditor.d.ts +4 -0
  106. package/dist/documents/blocks/ColumnsContainer/ColumnsContainerEditor.d.ts.map +1 -0
  107. package/dist/documents/blocks/ColumnsContainer/ColumnsContainerPropsSchema.d.ts +136 -0
  108. package/dist/documents/blocks/ColumnsContainer/ColumnsContainerPropsSchema.d.ts.map +1 -0
  109. package/dist/documents/blocks/Container/ContainerEditor.d.ts +4 -0
  110. package/dist/documents/blocks/Container/ContainerEditor.d.ts.map +1 -0
  111. package/dist/documents/blocks/Container/ContainerPropsSchema.d.ts +84 -0
  112. package/dist/documents/blocks/Container/ContainerPropsSchema.d.ts.map +1 -0
  113. package/dist/documents/blocks/EmailLayout/EmailLayoutEditor.d.ts +4 -0
  114. package/dist/documents/blocks/EmailLayout/EmailLayoutEditor.d.ts.map +1 -0
  115. package/dist/documents/blocks/EmailLayout/EmailLayoutPropsSchema.d.ts +32 -0
  116. package/dist/documents/blocks/EmailLayout/EmailLayoutPropsSchema.d.ts.map +1 -0
  117. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/BlockButton.d.ts +9 -0
  118. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/BlockButton.d.ts.map +1 -0
  119. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/BlocksMenu.d.ts +10 -0
  120. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/BlocksMenu.d.ts.map +1 -0
  121. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/DividerButton.d.ts +8 -0
  122. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/DividerButton.d.ts.map +1 -0
  123. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/PlaceholderButton.d.ts +7 -0
  124. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/PlaceholderButton.d.ts.map +1 -0
  125. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/buttons.d.ts +10 -0
  126. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/buttons.d.ts.map +1 -0
  127. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/index.d.ts +9 -0
  128. package/dist/documents/blocks/helpers/EditorChildrenIds/AddBlockMenu/index.d.ts.map +1 -0
  129. package/dist/documents/blocks/helpers/EditorChildrenIds/index.d.ts +13 -0
  130. package/dist/documents/blocks/helpers/EditorChildrenIds/index.d.ts.map +1 -0
  131. package/dist/documents/blocks/helpers/TStyle.d.ts +12 -0
  132. package/dist/documents/blocks/helpers/TStyle.d.ts.map +1 -0
  133. package/dist/documents/blocks/helpers/block-wrappers/EditorBlockWrapper.d.ts +7 -0
  134. package/dist/documents/blocks/helpers/block-wrappers/EditorBlockWrapper.d.ts.map +1 -0
  135. package/dist/documents/blocks/helpers/block-wrappers/ReaderBlockWrapper.d.ts +9 -0
  136. package/dist/documents/blocks/helpers/block-wrappers/ReaderBlockWrapper.d.ts.map +1 -0
  137. package/dist/documents/blocks/helpers/block-wrappers/TuneMenu.d.ts +7 -0
  138. package/dist/documents/blocks/helpers/block-wrappers/TuneMenu.d.ts.map +1 -0
  139. package/dist/documents/blocks/helpers/fontFamily.d.ts +7 -0
  140. package/dist/documents/blocks/helpers/fontFamily.d.ts.map +1 -0
  141. package/dist/documents/blocks/helpers/zod.d.ts +22 -0
  142. package/dist/documents/blocks/helpers/zod.d.ts.map +1 -0
  143. package/dist/documents/editor/EditorBlock.d.ts +13 -0
  144. package/dist/documents/editor/EditorBlock.d.ts.map +1 -0
  145. package/dist/documents/editor/EditorContext.d.ts +40 -0
  146. package/dist/documents/editor/EditorContext.d.ts.map +1 -0
  147. package/dist/documents/editor/core.d.ts +2777 -0
  148. package/dist/documents/editor/core.d.ts.map +1 -0
  149. package/dist/getConfiguration/index.d.ts +3 -0
  150. package/dist/getConfiguration/index.d.ts.map +1 -0
  151. package/dist/getConfiguration/sample/empty-email-message.d.ts +4 -0
  152. package/dist/getConfiguration/sample/empty-email-message.d.ts.map +1 -0
  153. package/dist/getConfiguration/sample/one-time-passcode.d.ts +4 -0
  154. package/dist/getConfiguration/sample/one-time-passcode.d.ts.map +1 -0
  155. package/dist/getConfiguration/sample/order-ecommerce.d.ts +4 -0
  156. package/dist/getConfiguration/sample/order-ecommerce.d.ts.map +1 -0
  157. package/dist/getConfiguration/sample/post-metrics-report.d.ts +4 -0
  158. package/dist/getConfiguration/sample/post-metrics-report.d.ts.map +1 -0
  159. package/dist/getConfiguration/sample/reservation-reminder.d.ts +4 -0
  160. package/dist/getConfiguration/sample/reservation-reminder.d.ts.map +1 -0
  161. package/dist/getConfiguration/sample/reset-password.d.ts +4 -0
  162. package/dist/getConfiguration/sample/reset-password.d.ts.map +1 -0
  163. package/dist/getConfiguration/sample/respond-to-message.d.ts +4 -0
  164. package/dist/getConfiguration/sample/respond-to-message.d.ts.map +1 -0
  165. package/dist/getConfiguration/sample/subscription-receipt.d.ts +4 -0
  166. package/dist/getConfiguration/sample/subscription-receipt.d.ts.map +1 -0
  167. package/dist/getConfiguration/sample/welcome.d.ts +4 -0
  168. package/dist/getConfiguration/sample/welcome.d.ts.map +1 -0
  169. package/dist/i18n/index.d.ts +18 -0
  170. package/dist/i18n/index.d.ts.map +1 -0
  171. package/dist/i18n/useTranslation.d.ts +9 -0
  172. package/dist/i18n/useTranslation.d.ts.map +1 -0
  173. package/dist/index.d.ts +11 -0
  174. package/dist/index.d.ts.map +1 -0
  175. package/dist/index.js +3534 -0
  176. package/dist/main.d.ts +2 -0
  177. package/dist/main.d.ts.map +1 -0
  178. package/dist/samples-SfLrANbd.js +6038 -0
  179. package/dist/theme.d.ts +3 -0
  180. package/dist/theme.d.ts.map +1 -0
  181. package/package.json +102 -0
package/dist/index.js ADDED
@@ -0,0 +1,3534 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import React, { useState, useRef, useEffect, Fragment as Fragment$1, createContext, useContext, useMemo } from "react";
3
+ import { Box, Typography, Stack, InputLabel, ToggleButtonGroup, Slider, TextField, Button, Menu, ButtonBase, MenuItem, ToggleButton, FormControlLabel, Switch, Drawer, Tabs, Tab, IconButton, Divider, Fade, Paper, Tooltip, Dialog, DialogTitle, DialogContent, Link, DialogActions, Alert, Snackbar, useTheme, ThemeProvider, CssBaseline } from "@mui/material";
4
+ import { create } from "zustand";
5
+ import { E as EMPTY_EMAIL_MESSAGE } from "./samples-SfLrANbd.js";
6
+ import { createTheme, lighten, darken, alpha } from "@mui/material/styles";
7
+ import { CloseOutlined, AddOutlined, TextFieldsOutlined, AlignVerticalTopOutlined, AlignVerticalBottomOutlined, AlignHorizontalLeftOutlined, AlignHorizontalRightOutlined, FormatAlignLeftOutlined, FormatAlignCenterOutlined, FormatAlignRightOutlined, RoundedCornerOutlined, AspectRatioOutlined, SpaceBarOutlined, VerticalAlignTopOutlined, VerticalAlignCenterOutlined, VerticalAlignBottomOutlined, HeightOutlined, LinkOutlined, CloudUploadOutlined, LanguageOutlined, HMobiledataOutlined, NotesOutlined, SmartButtonOutlined, ImageOutlined, AccountCircleOutlined, HorizontalRuleOutlined, Crop32Outlined, HtmlOutlined, ViewColumnOutlined, LibraryAddOutlined, ArrowUpwardOutlined, ArrowDownwardOutlined, DeleteOutlined, LastPageOutlined, AppRegistrationOutlined, FirstPageOutlined, MenuOutlined, FileDownloadOutlined, FileUploadOutlined, EditOutlined, PreviewOutlined, CodeOutlined, DataObjectOutlined, IosShareOutlined, MonitorOutlined, PhoneIphoneOutlined } from "@mui/icons-material";
8
+ import { AvatarPropsDefaults, AvatarPropsSchema, Avatar } from "@usewaypoint/block-avatar";
9
+ import { HexColorPicker, HexColorInput } from "react-colorful";
10
+ import { ButtonPropsDefaults, ButtonPropsSchema, Button as Button$1 } from "@usewaypoint/block-button";
11
+ import { z } from "zod";
12
+ import { ColumnsContainerPropsSchema as ColumnsContainerPropsSchema$1, ColumnsContainer } from "@usewaypoint/block-columns-container";
13
+ import { ContainerPropsSchema as ContainerPropsSchema$1, Container } from "@usewaypoint/block-container";
14
+ import { DividerPropsDefaults, DividerPropsSchema, Divider as Divider$1 } from "@usewaypoint/block-divider";
15
+ import { HeadingPropsDefaults, HeadingPropsSchema, Heading } from "@usewaypoint/block-heading";
16
+ import { HtmlPropsSchema, Html } from "@usewaypoint/block-html";
17
+ import { ImagePropsSchema, Image } from "@usewaypoint/block-image";
18
+ import { SpacerPropsDefaults, SpacerPropsSchema, Spacer } from "@usewaypoint/block-spacer";
19
+ import { TextPropsSchema, Text } from "@usewaypoint/block-text";
20
+ import { renderToStaticMarkup, Reader } from "@usewaypoint/email-builder";
21
+ import { buildBlockConfigurationDictionary, buildBlockComponent, buildBlockConfigurationSchema } from "@usewaypoint/document-core";
22
+ const sampleTemplates = {
23
+ welcome: () => import("./samples-SfLrANbd.js").then((n) => n.w).then((m) => m.default),
24
+ "one-time-password": () => import("./samples-SfLrANbd.js").then((n) => n.o).then((m) => m.default),
25
+ "order-ecomerce": () => import("./samples-SfLrANbd.js").then((n) => n.a).then((m) => m.default),
26
+ "post-metrics-report": () => import("./samples-SfLrANbd.js").then((n) => n.p).then((m) => m.default),
27
+ "reservation-reminder": () => import("./samples-SfLrANbd.js").then((n) => n.r).then((m) => m.default),
28
+ "reset-password": () => import("./samples-SfLrANbd.js").then((n) => n.b).then((m) => m.default),
29
+ "respond-to-message": () => import("./samples-SfLrANbd.js").then((n) => n.c).then((m) => m.default),
30
+ "subscription-receipt": () => import("./samples-SfLrANbd.js").then((n) => n.s).then((m) => m.default)
31
+ };
32
+ const templateCache = {};
33
+ function getConfiguration(template) {
34
+ if (template.startsWith("#sample/")) {
35
+ return EMPTY_EMAIL_MESSAGE;
36
+ }
37
+ if (template.startsWith("#code/")) {
38
+ const encodedString = template.replace("#code/", "");
39
+ const configurationString = decodeURIComponent(atob(encodedString));
40
+ try {
41
+ return JSON.parse(configurationString);
42
+ } catch {
43
+ console.error(`Couldn't load configuration from hash.`);
44
+ }
45
+ }
46
+ return EMPTY_EMAIL_MESSAGE;
47
+ }
48
+ async function loadSampleTemplate(sampleName) {
49
+ const loader = sampleTemplates[sampleName];
50
+ if (!loader) {
51
+ return EMPTY_EMAIL_MESSAGE;
52
+ }
53
+ if (templateCache[sampleName]) {
54
+ return templateCache[sampleName];
55
+ }
56
+ const template = await loader();
57
+ templateCache[sampleName] = template;
58
+ return template;
59
+ }
60
+ const common$1 = {
61
+ newDocument: "New Blank Document",
62
+ useBuiltInTemplates: "Use Built-in Templates",
63
+ emailBuilder: "Email Builder"
64
+ };
65
+ const samples$1 = {
66
+ welcomeEmail: "Welcome email",
67
+ oneTimePasscode: "One-time passcode (OTP)",
68
+ resetPassword: "Reset password",
69
+ orderEcommerce: "E-commerce receipt",
70
+ subscriptionReceipt: "Subscription receipt",
71
+ reservationReminder: "Reservation reminder",
72
+ postMetrics: "Post metrics",
73
+ respondToMessage: "Respond to inquiry"
74
+ };
75
+ const inspector$1 = {
76
+ styles: "Styles",
77
+ inspect: "Inspect",
78
+ clickBlockToInspect: "Click on a block to inspect.",
79
+ blockNotFound: "Block with id {{id}} was not found. Click on a block to reset."
80
+ };
81
+ const tabs$1 = {
82
+ edit: "Edit",
83
+ preview: "Preview",
84
+ htmlOutput: "HTML output",
85
+ jsonOutput: "JSON output"
86
+ };
87
+ const image$1 = {
88
+ title: "Image block",
89
+ sourceUrl: "Source URL",
90
+ altText: "Alt text",
91
+ clickThroughUrl: "Click through URL",
92
+ width: "Width",
93
+ height: "Height",
94
+ alignment: "Alignment",
95
+ backgroundColor: "Background color",
96
+ upload: "Upload",
97
+ url: "URL",
98
+ selectImage: "Select Image",
99
+ uploading: "Uploading...",
100
+ uploadHandlerNotConfigured: "Please configure imageUploadHandler to enable local upload"
101
+ };
102
+ const emailLayout$1 = {
103
+ global: "Global",
104
+ backdropColor: "Backdrop color",
105
+ canvasColor: "Canvas color",
106
+ canvasBorderColor: "Canvas border color",
107
+ canvasBorderRadius: "Canvas border radius",
108
+ pageWidth: "Page width",
109
+ fontFamily: "Font family",
110
+ textColor: "Text color"
111
+ };
112
+ const en = {
113
+ common: common$1,
114
+ samples: samples$1,
115
+ inspector: inspector$1,
116
+ tabs: tabs$1,
117
+ image: image$1,
118
+ emailLayout: emailLayout$1
119
+ };
120
+ const common = {
121
+ newDocument: "新建空白文档",
122
+ useBuiltInTemplates: "使用内置模板",
123
+ emailBuilder: "邮件编辑器"
124
+ };
125
+ const samples = {
126
+ welcomeEmail: "欢迎邮件",
127
+ oneTimePasscode: "一次性密码 (OTP)",
128
+ resetPassword: "重置密码",
129
+ orderEcommerce: "电商收据",
130
+ subscriptionReceipt: "订阅收据",
131
+ reservationReminder: "预约提醒",
132
+ postMetrics: "指标报告",
133
+ respondToMessage: "回复询问"
134
+ };
135
+ const inspector = {
136
+ styles: "样式",
137
+ inspect: "检查",
138
+ clickBlockToInspect: "点击一个块进行检查。",
139
+ blockNotFound: "未找到 id 为 {{id}} 的块。点击一个块以重置。"
140
+ };
141
+ const tabs = {
142
+ edit: "编辑",
143
+ preview: "预览",
144
+ htmlOutput: "HTML 输出",
145
+ jsonOutput: "JSON 输出"
146
+ };
147
+ const image = {
148
+ title: "图片块",
149
+ sourceUrl: "图片地址",
150
+ altText: "替代文本",
151
+ clickThroughUrl: "点击跳转链接",
152
+ width: "宽度",
153
+ height: "高度",
154
+ alignment: "对齐方式",
155
+ backgroundColor: "背景颜色",
156
+ upload: "上传",
157
+ url: "URL",
158
+ selectImage: "选择图片",
159
+ uploading: "上传中...",
160
+ uploadHandlerNotConfigured: "请配置 imageUploadHandler 以启用本地上传功能"
161
+ };
162
+ const emailLayout = {
163
+ global: "全局",
164
+ backdropColor: "背景颜色",
165
+ canvasColor: "画布颜色",
166
+ canvasBorderColor: "画布边框颜色",
167
+ canvasBorderRadius: "画布圆角",
168
+ pageWidth: "页面宽度",
169
+ fontFamily: "字体",
170
+ textColor: "文字颜色"
171
+ };
172
+ const zh = {
173
+ common,
174
+ samples,
175
+ inspector,
176
+ tabs,
177
+ image,
178
+ emailLayout
179
+ };
180
+ const translations = {
181
+ zh,
182
+ en
183
+ };
184
+ function t(key, params, language) {
185
+ const lang = language ?? getLanguage();
186
+ const keys = key.split(".");
187
+ let value = translations[lang];
188
+ for (const k of keys) {
189
+ if (value && typeof value === "object" && k in value) {
190
+ value = value[k];
191
+ } else {
192
+ return key;
193
+ }
194
+ }
195
+ if (typeof value !== "string") {
196
+ return key;
197
+ }
198
+ if (params) {
199
+ return value.replace(/\{\{(\w+)\}\}/g, (match, paramKey) => {
200
+ var _a;
201
+ return ((_a = params[paramKey]) == null ? void 0 : _a.toString()) ?? match;
202
+ });
203
+ }
204
+ return value;
205
+ }
206
+ function getLanguage() {
207
+ if (typeof window === "undefined") {
208
+ return "en";
209
+ }
210
+ const stored = localStorage.getItem("app-language");
211
+ if (stored && (stored === "zh" || stored === "en")) {
212
+ return stored;
213
+ }
214
+ const browserLang = navigator.language.toLowerCase();
215
+ return browserLang.startsWith("zh") ? "zh" : "en";
216
+ }
217
+ function setLanguage$1(lang) {
218
+ if (typeof window !== "undefined") {
219
+ localStorage.setItem("app-language", lang);
220
+ }
221
+ }
222
+ const editorStateStore = create((set, get) => ({
223
+ document: getConfiguration(typeof window !== "undefined" ? window.location.hash : ""),
224
+ selectedBlockId: null,
225
+ selectedSidebarTab: "styles",
226
+ selectedMainTab: "editor",
227
+ selectedScreenSize: "desktop",
228
+ inspectorDrawerOpen: true,
229
+ samplesDrawerOpen: true,
230
+ language: getLanguage(),
231
+ onChange: void 0
232
+ }));
233
+ function useDocument() {
234
+ return editorStateStore((s) => s.document);
235
+ }
236
+ function useSelectedBlockId() {
237
+ return editorStateStore((s) => s.selectedBlockId);
238
+ }
239
+ function useSelectedScreenSize() {
240
+ return editorStateStore((s) => s.selectedScreenSize);
241
+ }
242
+ function useSelectedMainTab() {
243
+ return editorStateStore((s) => s.selectedMainTab);
244
+ }
245
+ function setSelectedMainTab(selectedMainTab) {
246
+ return editorStateStore.setState({ selectedMainTab });
247
+ }
248
+ function useSelectedSidebarTab() {
249
+ return editorStateStore((s) => s.selectedSidebarTab);
250
+ }
251
+ function useInspectorDrawerOpen() {
252
+ return editorStateStore((s) => s.inspectorDrawerOpen);
253
+ }
254
+ function useSamplesDrawerOpen() {
255
+ return editorStateStore((s) => s.samplesDrawerOpen);
256
+ }
257
+ function setSelectedBlockId(selectedBlockId) {
258
+ const selectedSidebarTab = selectedBlockId === null ? "styles" : "block-configuration";
259
+ const options = {};
260
+ if (selectedBlockId !== null) {
261
+ options.inspectorDrawerOpen = true;
262
+ }
263
+ return editorStateStore.setState({
264
+ selectedBlockId,
265
+ selectedSidebarTab,
266
+ ...options
267
+ });
268
+ }
269
+ function setSidebarTab(selectedSidebarTab) {
270
+ return editorStateStore.setState({ selectedSidebarTab });
271
+ }
272
+ function resetDocument(document) {
273
+ editorStateStore.setState({
274
+ document,
275
+ selectedSidebarTab: "styles",
276
+ selectedBlockId: null
277
+ });
278
+ const onChange = editorStateStore.getState().onChange;
279
+ if (onChange) {
280
+ onChange(document);
281
+ }
282
+ }
283
+ function setDocument(document) {
284
+ const originalDocument = editorStateStore.getState().document;
285
+ const newDocument = {
286
+ ...originalDocument,
287
+ ...document
288
+ };
289
+ editorStateStore.setState({
290
+ document: newDocument
291
+ });
292
+ const onChange = editorStateStore.getState().onChange;
293
+ if (onChange) {
294
+ onChange(newDocument);
295
+ }
296
+ }
297
+ function setOnChange(onChange) {
298
+ return editorStateStore.setState({ onChange });
299
+ }
300
+ function toggleInspectorDrawerOpen() {
301
+ const inspectorDrawerOpen = !editorStateStore.getState().inspectorDrawerOpen;
302
+ return editorStateStore.setState({ inspectorDrawerOpen });
303
+ }
304
+ function toggleSamplesDrawerOpen() {
305
+ const samplesDrawerOpen = !editorStateStore.getState().samplesDrawerOpen;
306
+ return editorStateStore.setState({ samplesDrawerOpen });
307
+ }
308
+ function setSelectedScreenSize(selectedScreenSize) {
309
+ return editorStateStore.setState({ selectedScreenSize });
310
+ }
311
+ function useImageUploadHandler() {
312
+ return editorStateStore((s) => s.imageUploadHandler);
313
+ }
314
+ function setImageUploadHandler(handler) {
315
+ return editorStateStore.setState({ imageUploadHandler: handler });
316
+ }
317
+ function useLanguage() {
318
+ return editorStateStore((s) => s.language);
319
+ }
320
+ function setLanguage(lang) {
321
+ setLanguage$1(lang);
322
+ return editorStateStore.setState({ language: lang });
323
+ }
324
+ const BRAND_NAVY = "#212443";
325
+ const BRAND_BLUE = "#0079CC";
326
+ const BRAND_GREEN = "#1F8466";
327
+ const BRAND_RED = "#E81212";
328
+ const BRAND_YELLOW = "#F6DC9F";
329
+ const BRAND_PURPLE = "#6C0E7C";
330
+ const BRAND_BROWN = "#CC996C";
331
+ const STANDARD_FONT_FAMILY = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';
332
+ const MONOSPACE_FONT_FAMILY = 'ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono", "Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro", "Fira Mono", "Droid Sans Mono", "Courier New", monospace';
333
+ const BASE_THEME = createTheme({
334
+ palette: {
335
+ background: {
336
+ default: "#f2f5f7"
337
+ },
338
+ text: {
339
+ primary: "#1F1F21",
340
+ secondary: "#4F4F4F"
341
+ }
342
+ },
343
+ typography: {
344
+ fontFamily: STANDARD_FONT_FAMILY
345
+ }
346
+ });
347
+ const THEME = createTheme(BASE_THEME, {
348
+ palette: {
349
+ brand: {
350
+ navy: BRAND_NAVY,
351
+ blue: BRAND_BLUE,
352
+ red: BRAND_RED,
353
+ green: BRAND_GREEN,
354
+ yellow: BRAND_YELLOW,
355
+ purple: BRAND_PURPLE,
356
+ brown: BRAND_BROWN
357
+ },
358
+ success: {
359
+ main: BRAND_GREEN,
360
+ light: lighten(BRAND_GREEN, 0.15),
361
+ dark: darken(BRAND_GREEN, 0.15)
362
+ },
363
+ error: {
364
+ main: BRAND_RED,
365
+ light: lighten(BRAND_RED, 0.15),
366
+ dark: darken(BRAND_RED, 0.15)
367
+ },
368
+ cadet: {
369
+ 100: "#F9FAFB",
370
+ 200: "#F2F5F7",
371
+ 300: "#DCE4EA",
372
+ 400: "#A8BBCA",
373
+ 500: "#6A8BA4"
374
+ },
375
+ highlight: {
376
+ 100: lighten(BRAND_YELLOW, 0.8),
377
+ 200: lighten(BRAND_YELLOW, 0.6),
378
+ 300: lighten(BRAND_YELLOW, 0.4),
379
+ 400: lighten(BRAND_YELLOW, 0.2),
380
+ 500: BRAND_YELLOW
381
+ },
382
+ info: {
383
+ main: BRAND_BLUE
384
+ },
385
+ primary: {
386
+ main: BRAND_BLUE
387
+ }
388
+ },
389
+ components: {
390
+ MuiCssBaseline: {
391
+ styleOverrides: `
392
+ address {
393
+ font-style: normal;
394
+ }
395
+ fieldset {
396
+ border: none;
397
+ padding: 0;
398
+ }
399
+ pre {
400
+ font-family: ${MONOSPACE_FONT_FAMILY}
401
+ white-space: pre-wrap;
402
+ font-size: 12px;
403
+ }
404
+ `
405
+ },
406
+ MuiAlert: {
407
+ styleOverrides: {
408
+ root: {
409
+ fontSize: BASE_THEME.typography.pxToRem(14)
410
+ },
411
+ action: {
412
+ paddingTop: 0,
413
+ marginRight: 0
414
+ },
415
+ filledSuccess: {
416
+ backgroundColor: BRAND_GREEN
417
+ }
418
+ }
419
+ },
420
+ MuiStepLabel: {
421
+ styleOverrides: {
422
+ label: {
423
+ fontWeight: BASE_THEME.typography.fontWeightMedium
424
+ }
425
+ }
426
+ },
427
+ MuiDialog: {
428
+ defaultProps: {
429
+ fullWidth: true
430
+ }
431
+ },
432
+ MuiDialogContent: {
433
+ styleOverrides: {
434
+ root: {
435
+ paddingTop: BASE_THEME.spacing(1),
436
+ paddingBottom: BASE_THEME.spacing(2)
437
+ }
438
+ }
439
+ },
440
+ MuiDialogTitle: {
441
+ defaultProps: {
442
+ variant: "h4"
443
+ },
444
+ styleOverrides: {
445
+ root: {
446
+ paddingTop: BASE_THEME.spacing(3),
447
+ paddingBottom: BASE_THEME.spacing(1)
448
+ }
449
+ }
450
+ },
451
+ MuiDialogActions: {
452
+ styleOverrides: {
453
+ root: {
454
+ borderTop: "1px solid",
455
+ borderTopColor: BASE_THEME.palette.divider,
456
+ marginTop: BASE_THEME.spacing(2.5),
457
+ padding: `${BASE_THEME.spacing(1.5)} ${BASE_THEME.spacing(3)}`
458
+ }
459
+ }
460
+ },
461
+ MuiTableCell: {
462
+ styleOverrides: {
463
+ root: {
464
+ ...BASE_THEME.typography.body2,
465
+ borderColor: BASE_THEME.palette.grey[200]
466
+ },
467
+ head: {
468
+ ...BASE_THEME.typography.overline,
469
+ fontWeight: BASE_THEME.typography.fontWeightMedium,
470
+ letterSpacing: "0.075em",
471
+ color: BASE_THEME.palette.text.secondary
472
+ }
473
+ }
474
+ },
475
+ MuiTableRow: {
476
+ styleOverrides: {
477
+ root: {
478
+ "&:last-child td": {
479
+ borderBottom: 0
480
+ }
481
+ }
482
+ }
483
+ },
484
+ MuiAvatar: {
485
+ styleOverrides: {
486
+ root: {
487
+ textTransform: "uppercase",
488
+ fontSize: BASE_THEME.typography.pxToRem(14)
489
+ }
490
+ }
491
+ },
492
+ MuiChip: {
493
+ styleOverrides: {
494
+ root: {
495
+ "&.MuiChip-filledError, &.MuiChip-filledSuccess": {
496
+ fill: BASE_THEME.palette.primary.contrastText
497
+ }
498
+ },
499
+ sizeSmall: {
500
+ borderRadius: BASE_THEME.spacing(0.5),
501
+ fontSize: 12
502
+ },
503
+ iconSmall: {
504
+ fontSize: 14,
505
+ marginLeft: BASE_THEME.spacing(1)
506
+ },
507
+ colorSecondary: {
508
+ borderColor: BASE_THEME.palette.grey[400],
509
+ color: BASE_THEME.palette.text.secondary
510
+ },
511
+ label: {
512
+ fontWeight: BASE_THEME.typography.fontWeightMedium
513
+ }
514
+ }
515
+ },
516
+ MuiDrawer: {
517
+ defaultProps: {
518
+ PaperProps: {
519
+ elevation: 2
520
+ }
521
+ }
522
+ },
523
+ MuiTooltip: {
524
+ styleOverrides: {
525
+ tooltip: {
526
+ fontSize: BASE_THEME.typography.pxToRem(12),
527
+ backgroundColor: alpha(BASE_THEME.palette.text.primary, 0.9)
528
+ }
529
+ }
530
+ },
531
+ MuiSlider: {
532
+ styleOverrides: {
533
+ root: {
534
+ height: 1
535
+ },
536
+ track: {
537
+ height: 1,
538
+ border: "none"
539
+ },
540
+ rail: {
541
+ height: 1,
542
+ backgroundColor: BASE_THEME.palette.grey[500]
543
+ },
544
+ mark: {
545
+ backgroundColor: BASE_THEME.palette.grey[500]
546
+ },
547
+ markActive: {
548
+ height: 0
549
+ },
550
+ thumb: {
551
+ height: 16,
552
+ width: 16,
553
+ cursor: "col-resize",
554
+ "&:hover, &.Mui-active, &.Mui-focusVisible": {
555
+ boxShadow: `0 0 0 4px ${alpha(BRAND_BLUE, 0.2)}`
556
+ },
557
+ "&:before": {
558
+ display: "none"
559
+ }
560
+ }
561
+ }
562
+ },
563
+ MuiPaper: {
564
+ defaultProps: {
565
+ elevation: 2,
566
+ square: true
567
+ }
568
+ },
569
+ MuiButtonBase: {
570
+ defaultProps: {
571
+ disableTouchRipple: true,
572
+ focusRipple: true
573
+ },
574
+ styleOverrides: {
575
+ root: {
576
+ "&.MuiButton-containedSecondary.Mui-disabled": {
577
+ backgroundColor: BASE_THEME.palette.grey[100]
578
+ }
579
+ }
580
+ }
581
+ },
582
+ MuiButtonGroup: {
583
+ defaultProps: {
584
+ disableElevation: true
585
+ }
586
+ },
587
+ MuiIconButton: {
588
+ styleOverrides: {
589
+ edgeStart: {
590
+ marginLeft: BASE_THEME.spacing(-1)
591
+ },
592
+ colorSecondary: {
593
+ color: BASE_THEME.palette.grey[500]
594
+ }
595
+ }
596
+ },
597
+ MuiButton: {
598
+ defaultProps: {
599
+ disableElevation: true
600
+ },
601
+ styleOverrides: {
602
+ textPrimary: {
603
+ color: BASE_THEME.palette.text.primary
604
+ },
605
+ textSecondary: {
606
+ color: BASE_THEME.palette.text.secondary
607
+ },
608
+ outlinedPrimary: {
609
+ borderColor: BASE_THEME.palette.grey[300],
610
+ color: BASE_THEME.palette.text.primary,
611
+ "&:hover, &:active, &:focus": {
612
+ borderColor: BASE_THEME.palette.grey[500],
613
+ color: BASE_THEME.palette.text.primary
614
+ }
615
+ },
616
+ containedSecondary: {
617
+ backgroundColor: BASE_THEME.palette.common.white,
618
+ border: `1px solid ${BASE_THEME.palette.grey[300]}`,
619
+ color: BASE_THEME.palette.text.primary,
620
+ "&:hover, &:active, &:focus": {
621
+ backgroundColor: BASE_THEME.palette.common.white,
622
+ borderColor: BASE_THEME.palette.grey[500],
623
+ color: BASE_THEME.palette.text.primary
624
+ }
625
+ }
626
+ }
627
+ },
628
+ MuiToggleButton: {
629
+ styleOverrides: {
630
+ root: {
631
+ paddingLeft: BASE_THEME.spacing(1.5),
632
+ paddingRight: BASE_THEME.spacing(1.5)
633
+ }
634
+ }
635
+ },
636
+ MuiInputBase: {
637
+ styleOverrides: {
638
+ root: {
639
+ "&:not(.Mui-disabled, .Mui-error):before": {
640
+ borderBottom: `1px solid ${BASE_THEME.palette.grey[400]}`
641
+ },
642
+ "&:hover:not(.Mui-disabled, .Mui-error):before": {
643
+ borderBottom: `1px solid ${BASE_THEME.palette.grey[500]} !important`
644
+ },
645
+ "&:after": {
646
+ borderBottom: `1px solid ${BASE_THEME.palette.text.primary} !important`
647
+ },
648
+ "&.MuiOutlinedInput-root:not(.Mui-error)": {
649
+ "& fieldset": {
650
+ borderColor: BASE_THEME.palette.grey[300],
651
+ transition: "border-color 0.2s"
652
+ }
653
+ },
654
+ "&.MuiOutlinedInput-root:not(.Mui-disabled, .Mui-error)": {
655
+ "&:hover fieldset": {
656
+ borderColor: BASE_THEME.palette.grey[400]
657
+ },
658
+ "&.Mui-focused fieldset": {
659
+ borderColor: BASE_THEME.palette.text.secondary,
660
+ borderWidth: 1
661
+ }
662
+ }
663
+ },
664
+ input: {
665
+ fontSize: BASE_THEME.typography.pxToRem(14),
666
+ "&.Mui-disabled": {
667
+ WebkitTextFillColor: "inherit",
668
+ color: BASE_THEME.palette.text.secondary
669
+ }
670
+ },
671
+ inputSizeSmall: {}
672
+ }
673
+ },
674
+ MuiOutlinedInput: {
675
+ styleOverrides: {
676
+ notchedOutline: {
677
+ "& legend": {
678
+ fontSize: "0.85em",
679
+ maxWidth: "100%"
680
+ }
681
+ }
682
+ }
683
+ },
684
+ MuiInputAdornment: {
685
+ styleOverrides: {
686
+ root: {
687
+ "& .MuiTypography-root": {
688
+ fontSize: BASE_THEME.typography.pxToRem(14),
689
+ color: BASE_THEME.palette.text.secondary
690
+ }
691
+ }
692
+ }
693
+ },
694
+ MuiInputLabel: {
695
+ defaultProps: {
696
+ shrink: true
697
+ },
698
+ styleOverrides: {
699
+ shrink: {
700
+ transform: "scale(0.85)",
701
+ fontWeight: BASE_THEME.typography.fontWeightMedium,
702
+ "&.Mui-focused": {
703
+ color: BASE_THEME.palette.text.primary
704
+ },
705
+ "&.MuiInputLabel-standard": {
706
+ transform: "translate(0, -4px) scale(0.85)",
707
+ color: "#4F4F4F"
708
+ },
709
+ "&.MuiInputLabel-outlined": {
710
+ transform: "translate(15px, -8px) scale(0.85)"
711
+ }
712
+ }
713
+ }
714
+ },
715
+ MuiTabs: {
716
+ defaultProps: {
717
+ variant: "scrollable"
718
+ },
719
+ styleOverrides: {
720
+ indicator: {
721
+ height: 1,
722
+ backgroundColor: BASE_THEME.palette.text.primary
723
+ }
724
+ }
725
+ },
726
+ MuiTab: {
727
+ styleOverrides: {
728
+ root: {
729
+ textTransform: "none",
730
+ minWidth: BASE_THEME.spacing(2),
731
+ paddingLeft: BASE_THEME.spacing(1.5),
732
+ paddingRight: BASE_THEME.spacing(1.5),
733
+ fontSize: BASE_THEME.typography.pxToRem(14),
734
+ fontFamily: BASE_THEME.typography.fontFamily,
735
+ lineHeight: 1.5,
736
+ fontWeight: BASE_THEME.typography.fontWeightMedium,
737
+ transition: "color 0.2s",
738
+ "&.Mui-selected": {
739
+ color: BASE_THEME.palette.text.primary
740
+ },
741
+ "&:hover": {
742
+ color: BASE_THEME.palette.text.primary
743
+ }
744
+ }
745
+ }
746
+ },
747
+ MuiCard: {
748
+ styleOverrides: {
749
+ root: {
750
+ borderRadius: 0
751
+ }
752
+ }
753
+ },
754
+ MuiCardHeader: {
755
+ styleOverrides: {
756
+ title: {
757
+ fontSize: BASE_THEME.typography.pxToRem(18),
758
+ fontWeight: BASE_THEME.typography.fontWeightMedium
759
+ }
760
+ }
761
+ }
762
+ },
763
+ typography: {
764
+ fontFamily: BASE_THEME.typography.fontFamily,
765
+ h1: {
766
+ fontFamily: BASE_THEME.typography.fontFamily,
767
+ fontSize: BASE_THEME.typography.pxToRem(40),
768
+ lineHeight: 1.2,
769
+ letterSpacing: "-0.02em",
770
+ fontWeight: BASE_THEME.typography.fontWeightMedium
771
+ },
772
+ h2: {
773
+ fontFamily: BASE_THEME.typography.fontFamily,
774
+ fontSize: BASE_THEME.typography.pxToRem(32),
775
+ lineHeight: 1.2,
776
+ letterSpacing: "-0.02em",
777
+ fontWeight: BASE_THEME.typography.fontWeightMedium
778
+ },
779
+ h3: {
780
+ fontFamily: BASE_THEME.typography.fontFamily,
781
+ fontSize: BASE_THEME.typography.pxToRem(24),
782
+ lineHeight: 1.5,
783
+ letterSpacing: "-0.01em",
784
+ fontWeight: BASE_THEME.typography.fontWeightMedium
785
+ },
786
+ h4: {
787
+ fontFamily: BASE_THEME.typography.fontFamily,
788
+ fontSize: BASE_THEME.typography.pxToRem(20),
789
+ lineHeight: 1.5,
790
+ letterSpacing: "-0.01em",
791
+ fontWeight: BASE_THEME.typography.fontWeightMedium
792
+ },
793
+ h5: {
794
+ fontFamily: BASE_THEME.typography.fontFamily,
795
+ fontSize: BASE_THEME.typography.pxToRem(18),
796
+ lineHeight: 1.5,
797
+ letterSpacing: "-0.01em",
798
+ fontWeight: BASE_THEME.typography.fontWeightMedium
799
+ },
800
+ h6: {
801
+ fontFamily: BASE_THEME.typography.fontFamily,
802
+ fontSize: BASE_THEME.typography.pxToRem(16),
803
+ lineHeight: 1.5,
804
+ letterSpacing: "-0.005em",
805
+ fontWeight: BASE_THEME.typography.fontWeightMedium
806
+ },
807
+ body1: {
808
+ fontSize: BASE_THEME.typography.pxToRem(14)
809
+ },
810
+ body2: {
811
+ fontSize: BASE_THEME.typography.pxToRem(12)
812
+ },
813
+ overline: {
814
+ fontWeight: BASE_THEME.typography.fontWeightMedium,
815
+ letterSpacing: "0.05em"
816
+ },
817
+ button: {
818
+ textTransform: "none",
819
+ fontWeight: BASE_THEME.typography.fontWeightMedium,
820
+ lineHeight: 1.5
821
+ },
822
+ caption: {
823
+ letterSpacing: 0,
824
+ lineHeight: 1.5
825
+ }
826
+ },
827
+ shadows: [
828
+ "none",
829
+ "0px 4px 15px rgba(33, 36, 67, 0.04), 0px 0px 2px rgba(33, 36, 67, 0.04), 0px 0px 1px rgba(33, 36, 67, 0.04)",
830
+ "0px 10px 20px rgba(33, 36, 67, 0.04), 0px 2px 6px rgba(33, 36, 67, 0.04), 0px 0px 1px rgba(33, 36, 67, 0.04)",
831
+ "0px 16px 24px rgba(33, 36, 67, 0.05), 0px 2px 6px rgba(33, 36, 67, 0.05), 0px 0px 1px rgba(33, 36, 67, 0.05)",
832
+ "0px 24px 32px rgba(33, 36, 67, 0.06), 0px 16px 24px rgba(33, 36, 67, 0.06), 0px 4px 8px rgba(33, 36, 67, 0.06)",
833
+ ...Array(20).fill("none")
834
+ ]
835
+ });
836
+ function useTranslation() {
837
+ const language = useLanguage();
838
+ const t$1 = (key, params) => {
839
+ return t(key, params, language);
840
+ };
841
+ return { t: t$1, language };
842
+ }
843
+ function BaseSidebarPanel({ title, children }) {
844
+ return /* @__PURE__ */ jsxs(Box, { p: 2, children: [
845
+ /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "text.secondary", sx: { display: "block", mb: 2 }, children: title }),
846
+ /* @__PURE__ */ jsx(Stack, { spacing: 5, mb: 3, children })
847
+ ] });
848
+ }
849
+ function RadioGroupInput({ label, children, defaultValue, onChange }) {
850
+ const [value, setValue] = useState(defaultValue);
851
+ return /* @__PURE__ */ jsxs(Stack, { alignItems: "flex-start", children: [
852
+ /* @__PURE__ */ jsx(InputLabel, { shrink: true, children: label }),
853
+ /* @__PURE__ */ jsx(
854
+ ToggleButtonGroup,
855
+ {
856
+ exclusive: true,
857
+ fullWidth: true,
858
+ value,
859
+ size: "small",
860
+ onChange: (_, v) => {
861
+ if (typeof v !== "string") {
862
+ throw new Error("RadioGroupInput can only receive string values");
863
+ }
864
+ setValue(v);
865
+ onChange(v);
866
+ },
867
+ children
868
+ }
869
+ )
870
+ ] });
871
+ }
872
+ function RawSliderInput({ iconLabel, value, setValue, units, ...props }) {
873
+ return /* @__PURE__ */ jsxs(Stack, { direction: "row", alignItems: "center", spacing: 2, justifyContent: "space-between", width: "100%", children: [
874
+ /* @__PURE__ */ jsx(Box, { sx: { minWidth: 24, lineHeight: 1, flexShrink: 0 }, children: iconLabel }),
875
+ /* @__PURE__ */ jsx(
876
+ Slider,
877
+ {
878
+ ...props,
879
+ value,
880
+ onChange: (_, value2) => {
881
+ if (typeof value2 !== "number") {
882
+ throw new Error("RawSliderInput values can only receive numeric values");
883
+ }
884
+ setValue(value2);
885
+ }
886
+ }
887
+ ),
888
+ /* @__PURE__ */ jsx(Box, { sx: { minWidth: 32, textAlign: "right", flexShrink: 0 }, children: /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "text.secondary", sx: { lineHeight: 1 }, children: [
889
+ value,
890
+ units
891
+ ] }) })
892
+ ] });
893
+ }
894
+ function SliderInput({ label, defaultValue, onChange, ...props }) {
895
+ const [value, setValue] = useState(defaultValue);
896
+ return /* @__PURE__ */ jsxs(Stack, { spacing: 1, alignItems: "flex-start", children: [
897
+ /* @__PURE__ */ jsx(InputLabel, { shrink: true, children: label }),
898
+ /* @__PURE__ */ jsx(
899
+ RawSliderInput,
900
+ {
901
+ value,
902
+ setValue: (value2) => {
903
+ setValue(value2);
904
+ onChange(value2);
905
+ },
906
+ ...props
907
+ }
908
+ )
909
+ ] });
910
+ }
911
+ function TextInput({ helperText, label, placeholder, rows, InputProps: InputProps2, defaultValue, onChange }) {
912
+ const [value, setValue] = useState(defaultValue);
913
+ const isMultiline = typeof rows === "number" && rows > 1;
914
+ return /* @__PURE__ */ jsx(
915
+ TextField,
916
+ {
917
+ fullWidth: true,
918
+ multiline: isMultiline,
919
+ minRows: rows,
920
+ variant: isMultiline ? "outlined" : "standard",
921
+ label,
922
+ placeholder,
923
+ helperText,
924
+ InputProps: InputProps2,
925
+ value,
926
+ onChange: (ev) => {
927
+ const v = ev.target.value;
928
+ setValue(v);
929
+ onChange(v);
930
+ }
931
+ }
932
+ );
933
+ }
934
+ const TILE_BUTTON = {
935
+ width: 24,
936
+ height: 24
937
+ };
938
+ function Swatch({ paletteColors, value, onChange }) {
939
+ const renderButton = (colorValue) => {
940
+ return /* @__PURE__ */ jsx(
941
+ Button,
942
+ {
943
+ onClick: () => onChange(colorValue),
944
+ sx: {
945
+ ...TILE_BUTTON,
946
+ backgroundColor: colorValue,
947
+ border: "1px solid",
948
+ borderColor: value === colorValue ? "black" : "grey.200",
949
+ minWidth: 24,
950
+ display: "inline-flex",
951
+ "&:hover": {
952
+ backgroundColor: colorValue,
953
+ borderColor: "grey.500"
954
+ }
955
+ }
956
+ },
957
+ colorValue
958
+ );
959
+ };
960
+ return /* @__PURE__ */ jsx(Box, { width: "100%", sx: { display: "grid", gap: 1, gridTemplateColumns: "1fr 1fr 1fr 1fr 1fr 1fr" }, children: paletteColors.map((c) => renderButton(c)) });
961
+ }
962
+ const DEFAULT_PRESET_COLORS = [
963
+ "#E11D48",
964
+ "#DB2777",
965
+ "#C026D3",
966
+ "#9333EA",
967
+ "#7C3AED",
968
+ "#4F46E5",
969
+ "#2563EB",
970
+ "#0284C7",
971
+ "#0891B2",
972
+ "#0D9488",
973
+ "#059669",
974
+ "#16A34A",
975
+ "#65A30D",
976
+ "#CA8A04",
977
+ "#D97706",
978
+ "#EA580C",
979
+ "#DC2626",
980
+ "#FFFFFF",
981
+ "#FAFAFA",
982
+ "#F5F5F5",
983
+ "#E5E5E5",
984
+ "#D4D4D4",
985
+ "#A3A3A3",
986
+ "#737373",
987
+ "#525252",
988
+ "#404040",
989
+ "#262626",
990
+ "#171717",
991
+ "#0A0A0A",
992
+ "#000000"
993
+ ];
994
+ const SX = {
995
+ p: 1,
996
+ ".react-colorful__pointer ": {
997
+ width: 16,
998
+ height: 16
999
+ },
1000
+ ".react-colorful__saturation": {
1001
+ mb: 1,
1002
+ borderRadius: "4px"
1003
+ },
1004
+ ".react-colorful__last-control": {
1005
+ borderRadius: "4px"
1006
+ },
1007
+ ".react-colorful__hue-pointer": {
1008
+ width: "4px",
1009
+ borderRadius: "4px",
1010
+ height: 24,
1011
+ cursor: "col-resize"
1012
+ },
1013
+ ".react-colorful__saturation-pointer": {
1014
+ cursor: "all-scroll"
1015
+ },
1016
+ input: {
1017
+ padding: 1,
1018
+ border: "1px solid",
1019
+ borderColor: "grey.300",
1020
+ borderRadius: "4px",
1021
+ width: "100%"
1022
+ }
1023
+ };
1024
+ function Picker({ value, onChange }) {
1025
+ return /* @__PURE__ */ jsxs(Stack, { spacing: 1, sx: SX, children: [
1026
+ /* @__PURE__ */ jsx(HexColorPicker, { color: value, onChange }),
1027
+ /* @__PURE__ */ jsx(Swatch, { paletteColors: DEFAULT_PRESET_COLORS, value, onChange }),
1028
+ /* @__PURE__ */ jsx(Box, { pt: 1, children: /* @__PURE__ */ jsx(HexColorInput, { prefixed: true, color: value, onChange }) })
1029
+ ] });
1030
+ }
1031
+ const BUTTON_SX$1 = {
1032
+ border: "1px solid",
1033
+ borderColor: "cadet.400",
1034
+ width: 32,
1035
+ height: 32,
1036
+ borderRadius: "4px",
1037
+ bgcolor: "#FFFFFF"
1038
+ };
1039
+ function ColorInput$1({ label, defaultValue, onChange, nullable }) {
1040
+ const [anchorEl, setAnchorEl] = useState(null);
1041
+ const [value, setValue] = useState(defaultValue);
1042
+ const handleClickOpen = (event) => {
1043
+ setAnchorEl(event.currentTarget);
1044
+ };
1045
+ const renderResetButton = () => {
1046
+ if (!nullable) {
1047
+ return null;
1048
+ }
1049
+ if (typeof value !== "string" || value.trim().length === 0) {
1050
+ return null;
1051
+ }
1052
+ return /* @__PURE__ */ jsx(
1053
+ ButtonBase,
1054
+ {
1055
+ onClick: () => {
1056
+ setValue(null);
1057
+ onChange(null);
1058
+ },
1059
+ children: /* @__PURE__ */ jsx(CloseOutlined, { fontSize: "small", sx: { color: "grey.600" } })
1060
+ }
1061
+ );
1062
+ };
1063
+ const renderOpenButton = () => {
1064
+ if (value) {
1065
+ return /* @__PURE__ */ jsx(ButtonBase, { onClick: handleClickOpen, sx: { ...BUTTON_SX$1, bgcolor: value } });
1066
+ }
1067
+ return /* @__PURE__ */ jsx(ButtonBase, { onClick: handleClickOpen, sx: { ...BUTTON_SX$1 }, children: /* @__PURE__ */ jsx(AddOutlined, { fontSize: "small" }) });
1068
+ };
1069
+ return /* @__PURE__ */ jsxs(Stack, { alignItems: "flex-start", children: [
1070
+ /* @__PURE__ */ jsx(InputLabel, { sx: { mb: 0.5 }, children: label }),
1071
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, children: [
1072
+ renderOpenButton(),
1073
+ renderResetButton()
1074
+ ] }),
1075
+ /* @__PURE__ */ jsx(
1076
+ Menu,
1077
+ {
1078
+ anchorEl,
1079
+ open: Boolean(anchorEl),
1080
+ onClose: () => setAnchorEl(null),
1081
+ MenuListProps: {
1082
+ sx: { height: "auto", padding: 0 }
1083
+ },
1084
+ children: /* @__PURE__ */ jsx(
1085
+ Picker,
1086
+ {
1087
+ value: value || "",
1088
+ onChange: (v) => {
1089
+ setValue(v);
1090
+ onChange(v);
1091
+ }
1092
+ }
1093
+ )
1094
+ }
1095
+ )
1096
+ ] });
1097
+ }
1098
+ function ColorInput(props) {
1099
+ return /* @__PURE__ */ jsx(ColorInput$1, { ...props, nullable: false });
1100
+ }
1101
+ function NullableColorInput(props) {
1102
+ return /* @__PURE__ */ jsx(ColorInput$1, { ...props, nullable: true });
1103
+ }
1104
+ const FONT_FAMILIES = [
1105
+ {
1106
+ key: "MODERN_SANS",
1107
+ label: "Modern sans",
1108
+ value: '"Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif'
1109
+ },
1110
+ {
1111
+ key: "BOOK_SANS",
1112
+ label: "Book sans",
1113
+ value: 'Optima, Candara, "Noto Sans", source-sans-pro, sans-serif'
1114
+ },
1115
+ {
1116
+ key: "ORGANIC_SANS",
1117
+ label: "Organic sans",
1118
+ value: 'Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif'
1119
+ },
1120
+ {
1121
+ key: "GEOMETRIC_SANS",
1122
+ label: "Geometric sans",
1123
+ value: 'Avenir, "Avenir Next LT Pro", Montserrat, Corbel, "URW Gothic", source-sans-pro, sans-serif'
1124
+ },
1125
+ {
1126
+ key: "HEAVY_SANS",
1127
+ label: "Heavy sans",
1128
+ value: 'Bahnschrift, "DIN Alternate", "Franklin Gothic Medium", "Nimbus Sans Narrow", sans-serif-condensed, sans-serif'
1129
+ },
1130
+ {
1131
+ key: "ROUNDED_SANS",
1132
+ label: "Rounded sans",
1133
+ value: 'ui-rounded, "Hiragino Maru Gothic ProN", Quicksand, Comfortaa, Manjari, "Arial Rounded MT Bold", Calibri, source-sans-pro, sans-serif'
1134
+ },
1135
+ {
1136
+ key: "MODERN_SERIF",
1137
+ label: "Modern serif",
1138
+ value: 'Charter, "Bitstream Charter", "Sitka Text", Cambria, serif'
1139
+ },
1140
+ {
1141
+ key: "BOOK_SERIF",
1142
+ label: "Book serif",
1143
+ value: '"Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif'
1144
+ },
1145
+ {
1146
+ key: "MONOSPACE",
1147
+ label: "Monospace",
1148
+ value: '"Nimbus Mono PS", "Courier New", "Cutive Mono", monospace'
1149
+ }
1150
+ ];
1151
+ const OPTIONS = FONT_FAMILIES.map((option) => /* @__PURE__ */ jsx(MenuItem, { value: option.key, sx: { fontFamily: option.value }, children: option.label }, option.key));
1152
+ function NullableFontFamily({ label, onChange, defaultValue }) {
1153
+ const [value, setValue] = useState(defaultValue ?? "inherit");
1154
+ return /* @__PURE__ */ jsxs(
1155
+ TextField,
1156
+ {
1157
+ select: true,
1158
+ variant: "standard",
1159
+ label,
1160
+ value,
1161
+ onChange: (ev) => {
1162
+ const v = ev.target.value;
1163
+ setValue(v);
1164
+ onChange(v === null ? null : v);
1165
+ },
1166
+ children: [
1167
+ /* @__PURE__ */ jsx(MenuItem, { value: "inherit", children: "Match email settings" }),
1168
+ OPTIONS
1169
+ ]
1170
+ }
1171
+ );
1172
+ }
1173
+ function FontSizeInput({ label, defaultValue, onChange }) {
1174
+ const [value, setValue] = useState(defaultValue);
1175
+ const handleChange = (value2) => {
1176
+ setValue(value2);
1177
+ onChange(value2);
1178
+ };
1179
+ return /* @__PURE__ */ jsxs(Stack, { spacing: 1, alignItems: "flex-start", children: [
1180
+ /* @__PURE__ */ jsx(InputLabel, { shrink: true, children: label }),
1181
+ /* @__PURE__ */ jsx(
1182
+ RawSliderInput,
1183
+ {
1184
+ iconLabel: /* @__PURE__ */ jsx(TextFieldsOutlined, { sx: { fontSize: 16 } }),
1185
+ value,
1186
+ setValue: handleChange,
1187
+ units: "px",
1188
+ step: 1,
1189
+ min: 10,
1190
+ max: 48
1191
+ }
1192
+ )
1193
+ ] });
1194
+ }
1195
+ function FontWeightInput({ label, defaultValue, onChange }) {
1196
+ const [value, setValue] = useState(defaultValue);
1197
+ return /* @__PURE__ */ jsxs(
1198
+ RadioGroupInput,
1199
+ {
1200
+ label,
1201
+ defaultValue: value,
1202
+ onChange: (fontWeight) => {
1203
+ setValue(fontWeight);
1204
+ onChange(fontWeight);
1205
+ },
1206
+ children: [
1207
+ /* @__PURE__ */ jsx(ToggleButton, { value: "normal", children: "Regular" }),
1208
+ /* @__PURE__ */ jsx(ToggleButton, { value: "bold", children: "Bold" })
1209
+ ]
1210
+ }
1211
+ );
1212
+ }
1213
+ function PaddingInput({ label, defaultValue, onChange }) {
1214
+ const [value, setValue] = useState(() => {
1215
+ if (defaultValue) {
1216
+ return defaultValue;
1217
+ }
1218
+ return {
1219
+ top: 0,
1220
+ left: 0,
1221
+ bottom: 0,
1222
+ right: 0
1223
+ };
1224
+ });
1225
+ function handleChange(internalName, nValue) {
1226
+ const v = {
1227
+ ...value,
1228
+ [internalName]: nValue
1229
+ };
1230
+ setValue(v);
1231
+ onChange(v);
1232
+ }
1233
+ return /* @__PURE__ */ jsxs(Stack, { spacing: 2, alignItems: "flex-start", pb: 1, children: [
1234
+ /* @__PURE__ */ jsx(InputLabel, { shrink: true, children: label }),
1235
+ /* @__PURE__ */ jsx(
1236
+ RawSliderInput,
1237
+ {
1238
+ iconLabel: /* @__PURE__ */ jsx(AlignVerticalTopOutlined, { sx: { fontSize: 16 } }),
1239
+ value: value.top,
1240
+ setValue: (num) => handleChange("top", num),
1241
+ units: "px",
1242
+ step: 4,
1243
+ min: 0,
1244
+ max: 80,
1245
+ marks: true
1246
+ }
1247
+ ),
1248
+ /* @__PURE__ */ jsx(
1249
+ RawSliderInput,
1250
+ {
1251
+ iconLabel: /* @__PURE__ */ jsx(AlignVerticalBottomOutlined, { sx: { fontSize: 16 } }),
1252
+ value: value.bottom,
1253
+ setValue: (num) => handleChange("bottom", num),
1254
+ units: "px",
1255
+ step: 4,
1256
+ min: 0,
1257
+ max: 80,
1258
+ marks: true
1259
+ }
1260
+ ),
1261
+ /* @__PURE__ */ jsx(
1262
+ RawSliderInput,
1263
+ {
1264
+ iconLabel: /* @__PURE__ */ jsx(AlignHorizontalLeftOutlined, { sx: { fontSize: 16 } }),
1265
+ value: value.left,
1266
+ setValue: (num) => handleChange("left", num),
1267
+ units: "px",
1268
+ step: 4,
1269
+ min: 0,
1270
+ max: 80,
1271
+ marks: true
1272
+ }
1273
+ ),
1274
+ /* @__PURE__ */ jsx(
1275
+ RawSliderInput,
1276
+ {
1277
+ iconLabel: /* @__PURE__ */ jsx(AlignHorizontalRightOutlined, { sx: { fontSize: 16 } }),
1278
+ value: value.right,
1279
+ setValue: (num) => handleChange("right", num),
1280
+ units: "px",
1281
+ step: 4,
1282
+ min: 0,
1283
+ max: 80,
1284
+ marks: true
1285
+ }
1286
+ )
1287
+ ] });
1288
+ }
1289
+ function TextAlignInput({ label, defaultValue, onChange }) {
1290
+ const [value, setValue] = useState(defaultValue ?? "left");
1291
+ return /* @__PURE__ */ jsxs(
1292
+ RadioGroupInput,
1293
+ {
1294
+ label,
1295
+ defaultValue: value,
1296
+ onChange: (value2) => {
1297
+ setValue(value2);
1298
+ onChange(value2);
1299
+ },
1300
+ children: [
1301
+ /* @__PURE__ */ jsx(ToggleButton, { value: "left", children: /* @__PURE__ */ jsx(FormatAlignLeftOutlined, { fontSize: "small" }) }),
1302
+ /* @__PURE__ */ jsx(ToggleButton, { value: "center", children: /* @__PURE__ */ jsx(FormatAlignCenterOutlined, { fontSize: "small" }) }),
1303
+ /* @__PURE__ */ jsx(ToggleButton, { value: "right", children: /* @__PURE__ */ jsx(FormatAlignRightOutlined, { fontSize: "small" }) })
1304
+ ]
1305
+ }
1306
+ );
1307
+ }
1308
+ function SingleStylePropertyPanel({ name, value, onChange }) {
1309
+ const defaultValue = value[name] ?? null;
1310
+ const handleChange = (v) => {
1311
+ onChange({ ...value, [name]: v });
1312
+ };
1313
+ switch (name) {
1314
+ case "backgroundColor":
1315
+ return /* @__PURE__ */ jsx(NullableColorInput, { label: "Background color", defaultValue, onChange: handleChange });
1316
+ case "borderColor":
1317
+ return /* @__PURE__ */ jsx(NullableColorInput, { label: "Border color", defaultValue, onChange: handleChange });
1318
+ case "borderRadius":
1319
+ return /* @__PURE__ */ jsx(
1320
+ SliderInput,
1321
+ {
1322
+ iconLabel: /* @__PURE__ */ jsx(RoundedCornerOutlined, {}),
1323
+ units: "px",
1324
+ step: 4,
1325
+ marks: true,
1326
+ min: 0,
1327
+ max: 48,
1328
+ label: "Border radius",
1329
+ defaultValue,
1330
+ onChange: handleChange
1331
+ }
1332
+ );
1333
+ case "color":
1334
+ return /* @__PURE__ */ jsx(NullableColorInput, { label: "Text color", defaultValue, onChange: handleChange });
1335
+ case "fontFamily":
1336
+ return /* @__PURE__ */ jsx(NullableFontFamily, { label: "Font family", defaultValue, onChange: handleChange });
1337
+ case "fontSize":
1338
+ return /* @__PURE__ */ jsx(FontSizeInput, { label: "Font size", defaultValue, onChange: handleChange });
1339
+ case "fontWeight":
1340
+ return /* @__PURE__ */ jsx(FontWeightInput, { label: "Font weight", defaultValue, onChange: handleChange });
1341
+ case "textAlign":
1342
+ return /* @__PURE__ */ jsx(TextAlignInput, { label: "Alignment", defaultValue, onChange: handleChange });
1343
+ case "padding":
1344
+ return /* @__PURE__ */ jsx(PaddingInput, { label: "Padding", defaultValue, onChange: handleChange });
1345
+ }
1346
+ }
1347
+ function MultiStylePropertyPanel({ names, value, onChange }) {
1348
+ return /* @__PURE__ */ jsx(Fragment, { children: names.map((name) => /* @__PURE__ */ jsx(SingleStylePropertyPanel, { name, value: value || {}, onChange }, name)) });
1349
+ }
1350
+ function AvatarSidebarPanel({ data, setData }) {
1351
+ var _a, _b, _c, _d;
1352
+ const [, setErrors] = useState(null);
1353
+ const updateData = (d) => {
1354
+ const res = AvatarPropsSchema.safeParse(d);
1355
+ if (res.success) {
1356
+ setData(res.data);
1357
+ setErrors(null);
1358
+ } else {
1359
+ setErrors(res.error);
1360
+ }
1361
+ };
1362
+ const size = ((_a = data.props) == null ? void 0 : _a.size) ?? AvatarPropsDefaults.size;
1363
+ const imageUrl = ((_b = data.props) == null ? void 0 : _b.imageUrl) ?? AvatarPropsDefaults.imageUrl;
1364
+ const alt = ((_c = data.props) == null ? void 0 : _c.alt) ?? AvatarPropsDefaults.alt;
1365
+ const shape = ((_d = data.props) == null ? void 0 : _d.shape) ?? AvatarPropsDefaults.shape;
1366
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Avatar block", children: [
1367
+ /* @__PURE__ */ jsx(
1368
+ SliderInput,
1369
+ {
1370
+ label: "Size",
1371
+ iconLabel: /* @__PURE__ */ jsx(AspectRatioOutlined, { sx: { color: "text.secondary" } }),
1372
+ units: "px",
1373
+ step: 3,
1374
+ min: 32,
1375
+ max: 256,
1376
+ defaultValue: size,
1377
+ onChange: (size2) => {
1378
+ updateData({ ...data, props: { ...data.props, size: size2 } });
1379
+ }
1380
+ }
1381
+ ),
1382
+ /* @__PURE__ */ jsxs(
1383
+ RadioGroupInput,
1384
+ {
1385
+ label: "Shape",
1386
+ defaultValue: shape,
1387
+ onChange: (shape2) => {
1388
+ updateData({ ...data, props: { ...data.props, shape: shape2 } });
1389
+ },
1390
+ children: [
1391
+ /* @__PURE__ */ jsx(ToggleButton, { value: "circle", children: "Circle" }),
1392
+ /* @__PURE__ */ jsx(ToggleButton, { value: "square", children: "Square" }),
1393
+ /* @__PURE__ */ jsx(ToggleButton, { value: "rounded", children: "Rounded" })
1394
+ ]
1395
+ }
1396
+ ),
1397
+ /* @__PURE__ */ jsx(
1398
+ TextInput,
1399
+ {
1400
+ label: "Image URL",
1401
+ defaultValue: imageUrl,
1402
+ onChange: (imageUrl2) => {
1403
+ updateData({ ...data, props: { ...data.props, imageUrl: imageUrl2 } });
1404
+ }
1405
+ }
1406
+ ),
1407
+ /* @__PURE__ */ jsx(
1408
+ TextInput,
1409
+ {
1410
+ label: "Alt text",
1411
+ defaultValue: alt,
1412
+ onChange: (alt2) => {
1413
+ updateData({ ...data, props: { ...data.props, alt: alt2 } });
1414
+ }
1415
+ }
1416
+ ),
1417
+ /* @__PURE__ */ jsx(
1418
+ MultiStylePropertyPanel,
1419
+ {
1420
+ names: ["textAlign", "padding"],
1421
+ value: data.style,
1422
+ onChange: (style) => updateData({ ...data, style })
1423
+ }
1424
+ )
1425
+ ] });
1426
+ }
1427
+ function ButtonSidebarPanel({ data, setData }) {
1428
+ var _a, _b, _c, _d, _e, _f, _g;
1429
+ const [, setErrors] = useState(null);
1430
+ const updateData = (d) => {
1431
+ const res = ButtonPropsSchema.safeParse(d);
1432
+ if (res.success) {
1433
+ setData(res.data);
1434
+ setErrors(null);
1435
+ } else {
1436
+ setErrors(res.error);
1437
+ }
1438
+ };
1439
+ const text = ((_a = data.props) == null ? void 0 : _a.text) ?? ButtonPropsDefaults.text;
1440
+ const url = ((_b = data.props) == null ? void 0 : _b.url) ?? ButtonPropsDefaults.url;
1441
+ const fullWidth = ((_c = data.props) == null ? void 0 : _c.fullWidth) ?? ButtonPropsDefaults.fullWidth;
1442
+ const size = ((_d = data.props) == null ? void 0 : _d.size) ?? ButtonPropsDefaults.size;
1443
+ const buttonStyle = ((_e = data.props) == null ? void 0 : _e.buttonStyle) ?? ButtonPropsDefaults.buttonStyle;
1444
+ const buttonTextColor = ((_f = data.props) == null ? void 0 : _f.buttonTextColor) ?? ButtonPropsDefaults.buttonTextColor;
1445
+ const buttonBackgroundColor = ((_g = data.props) == null ? void 0 : _g.buttonBackgroundColor) ?? ButtonPropsDefaults.buttonBackgroundColor;
1446
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Button block", children: [
1447
+ /* @__PURE__ */ jsx(
1448
+ TextInput,
1449
+ {
1450
+ label: "Text",
1451
+ defaultValue: text,
1452
+ onChange: (text2) => updateData({ ...data, props: { ...data.props, text: text2 } })
1453
+ }
1454
+ ),
1455
+ /* @__PURE__ */ jsx(
1456
+ TextInput,
1457
+ {
1458
+ label: "Url",
1459
+ defaultValue: url,
1460
+ onChange: (url2) => updateData({ ...data, props: { ...data.props, url: url2 } })
1461
+ }
1462
+ ),
1463
+ /* @__PURE__ */ jsxs(
1464
+ RadioGroupInput,
1465
+ {
1466
+ label: "Width",
1467
+ defaultValue: fullWidth ? "FULL_WIDTH" : "AUTO",
1468
+ onChange: (v) => updateData({ ...data, props: { ...data.props, fullWidth: v === "FULL_WIDTH" } }),
1469
+ children: [
1470
+ /* @__PURE__ */ jsx(ToggleButton, { value: "FULL_WIDTH", children: "Full" }),
1471
+ /* @__PURE__ */ jsx(ToggleButton, { value: "AUTO", children: "Auto" })
1472
+ ]
1473
+ }
1474
+ ),
1475
+ /* @__PURE__ */ jsxs(
1476
+ RadioGroupInput,
1477
+ {
1478
+ label: "Size",
1479
+ defaultValue: size,
1480
+ onChange: (size2) => updateData({ ...data, props: { ...data.props, size: size2 } }),
1481
+ children: [
1482
+ /* @__PURE__ */ jsx(ToggleButton, { value: "x-small", children: "Xs" }),
1483
+ /* @__PURE__ */ jsx(ToggleButton, { value: "small", children: "Sm" }),
1484
+ /* @__PURE__ */ jsx(ToggleButton, { value: "medium", children: "Md" }),
1485
+ /* @__PURE__ */ jsx(ToggleButton, { value: "large", children: "Lg" })
1486
+ ]
1487
+ }
1488
+ ),
1489
+ /* @__PURE__ */ jsxs(
1490
+ RadioGroupInput,
1491
+ {
1492
+ label: "Style",
1493
+ defaultValue: buttonStyle,
1494
+ onChange: (buttonStyle2) => updateData({ ...data, props: { ...data.props, buttonStyle: buttonStyle2 } }),
1495
+ children: [
1496
+ /* @__PURE__ */ jsx(ToggleButton, { value: "rectangle", children: "Rectangle" }),
1497
+ /* @__PURE__ */ jsx(ToggleButton, { value: "rounded", children: "Rounded" }),
1498
+ /* @__PURE__ */ jsx(ToggleButton, { value: "pill", children: "Pill" })
1499
+ ]
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ jsx(
1503
+ ColorInput,
1504
+ {
1505
+ label: "Text color",
1506
+ defaultValue: buttonTextColor,
1507
+ onChange: (buttonTextColor2) => updateData({ ...data, props: { ...data.props, buttonTextColor: buttonTextColor2 } })
1508
+ }
1509
+ ),
1510
+ /* @__PURE__ */ jsx(
1511
+ ColorInput,
1512
+ {
1513
+ label: "Button color",
1514
+ defaultValue: buttonBackgroundColor,
1515
+ onChange: (buttonBackgroundColor2) => updateData({ ...data, props: { ...data.props, buttonBackgroundColor: buttonBackgroundColor2 } })
1516
+ }
1517
+ ),
1518
+ /* @__PURE__ */ jsx(
1519
+ MultiStylePropertyPanel,
1520
+ {
1521
+ names: ["backgroundColor", "fontFamily", "fontSize", "fontWeight", "textAlign", "padding"],
1522
+ value: data.style,
1523
+ onChange: (style) => updateData({ ...data, style })
1524
+ }
1525
+ )
1526
+ ] });
1527
+ }
1528
+ const BasePropsShape = ColumnsContainerPropsSchema$1.shape.props.unwrap().unwrap().shape;
1529
+ const ColumnsContainerPropsSchema = z.object({
1530
+ style: ColumnsContainerPropsSchema$1.shape.style,
1531
+ props: z.object({
1532
+ ...BasePropsShape,
1533
+ columns: z.tuple([
1534
+ z.object({ childrenIds: z.array(z.string()) }),
1535
+ z.object({ childrenIds: z.array(z.string()) }),
1536
+ z.object({ childrenIds: z.array(z.string()) })
1537
+ ])
1538
+ }).optional().nullable()
1539
+ });
1540
+ function TextDimensionInput({ label, defaultValue, onChange }) {
1541
+ const handleChange = (ev) => {
1542
+ const value = parseInt(ev.target.value);
1543
+ onChange(isNaN(value) ? null : value);
1544
+ };
1545
+ return /* @__PURE__ */ jsx(
1546
+ TextField,
1547
+ {
1548
+ fullWidth: true,
1549
+ onChange: handleChange,
1550
+ defaultValue,
1551
+ label,
1552
+ variant: "standard",
1553
+ placeholder: "auto",
1554
+ size: "small",
1555
+ InputProps: {
1556
+ endAdornment: /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "text.secondary", children: "px" })
1557
+ }
1558
+ }
1559
+ );
1560
+ }
1561
+ function ColumnWidthsInput({ defaultValue, onChange }) {
1562
+ const [currentValue, setCurrentValue] = useState(() => {
1563
+ if (defaultValue) {
1564
+ return defaultValue;
1565
+ }
1566
+ return [null, null, null];
1567
+ });
1568
+ const setIndexValue = (index, value) => {
1569
+ const nValue = [...currentValue];
1570
+ nValue[index] = value;
1571
+ setCurrentValue(nValue);
1572
+ onChange(nValue);
1573
+ };
1574
+ let column3 = null;
1575
+ {
1576
+ column3 = /* @__PURE__ */ jsx(
1577
+ TextDimensionInput,
1578
+ {
1579
+ label: "Column 3",
1580
+ defaultValue: currentValue == null ? void 0 : currentValue[2],
1581
+ onChange: (v) => {
1582
+ setIndexValue(2, v);
1583
+ }
1584
+ }
1585
+ );
1586
+ }
1587
+ return /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, children: [
1588
+ /* @__PURE__ */ jsx(
1589
+ TextDimensionInput,
1590
+ {
1591
+ label: "Column 1",
1592
+ defaultValue: currentValue == null ? void 0 : currentValue[0],
1593
+ onChange: (v) => {
1594
+ setIndexValue(0, v);
1595
+ }
1596
+ }
1597
+ ),
1598
+ /* @__PURE__ */ jsx(
1599
+ TextDimensionInput,
1600
+ {
1601
+ label: "Column 2",
1602
+ defaultValue: currentValue == null ? void 0 : currentValue[1],
1603
+ onChange: (v) => {
1604
+ setIndexValue(1, v);
1605
+ }
1606
+ }
1607
+ ),
1608
+ column3
1609
+ ] });
1610
+ }
1611
+ function ColumnsContainerPanel({ data, setData }) {
1612
+ var _a, _b, _c, _d;
1613
+ const [, setErrors] = useState(null);
1614
+ const updateData = (d) => {
1615
+ const res = ColumnsContainerPropsSchema.safeParse(d);
1616
+ if (res.success) {
1617
+ setData(res.data);
1618
+ setErrors(null);
1619
+ } else {
1620
+ setErrors(res.error);
1621
+ }
1622
+ };
1623
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Columns block", children: [
1624
+ /* @__PURE__ */ jsxs(
1625
+ RadioGroupInput,
1626
+ {
1627
+ label: "Number of columns",
1628
+ defaultValue: ((_a = data.props) == null ? void 0 : _a.columnsCount) === 2 ? "2" : "3",
1629
+ onChange: (v) => {
1630
+ updateData({ ...data, props: { ...data.props, columnsCount: v === "2" ? 2 : 3 } });
1631
+ },
1632
+ children: [
1633
+ /* @__PURE__ */ jsx(ToggleButton, { value: "2", children: "2" }),
1634
+ /* @__PURE__ */ jsx(ToggleButton, { value: "3", children: "3" })
1635
+ ]
1636
+ }
1637
+ ),
1638
+ /* @__PURE__ */ jsx(
1639
+ ColumnWidthsInput,
1640
+ {
1641
+ defaultValue: (_b = data.props) == null ? void 0 : _b.fixedWidths,
1642
+ onChange: (fixedWidths) => {
1643
+ updateData({ ...data, props: { ...data.props, fixedWidths } });
1644
+ }
1645
+ }
1646
+ ),
1647
+ /* @__PURE__ */ jsx(
1648
+ SliderInput,
1649
+ {
1650
+ label: "Columns gap",
1651
+ iconLabel: /* @__PURE__ */ jsx(SpaceBarOutlined, { sx: { color: "text.secondary" } }),
1652
+ units: "px",
1653
+ step: 4,
1654
+ marks: true,
1655
+ min: 0,
1656
+ max: 80,
1657
+ defaultValue: ((_c = data.props) == null ? void 0 : _c.columnsGap) ?? 0,
1658
+ onChange: (columnsGap) => updateData({ ...data, props: { ...data.props, columnsGap } })
1659
+ }
1660
+ ),
1661
+ /* @__PURE__ */ jsxs(
1662
+ RadioGroupInput,
1663
+ {
1664
+ label: "Alignment",
1665
+ defaultValue: ((_d = data.props) == null ? void 0 : _d.contentAlignment) ?? "middle",
1666
+ onChange: (contentAlignment) => {
1667
+ updateData({ ...data, props: { ...data.props, contentAlignment } });
1668
+ },
1669
+ children: [
1670
+ /* @__PURE__ */ jsx(ToggleButton, { value: "top", children: /* @__PURE__ */ jsx(VerticalAlignTopOutlined, { fontSize: "small" }) }),
1671
+ /* @__PURE__ */ jsx(ToggleButton, { value: "middle", children: /* @__PURE__ */ jsx(VerticalAlignCenterOutlined, { fontSize: "small" }) }),
1672
+ /* @__PURE__ */ jsx(ToggleButton, { value: "bottom", children: /* @__PURE__ */ jsx(VerticalAlignBottomOutlined, { fontSize: "small" }) })
1673
+ ]
1674
+ }
1675
+ ),
1676
+ /* @__PURE__ */ jsx(
1677
+ MultiStylePropertyPanel,
1678
+ {
1679
+ names: ["backgroundColor", "padding"],
1680
+ value: data.style,
1681
+ onChange: (style) => updateData({ ...data, style })
1682
+ }
1683
+ )
1684
+ ] });
1685
+ }
1686
+ const ContainerPropsSchema = z.object({
1687
+ style: ContainerPropsSchema$1.shape.style,
1688
+ props: z.object({
1689
+ childrenIds: z.array(z.string()).optional().nullable()
1690
+ }).optional().nullable()
1691
+ });
1692
+ function ContainerSidebarPanel({ data, setData }) {
1693
+ const [, setErrors] = useState(null);
1694
+ const updateData = (d) => {
1695
+ const res = ContainerPropsSchema.safeParse(d);
1696
+ if (res.success) {
1697
+ setData(res.data);
1698
+ setErrors(null);
1699
+ } else {
1700
+ setErrors(res.error);
1701
+ }
1702
+ };
1703
+ return /* @__PURE__ */ jsx(BaseSidebarPanel, { title: "Container block", children: /* @__PURE__ */ jsx(
1704
+ MultiStylePropertyPanel,
1705
+ {
1706
+ names: ["backgroundColor", "borderColor", "borderRadius", "padding"],
1707
+ value: data.style,
1708
+ onChange: (style) => updateData({ ...data, style })
1709
+ }
1710
+ ) });
1711
+ }
1712
+ function DividerSidebarPanel({ data, setData }) {
1713
+ var _a, _b;
1714
+ const [, setErrors] = useState(null);
1715
+ const updateData = (d) => {
1716
+ const res = DividerPropsSchema.safeParse(d);
1717
+ if (res.success) {
1718
+ setData(res.data);
1719
+ setErrors(null);
1720
+ } else {
1721
+ setErrors(res.error);
1722
+ }
1723
+ };
1724
+ const lineColor = ((_a = data.props) == null ? void 0 : _a.lineColor) ?? DividerPropsDefaults.lineColor;
1725
+ const lineHeight = ((_b = data.props) == null ? void 0 : _b.lineHeight) ?? DividerPropsDefaults.lineHeight;
1726
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Divider block", children: [
1727
+ /* @__PURE__ */ jsx(
1728
+ ColorInput,
1729
+ {
1730
+ label: "Color",
1731
+ defaultValue: lineColor,
1732
+ onChange: (lineColor2) => updateData({ ...data, props: { ...data.props, lineColor: lineColor2 } })
1733
+ }
1734
+ ),
1735
+ /* @__PURE__ */ jsx(
1736
+ SliderInput,
1737
+ {
1738
+ label: "Height",
1739
+ iconLabel: /* @__PURE__ */ jsx(HeightOutlined, { sx: { color: "text.secondary" } }),
1740
+ units: "px",
1741
+ step: 1,
1742
+ min: 1,
1743
+ max: 24,
1744
+ defaultValue: lineHeight,
1745
+ onChange: (lineHeight2) => updateData({ ...data, props: { ...data.props, lineHeight: lineHeight2 } })
1746
+ }
1747
+ ),
1748
+ /* @__PURE__ */ jsx(
1749
+ MultiStylePropertyPanel,
1750
+ {
1751
+ names: ["backgroundColor", "padding"],
1752
+ value: data.style,
1753
+ onChange: (style) => updateData({ ...data, style })
1754
+ }
1755
+ )
1756
+ ] });
1757
+ }
1758
+ const COLOR_SCHEMA = z.string().regex(/^#[0-9a-fA-F]{6}$/).nullable().optional();
1759
+ const FONT_FAMILY_SCHEMA = z.enum([
1760
+ "MODERN_SANS",
1761
+ "BOOK_SANS",
1762
+ "ORGANIC_SANS",
1763
+ "GEOMETRIC_SANS",
1764
+ "HEAVY_SANS",
1765
+ "ROUNDED_SANS",
1766
+ "MODERN_SERIF",
1767
+ "BOOK_SERIF",
1768
+ "MONOSPACE"
1769
+ ]).nullable().optional();
1770
+ const EmailLayoutPropsSchema = z.object({
1771
+ backdropColor: COLOR_SCHEMA,
1772
+ borderColor: COLOR_SCHEMA,
1773
+ borderRadius: z.number().optional().nullable(),
1774
+ canvasColor: COLOR_SCHEMA,
1775
+ textColor: COLOR_SCHEMA,
1776
+ fontFamily: FONT_FAMILY_SCHEMA,
1777
+ width: z.number().optional().nullable(),
1778
+ childrenIds: z.array(z.string()).optional().nullable()
1779
+ });
1780
+ function EmailLayoutSidebarFields({ data, setData }) {
1781
+ const [, setErrors] = useState(null);
1782
+ const updateData = (d) => {
1783
+ const res = EmailLayoutPropsSchema.safeParse(d);
1784
+ if (res.success) {
1785
+ setData(res.data);
1786
+ setErrors(null);
1787
+ } else {
1788
+ setErrors(res.error);
1789
+ }
1790
+ };
1791
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Global", children: [
1792
+ /* @__PURE__ */ jsx(
1793
+ ColorInput,
1794
+ {
1795
+ label: "Backdrop color",
1796
+ defaultValue: data.backdropColor ?? "#F5F5F5",
1797
+ onChange: (backdropColor) => updateData({ ...data, backdropColor })
1798
+ }
1799
+ ),
1800
+ /* @__PURE__ */ jsx(
1801
+ ColorInput,
1802
+ {
1803
+ label: "Canvas color",
1804
+ defaultValue: data.canvasColor ?? "#FFFFFF",
1805
+ onChange: (canvasColor) => updateData({ ...data, canvasColor })
1806
+ }
1807
+ ),
1808
+ /* @__PURE__ */ jsx(
1809
+ NullableColorInput,
1810
+ {
1811
+ label: "Canvas border color",
1812
+ defaultValue: data.borderColor ?? null,
1813
+ onChange: (borderColor) => updateData({ ...data, borderColor })
1814
+ }
1815
+ ),
1816
+ /* @__PURE__ */ jsx(
1817
+ SliderInput,
1818
+ {
1819
+ iconLabel: /* @__PURE__ */ jsx(RoundedCornerOutlined, {}),
1820
+ units: "px",
1821
+ step: 4,
1822
+ marks: true,
1823
+ min: 0,
1824
+ max: 48,
1825
+ label: "Canvas border radius",
1826
+ defaultValue: data.borderRadius ?? 0,
1827
+ onChange: (borderRadius) => updateData({ ...data, borderRadius })
1828
+ }
1829
+ ),
1830
+ /* @__PURE__ */ jsx(
1831
+ SliderInput,
1832
+ {
1833
+ iconLabel: /* @__PURE__ */ jsx(AspectRatioOutlined, {}),
1834
+ units: "px",
1835
+ step: 20,
1836
+ marks: true,
1837
+ min: 400,
1838
+ max: 1200,
1839
+ label: "Page width",
1840
+ defaultValue: data.width ?? 600,
1841
+ onChange: (width) => updateData({ ...data, width })
1842
+ }
1843
+ ),
1844
+ /* @__PURE__ */ jsx(
1845
+ NullableFontFamily,
1846
+ {
1847
+ label: "Font family",
1848
+ defaultValue: "MODERN_SANS",
1849
+ onChange: (fontFamily) => updateData({ ...data, fontFamily })
1850
+ }
1851
+ ),
1852
+ /* @__PURE__ */ jsx(
1853
+ ColorInput,
1854
+ {
1855
+ label: "Text color",
1856
+ defaultValue: data.textColor ?? "#262626",
1857
+ onChange: (textColor) => updateData({ ...data, textColor })
1858
+ }
1859
+ )
1860
+ ] });
1861
+ }
1862
+ function HeadingSidebarPanel({ data, setData }) {
1863
+ var _a, _b;
1864
+ const [, setErrors] = useState(null);
1865
+ const updateData = (d) => {
1866
+ const res = HeadingPropsSchema.safeParse(d);
1867
+ if (res.success) {
1868
+ setData(res.data);
1869
+ setErrors(null);
1870
+ } else {
1871
+ setErrors(res.error);
1872
+ }
1873
+ };
1874
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Heading block", children: [
1875
+ /* @__PURE__ */ jsx(
1876
+ TextInput,
1877
+ {
1878
+ label: "Content",
1879
+ rows: 3,
1880
+ defaultValue: ((_a = data.props) == null ? void 0 : _a.text) ?? HeadingPropsDefaults.text,
1881
+ onChange: (text) => {
1882
+ updateData({ ...data, props: { ...data.props, text } });
1883
+ }
1884
+ }
1885
+ ),
1886
+ /* @__PURE__ */ jsxs(
1887
+ RadioGroupInput,
1888
+ {
1889
+ label: "Level",
1890
+ defaultValue: ((_b = data.props) == null ? void 0 : _b.level) ?? HeadingPropsDefaults.level,
1891
+ onChange: (level) => {
1892
+ updateData({ ...data, props: { ...data.props, level } });
1893
+ },
1894
+ children: [
1895
+ /* @__PURE__ */ jsx(ToggleButton, { value: "h1", children: "H1" }),
1896
+ /* @__PURE__ */ jsx(ToggleButton, { value: "h2", children: "H2" }),
1897
+ /* @__PURE__ */ jsx(ToggleButton, { value: "h3", children: "H3" })
1898
+ ]
1899
+ }
1900
+ ),
1901
+ /* @__PURE__ */ jsx(
1902
+ MultiStylePropertyPanel,
1903
+ {
1904
+ names: ["color", "backgroundColor", "fontFamily", "fontWeight", "textAlign", "padding"],
1905
+ value: data.style,
1906
+ onChange: (style) => updateData({ ...data, style })
1907
+ }
1908
+ )
1909
+ ] });
1910
+ }
1911
+ function HtmlSidebarPanel({ data, setData }) {
1912
+ var _a;
1913
+ const [, setErrors] = useState(null);
1914
+ const updateData = (d) => {
1915
+ const res = HtmlPropsSchema.safeParse(d);
1916
+ if (res.success) {
1917
+ setData(res.data);
1918
+ setErrors(null);
1919
+ } else {
1920
+ setErrors(res.error);
1921
+ }
1922
+ };
1923
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Html block", children: [
1924
+ /* @__PURE__ */ jsx(
1925
+ TextInput,
1926
+ {
1927
+ label: "Content",
1928
+ rows: 5,
1929
+ defaultValue: ((_a = data.props) == null ? void 0 : _a.contents) ?? "",
1930
+ onChange: (contents) => updateData({ ...data, props: { ...data.props, contents } })
1931
+ }
1932
+ ),
1933
+ /* @__PURE__ */ jsx(
1934
+ MultiStylePropertyPanel,
1935
+ {
1936
+ names: ["color", "backgroundColor", "fontFamily", "fontSize", "textAlign", "padding"],
1937
+ value: data.style,
1938
+ onChange: (style) => updateData({ ...data, style })
1939
+ }
1940
+ )
1941
+ ] });
1942
+ }
1943
+ function ImageSidebarPanel({ data, setData }) {
1944
+ var _a, _b, _c, _d, _e, _f;
1945
+ const [, setErrors] = useState(null);
1946
+ const [uploadMode, setUploadMode] = useState("url");
1947
+ const [uploading, setUploading] = useState(false);
1948
+ const fileInputRef = useRef(null);
1949
+ const imageUploadHandler = useImageUploadHandler();
1950
+ const updateData = (d) => {
1951
+ const res = ImagePropsSchema.safeParse(d);
1952
+ if (res.success) {
1953
+ setData(res.data);
1954
+ setErrors(null);
1955
+ } else {
1956
+ setErrors(res.error);
1957
+ }
1958
+ };
1959
+ const handleFileSelect = async (event) => {
1960
+ var _a2;
1961
+ const file = (_a2 = event.target.files) == null ? void 0 : _a2[0];
1962
+ if (!file)
1963
+ return;
1964
+ if (!imageUploadHandler) {
1965
+ console.warn("Image upload handler is not configured. Please set imageUploadHandler in EditorContext.");
1966
+ return;
1967
+ }
1968
+ setUploading(true);
1969
+ try {
1970
+ const url = await imageUploadHandler(file);
1971
+ updateData({ ...data, props: { ...data.props, url } });
1972
+ setUploadMode("url");
1973
+ } catch (error) {
1974
+ console.error("Failed to upload image:", error);
1975
+ } finally {
1976
+ setUploading(false);
1977
+ if (fileInputRef.current) {
1978
+ fileInputRef.current.value = "";
1979
+ }
1980
+ }
1981
+ };
1982
+ const handleUploadClick = () => {
1983
+ var _a2;
1984
+ (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
1985
+ };
1986
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Image block", children: [
1987
+ /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
1988
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 1, children: [
1989
+ /* @__PURE__ */ jsxs(
1990
+ ToggleButton,
1991
+ {
1992
+ value: "url",
1993
+ selected: uploadMode === "url",
1994
+ onChange: () => setUploadMode("url"),
1995
+ size: "small",
1996
+ fullWidth: true,
1997
+ children: [
1998
+ /* @__PURE__ */ jsx(LinkOutlined, { fontSize: "small", sx: { mr: 0.5 } }),
1999
+ "URL"
2000
+ ]
2001
+ }
2002
+ ),
2003
+ /* @__PURE__ */ jsxs(
2004
+ ToggleButton,
2005
+ {
2006
+ value: "upload",
2007
+ selected: uploadMode === "upload",
2008
+ onChange: () => setUploadMode("upload"),
2009
+ size: "small",
2010
+ fullWidth: true,
2011
+ disabled: !imageUploadHandler,
2012
+ children: [
2013
+ /* @__PURE__ */ jsx(CloudUploadOutlined, { fontSize: "small", sx: { mr: 0.5 } }),
2014
+ "上传"
2015
+ ]
2016
+ }
2017
+ )
2018
+ ] }),
2019
+ uploadMode === "url" ? /* @__PURE__ */ jsx(
2020
+ TextInput,
2021
+ {
2022
+ label: "Source URL",
2023
+ defaultValue: ((_a = data.props) == null ? void 0 : _a.url) ?? "",
2024
+ onChange: (v) => {
2025
+ const url = v.trim().length === 0 ? null : v.trim();
2026
+ updateData({ ...data, props: { ...data.props, url } });
2027
+ }
2028
+ }
2029
+ ) : /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
2030
+ /* @__PURE__ */ jsx(
2031
+ "input",
2032
+ {
2033
+ ref: fileInputRef,
2034
+ type: "file",
2035
+ accept: "image/*",
2036
+ style: { display: "none" },
2037
+ onChange: handleFileSelect
2038
+ }
2039
+ ),
2040
+ /* @__PURE__ */ jsx(
2041
+ Button,
2042
+ {
2043
+ variant: "outlined",
2044
+ startIcon: /* @__PURE__ */ jsx(CloudUploadOutlined, {}),
2045
+ onClick: handleUploadClick,
2046
+ disabled: uploading || !imageUploadHandler,
2047
+ fullWidth: true,
2048
+ children: uploading ? "上传中..." : "选择图片"
2049
+ }
2050
+ ),
2051
+ !imageUploadHandler && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", children: "请配置 imageUploadHandler 以启用本地上传功能" })
2052
+ ] })
2053
+ ] }),
2054
+ /* @__PURE__ */ jsx(
2055
+ TextInput,
2056
+ {
2057
+ label: "Alt text",
2058
+ defaultValue: ((_b = data.props) == null ? void 0 : _b.alt) ?? "",
2059
+ onChange: (alt) => updateData({ ...data, props: { ...data.props, alt } })
2060
+ }
2061
+ ),
2062
+ /* @__PURE__ */ jsx(
2063
+ TextInput,
2064
+ {
2065
+ label: "Click through URL",
2066
+ defaultValue: ((_c = data.props) == null ? void 0 : _c.linkHref) ?? "",
2067
+ onChange: (v) => {
2068
+ const linkHref = v.trim().length === 0 ? null : v.trim();
2069
+ updateData({ ...data, props: { ...data.props, linkHref } });
2070
+ }
2071
+ }
2072
+ ),
2073
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, children: [
2074
+ /* @__PURE__ */ jsx(
2075
+ TextDimensionInput,
2076
+ {
2077
+ label: "Width",
2078
+ defaultValue: (_d = data.props) == null ? void 0 : _d.width,
2079
+ onChange: (width) => updateData({ ...data, props: { ...data.props, width } })
2080
+ }
2081
+ ),
2082
+ /* @__PURE__ */ jsx(
2083
+ TextDimensionInput,
2084
+ {
2085
+ label: "Height",
2086
+ defaultValue: (_e = data.props) == null ? void 0 : _e.height,
2087
+ onChange: (height) => updateData({ ...data, props: { ...data.props, height } })
2088
+ }
2089
+ )
2090
+ ] }),
2091
+ /* @__PURE__ */ jsxs(
2092
+ RadioGroupInput,
2093
+ {
2094
+ label: "Alignment",
2095
+ defaultValue: ((_f = data.props) == null ? void 0 : _f.contentAlignment) ?? "middle",
2096
+ onChange: (contentAlignment) => updateData({ ...data, props: { ...data.props, contentAlignment } }),
2097
+ children: [
2098
+ /* @__PURE__ */ jsx(ToggleButton, { value: "top", children: /* @__PURE__ */ jsx(VerticalAlignTopOutlined, { fontSize: "small" }) }),
2099
+ /* @__PURE__ */ jsx(ToggleButton, { value: "middle", children: /* @__PURE__ */ jsx(VerticalAlignCenterOutlined, { fontSize: "small" }) }),
2100
+ /* @__PURE__ */ jsx(ToggleButton, { value: "bottom", children: /* @__PURE__ */ jsx(VerticalAlignBottomOutlined, { fontSize: "small" }) })
2101
+ ]
2102
+ }
2103
+ ),
2104
+ /* @__PURE__ */ jsx(
2105
+ MultiStylePropertyPanel,
2106
+ {
2107
+ names: ["backgroundColor", "textAlign", "padding"],
2108
+ value: data.style,
2109
+ onChange: (style) => updateData({ ...data, style })
2110
+ }
2111
+ )
2112
+ ] });
2113
+ }
2114
+ function SpacerSidebarPanel({ data, setData }) {
2115
+ var _a;
2116
+ const [, setErrors] = useState(null);
2117
+ const updateData = (d) => {
2118
+ const res = SpacerPropsSchema.safeParse(d);
2119
+ if (res.success) {
2120
+ setData(res.data);
2121
+ setErrors(null);
2122
+ } else {
2123
+ setErrors(res.error);
2124
+ }
2125
+ };
2126
+ return /* @__PURE__ */ jsx(BaseSidebarPanel, { title: "Spacer block", children: /* @__PURE__ */ jsx(
2127
+ SliderInput,
2128
+ {
2129
+ label: "Height",
2130
+ iconLabel: /* @__PURE__ */ jsx(HeightOutlined, { sx: { color: "text.secondary" } }),
2131
+ units: "px",
2132
+ step: 4,
2133
+ min: 4,
2134
+ max: 128,
2135
+ defaultValue: ((_a = data.props) == null ? void 0 : _a.height) ?? SpacerPropsDefaults.height,
2136
+ onChange: (height) => updateData({ ...data, props: { ...data.props, height } })
2137
+ }
2138
+ ) });
2139
+ }
2140
+ function BooleanInput({ label, defaultValue, onChange }) {
2141
+ const [value, setValue] = useState(defaultValue);
2142
+ return /* @__PURE__ */ jsx(
2143
+ FormControlLabel,
2144
+ {
2145
+ label,
2146
+ control: /* @__PURE__ */ jsx(
2147
+ Switch,
2148
+ {
2149
+ checked: value,
2150
+ onChange: (_, checked) => {
2151
+ setValue(checked);
2152
+ onChange(checked);
2153
+ }
2154
+ }
2155
+ )
2156
+ }
2157
+ );
2158
+ }
2159
+ function TextSidebarPanel({ data, setData }) {
2160
+ var _a, _b;
2161
+ const [, setErrors] = useState(null);
2162
+ const updateData = (d) => {
2163
+ const res = TextPropsSchema.safeParse(d);
2164
+ if (res.success) {
2165
+ setData(res.data);
2166
+ setErrors(null);
2167
+ } else {
2168
+ setErrors(res.error);
2169
+ }
2170
+ };
2171
+ return /* @__PURE__ */ jsxs(BaseSidebarPanel, { title: "Text block", children: [
2172
+ /* @__PURE__ */ jsx(
2173
+ TextInput,
2174
+ {
2175
+ label: "Content",
2176
+ rows: 5,
2177
+ defaultValue: ((_a = data.props) == null ? void 0 : _a.text) ?? "",
2178
+ onChange: (text) => updateData({ ...data, props: { ...data.props, text } })
2179
+ }
2180
+ ),
2181
+ /* @__PURE__ */ jsx(
2182
+ BooleanInput,
2183
+ {
2184
+ label: "Markdown",
2185
+ defaultValue: ((_b = data.props) == null ? void 0 : _b.markdown) ?? false,
2186
+ onChange: (markdown) => updateData({ ...data, props: { ...data.props, markdown } })
2187
+ }
2188
+ ),
2189
+ /* @__PURE__ */ jsx(
2190
+ MultiStylePropertyPanel,
2191
+ {
2192
+ names: ["color", "backgroundColor", "fontFamily", "fontSize", "fontWeight", "textAlign", "padding"],
2193
+ value: data.style,
2194
+ onChange: (style) => updateData({ ...data, style })
2195
+ }
2196
+ )
2197
+ ] });
2198
+ }
2199
+ function renderMessage(val) {
2200
+ return /* @__PURE__ */ jsx(Box, { sx: { m: 3, p: 1, border: "1px dashed", borderColor: "divider" }, children: /* @__PURE__ */ jsx(Typography, { color: "text.secondary", children: val }) });
2201
+ }
2202
+ function ConfigurationPanel() {
2203
+ const { t: t2 } = useTranslation();
2204
+ const document = useDocument();
2205
+ const selectedBlockId = useSelectedBlockId();
2206
+ if (!selectedBlockId) {
2207
+ return renderMessage(t2("inspector.clickBlockToInspect"));
2208
+ }
2209
+ const block = document[selectedBlockId];
2210
+ if (!block) {
2211
+ return renderMessage(t2("inspector.blockNotFound", { id: selectedBlockId }));
2212
+ }
2213
+ const setBlock = (conf) => setDocument({ [selectedBlockId]: conf });
2214
+ const { data, type } = block;
2215
+ switch (type) {
2216
+ case "Avatar":
2217
+ return /* @__PURE__ */ jsx(AvatarSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2218
+ case "Button":
2219
+ return /* @__PURE__ */ jsx(ButtonSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2220
+ case "ColumnsContainer":
2221
+ return /* @__PURE__ */ jsx(ColumnsContainerPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2222
+ case "Container":
2223
+ return /* @__PURE__ */ jsx(ContainerSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2224
+ case "Divider":
2225
+ return /* @__PURE__ */ jsx(DividerSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2226
+ case "Heading":
2227
+ return /* @__PURE__ */ jsx(HeadingSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2228
+ case "Html":
2229
+ return /* @__PURE__ */ jsx(HtmlSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2230
+ case "Image":
2231
+ return /* @__PURE__ */ jsx(ImageSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2232
+ case "EmailLayout":
2233
+ return /* @__PURE__ */ jsx(EmailLayoutSidebarFields, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2234
+ case "Spacer":
2235
+ return /* @__PURE__ */ jsx(SpacerSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2236
+ case "Text":
2237
+ return /* @__PURE__ */ jsx(TextSidebarPanel, { data, setData: (data2) => setBlock({ type, data: data2 }) }, selectedBlockId);
2238
+ default:
2239
+ return /* @__PURE__ */ jsx("pre", { children: JSON.stringify(block, null, " ") });
2240
+ }
2241
+ }
2242
+ function StylesPanel() {
2243
+ const block = useDocument().root;
2244
+ if (!block) {
2245
+ return /* @__PURE__ */ jsx("p", { children: "Block not found" });
2246
+ }
2247
+ const { data, type } = block;
2248
+ if (type !== "EmailLayout") {
2249
+ throw new Error('Expected "root" element to be of type EmailLayout');
2250
+ }
2251
+ return /* @__PURE__ */ jsx(EmailLayoutSidebarFields, { data, setData: (data2) => setDocument({ root: { type, data: data2 } }) }, "root");
2252
+ }
2253
+ const INSPECTOR_DRAWER_WIDTH = 320;
2254
+ function InspectorDrawer() {
2255
+ const { t: t2 } = useTranslation();
2256
+ const selectedSidebarTab = useSelectedSidebarTab();
2257
+ const inspectorDrawerOpen = useInspectorDrawerOpen();
2258
+ const renderCurrentSidebarPanel = () => {
2259
+ switch (selectedSidebarTab) {
2260
+ case "block-configuration":
2261
+ return /* @__PURE__ */ jsx(ConfigurationPanel, {});
2262
+ case "styles":
2263
+ return /* @__PURE__ */ jsx(StylesPanel, {});
2264
+ }
2265
+ };
2266
+ return /* @__PURE__ */ jsxs(
2267
+ Drawer,
2268
+ {
2269
+ variant: "persistent",
2270
+ anchor: "right",
2271
+ open: inspectorDrawerOpen,
2272
+ sx: {
2273
+ width: inspectorDrawerOpen ? INSPECTOR_DRAWER_WIDTH : 0
2274
+ },
2275
+ children: [
2276
+ /* @__PURE__ */ jsx(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: 49, borderBottom: 1, borderColor: "divider" }, children: /* @__PURE__ */ jsx(Box, { px: 2, children: /* @__PURE__ */ jsxs(Tabs, { value: selectedSidebarTab, onChange: (_, v) => setSidebarTab(v), children: [
2277
+ /* @__PURE__ */ jsx(Tab, { value: "styles", label: t2("inspector.styles") }),
2278
+ /* @__PURE__ */ jsx(Tab, { value: "block-configuration", label: t2("inspector.inspect") })
2279
+ ] }) }) }),
2280
+ /* @__PURE__ */ jsx(Box, { sx: { width: INSPECTOR_DRAWER_WIDTH, height: "calc(100% - 49px)", overflow: "auto" }, children: renderCurrentSidebarPanel() })
2281
+ ]
2282
+ }
2283
+ );
2284
+ }
2285
+ function LanguageSwitcher() {
2286
+ const language = useLanguage();
2287
+ const [anchorEl, setAnchorEl] = React.useState(null);
2288
+ const open = Boolean(anchorEl);
2289
+ const handleClick = (event) => {
2290
+ setAnchorEl(event.currentTarget);
2291
+ };
2292
+ const handleClose = () => {
2293
+ setAnchorEl(null);
2294
+ };
2295
+ const handleLanguageChange = (lang) => {
2296
+ setLanguage(lang);
2297
+ handleClose();
2298
+ };
2299
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2300
+ /* @__PURE__ */ jsx(IconButton, { onClick: handleClick, size: "small", sx: { color: "text.secondary" }, children: /* @__PURE__ */ jsx(LanguageOutlined, { fontSize: "small" }) }),
2301
+ /* @__PURE__ */ jsxs(Menu, { anchorEl, open, onClose: handleClose, children: [
2302
+ /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleLanguageChange("zh"), selected: language === "zh", children: "中文" }),
2303
+ /* @__PURE__ */ jsx(MenuItem, { onClick: () => handleLanguageChange("en"), selected: language === "en", children: "English" })
2304
+ ] })
2305
+ ] });
2306
+ }
2307
+ function SidebarButton({ href, children }) {
2308
+ const [loading, setLoading] = useState(false);
2309
+ const handleClick = async () => {
2310
+ if (href.startsWith("#sample/")) {
2311
+ setLoading(true);
2312
+ try {
2313
+ const sampleName = href.replace("#sample/", "");
2314
+ const template = await loadSampleTemplate(sampleName);
2315
+ resetDocument(template);
2316
+ } catch (error) {
2317
+ console.error("Failed to load template:", error);
2318
+ } finally {
2319
+ setLoading(false);
2320
+ }
2321
+ } else {
2322
+ resetDocument(getConfiguration(href));
2323
+ }
2324
+ };
2325
+ return /* @__PURE__ */ jsx(Button, { size: "small", href, onClick: handleClick, disabled: loading, children: loading ? "Loading..." : children });
2326
+ }
2327
+ const SAMPLES_DRAWER_WIDTH = 240;
2328
+ function SamplesDrawer() {
2329
+ const { t: t2 } = useTranslation();
2330
+ const samplesDrawerOpen = useSamplesDrawerOpen();
2331
+ const currentHash = typeof window !== "undefined" ? window.location.hash : "";
2332
+ const isNewDocument = !currentHash || currentHash === "#";
2333
+ const handleNewDocumentClick = () => {
2334
+ resetDocument(getConfiguration("#"));
2335
+ if (typeof window !== "undefined") {
2336
+ window.location.hash = "#";
2337
+ }
2338
+ };
2339
+ return /* @__PURE__ */ jsx(
2340
+ Drawer,
2341
+ {
2342
+ variant: "persistent",
2343
+ anchor: "left",
2344
+ open: samplesDrawerOpen,
2345
+ sx: {
2346
+ width: samplesDrawerOpen ? SAMPLES_DRAWER_WIDTH : 0
2347
+ },
2348
+ children: /* @__PURE__ */ jsx(Stack, { spacing: 3, py: 1, px: 2, width: SAMPLES_DRAWER_WIDTH, children: /* @__PURE__ */ jsxs(Stack, { spacing: 2, sx: { "& .MuiButtonBase-root": { width: "100%", justifyContent: "flex-start" } }, children: [
2349
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", component: "h1", sx: { p: 0.75 }, children: t2("common.emailBuilder") }),
2350
+ /* @__PURE__ */ jsx(Stack, { spacing: 1, alignItems: "flex-start", children: /* @__PURE__ */ jsx(
2351
+ Button,
2352
+ {
2353
+ size: "small",
2354
+ variant: "contained",
2355
+ color: "primary",
2356
+ href: "#",
2357
+ onClick: handleNewDocumentClick,
2358
+ sx: {
2359
+ fontWeight: isNewDocument ? 600 : 400,
2360
+ width: "100%",
2361
+ justifyContent: "flex-start"
2362
+ },
2363
+ children: t2("common.newDocument")
2364
+ }
2365
+ ) }),
2366
+ /* @__PURE__ */ jsx(Divider, {}),
2367
+ /* @__PURE__ */ jsxs(Stack, { spacing: 1, children: [
2368
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "text.secondary", sx: { px: 0.75, fontWeight: 500 }, children: t2("common.useBuiltInTemplates") }),
2369
+ /* @__PURE__ */ jsxs(Stack, { alignItems: "flex-start", children: [
2370
+ /* @__PURE__ */ jsx(SidebarButton, { href: "#sample/welcome", children: t2("samples.welcomeEmail") }),
2371
+ /* @__PURE__ */ jsx(SidebarButton, { href: "#sample/reservation-reminder", children: t2("samples.reservationReminder") })
2372
+ ] })
2373
+ ] })
2374
+ ] }) })
2375
+ }
2376
+ );
2377
+ }
2378
+ const BUTTON_SX = { p: 1.5, display: "flex", flexDirection: "column" };
2379
+ const ICON_SX = {
2380
+ mb: 0.75,
2381
+ width: "100%",
2382
+ bgcolor: "cadet.200",
2383
+ display: "flex",
2384
+ justifyContent: "center",
2385
+ p: 1,
2386
+ border: "1px solid",
2387
+ borderColor: "cadet.300"
2388
+ };
2389
+ function BlockTypeButton({ label, icon, onClick }) {
2390
+ return /* @__PURE__ */ jsxs(
2391
+ Button,
2392
+ {
2393
+ sx: BUTTON_SX,
2394
+ onClick: (ev) => {
2395
+ ev.stopPropagation();
2396
+ onClick();
2397
+ },
2398
+ children: [
2399
+ /* @__PURE__ */ jsx(Box, { sx: ICON_SX, children: icon }),
2400
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", children: label })
2401
+ ]
2402
+ }
2403
+ );
2404
+ }
2405
+ const BUTTONS = [
2406
+ {
2407
+ label: "Heading",
2408
+ icon: /* @__PURE__ */ jsx(HMobiledataOutlined, {}),
2409
+ block: () => ({
2410
+ type: "Heading",
2411
+ data: {
2412
+ props: { text: "Hello friend" },
2413
+ style: {
2414
+ padding: { top: 16, bottom: 16, left: 24, right: 24 }
2415
+ }
2416
+ }
2417
+ })
2418
+ },
2419
+ {
2420
+ label: "Text",
2421
+ icon: /* @__PURE__ */ jsx(NotesOutlined, {}),
2422
+ block: () => ({
2423
+ type: "Text",
2424
+ data: {
2425
+ props: { text: "My new text block" },
2426
+ style: {
2427
+ padding: { top: 16, bottom: 16, left: 24, right: 24 },
2428
+ fontWeight: "normal"
2429
+ }
2430
+ }
2431
+ })
2432
+ },
2433
+ {
2434
+ label: "Button",
2435
+ icon: /* @__PURE__ */ jsx(SmartButtonOutlined, {}),
2436
+ block: () => ({
2437
+ type: "Button",
2438
+ data: {
2439
+ props: {
2440
+ text: "Button",
2441
+ url: "https://www.usewaypoint.com"
2442
+ },
2443
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
2444
+ }
2445
+ })
2446
+ },
2447
+ {
2448
+ label: "Image",
2449
+ icon: /* @__PURE__ */ jsx(ImageOutlined, {}),
2450
+ block: () => ({
2451
+ type: "Image",
2452
+ data: {
2453
+ props: {
2454
+ url: "https://assets.usewaypoint.com/sample-image.jpg",
2455
+ alt: "Sample product",
2456
+ contentAlignment: "middle",
2457
+ linkHref: null
2458
+ },
2459
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
2460
+ }
2461
+ })
2462
+ },
2463
+ {
2464
+ label: "Avatar",
2465
+ icon: /* @__PURE__ */ jsx(AccountCircleOutlined, {}),
2466
+ block: () => ({
2467
+ type: "Avatar",
2468
+ data: {
2469
+ props: {
2470
+ imageUrl: "https://ui-avatars.com/api/?size=128",
2471
+ shape: "circle"
2472
+ },
2473
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
2474
+ }
2475
+ })
2476
+ },
2477
+ {
2478
+ label: "Divider",
2479
+ icon: /* @__PURE__ */ jsx(HorizontalRuleOutlined, {}),
2480
+ block: () => ({
2481
+ type: "Divider",
2482
+ data: {
2483
+ style: { padding: { top: 16, right: 0, bottom: 16, left: 0 } },
2484
+ props: {
2485
+ lineColor: "#CCCCCC"
2486
+ }
2487
+ }
2488
+ })
2489
+ },
2490
+ {
2491
+ label: "Spacer",
2492
+ icon: /* @__PURE__ */ jsx(Crop32Outlined, {}),
2493
+ block: () => ({
2494
+ type: "Spacer",
2495
+ data: {}
2496
+ })
2497
+ },
2498
+ {
2499
+ label: "Html",
2500
+ icon: /* @__PURE__ */ jsx(HtmlOutlined, {}),
2501
+ block: () => ({
2502
+ type: "Html",
2503
+ data: {
2504
+ props: { contents: "<strong>Hello world</strong>" },
2505
+ style: {
2506
+ fontSize: 16,
2507
+ textAlign: null,
2508
+ padding: { top: 16, bottom: 16, left: 24, right: 24 }
2509
+ }
2510
+ }
2511
+ })
2512
+ },
2513
+ {
2514
+ label: "Columns",
2515
+ icon: /* @__PURE__ */ jsx(ViewColumnOutlined, {}),
2516
+ block: () => ({
2517
+ type: "ColumnsContainer",
2518
+ data: {
2519
+ props: {
2520
+ columnsGap: 16,
2521
+ columnsCount: 3,
2522
+ columns: [{ childrenIds: [] }, { childrenIds: [] }, { childrenIds: [] }]
2523
+ },
2524
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
2525
+ }
2526
+ })
2527
+ },
2528
+ {
2529
+ label: "Container",
2530
+ icon: /* @__PURE__ */ jsx(LibraryAddOutlined, {}),
2531
+ block: () => ({
2532
+ type: "Container",
2533
+ data: {
2534
+ style: { padding: { top: 16, bottom: 16, left: 24, right: 24 } }
2535
+ }
2536
+ })
2537
+ }
2538
+ // { label: 'ProgressBar', icon: <ProgressBarOutlined />, block: () => ({}) },
2539
+ // { label: 'LoopContainer', icon: <ViewListOutlined />, block: () => ({}) },
2540
+ ];
2541
+ function BlocksMenu({ anchorEl, setAnchorEl, onSelect }) {
2542
+ const onClose = () => {
2543
+ setAnchorEl(null);
2544
+ };
2545
+ const onClick = (block) => {
2546
+ onSelect(block);
2547
+ setAnchorEl(null);
2548
+ };
2549
+ if (anchorEl === null) {
2550
+ return null;
2551
+ }
2552
+ return /* @__PURE__ */ jsx(
2553
+ Menu,
2554
+ {
2555
+ open: true,
2556
+ anchorEl,
2557
+ onClose,
2558
+ anchorOrigin: { vertical: "bottom", horizontal: "center" },
2559
+ transformOrigin: { vertical: "top", horizontal: "center" },
2560
+ children: /* @__PURE__ */ jsx(Box, { sx: { p: 1, display: "grid", gridTemplateColumns: "1fr 1fr 1fr 1fr" }, children: BUTTONS.map((k, i) => /* @__PURE__ */ jsx(BlockTypeButton, { label: k.label, icon: k.icon, onClick: () => onClick(k.block()) }, i)) })
2561
+ }
2562
+ );
2563
+ }
2564
+ function DividerButton({ buttonElement, onClick }) {
2565
+ const [visible, setVisible] = useState(false);
2566
+ useEffect(() => {
2567
+ function listener({ clientX, clientY }) {
2568
+ if (!buttonElement) {
2569
+ return;
2570
+ }
2571
+ const rect = buttonElement.getBoundingClientRect();
2572
+ const rectY = rect.y;
2573
+ const bottomX = rect.x;
2574
+ const topX = bottomX + rect.width;
2575
+ if (Math.abs(clientY - rectY) < 20) {
2576
+ if (bottomX < clientX && clientX < topX) {
2577
+ setVisible(true);
2578
+ return;
2579
+ }
2580
+ }
2581
+ setVisible(false);
2582
+ }
2583
+ window.addEventListener("mousemove", listener);
2584
+ return () => {
2585
+ window.removeEventListener("mousemove", listener);
2586
+ };
2587
+ }, [buttonElement, setVisible]);
2588
+ return /* @__PURE__ */ jsx(Fade, { in: visible, children: /* @__PURE__ */ jsx(
2589
+ IconButton,
2590
+ {
2591
+ size: "small",
2592
+ sx: {
2593
+ p: 0.12,
2594
+ position: "absolute",
2595
+ top: "-12px",
2596
+ left: "50%",
2597
+ transform: "translateX(-10px)",
2598
+ bgcolor: "brand.blue",
2599
+ color: "primary.contrastText",
2600
+ zIndex: "fab",
2601
+ "&:hover, &:active, &:focus": {
2602
+ bgcolor: "brand.blue",
2603
+ color: "primary.contrastText"
2604
+ }
2605
+ },
2606
+ onClick: (ev) => {
2607
+ ev.stopPropagation();
2608
+ onClick();
2609
+ },
2610
+ children: /* @__PURE__ */ jsx(AddOutlined, { fontSize: "small" })
2611
+ }
2612
+ ) });
2613
+ }
2614
+ function PlaceholderButton({ onClick }) {
2615
+ return /* @__PURE__ */ jsx(
2616
+ ButtonBase,
2617
+ {
2618
+ onClick: (ev) => {
2619
+ ev.stopPropagation();
2620
+ onClick();
2621
+ },
2622
+ sx: {
2623
+ display: "flex",
2624
+ alignContent: "center",
2625
+ justifyContent: "center",
2626
+ height: 48,
2627
+ width: "100%",
2628
+ bgcolor: "rgba(0,0,0, 0.05)"
2629
+ },
2630
+ children: /* @__PURE__ */ jsx(
2631
+ AddOutlined,
2632
+ {
2633
+ sx: {
2634
+ p: 0.12,
2635
+ bgcolor: "brand.blue",
2636
+ borderRadius: 24,
2637
+ color: "primary.contrastText"
2638
+ },
2639
+ fontSize: "small"
2640
+ }
2641
+ )
2642
+ }
2643
+ );
2644
+ }
2645
+ function AddBlockButton({ onSelect, placeholder }) {
2646
+ const [menuAnchorEl, setMenuAnchorEl] = useState(null);
2647
+ const [buttonElement, setButtonElement] = useState(null);
2648
+ const handleButtonClick = () => {
2649
+ setMenuAnchorEl(buttonElement);
2650
+ };
2651
+ const renderButton = () => {
2652
+ if (placeholder) {
2653
+ return /* @__PURE__ */ jsx(PlaceholderButton, { onClick: handleButtonClick });
2654
+ } else {
2655
+ return /* @__PURE__ */ jsx(DividerButton, { buttonElement, onClick: handleButtonClick });
2656
+ }
2657
+ };
2658
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2659
+ /* @__PURE__ */ jsx("div", { ref: setButtonElement, style: { position: "relative" }, children: renderButton() }),
2660
+ /* @__PURE__ */ jsx(BlocksMenu, { anchorEl: menuAnchorEl, setAnchorEl: setMenuAnchorEl, onSelect })
2661
+ ] });
2662
+ }
2663
+ function generateId() {
2664
+ return `block-${Date.now()}`;
2665
+ }
2666
+ function EditorChildrenIds({ childrenIds, onChange }) {
2667
+ const appendBlock = (block) => {
2668
+ const blockId = generateId();
2669
+ return onChange({
2670
+ blockId,
2671
+ block,
2672
+ childrenIds: [...childrenIds || [], blockId]
2673
+ });
2674
+ };
2675
+ const insertBlock = (block, index) => {
2676
+ const blockId = generateId();
2677
+ const newChildrenIds = [...childrenIds || []];
2678
+ newChildrenIds.splice(index, 0, blockId);
2679
+ return onChange({
2680
+ blockId,
2681
+ block,
2682
+ childrenIds: newChildrenIds
2683
+ });
2684
+ };
2685
+ if (!childrenIds || childrenIds.length === 0) {
2686
+ return /* @__PURE__ */ jsx(AddBlockButton, { placeholder: true, onSelect: appendBlock });
2687
+ }
2688
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2689
+ childrenIds.map((childId, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
2690
+ /* @__PURE__ */ jsx(AddBlockButton, { onSelect: (block) => insertBlock(block, i) }),
2691
+ /* @__PURE__ */ jsx(EditorBlock, { id: childId })
2692
+ ] }, childId)),
2693
+ /* @__PURE__ */ jsx(AddBlockButton, { onSelect: appendBlock })
2694
+ ] });
2695
+ }
2696
+ const EMPTY_COLUMNS = [{ childrenIds: [] }, { childrenIds: [] }, { childrenIds: [] }];
2697
+ function ColumnsContainerEditor({ style, props }) {
2698
+ var _a, _b, _c;
2699
+ const currentBlockId = useCurrentBlockId();
2700
+ const { columns, ...restProps } = props ?? {};
2701
+ const columnsValue = columns ?? EMPTY_COLUMNS;
2702
+ const updateColumn = (columnIndex, { block, blockId, childrenIds }) => {
2703
+ const nColumns = [...columnsValue];
2704
+ nColumns[columnIndex] = { childrenIds };
2705
+ setDocument({
2706
+ [blockId]: block,
2707
+ [currentBlockId]: {
2708
+ type: "ColumnsContainer",
2709
+ data: ColumnsContainerPropsSchema.parse({
2710
+ style,
2711
+ props: {
2712
+ ...restProps,
2713
+ columns: nColumns
2714
+ }
2715
+ })
2716
+ }
2717
+ });
2718
+ setSelectedBlockId(blockId);
2719
+ };
2720
+ return /* @__PURE__ */ jsx(
2721
+ ColumnsContainer,
2722
+ {
2723
+ props: restProps,
2724
+ style,
2725
+ columns: [
2726
+ /* @__PURE__ */ jsx(EditorChildrenIds, { childrenIds: (_a = columns == null ? void 0 : columns[0]) == null ? void 0 : _a.childrenIds, onChange: (change) => updateColumn(0, change) }),
2727
+ /* @__PURE__ */ jsx(EditorChildrenIds, { childrenIds: (_b = columns == null ? void 0 : columns[1]) == null ? void 0 : _b.childrenIds, onChange: (change) => updateColumn(1, change) }),
2728
+ /* @__PURE__ */ jsx(EditorChildrenIds, { childrenIds: (_c = columns == null ? void 0 : columns[2]) == null ? void 0 : _c.childrenIds, onChange: (change) => updateColumn(2, change) })
2729
+ ]
2730
+ }
2731
+ );
2732
+ }
2733
+ function ContainerEditor({ style, props }) {
2734
+ const childrenIds = (props == null ? void 0 : props.childrenIds) ?? [];
2735
+ const document = useDocument();
2736
+ const currentBlockId = useCurrentBlockId();
2737
+ return /* @__PURE__ */ jsx(Container, { style, children: /* @__PURE__ */ jsx(
2738
+ EditorChildrenIds,
2739
+ {
2740
+ childrenIds,
2741
+ onChange: ({ block, blockId, childrenIds: childrenIds2 }) => {
2742
+ setDocument({
2743
+ [blockId]: block,
2744
+ [currentBlockId]: {
2745
+ type: "Container",
2746
+ data: {
2747
+ ...document[currentBlockId].data,
2748
+ props: { childrenIds: childrenIds2 }
2749
+ }
2750
+ }
2751
+ });
2752
+ setSelectedBlockId(blockId);
2753
+ }
2754
+ }
2755
+ ) });
2756
+ }
2757
+ function getFontFamily(fontFamily) {
2758
+ const f = fontFamily ?? "MODERN_SANS";
2759
+ switch (f) {
2760
+ case "MODERN_SANS":
2761
+ return '"Helvetica Neue", "Arial Nova", "Nimbus Sans", Arial, sans-serif';
2762
+ case "BOOK_SANS":
2763
+ return 'Optima, Candara, "Noto Sans", source-sans-pro, sans-serif';
2764
+ case "ORGANIC_SANS":
2765
+ return 'Seravek, "Gill Sans Nova", Ubuntu, Calibri, "DejaVu Sans", source-sans-pro, sans-serif';
2766
+ case "GEOMETRIC_SANS":
2767
+ return 'Avenir, "Avenir Next LT Pro", Montserrat, Corbel, "URW Gothic", source-sans-pro, sans-serif';
2768
+ case "HEAVY_SANS":
2769
+ return 'Bahnschrift, "DIN Alternate", "Franklin Gothic Medium", "Nimbus Sans Narrow", sans-serif-condensed, sans-serif';
2770
+ case "ROUNDED_SANS":
2771
+ return 'ui-rounded, "Hiragino Maru Gothic ProN", Quicksand, Comfortaa, Manjari, "Arial Rounded MT Bold", Calibri, source-sans-pro, sans-serif';
2772
+ case "MODERN_SERIF":
2773
+ return 'Charter, "Bitstream Charter", "Sitka Text", Cambria, serif';
2774
+ case "BOOK_SERIF":
2775
+ return '"Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif';
2776
+ case "MONOSPACE":
2777
+ return '"Nimbus Mono PS", "Courier New", "Cutive Mono", monospace';
2778
+ }
2779
+ }
2780
+ function EmailLayoutEditor(props) {
2781
+ const childrenIds = props.childrenIds ?? [];
2782
+ const document = useDocument();
2783
+ const currentBlockId = useCurrentBlockId();
2784
+ return /* @__PURE__ */ jsx(
2785
+ "div",
2786
+ {
2787
+ onClick: () => {
2788
+ setSelectedBlockId(null);
2789
+ },
2790
+ style: {
2791
+ backgroundColor: props.backdropColor ?? "#F5F5F5",
2792
+ color: props.textColor ?? "#262626",
2793
+ fontFamily: getFontFamily(props.fontFamily),
2794
+ fontSize: "16px",
2795
+ fontWeight: "400",
2796
+ letterSpacing: "0.15008px",
2797
+ lineHeight: "1.5",
2798
+ margin: "0",
2799
+ padding: "32px 0",
2800
+ width: "100%",
2801
+ minHeight: "100%"
2802
+ },
2803
+ children: /* @__PURE__ */ jsx(
2804
+ "table",
2805
+ {
2806
+ align: "center",
2807
+ width: "100%",
2808
+ style: {
2809
+ margin: "0 auto",
2810
+ maxWidth: props.width ? `${props.width}px` : "600px",
2811
+ backgroundColor: props.canvasColor ?? "#FFFFFF",
2812
+ borderRadius: props.borderRadius ?? void 0,
2813
+ border: (() => {
2814
+ const v = props.borderColor;
2815
+ if (!v) {
2816
+ return void 0;
2817
+ }
2818
+ return `1px solid ${v}`;
2819
+ })()
2820
+ },
2821
+ role: "presentation",
2822
+ cellSpacing: "0",
2823
+ cellPadding: "0",
2824
+ border: 0,
2825
+ children: /* @__PURE__ */ jsx("tbody", { children: /* @__PURE__ */ jsx("tr", { style: { width: "100%" }, children: /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(
2826
+ EditorChildrenIds,
2827
+ {
2828
+ childrenIds,
2829
+ onChange: ({ block, blockId, childrenIds: childrenIds2 }) => {
2830
+ setDocument({
2831
+ [blockId]: block,
2832
+ [currentBlockId]: {
2833
+ type: "EmailLayout",
2834
+ data: {
2835
+ ...document[currentBlockId].data,
2836
+ childrenIds: childrenIds2
2837
+ }
2838
+ }
2839
+ });
2840
+ setSelectedBlockId(blockId);
2841
+ }
2842
+ }
2843
+ ) }) }) })
2844
+ }
2845
+ )
2846
+ }
2847
+ );
2848
+ }
2849
+ const sx = {
2850
+ position: "absolute",
2851
+ top: 0,
2852
+ left: -56,
2853
+ borderRadius: 64,
2854
+ paddingX: 0.5,
2855
+ paddingY: 1,
2856
+ zIndex: "fab"
2857
+ };
2858
+ function TuneMenu({ blockId }) {
2859
+ const document = useDocument();
2860
+ const handleDeleteClick = () => {
2861
+ var _a, _b, _c;
2862
+ const filterChildrenIds = (childrenIds) => {
2863
+ if (!childrenIds) {
2864
+ return childrenIds;
2865
+ }
2866
+ return childrenIds.filter((f) => f !== blockId);
2867
+ };
2868
+ const nDocument = { ...document };
2869
+ for (const [id, b] of Object.entries(nDocument)) {
2870
+ const block = b;
2871
+ if (id === blockId) {
2872
+ continue;
2873
+ }
2874
+ switch (block.type) {
2875
+ case "EmailLayout":
2876
+ nDocument[id] = {
2877
+ ...block,
2878
+ data: {
2879
+ ...block.data,
2880
+ childrenIds: filterChildrenIds(block.data.childrenIds)
2881
+ }
2882
+ };
2883
+ break;
2884
+ case "Container":
2885
+ nDocument[id] = {
2886
+ ...block,
2887
+ data: {
2888
+ ...block.data,
2889
+ props: {
2890
+ ...block.data.props,
2891
+ childrenIds: filterChildrenIds((_a = block.data.props) == null ? void 0 : _a.childrenIds)
2892
+ }
2893
+ }
2894
+ };
2895
+ break;
2896
+ case "ColumnsContainer":
2897
+ nDocument[id] = {
2898
+ type: "ColumnsContainer",
2899
+ data: {
2900
+ style: block.data.style,
2901
+ props: {
2902
+ ...block.data.props,
2903
+ columns: (_c = (_b = block.data.props) == null ? void 0 : _b.columns) == null ? void 0 : _c.map((c) => ({
2904
+ childrenIds: filterChildrenIds(c.childrenIds)
2905
+ }))
2906
+ }
2907
+ }
2908
+ };
2909
+ break;
2910
+ default:
2911
+ nDocument[id] = block;
2912
+ }
2913
+ }
2914
+ delete nDocument[blockId];
2915
+ resetDocument(nDocument);
2916
+ };
2917
+ const handleMoveClick = (direction) => {
2918
+ var _a, _b, _c;
2919
+ const moveChildrenIds = (ids) => {
2920
+ if (!ids) {
2921
+ return ids;
2922
+ }
2923
+ const index = ids.indexOf(blockId);
2924
+ if (index < 0) {
2925
+ return ids;
2926
+ }
2927
+ const childrenIds = [...ids];
2928
+ if (direction === "up" && index > 0) {
2929
+ [childrenIds[index], childrenIds[index - 1]] = [childrenIds[index - 1], childrenIds[index]];
2930
+ } else if (direction === "down" && index < childrenIds.length - 1) {
2931
+ [childrenIds[index], childrenIds[index + 1]] = [childrenIds[index + 1], childrenIds[index]];
2932
+ }
2933
+ return childrenIds;
2934
+ };
2935
+ const nDocument = { ...document };
2936
+ for (const [id, b] of Object.entries(nDocument)) {
2937
+ const block = b;
2938
+ if (id === blockId) {
2939
+ continue;
2940
+ }
2941
+ switch (block.type) {
2942
+ case "EmailLayout":
2943
+ nDocument[id] = {
2944
+ ...block,
2945
+ data: {
2946
+ ...block.data,
2947
+ childrenIds: moveChildrenIds(block.data.childrenIds)
2948
+ }
2949
+ };
2950
+ break;
2951
+ case "Container":
2952
+ nDocument[id] = {
2953
+ ...block,
2954
+ data: {
2955
+ ...block.data,
2956
+ props: {
2957
+ ...block.data.props,
2958
+ childrenIds: moveChildrenIds((_a = block.data.props) == null ? void 0 : _a.childrenIds)
2959
+ }
2960
+ }
2961
+ };
2962
+ break;
2963
+ case "ColumnsContainer":
2964
+ nDocument[id] = {
2965
+ type: "ColumnsContainer",
2966
+ data: {
2967
+ style: block.data.style,
2968
+ props: {
2969
+ ...block.data.props,
2970
+ columns: (_c = (_b = block.data.props) == null ? void 0 : _b.columns) == null ? void 0 : _c.map((c) => ({
2971
+ childrenIds: moveChildrenIds(c.childrenIds)
2972
+ }))
2973
+ }
2974
+ }
2975
+ };
2976
+ break;
2977
+ default:
2978
+ nDocument[id] = block;
2979
+ }
2980
+ }
2981
+ resetDocument(nDocument);
2982
+ setSelectedBlockId(blockId);
2983
+ };
2984
+ return /* @__PURE__ */ jsx(Paper, { sx, onClick: (ev) => ev.stopPropagation(), children: /* @__PURE__ */ jsxs(Stack, { children: [
2985
+ /* @__PURE__ */ jsx(Tooltip, { title: "Move up", placement: "left-start", children: /* @__PURE__ */ jsx(IconButton, { onClick: () => handleMoveClick("up"), sx: { color: "text.primary" }, children: /* @__PURE__ */ jsx(ArrowUpwardOutlined, { fontSize: "small" }) }) }),
2986
+ /* @__PURE__ */ jsx(Tooltip, { title: "Move down", placement: "left-start", children: /* @__PURE__ */ jsx(IconButton, { onClick: () => handleMoveClick("down"), sx: { color: "text.primary" }, children: /* @__PURE__ */ jsx(ArrowDownwardOutlined, { fontSize: "small" }) }) }),
2987
+ /* @__PURE__ */ jsx(Tooltip, { title: "Delete", placement: "left-start", children: /* @__PURE__ */ jsx(IconButton, { onClick: handleDeleteClick, sx: { color: "text.primary" }, children: /* @__PURE__ */ jsx(DeleteOutlined, { fontSize: "small" }) }) })
2988
+ ] }) });
2989
+ }
2990
+ function EditorBlockWrapper({ children }) {
2991
+ const selectedBlockId = useSelectedBlockId();
2992
+ const [mouseInside, setMouseInside] = useState(false);
2993
+ const blockId = useCurrentBlockId();
2994
+ let outline;
2995
+ if (selectedBlockId === blockId) {
2996
+ outline = "2px solid rgba(0,121,204, 1)";
2997
+ } else if (mouseInside) {
2998
+ outline = "2px solid rgba(0,121,204, 0.3)";
2999
+ }
3000
+ const renderMenu = () => {
3001
+ if (selectedBlockId !== blockId) {
3002
+ return null;
3003
+ }
3004
+ return /* @__PURE__ */ jsx(TuneMenu, { blockId });
3005
+ };
3006
+ return /* @__PURE__ */ jsxs(
3007
+ Box,
3008
+ {
3009
+ sx: {
3010
+ position: "relative",
3011
+ maxWidth: "100%",
3012
+ outlineOffset: "-1px",
3013
+ outline
3014
+ },
3015
+ onMouseEnter: (ev) => {
3016
+ setMouseInside(true);
3017
+ ev.stopPropagation();
3018
+ },
3019
+ onMouseLeave: () => {
3020
+ setMouseInside(false);
3021
+ },
3022
+ onClick: (ev) => {
3023
+ setSelectedBlockId(blockId);
3024
+ ev.stopPropagation();
3025
+ ev.preventDefault();
3026
+ },
3027
+ children: [
3028
+ renderMenu(),
3029
+ children
3030
+ ]
3031
+ }
3032
+ );
3033
+ }
3034
+ const EDITOR_DICTIONARY = buildBlockConfigurationDictionary({
3035
+ Avatar: {
3036
+ schema: AvatarPropsSchema,
3037
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Avatar, { ...props }) })
3038
+ },
3039
+ Button: {
3040
+ schema: ButtonPropsSchema,
3041
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Button$1, { ...props }) })
3042
+ },
3043
+ Container: {
3044
+ schema: ContainerPropsSchema,
3045
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(ContainerEditor, { ...props }) })
3046
+ },
3047
+ ColumnsContainer: {
3048
+ schema: ColumnsContainerPropsSchema,
3049
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(ColumnsContainerEditor, { ...props }) })
3050
+ },
3051
+ Heading: {
3052
+ schema: HeadingPropsSchema,
3053
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Heading, { ...props }) })
3054
+ },
3055
+ Html: {
3056
+ schema: HtmlPropsSchema,
3057
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Html, { ...props }) })
3058
+ },
3059
+ Image: {
3060
+ schema: ImagePropsSchema,
3061
+ Component: (data) => {
3062
+ var _a;
3063
+ const props = {
3064
+ ...data,
3065
+ props: {
3066
+ ...data.props,
3067
+ url: ((_a = data.props) == null ? void 0 : _a.url) ?? "https://placehold.co/600x400@2x/F8F8F8/CCC?text=Your%20image"
3068
+ }
3069
+ };
3070
+ return /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Image, { ...props }) });
3071
+ }
3072
+ },
3073
+ Text: {
3074
+ schema: TextPropsSchema,
3075
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Text, { ...props }) })
3076
+ },
3077
+ EmailLayout: {
3078
+ schema: EmailLayoutPropsSchema,
3079
+ Component: (p) => /* @__PURE__ */ jsx(EmailLayoutEditor, { ...p })
3080
+ },
3081
+ Spacer: {
3082
+ schema: SpacerPropsSchema,
3083
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Spacer, { ...props }) })
3084
+ },
3085
+ Divider: {
3086
+ schema: DividerPropsSchema,
3087
+ Component: (props) => /* @__PURE__ */ jsx(EditorBlockWrapper, { children: /* @__PURE__ */ jsx(Divider$1, { ...props }) })
3088
+ }
3089
+ });
3090
+ const EditorBlock$1 = buildBlockComponent(EDITOR_DICTIONARY);
3091
+ const EditorBlockSchema = buildBlockConfigurationSchema(EDITOR_DICTIONARY);
3092
+ const EditorConfigurationSchema = z.record(z.string(), EditorBlockSchema);
3093
+ const EditorBlockContext = createContext(null);
3094
+ const useCurrentBlockId = () => useContext(EditorBlockContext);
3095
+ function EditorBlock({ id }) {
3096
+ const document = useDocument();
3097
+ const block = document[id];
3098
+ if (!block) {
3099
+ throw new Error("Could not find block");
3100
+ }
3101
+ return /* @__PURE__ */ jsx(EditorBlockContext.Provider, { value: id, children: /* @__PURE__ */ jsx(EditorBlock$1, { ...block }) });
3102
+ }
3103
+ function ToggleInspectorPanelButton() {
3104
+ const inspectorDrawerOpen = useInspectorDrawerOpen();
3105
+ const handleClick = () => {
3106
+ toggleInspectorDrawerOpen();
3107
+ };
3108
+ if (inspectorDrawerOpen) {
3109
+ return /* @__PURE__ */ jsx(IconButton, { onClick: handleClick, children: /* @__PURE__ */ jsx(LastPageOutlined, { fontSize: "small" }) });
3110
+ }
3111
+ return /* @__PURE__ */ jsx(IconButton, { onClick: handleClick, children: /* @__PURE__ */ jsx(AppRegistrationOutlined, { fontSize: "small" }) });
3112
+ }
3113
+ function useIcon() {
3114
+ const samplesDrawerOpen = useSamplesDrawerOpen();
3115
+ if (samplesDrawerOpen) {
3116
+ return /* @__PURE__ */ jsx(FirstPageOutlined, { fontSize: "small" });
3117
+ }
3118
+ return /* @__PURE__ */ jsx(MenuOutlined, { fontSize: "small" });
3119
+ }
3120
+ function ToggleSamplesPanelButton() {
3121
+ const icon = useIcon();
3122
+ return /* @__PURE__ */ jsx(IconButton, { onClick: toggleSamplesDrawerOpen, children: icon });
3123
+ }
3124
+ function DownloadJson() {
3125
+ const doc = useDocument();
3126
+ const href = useMemo(() => {
3127
+ return `data:text/plain,${encodeURIComponent(JSON.stringify(doc, null, " "))}`;
3128
+ }, [doc]);
3129
+ return /* @__PURE__ */ jsx(Tooltip, { title: "Download JSON file", children: /* @__PURE__ */ jsx(IconButton, { href, download: "emailTemplate.json", children: /* @__PURE__ */ jsx(FileDownloadOutlined, { fontSize: "small" }) }) });
3130
+ }
3131
+ let hljs;
3132
+ let jsonHighlighter;
3133
+ let xmlHighlighter;
3134
+ let prettierFormat;
3135
+ let prettierPluginBabel;
3136
+ let prettierPluginEstree;
3137
+ let prettierPluginHtml;
3138
+ async function loadHighlightJs() {
3139
+ if (!hljs) {
3140
+ hljs = await import("highlight.js");
3141
+ jsonHighlighter = await import("highlight.js/lib/languages/json");
3142
+ xmlHighlighter = await import("highlight.js/lib/languages/xml");
3143
+ hljs.default.registerLanguage("json", jsonHighlighter.default);
3144
+ hljs.default.registerLanguage("html", xmlHighlighter.default);
3145
+ }
3146
+ return hljs.default;
3147
+ }
3148
+ async function loadPrettier() {
3149
+ if (!prettierFormat) {
3150
+ const prettier = await import("prettier/standalone");
3151
+ prettierFormat = prettier.format;
3152
+ prettierPluginBabel = await import("prettier/plugins/babel");
3153
+ prettierPluginEstree = await import("prettier/plugins/estree");
3154
+ prettierPluginHtml = await import("prettier/plugins/html");
3155
+ }
3156
+ return prettierFormat;
3157
+ }
3158
+ async function html(value) {
3159
+ const [hljsInstance, format] = await Promise.all([loadHighlightJs(), loadPrettier()]);
3160
+ const prettyValue = await format(value, {
3161
+ parser: "html",
3162
+ plugins: [prettierPluginHtml.default]
3163
+ });
3164
+ return hljsInstance.highlight(prettyValue, { language: "html" }).value;
3165
+ }
3166
+ async function json(value) {
3167
+ const [hljsInstance, format] = await Promise.all([loadHighlightJs(), loadPrettier()]);
3168
+ const prettyValue = await format(value, {
3169
+ parser: "json",
3170
+ printWidth: 0,
3171
+ trailingComma: "all",
3172
+ plugins: [prettierPluginBabel.default, prettierPluginEstree.default]
3173
+ });
3174
+ return hljsInstance.highlight(prettyValue, { language: "javascript" }).value;
3175
+ }
3176
+ function HighlightedCodePanel({ type, value }) {
3177
+ const [code, setCode] = useState(null);
3178
+ useEffect(() => {
3179
+ switch (type) {
3180
+ case "html":
3181
+ html(value).then(setCode);
3182
+ return;
3183
+ case "json":
3184
+ json(value).then(setCode);
3185
+ return;
3186
+ }
3187
+ }, [setCode, value, type]);
3188
+ if (code === null) {
3189
+ return null;
3190
+ }
3191
+ return /* @__PURE__ */ jsx(
3192
+ "pre",
3193
+ {
3194
+ style: { margin: 0, padding: 16 },
3195
+ dangerouslySetInnerHTML: { __html: code },
3196
+ onClick: (ev) => {
3197
+ const s = window.getSelection();
3198
+ if (s === null) {
3199
+ return;
3200
+ }
3201
+ s.selectAllChildren(ev.currentTarget);
3202
+ }
3203
+ }
3204
+ );
3205
+ }
3206
+ function HtmlPanel() {
3207
+ const document = useDocument();
3208
+ const code = useMemo(() => renderToStaticMarkup(document, { rootBlockId: "root" }), [document]);
3209
+ return /* @__PURE__ */ jsx(HighlightedCodePanel, { type: "html", value: code });
3210
+ }
3211
+ function validateTextAreaValue(value) {
3212
+ let jsonObject = void 0;
3213
+ try {
3214
+ jsonObject = JSON.parse(value);
3215
+ } catch {
3216
+ return { error: "Invalid json" };
3217
+ }
3218
+ const parseResult = EditorConfigurationSchema.safeParse(jsonObject);
3219
+ if (!parseResult.success) {
3220
+ return { error: "Invalid JSON schema" };
3221
+ }
3222
+ if (!parseResult.data.root) {
3223
+ return { error: 'Missing "root" node' };
3224
+ }
3225
+ return { data: parseResult.data };
3226
+ }
3227
+ function ImportJsonDialog({ onClose }) {
3228
+ const [value, setValue] = useState("");
3229
+ const [error, setError] = useState(null);
3230
+ const handleChange = (ev) => {
3231
+ const v = ev.currentTarget.value;
3232
+ setValue(v);
3233
+ const { error: error2 } = validateTextAreaValue(v);
3234
+ setError(error2 ?? null);
3235
+ };
3236
+ let errorAlert = null;
3237
+ if (error) {
3238
+ errorAlert = /* @__PURE__ */ jsx(Alert, { color: "error", children: error });
3239
+ }
3240
+ return /* @__PURE__ */ jsxs(Dialog, { open: true, onClose, children: [
3241
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Import JSON" }),
3242
+ /* @__PURE__ */ jsxs(
3243
+ "form",
3244
+ {
3245
+ onSubmit: (ev) => {
3246
+ ev.preventDefault();
3247
+ const { error: error2, data } = validateTextAreaValue(value);
3248
+ setError(error2 ?? null);
3249
+ if (!data) {
3250
+ return;
3251
+ }
3252
+ resetDocument(data);
3253
+ onClose();
3254
+ },
3255
+ children: [
3256
+ /* @__PURE__ */ jsxs(DialogContent, { children: [
3257
+ /* @__PURE__ */ jsxs(Typography, { color: "text.secondary", paragraph: true, children: [
3258
+ "Copy and paste an EmailBuilder.js JSON (",
3259
+ /* @__PURE__ */ jsx(
3260
+ Link,
3261
+ {
3262
+ href: "https://gist.githubusercontent.com/jordanisip/efb61f56ba71bd36d3a9440122cb7f50/raw/30ea74a6ac7e52ebdc309bce07b71a9286ce2526/emailBuilderTemplate.json",
3263
+ target: "_blank",
3264
+ underline: "none",
3265
+ children: "example"
3266
+ }
3267
+ ),
3268
+ ")."
3269
+ ] }),
3270
+ errorAlert,
3271
+ /* @__PURE__ */ jsx(
3272
+ TextField,
3273
+ {
3274
+ error: error !== null,
3275
+ value,
3276
+ onChange: handleChange,
3277
+ type: "text",
3278
+ helperText: "This will override your current template.",
3279
+ variant: "outlined",
3280
+ fullWidth: true,
3281
+ rows: 10,
3282
+ multiline: true
3283
+ }
3284
+ )
3285
+ ] }),
3286
+ /* @__PURE__ */ jsxs(DialogActions, { children: [
3287
+ /* @__PURE__ */ jsx(Button, { type: "button", onClick: onClose, children: "Cancel" }),
3288
+ /* @__PURE__ */ jsx(Button, { variant: "contained", type: "submit", disabled: error !== null, children: "Import" })
3289
+ ] })
3290
+ ]
3291
+ }
3292
+ )
3293
+ ] });
3294
+ }
3295
+ function ImportJson() {
3296
+ const [open, setOpen] = useState(false);
3297
+ let dialog = null;
3298
+ if (open) {
3299
+ dialog = /* @__PURE__ */ jsx(ImportJsonDialog, { onClose: () => setOpen(false) });
3300
+ }
3301
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3302
+ /* @__PURE__ */ jsx(Tooltip, { title: "Import JSON", children: /* @__PURE__ */ jsx(IconButton, { onClick: () => setOpen(true), children: /* @__PURE__ */ jsx(FileUploadOutlined, { fontSize: "small" }) }) }),
3303
+ dialog
3304
+ ] });
3305
+ }
3306
+ function JsonPanel() {
3307
+ const document = useDocument();
3308
+ const code = useMemo(() => JSON.stringify(document, null, " "), [document]);
3309
+ return /* @__PURE__ */ jsx(HighlightedCodePanel, { type: "json", value: code });
3310
+ }
3311
+ function MainTabsGroup() {
3312
+ const { t: t2 } = useTranslation();
3313
+ const selectedMainTab = useSelectedMainTab();
3314
+ const handleChange = (_, v) => {
3315
+ switch (v) {
3316
+ case "json":
3317
+ case "preview":
3318
+ case "editor":
3319
+ case "html":
3320
+ setSelectedMainTab(v);
3321
+ return;
3322
+ default:
3323
+ setSelectedMainTab("editor");
3324
+ }
3325
+ };
3326
+ return /* @__PURE__ */ jsxs(Tabs, { value: selectedMainTab, onChange: handleChange, children: [
3327
+ /* @__PURE__ */ jsx(
3328
+ Tab,
3329
+ {
3330
+ value: "editor",
3331
+ label: /* @__PURE__ */ jsx(Tooltip, { title: t2("tabs.edit"), children: /* @__PURE__ */ jsx(EditOutlined, { fontSize: "small" }) })
3332
+ }
3333
+ ),
3334
+ /* @__PURE__ */ jsx(
3335
+ Tab,
3336
+ {
3337
+ value: "preview",
3338
+ label: /* @__PURE__ */ jsx(Tooltip, { title: t2("tabs.preview"), children: /* @__PURE__ */ jsx(PreviewOutlined, { fontSize: "small" }) })
3339
+ }
3340
+ ),
3341
+ /* @__PURE__ */ jsx(
3342
+ Tab,
3343
+ {
3344
+ value: "html",
3345
+ label: /* @__PURE__ */ jsx(Tooltip, { title: t2("tabs.htmlOutput"), children: /* @__PURE__ */ jsx(CodeOutlined, { fontSize: "small" }) })
3346
+ }
3347
+ ),
3348
+ /* @__PURE__ */ jsx(
3349
+ Tab,
3350
+ {
3351
+ value: "json",
3352
+ label: /* @__PURE__ */ jsx(Tooltip, { title: t2("tabs.jsonOutput"), children: /* @__PURE__ */ jsx(DataObjectOutlined, { fontSize: "small" }) })
3353
+ }
3354
+ )
3355
+ ] });
3356
+ }
3357
+ function ShareButton() {
3358
+ const document = useDocument();
3359
+ const [message, setMessage] = useState(null);
3360
+ const onClick = async () => {
3361
+ const c = encodeURIComponent(JSON.stringify(document));
3362
+ location.hash = `#code/${btoa(c)}`;
3363
+ setMessage("The URL was updated. Copy it to share your current template.");
3364
+ };
3365
+ const onClose = () => {
3366
+ setMessage(null);
3367
+ };
3368
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3369
+ /* @__PURE__ */ jsx(IconButton, { onClick, children: /* @__PURE__ */ jsx(Tooltip, { title: "Share current template", children: /* @__PURE__ */ jsx(IosShareOutlined, { fontSize: "small" }) }) }),
3370
+ /* @__PURE__ */ jsx(
3371
+ Snackbar,
3372
+ {
3373
+ anchorOrigin: { vertical: "top", horizontal: "center" },
3374
+ open: message !== null,
3375
+ onClose,
3376
+ message
3377
+ }
3378
+ )
3379
+ ] });
3380
+ }
3381
+ function TemplatePanel() {
3382
+ const document = useDocument();
3383
+ const selectedMainTab = useSelectedMainTab();
3384
+ const selectedScreenSize = useSelectedScreenSize();
3385
+ let mainBoxSx = {
3386
+ height: "100%"
3387
+ };
3388
+ if (selectedScreenSize === "mobile") {
3389
+ mainBoxSx = {
3390
+ ...mainBoxSx,
3391
+ margin: "32px auto",
3392
+ width: 370,
3393
+ height: 800,
3394
+ boxShadow: "rgba(33, 36, 67, 0.04) 0px 10px 20px, rgba(33, 36, 67, 0.04) 0px 2px 6px, rgba(33, 36, 67, 0.04) 0px 0px 1px"
3395
+ };
3396
+ }
3397
+ const handleScreenSizeChange = (_, value) => {
3398
+ switch (value) {
3399
+ case "mobile":
3400
+ case "desktop":
3401
+ setSelectedScreenSize(value);
3402
+ return;
3403
+ default:
3404
+ setSelectedScreenSize("desktop");
3405
+ }
3406
+ };
3407
+ const renderMainPanel = () => {
3408
+ switch (selectedMainTab) {
3409
+ case "editor":
3410
+ return /* @__PURE__ */ jsx(Box, { sx: mainBoxSx, children: /* @__PURE__ */ jsx(EditorBlock, { id: "root" }) });
3411
+ case "preview":
3412
+ return /* @__PURE__ */ jsx(Box, { sx: mainBoxSx, children: /* @__PURE__ */ jsx(Reader, { document, rootBlockId: "root" }) });
3413
+ case "html":
3414
+ return /* @__PURE__ */ jsx(HtmlPanel, {});
3415
+ case "json":
3416
+ return /* @__PURE__ */ jsx(JsonPanel, {});
3417
+ }
3418
+ };
3419
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3420
+ /* @__PURE__ */ jsxs(
3421
+ Stack,
3422
+ {
3423
+ sx: {
3424
+ height: 49,
3425
+ borderBottom: 1,
3426
+ borderColor: "divider",
3427
+ backgroundColor: "white",
3428
+ position: "sticky",
3429
+ top: 0,
3430
+ zIndex: "appBar",
3431
+ px: 1
3432
+ },
3433
+ direction: "row",
3434
+ justifyContent: "space-between",
3435
+ alignItems: "center",
3436
+ children: [
3437
+ /* @__PURE__ */ jsx(ToggleSamplesPanelButton, {}),
3438
+ /* @__PURE__ */ jsxs(Stack, { px: 2, direction: "row", gap: 2, width: "100%", justifyContent: "space-between", alignItems: "center", children: [
3439
+ /* @__PURE__ */ jsx(Stack, { direction: "row", spacing: 2, children: /* @__PURE__ */ jsx(MainTabsGroup, {}) }),
3440
+ /* @__PURE__ */ jsxs(Stack, { direction: "row", spacing: 2, children: [
3441
+ /* @__PURE__ */ jsx(DownloadJson, {}),
3442
+ /* @__PURE__ */ jsx(ImportJson, {}),
3443
+ /* @__PURE__ */ jsxs(ToggleButtonGroup, { value: selectedScreenSize, exclusive: true, size: "small", onChange: handleScreenSizeChange, children: [
3444
+ /* @__PURE__ */ jsx(ToggleButton, { value: "desktop", children: /* @__PURE__ */ jsx(Tooltip, { title: "Desktop view", children: /* @__PURE__ */ jsx(MonitorOutlined, { fontSize: "small" }) }) }),
3445
+ /* @__PURE__ */ jsx(ToggleButton, { value: "mobile", children: /* @__PURE__ */ jsx(Tooltip, { title: "Mobile view", children: /* @__PURE__ */ jsx(PhoneIphoneOutlined, { fontSize: "small" }) }) })
3446
+ ] }),
3447
+ /* @__PURE__ */ jsx(ShareButton, {})
3448
+ ] })
3449
+ ] }),
3450
+ /* @__PURE__ */ jsx(ToggleInspectorPanelButton, {})
3451
+ ]
3452
+ }
3453
+ ),
3454
+ /* @__PURE__ */ jsx(Box, { sx: { height: "calc(100vh - 49px)", overflow: "auto", minWidth: 370 }, children: renderMainPanel() })
3455
+ ] });
3456
+ }
3457
+ function useDrawerTransition(cssProperty, open) {
3458
+ const { transitions } = useTheme();
3459
+ return transitions.create(cssProperty, {
3460
+ easing: !open ? transitions.easing.sharp : transitions.easing.easeOut,
3461
+ duration: !open ? transitions.duration.leavingScreen : transitions.duration.enteringScreen
3462
+ });
3463
+ }
3464
+ function App() {
3465
+ const inspectorDrawerOpen = useInspectorDrawerOpen();
3466
+ const samplesDrawerOpen = useSamplesDrawerOpen();
3467
+ const marginLeftTransition = useDrawerTransition("margin-left", samplesDrawerOpen);
3468
+ const marginRightTransition = useDrawerTransition("margin-right", inspectorDrawerOpen);
3469
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3470
+ /* @__PURE__ */ jsx(InspectorDrawer, {}),
3471
+ /* @__PURE__ */ jsx(SamplesDrawer, {}),
3472
+ /* @__PURE__ */ jsxs(
3473
+ Stack,
3474
+ {
3475
+ sx: {
3476
+ marginRight: inspectorDrawerOpen ? `${INSPECTOR_DRAWER_WIDTH}px` : 0,
3477
+ marginLeft: samplesDrawerOpen ? `${SAMPLES_DRAWER_WIDTH}px` : 0,
3478
+ transition: `${marginLeftTransition}, ${marginRightTransition}`
3479
+ },
3480
+ children: [
3481
+ /* @__PURE__ */ jsx(Box, { sx: { position: "absolute", top: 8, right: 8, zIndex: 1e3 }, children: /* @__PURE__ */ jsx(LanguageSwitcher, {}) }),
3482
+ /* @__PURE__ */ jsx(TemplatePanel, {})
3483
+ ]
3484
+ }
3485
+ )
3486
+ ] });
3487
+ }
3488
+ function EmailBuilder({
3489
+ initialDocument,
3490
+ initialLanguage = "en",
3491
+ imageUploadHandler,
3492
+ onChange,
3493
+ theme: customTheme
3494
+ }) {
3495
+ const currentLanguage = useLanguage();
3496
+ useEffect(() => {
3497
+ if (initialDocument) {
3498
+ resetDocument(initialDocument);
3499
+ }
3500
+ if (initialLanguage) {
3501
+ setLanguage(initialLanguage);
3502
+ }
3503
+ if (imageUploadHandler) {
3504
+ setImageUploadHandler(imageUploadHandler);
3505
+ }
3506
+ if (onChange) {
3507
+ setOnChange(onChange);
3508
+ }
3509
+ }, []);
3510
+ useEffect(() => {
3511
+ if (initialLanguage && initialLanguage !== currentLanguage) {
3512
+ setLanguage(initialLanguage);
3513
+ }
3514
+ }, [initialLanguage, currentLanguage]);
3515
+ useEffect(() => {
3516
+ if (imageUploadHandler) {
3517
+ setImageUploadHandler(imageUploadHandler);
3518
+ }
3519
+ }, [imageUploadHandler]);
3520
+ useEffect(() => {
3521
+ if (onChange) {
3522
+ setOnChange(onChange);
3523
+ }
3524
+ }, [onChange]);
3525
+ return /* @__PURE__ */ jsxs(ThemeProvider, { theme: customTheme || THEME, children: [
3526
+ /* @__PURE__ */ jsx(CssBaseline, {}),
3527
+ /* @__PURE__ */ jsx(App, {})
3528
+ ] });
3529
+ }
3530
+ export {
3531
+ EmailBuilder,
3532
+ useDocument,
3533
+ useLanguage
3534
+ };