@kgalexander/mcreate 1.0.9 → 1.0.11

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.
@@ -142,6 +142,57 @@ var SOCIAL_OPTIONS = [
142
142
  }
143
143
  ];
144
144
 
145
+ // src/core/editor/constant/fonts.ts
146
+ var emailSafeFonts = [
147
+ { name: "Arial", value: "arial" },
148
+ { name: "Helvetica", value: "helvetica" },
149
+ { name: "Times New Roman", value: "times-new-roman" },
150
+ { name: "Tahoma", value: "tahoma" },
151
+ { name: "Trebuchet MS", value: "trebuchet-ms" },
152
+ { name: "Lucida Console", value: "lucida-console" },
153
+ { name: "Courier New", value: "courier-new" },
154
+ { name: "Georgia", value: "georgia" },
155
+ { name: "Verdana", value: "verdana" }
156
+ ];
157
+ var OtherFonts = [
158
+ { name: "Abril Fatface", value: "abril-fatface-regular", url: "https://fonts.googleapis.com/css?family=Abril+Fatface" },
159
+ { name: "Alegreya", value: "alegreya", url: "https://fonts.googleapis.com/css?family=Alegreya" },
160
+ { name: "Alegreya Sans", value: "alegreya-sans", url: "https://fonts.googleapis.com/css?family=Alegreya+Sans" },
161
+ { name: "Anton", value: "anton", url: "https://fonts.googleapis.com/css?family=Anton" },
162
+ { name: "Arimo", value: "arimo", url: "https://fonts.googleapis.com/css?family=Arimo" },
163
+ { name: "Arvo", value: "arvo", url: "https://fonts.googleapis.com/css?family=Arvo" },
164
+ { name: "Catamaran", value: "catamaran", url: "https://fonts.googleapis.com/css?family=Catamaran" },
165
+ { name: "Comic Neue", value: "comic-neue", url: "https://fonts.googleapis.com/css?family=Comic+Neue" },
166
+ { name: "Della Respira", value: "della-respira", url: "https://fonts.googleapis.com/css2?family=Della+Respira&display=swap" },
167
+ { name: "DM Sans", value: "dm-sans", url: "https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&display=swap" },
168
+ { name: "Gilda Display", value: "gilda-display", url: "https://fonts.googleapis.com/css2?family=Gilda+Display&display=swap" },
169
+ { name: "Lato", value: "lato", url: "https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap" },
170
+ { name: "Lora", value: "lora", url: "https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&display=swap" },
171
+ { name: "Marcellus", value: "marcellus", url: "https://fonts.googleapis.com/css2?family=Marcellus&display=swap" },
172
+ { name: "Merriweather", value: "merriweather", url: "https://fonts.googleapis.com/css2?family=Merriweather:wght@300;400;700&display=swap" },
173
+ { name: "Merriweather Sans", value: "merriweather-sans", url: "https://fonts.googleapis.com/css2?family=Merriweather+Sans:wght@300;400;500;600;700&display=swap" },
174
+ { name: "Nanum Gothic Coding", value: "nanum-gothic-coding", url: "https://fonts.googleapis.com/css2?family=Nanum+Gothic+Coding:wght@400;700&display=swap" },
175
+ { name: "Neuton", value: "neuton", url: "https://fonts.googleapis.com/css2?family=Neuton:wght@300;400;700&display=swap" },
176
+ { name: "Noticia Text", value: "noticia-text", url: "https://fonts.googleapis.com/css2?family=Noticia+Text:wght@400;700&display=swap" },
177
+ { name: "Noto Sans", value: "noto-sans", url: "https://fonts.googleapis.com/css2?family=Noto+Sans:wght@300;400;500;600;700&display=swap" },
178
+ { name: "Open Sans", value: "open-sans", url: "https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&display=swap" },
179
+ { name: "Playfair Display", value: "playfair-display", url: "https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500;600;700&display=swap" },
180
+ { name: "Raleway", value: "raleway", url: "https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;500;600;700&display=swap" },
181
+ { name: "Recursive", value: "recursive", url: "https://fonts.googleapis.com/css2?family=Recursive:wght@300;400;500;600;700&display=swap" },
182
+ { name: "Roboto", value: "roboto", url: "https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" },
183
+ { name: "Source Sans 3", value: "source-sans-3", url: "https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@300;400;500;600;700&display=swap" },
184
+ { name: "Source Code Pro", value: "source-code-pro", url: "https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@300;400;500;600;700&display=swap" },
185
+ { name: "Space Mono", value: "space-mono", url: "https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap" },
186
+ { name: "Syncopate", value: "syncopate", url: "https://fonts.googleapis.com/css2?family=Syncopate:wght@400;700&display=swap" },
187
+ { name: "Work Sans", value: "work-sans", url: "https://fonts.googleapis.com/css2?family=Work+Sans:wght@300;400;500;600;700&display=swap" }
188
+ ];
189
+ function getGoogleFont(fontName) {
190
+ return OtherFonts.find((f) => f.name.toLowerCase() === fontName.toLowerCase());
191
+ }
192
+ function getGoogleFontUrl(fontName) {
193
+ return getGoogleFont(fontName)?.url;
194
+ }
195
+
145
196
  // src/core/editor/utils/border.ts
146
197
  var DEFAULT_BORDER = {
147
198
  width: 0,
@@ -222,16 +273,6 @@ var ALIGNMENT_ICONS = {
222
273
  center: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-center.svg",
223
274
  right: "https://mzyngaqmbvhpgmmipndy.supabase.co/storage/v1/object/public/Maillow/icons/align-vertical-space-around-right.svg"
224
275
  };
225
- var FONTS = [
226
- "Arial",
227
- "Helvetica",
228
- "Times New Roman",
229
- "Courier New",
230
- "Verdana",
231
- "Tahoma",
232
- "Trebuchet MS",
233
- "Georgia"
234
- ];
235
276
  var TEXT_ALIGNMENT_ICONS = {
236
277
  left: AlignLeftIcon,
237
278
  center: AlignCenterIcon,
@@ -1120,6 +1161,35 @@ function rootChildrenToMjml(children, parentContext) {
1120
1161
  return "";
1121
1162
  }).join("\n");
1122
1163
  }
1164
+ function collectUsedGoogleFonts(template) {
1165
+ const fontNames = /* @__PURE__ */ new Set();
1166
+ const googleFontNames = new Set(OtherFonts.map((f) => f.name.toLowerCase()));
1167
+ function extractFromFontFamily(fontFamily) {
1168
+ if (!fontFamily) return;
1169
+ const fonts = fontFamily.split(",").map((f) => f.trim().replace(/['"]/g, ""));
1170
+ for (const f of fonts) {
1171
+ if (googleFontNames.has(f.toLowerCase())) {
1172
+ const original = OtherFonts.find((of) => of.name.toLowerCase() === f.toLowerCase());
1173
+ if (original) fontNames.add(original.name);
1174
+ }
1175
+ }
1176
+ }
1177
+ function scanElement(el) {
1178
+ if (!el) return;
1179
+ extractFromFontFamily(el.attributes?.["font-family"]);
1180
+ const content = el.data?.value?.content;
1181
+ if (typeof content === "string") {
1182
+ const matches = content.matchAll(/font-family:\s*([^;"]+)/gi);
1183
+ for (const m of matches) extractFromFontFamily(m[1]);
1184
+ }
1185
+ if (Array.isArray(el.children)) el.children.forEach(scanElement);
1186
+ }
1187
+ template.content.forEach(scanElement);
1188
+ return [...fontNames].map((name) => {
1189
+ const url = getGoogleFontUrl(name);
1190
+ return url ? { name, url } : null;
1191
+ }).filter((f) => f !== null);
1192
+ }
1123
1193
  function json2mjml(template, mode = "production", options = {}) {
1124
1194
  const showCompanyFooter = template.content[0]?.data?.value?.showCompanyFooter ?? true;
1125
1195
  const footerMutation = needsCompanyFooterMutation(template);
@@ -1165,12 +1235,15 @@ function json2mjml(template, mode = "production", options = {}) {
1165
1235
  allContent += pageContent;
1166
1236
  }
1167
1237
  const linkColor = template.content[0]?.data?.value?.linkColor || "#0000ff";
1238
+ const usedGoogleFonts = collectUsedGoogleFonts(template);
1239
+ const mjFontTags = usedGoogleFonts.map((f) => `<mj-font name="${f.name}" href="${f.url}" />`).join("\n ");
1168
1240
  return `
1169
1241
  <mjml>
1170
1242
 
1171
1243
  <mj-head>
1172
1244
 
1173
1245
  <mj-breakpoint width="480px" />
1246
+ ${mjFontTags}
1174
1247
 
1175
1248
  <mj-style>
1176
1249
  p { margin: 0px 0px 0px 0px !important; }
@@ -3527,6 +3600,26 @@ var ShadowDomRenderer = memo(function ShadowDomRenderer2({
3527
3600
  shadowRootRef.current.appendChild(styleEl);
3528
3601
  shadowRootRef.current.appendChild(contentWrapper);
3529
3602
  }, [html]);
3603
+ useEffect(() => {
3604
+ const templateState = useEditorStore.getState().template;
3605
+ if (!templateState) return;
3606
+ const htmlStr = html + JSON.stringify(templateState);
3607
+ const neededUrls = /* @__PURE__ */ new Set();
3608
+ for (const font of OtherFonts) {
3609
+ if (font.url && htmlStr.includes(font.name)) {
3610
+ neededUrls.add(font.url);
3611
+ }
3612
+ }
3613
+ for (const url of neededUrls) {
3614
+ if (!document.querySelector(`link[data-google-font][href="${url}"]`)) {
3615
+ const link = document.createElement("link");
3616
+ link.rel = "stylesheet";
3617
+ link.href = url;
3618
+ link.setAttribute("data-google-font", "true");
3619
+ document.head.appendChild(link);
3620
+ }
3621
+ }
3622
+ }, [html]);
3530
3623
  useEffect(() => {
3531
3624
  if (!shadowRootRef.current) return;
3532
3625
  const styleEl = shadowRootRef.current.querySelector("#editor-styles");
@@ -12942,13 +13035,14 @@ import { MoreHorizontalIcon as MoreHorizontalIcon3, PlusCircleIcon } from "lucid
12942
13035
  import { createContext, useContext, useState as useState5 } from "react";
12943
13036
  import { jsx as jsx31 } from "react/jsx-runtime";
12944
13037
  var SidebarContext = createContext(null);
12945
- var PICKER_VIEWS = ["color", "images", "add-social"];
13038
+ var PICKER_VIEWS = ["color", "images", "add-social", "fonts"];
12946
13039
  function SidebarProvider({ children }) {
12947
13040
  const [activeView, setActiveViewState] = useState5("elements");
12948
13041
  const [lastView, setLastView] = useState5("elements");
12949
13042
  const [colorType, setColorType] = useState5("Color");
12950
13043
  const [colorTarget, setColorTarget] = useState5(null);
12951
13044
  const [imageTarget, setImageTarget] = useState5(null);
13045
+ const [fontTarget, setFontTarget] = useState5(null);
12952
13046
  const setActiveView = (view) => {
12953
13047
  if (view !== activeView) {
12954
13048
  if (!PICKER_VIEWS.includes(activeView)) {
@@ -12957,7 +13051,7 @@ function SidebarProvider({ children }) {
12957
13051
  }
12958
13052
  setActiveViewState(view);
12959
13053
  };
12960
- return /* @__PURE__ */ jsx31(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget }, children });
13054
+ return /* @__PURE__ */ jsx31(SidebarContext.Provider, { value: { activeView, setActiveView, lastView, colorType, setColorType, colorTarget, setColorTarget, imageTarget, setImageTarget, fontTarget, setFontTarget }, children });
12961
13055
  }
12962
13056
  function useSidebarContext() {
12963
13057
  const context = useContext(SidebarContext);
@@ -16036,13 +16130,14 @@ export {
16036
16130
  getParentByIdx,
16037
16131
  SOCIAL_ITEMS,
16038
16132
  SOCIAL_OPTIONS,
16133
+ emailSafeFonts,
16134
+ OtherFonts,
16039
16135
  parseBorder,
16040
16136
  formatBorder,
16041
16137
  parsePrice,
16042
16138
  MAX_TEMPLATE_SIZE,
16043
16139
  BUTTON_ALIGNMENTS,
16044
16140
  ALIGNMENT_ICONS,
16045
- FONTS,
16046
16141
  TEXT_ALIGNMENT_ICONS,
16047
16142
  TEXT_TYPE_OPTIONS,
16048
16143
  DEFAULT_FONT_SIZE,
@@ -5,7 +5,7 @@ import {
5
5
  MAILLOW_EMAIL_EDITOR_VERSION,
6
6
  Preview,
7
7
  useEditorStore
8
- } from "./chunk-R3LRNUKL.mjs";
8
+ } from "./chunk-CLU5KQRY.mjs";
9
9
  export {
10
10
  Editor,
11
11
  History,
package/dist/index.d.mts CHANGED
@@ -320,6 +320,14 @@ declare function TemplatePage({ templateId, initialTemplate, onSave, onToast, on
320
320
 
321
321
  declare const MAX_TEMPLATE_SIZE: number;
322
322
 
323
+ type FontEntry = {
324
+ name: string;
325
+ value: string;
326
+ url?: string;
327
+ };
328
+ declare const emailSafeFonts: FontEntry[];
329
+ declare const OtherFonts: FontEntry[];
330
+
323
331
  interface MergeFieldType {
324
332
  label: string;
325
333
  value: string;
@@ -370,4 +378,4 @@ interface RenderOptions {
370
378
  */
371
379
  declare function json2mjml(template: TemplateJSON, mode?: RenderMode, options?: RenderOptions): string;
372
380
 
373
- export { Editor, type ImageData, MAX_TEMPLATE_SIZE, type MergeField, type MergeFieldType, type MissingLinkType, type OnDeleteCallback, type OnDuplicateCallback, type OnExitCallback, type OnImageUploadCallback, type OnSaveCallback, type OnToastCallback, type PaidLevel, type PreviewValidationType, type TemplateJSON, TemplatePage, type ToastOptions, type ToastType, campaign_validation_warnings, json2mjml, validate_campaign_onCreate, validate_editor_onPreview };
381
+ export { Editor, type ImageData, MAX_TEMPLATE_SIZE, type MergeField, type MergeFieldType, type MissingLinkType, type OnDeleteCallback, type OnDuplicateCallback, type OnExitCallback, type OnImageUploadCallback, type OnSaveCallback, type OnToastCallback, OtherFonts, type PaidLevel, type PreviewValidationType, type TemplateJSON, TemplatePage, type ToastOptions, type ToastType, campaign_validation_warnings, emailSafeFonts, json2mjml, validate_campaign_onCreate, validate_editor_onPreview };
package/dist/index.d.ts CHANGED
@@ -320,6 +320,14 @@ declare function TemplatePage({ templateId, initialTemplate, onSave, onToast, on
320
320
 
321
321
  declare const MAX_TEMPLATE_SIZE: number;
322
322
 
323
+ type FontEntry = {
324
+ name: string;
325
+ value: string;
326
+ url?: string;
327
+ };
328
+ declare const emailSafeFonts: FontEntry[];
329
+ declare const OtherFonts: FontEntry[];
330
+
323
331
  interface MergeFieldType {
324
332
  label: string;
325
333
  value: string;
@@ -370,4 +378,4 @@ interface RenderOptions {
370
378
  */
371
379
  declare function json2mjml(template: TemplateJSON, mode?: RenderMode, options?: RenderOptions): string;
372
380
 
373
- export { Editor, type ImageData, MAX_TEMPLATE_SIZE, type MergeField, type MergeFieldType, type MissingLinkType, type OnDeleteCallback, type OnDuplicateCallback, type OnExitCallback, type OnImageUploadCallback, type OnSaveCallback, type OnToastCallback, type PaidLevel, type PreviewValidationType, type TemplateJSON, TemplatePage, type ToastOptions, type ToastType, campaign_validation_warnings, json2mjml, validate_campaign_onCreate, validate_editor_onPreview };
381
+ export { Editor, type ImageData, MAX_TEMPLATE_SIZE, type MergeField, type MergeFieldType, type MissingLinkType, type OnDeleteCallback, type OnDuplicateCallback, type OnExitCallback, type OnImageUploadCallback, type OnSaveCallback, type OnToastCallback, OtherFonts, type PaidLevel, type PreviewValidationType, type TemplateJSON, TemplatePage, type ToastOptions, type ToastType, campaign_validation_warnings, emailSafeFonts, json2mjml, validate_campaign_onCreate, validate_editor_onPreview };