mail-editor-pancake 0.2.7 → 0.3.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 (60) hide show
  1. package/README.md +37 -4
  2. package/package.json +1 -1
  3. package/packages/blocks/dist/index.js +275 -263
  4. package/packages/blocks/dist/index.js.map +1 -1
  5. package/packages/blocks/package.json +1 -3
  6. package/packages/blocks/src/button.ts +1 -1
  7. package/packages/blocks/src/hero.ts +6 -3
  8. package/packages/blocks/src/i18n.ts +10 -11
  9. package/packages/blocks/src/image.ts +2 -1
  10. package/packages/blocks/src/index.ts +5 -3
  11. package/packages/blocks/src/social.ts +3 -3
  12. package/packages/blocks/src/socialGroup.ts +4 -4
  13. package/packages/blocks/src/socialShared.ts +23 -3
  14. package/packages/blocks/src/text.ts +8 -4
  15. package/packages/blocks/vite.config.ts +1 -1
  16. package/packages/core/dist/index.d.ts +96 -1
  17. package/packages/core/dist/index.js +4349 -3594
  18. package/packages/core/dist/index.js.map +1 -1
  19. package/packages/core/dist/style.css +1 -1
  20. package/packages/core/package.json +1 -3
  21. package/packages/core/src/editor/BlockCodeModal.ts +6 -7
  22. package/packages/core/src/editor/Canvas.ts +559 -21
  23. package/packages/core/src/editor/ColorPickerPopover.ts +2 -2
  24. package/packages/core/src/editor/Editor.ts +381 -41
  25. package/packages/core/src/editor/ExportModal.ts +7 -9
  26. package/packages/core/src/editor/FocusBreadcrumb.ts +3 -3
  27. package/packages/core/src/editor/ImportDocModal.ts +50 -7
  28. package/packages/core/src/editor/InlineEditor.ts +43 -39
  29. package/packages/core/src/editor/LeftPanel.ts +2 -4
  30. package/packages/core/src/editor/Modal.ts +1 -1
  31. package/packages/core/src/editor/PreviewModal.ts +3 -8
  32. package/packages/core/src/editor/RichTextToolbar.ts +26 -15
  33. package/packages/core/src/editor/RightPanel.ts +142 -126
  34. package/packages/core/src/editor/SourceView.ts +5 -3
  35. package/packages/core/src/editor/Topbar.ts +79 -34
  36. package/packages/core/src/editor/VariablePickerPanel.ts +3 -5
  37. package/packages/core/src/editor/imageAssets.ts +1 -1
  38. package/packages/core/src/editor/styles.css +258 -86
  39. package/packages/core/src/i18n/index.ts +139 -41
  40. package/packages/core/src/index.ts +11 -1
  41. package/packages/core/src/renderer/index.ts +3 -6
  42. package/packages/core/src/renderer/mjml.ts +5 -10
  43. package/packages/core/src/store/store.ts +2 -6
  44. package/packages/core/src/types.ts +3 -3
  45. package/packages/core/src/utils/accentColor.ts +3 -3
  46. package/packages/core/src/utils/docClipboard.ts +107 -2
  47. package/packages/core/src/utils/dynamicVariantHtml.ts +1 -1
  48. package/packages/core/src/utils/emailListStyles.ts +1 -1
  49. package/packages/core/src/utils/fontWeightSteps.ts +7 -6
  50. package/packages/core/src/utils/html.ts +3 -2
  51. package/packages/core/src/utils/inlineListEditing.ts +19 -35
  52. package/packages/core/src/utils/link.ts +3 -6
  53. package/packages/core/src/utils/lockedMjml.ts +2 -2
  54. package/packages/core/src/utils/modalSize.ts +4 -3
  55. package/packages/core/src/utils/richHtmlEmpty.ts +3 -1
  56. package/packages/core/src/variables/index.ts +4 -5
  57. package/packages/core/vite.config.ts +1 -1
  58. package/playground/vanilla/index.html +17 -0
  59. package/playground/vanilla/src/main.ts +152 -123
  60. package/playground/vanilla/vite.config.ts +5 -2
@@ -284,7 +284,179 @@ const b = {
284
284
  const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, o = Q(e.html) ? '<div class="sm-html-mjml-warn">检测到 MJML 标签,此处应只写 HTML,预览可能显示异常。</div>' : "";
285
285
  return `<div class="sm-html-content" style="padding:${t};min-height:1em;">${o}${e.html}</div>`;
286
286
  }
287
- }), w = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), se = h({
287
+ }), se = {
288
+ align: "blocks.field.align",
289
+ textAlign: "blocks.field.textAlign",
290
+ verticalAlign: "blocks.field.verticalAlign",
291
+ color: "blocks.field.color",
292
+ textColor: "blocks.field.textColor",
293
+ backgroundColor: "blocks.field.backgroundColor",
294
+ backgroundUrl: "blocks.field.backgroundUrl",
295
+ height: "blocks.field.heightPx",
296
+ width: "blocks.field.width",
297
+ thickness: "blocks.field.thicknessPx",
298
+ paddingTop: "blocks.field.padding",
299
+ text: "blocks.field.text",
300
+ href: "blocks.field.link",
301
+ src: "blocks.field.imageUrl",
302
+ alt: "blocks.field.alt",
303
+ fontSize: "blocks.field.fontSize",
304
+ fontFamily: "blocks.field.fontFamily",
305
+ fontWeight: "blocks.field.fontWeight",
306
+ lineHeight: "blocks.field.lineHeight",
307
+ html: "blocks.field.html",
308
+ borderRadius: "blocks.field.borderRadius",
309
+ innerPaddingV: "blocks.field.buttonInnerPaddingV",
310
+ innerPaddingH: "blocks.field.buttonInnerPaddingH",
311
+ elements: "blocks.field.socialLinks",
312
+ labelFontSize: "blocks.field.labelFontSize",
313
+ labelFontWeight: "blocks.field.labelFontWeight",
314
+ labelColor: "blocks.field.labelColor",
315
+ iconSize: "blocks.field.iconSize",
316
+ iconBorderRadius: "blocks.field.iconRadius",
317
+ iconSpacing: "blocks.field.iconSpacing",
318
+ companyName: "blocks.field.companyName",
319
+ address: "blocks.field.address",
320
+ unsubscribeText: "blocks.field.unsubscribeText",
321
+ unsubscribeHref: "blocks.field.unsubscribeLink"
322
+ }, de = {
323
+ button: {
324
+ backgroundColor: "blocks.field.backgroundColor",
325
+ color: "blocks.field.textColor",
326
+ width: "blocks.field.width"
327
+ },
328
+ divider: {
329
+ width: "blocks.field.widthPercentOrPx",
330
+ paddingTop: "blocks.field.topMargin",
331
+ paddingBottom: "blocks.field.bottomMargin"
332
+ },
333
+ hero: {
334
+ backgroundColor: "blocks.field.backgroundPlaceholderColor",
335
+ height: "blocks.field.areaHeightPx",
336
+ content: "blocks.field.bodyHtml"
337
+ },
338
+ html: {
339
+ paddingTop: "blocks.field.padding"
340
+ },
341
+ image: {
342
+ href: "blocks.field.href",
343
+ width: "blocks.field.widthPx"
344
+ },
345
+ logo: {
346
+ src: "blocks.field.logoImage",
347
+ href: "blocks.field.websiteLink",
348
+ width: "blocks.field.widthPx"
349
+ },
350
+ text: {
351
+ content: "blocks.field.contentHtml"
352
+ }
353
+ }, N = {
354
+ button: { width: "blocks.help.buttonWidth" },
355
+ hero: {
356
+ backgroundColor: "blocks.help.imageFallbackColor",
357
+ content: "blocks.help.canvasEditRecommendedShort"
358
+ },
359
+ html: { html: "blocks.help.htmlOnly" },
360
+ image: { height: "blocks.help.imageAutoHeight" },
361
+ "social-group": {
362
+ elements: "blocks.help.socialLinks",
363
+ iconBorderRadius: "blocks.help.iconRadius",
364
+ iconSpacing: "blocks.help.iconSpacing"
365
+ },
366
+ social: {
367
+ elements: "blocks.help.bizSocialLinks",
368
+ iconBorderRadius: "blocks.help.iconRadius",
369
+ iconSpacing: "blocks.help.bizIconSpacing"
370
+ },
371
+ text: {
372
+ content: "blocks.help.canvasEditRecommended",
373
+ lineHeight: "blocks.help.globalLineHeight"
374
+ }
375
+ }, I = {
376
+ button: { width: "blocks.placeholder.buttonWidth" },
377
+ image: { alt: "blocks.field.imageDescription" },
378
+ text: {
379
+ color: "blocks.field.inheritGlobalPlaceholder",
380
+ fontFamily: "blocks.field.inheritGlobalPlaceholder"
381
+ }
382
+ }, ge = {
383
+ button: "blocks.field.buttonTextPlaceholder",
384
+ hero: "blocks.field.heroPlaceholder",
385
+ html: "blocks.field.htmlPlaceholder",
386
+ text: "blocks.field.textPlaceholder"
387
+ }, pe = {
388
+ button: { text: "blocks.button.defaultText" },
389
+ hero: { content: "blocks.hero.defaultContent" },
390
+ html: { html: "blocks.html.defaultHtml" },
391
+ text: { content: "blocks.text.defaultContent" },
392
+ footer: {
393
+ companyName: "blocks.footer.defaultCompanyName",
394
+ address: "blocks.footer.defaultAddress",
395
+ unsubscribeText: "blocks.footer.defaultUnsubscribeText"
396
+ }
397
+ };
398
+ function S(e, t) {
399
+ return e.map((o) => he(o, t));
400
+ }
401
+ function he(e, t) {
402
+ const o = K(e.type), l = `blocks.${o}.name`, n = t(l), i = fe(o, e, t);
403
+ return {
404
+ ...e,
405
+ name: n === l ? e.name : n,
406
+ defaultProps: be(e, t),
407
+ schema: e.schema.map((r) => me(o, r, t)),
408
+ renderPreview: xe(e, i),
409
+ inlineEditable: e.inlineEditable ? {
410
+ ...e.inlineEditable,
411
+ placeholder: i
412
+ } : void 0
413
+ };
414
+ }
415
+ function be(e, t) {
416
+ const o = { ...e.defaultProps }, l = pe[K(e.type)] ?? {};
417
+ for (const [n, i] of Object.entries(l))
418
+ o[n] = t(i);
419
+ return o;
420
+ }
421
+ function me(e, t, o) {
422
+ var n, i, r, c;
423
+ const l = ((n = de[e]) == null ? void 0 : n[t.key]) ?? se[t.key];
424
+ return {
425
+ ...t,
426
+ label: l ? o(l) : t.label,
427
+ placeholder: (i = I[e]) != null && i[t.key] ? o(I[e][t.key]) : t.placeholder,
428
+ help: (r = N[e]) != null && r[t.key] ? o(N[e][t.key]) : t.help,
429
+ options: (c = t.options) == null ? void 0 : c.map((a) => ({
430
+ ...a,
431
+ label: ue(a, o)
432
+ }))
433
+ };
434
+ }
435
+ function ue(e, t) {
436
+ return e.value === "left" ? t("common.left") : e.value === "center" ? t("common.center") : e.value === "right" ? t("common.right") : e.value === "top" ? t("blocks.option.top") : e.value === "middle" ? t("blocks.option.middle") : e.value === "bottom" ? t("blocks.option.bottom") : e.value === "" ? t("common.inheritGlobal") : e.label;
437
+ }
438
+ function fe(e, t, o) {
439
+ var n;
440
+ const l = ge[e];
441
+ return l ? o(l) : (n = t.inlineEditable) == null ? void 0 : n.placeholder;
442
+ }
443
+ function xe(e, t) {
444
+ var n;
445
+ if (!e.renderPreview || !((n = e.inlineEditable) != null && n.placeholder) || !t)
446
+ return e.renderPreview;
447
+ const o = W(e.inlineEditable.placeholder), l = W(t);
448
+ return (i, r) => e.renderPreview(i, r).replaceAll(
449
+ `data-placeholder="${o}"`,
450
+ `data-placeholder="${l}"`
451
+ );
452
+ }
453
+ function W(e) {
454
+ return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
455
+ }
456
+ function K(e) {
457
+ return e.startsWith("custom:") ? e.slice(7) : e;
458
+ }
459
+ const w = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), ke = h({
288
460
  type: "image",
289
461
  name: "图片",
290
462
  category: "content",
@@ -337,7 +509,7 @@ const b = {
337
509
  e.src
338
510
  )}" alt="${w(e.alt)}" style="display:block;${t}max-width:100%;${l}border:0;outline:none;" /></div>`;
339
511
  }
340
- }), z = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), de = h({
512
+ }), z = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), ye = h({
341
513
  type: "custom:logo",
342
514
  name: "公司 Logo",
343
515
  category: "custom",
@@ -372,17 +544,29 @@ const b = {
372
544
  )}" alt="logo" style="display:block;${t}width:${e.width}px;max-width:100%;height:auto;" /></div>`;
373
545
  }
374
546
  });
375
- function K(e) {
547
+ function V(e) {
376
548
  const t = e.trim();
377
549
  return t === "ig" ? "instagram" : t === "rabbit" || t === "tiktok" || t === "reddit" ? "web" : t;
378
550
  }
379
- const ge = [
551
+ const $e = /* @__PURE__ */ new Set([
552
+ "facebook",
553
+ "twitter",
554
+ "x",
555
+ "google",
556
+ "pinterest",
557
+ "linkedin"
558
+ ]);
559
+ function we(e) {
560
+ const t = V(e);
561
+ return $e.has(t) ? `${t}-noshare` : t;
562
+ }
563
+ const ve = [
380
564
  { label: "X", value: "x" },
381
565
  { label: "Rabbit", value: "rabbit" },
382
566
  { label: "Facebook", value: "facebook" },
383
567
  { label: "TikTok", value: "tiktok" },
384
568
  { label: "Instagram", value: "ig" }
385
- ], pe = [
569
+ ], Se = [
386
570
  { label: "微信", value: "wechat" },
387
571
  { label: "微博", value: "weibo" },
388
572
  { label: "X", value: "x" },
@@ -393,7 +577,7 @@ const ge = [
393
577
  { label: "YouTube", value: "youtube" },
394
578
  { label: "Reddit", value: "reddit" },
395
579
  { label: "网页", value: "web" }
396
- ], he = {
580
+ ], Ce = {
397
581
  wechat: { color: "#1AAD19", preview: "信" },
398
582
  weibo: { color: "#E6162D", preview: "微" },
399
583
  x: { color: "#000000", preview: "X" },
@@ -408,11 +592,11 @@ const ge = [
408
592
  rabbit: { color: "#FF2442", preview: "R" },
409
593
  website: { color: "#6b7280", preview: "◇" },
410
594
  web: { color: "#6b7280", preview: "◇" }
411
- }, p = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), be = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
412
- function V(e) {
413
- return he[e] ?? { color: "#6b7280", preview: "·" };
595
+ }, p = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), Be = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
596
+ function U(e) {
597
+ return Ce[e] ?? { color: "#6b7280", preview: "·" };
414
598
  }
415
- const me = "https://www.mailjet.com/images/theme/v1/icons/ico-social/", ue = {
599
+ const ze = "https://www.mailjet.com/images/theme/v1/icons/ico-social/", Le = {
416
600
  facebook: "facebook.png",
417
601
  twitter: "twitter.png",
418
602
  x: "twitter-x.png",
@@ -431,80 +615,80 @@ const me = "https://www.mailjet.com/images/theme/v1/icons/ico-social/", ue = {
431
615
  soundcloud: "soundcloud.png",
432
616
  dribbble: "dribbble.png"
433
617
  };
434
- function fe(e) {
435
- const t = ue[K(e)];
436
- return t ? `${me}${t}` : null;
618
+ function Re(e) {
619
+ const t = Le[V(e)];
620
+ return t ? `${ze}${t}` : null;
437
621
  }
438
- function U(e) {
439
- const { network: t, iconSize: o, iconBorderRadius: l, iconSrc: n, backgroundColor: i } = e, r = xe(o, l), c = V(t), a = (i == null ? void 0 : i.trim()) || c.color, d = (n == null ? void 0 : n.trim()) || fe(t);
622
+ function D(e) {
623
+ const { network: t, iconSize: o, iconBorderRadius: l, iconSrc: n, backgroundColor: i } = e, r = Me(o, l), c = U(t), a = (i == null ? void 0 : i.trim()) || c.color, d = (n == null ? void 0 : n.trim()) || Re(t);
440
624
  return d ? `<span style="display:inline-flex;width:${o}px;height:${o}px;border-radius:${r};background:${a};overflow:hidden;align-items:center;justify-content:center;flex-shrink:0;line-height:0;"><img src="${p(d)}" alt="" width="${o}" height="${o}" style="display:block;width:${o}px;height:${o}px;border-radius:${r};" /></span>` : `<span style="display:inline-flex;width:${o}px;height:${o}px;border-radius:${r};background:${a};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(
441
625
  o / 2
442
626
  )}px;font-weight:600;flex-shrink:0;overflow:hidden;">${c.preview}</span>`;
443
627
  }
444
- function S(e) {
628
+ function C(e) {
445
629
  return `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`;
446
630
  }
447
- function D(e, t) {
631
+ function G(e, t) {
448
632
  const o = Math.max(1, Number(e) || 28), l = Number(t);
449
633
  if (!Number.isFinite(l) || l <= 0) return "0px";
450
634
  const n = o / 2;
451
635
  return l >= 999 || l >= n ? "999px" : `${Math.min(l, o)}px`;
452
636
  }
453
- function xe(e, t) {
637
+ function Me(e, t) {
454
638
  const o = Math.max(1, Number(e) || 28), l = Number(t);
455
639
  if (!Number.isFinite(l) || l <= 0) return "0";
456
640
  const n = o / 2;
457
641
  return l >= 999 || l >= n ? "50%" : `${Math.min(l, o)}px`;
458
642
  }
459
- function C(e, t = 10) {
643
+ function B(e, t = 10) {
460
644
  const o = Number(e);
461
645
  return !Number.isFinite(o) || o < 0 ? t : Math.min(64, Math.round(o));
462
646
  }
463
- function G(e) {
647
+ function J(e) {
464
648
  return e === "right" ? "flex-end" : e === "left" ? "flex-start" : "center";
465
649
  }
466
- function J(e, t) {
650
+ function q(e, t) {
467
651
  var c;
468
652
  const o = t.labelFontSize > 0 ? t.labelFontSize : 13, l = Math.max(8, Math.min(48, o)), n = k(t.labelFontWeight), i = ((c = t.labelColor) == null ? void 0 : c.trim()) || "#333333", r = p(n);
469
653
  return e.map((a) => {
470
654
  var T, P, F;
471
- const d = V(a.network), s = ((T = a.backgroundColor) == null ? void 0 : T.trim()) || d.color, u = [
472
- `name="${p(K(a.network))}"`,
655
+ const d = U(a.network), s = ((T = a.backgroundColor) == null ? void 0 : T.trim()) || d.color, u = [
656
+ `name="${p(we(a.network))}"`,
473
657
  `href="${p(a.href)}"`,
474
658
  `background-color="${p(s)}"`,
475
659
  `color="${p(i)}"`,
476
660
  `font-size="${l}px"`,
477
661
  `font-weight="${r}"`
478
- ].join(" "), y = (P = a.iconSrc) == null ? void 0 : P.trim(), f = y ? `${u} src="${p(y)}"` : u, R = ((F = a.label) == null ? void 0 : F.trim()) ?? "";
479
- return R ? ` <mj-social-element ${f}>
480
- ${be(R)}
662
+ ].join(" "), y = (P = a.iconSrc) == null ? void 0 : P.trim(), f = y ? `${u} src="${p(y)}"` : u, M = ((F = a.label) == null ? void 0 : F.trim()) ?? "";
663
+ return M ? ` <mj-social-element ${f}>
664
+ ${Be(M)}
481
665
  </mj-social-element>` : ` <mj-social-element ${f} />`;
482
666
  }).join(`
483
667
  `);
484
668
  }
485
- const q = [
669
+ const Y = [
486
670
  { network: "x", href: "https://x.com/" },
487
671
  { network: "rabbit", href: "https://example.com" },
488
672
  { network: "facebook", href: "https://facebook.com/" },
489
673
  { network: "tiktok", href: "https://www.tiktok.com/" },
490
674
  { network: "ig", href: "https://instagram.com/" }
491
675
  ];
492
- function I(e) {
676
+ function _(e) {
493
677
  var o;
494
678
  if ((o = e.elements) != null && o.length) return e.elements;
495
679
  const t = e.links;
496
680
  return Array.isArray(t) && t.length ? t.map((l) => ({
497
681
  network: String(l.network ?? "web"),
498
682
  href: String(l.href ?? "")
499
- })) : q;
683
+ })) : Y;
500
684
  }
501
- const ke = h({
685
+ const Te = h({
502
686
  type: "custom:social",
503
687
  name: "社交链接",
504
688
  category: "custom",
505
689
  icon: b.social,
506
690
  defaultProps: {
507
- elements: q,
691
+ elements: Y,
508
692
  align: "center",
509
693
  iconSize: 28,
510
694
  iconBorderRadius: 999,
@@ -522,7 +706,7 @@ const ke = h({
522
706
  key: "elements",
523
707
  label: "社交链接",
524
708
  type: "socialLinkList",
525
- options: ge,
709
+ options: ve,
526
710
  help: "平台:X、Rabbit、Facebook、TikTok、Instagram (ig)。可填标签、自定义图标 URL。MJML 侧 Rabbit/TikTok 使用 web 占位图标,需要品牌图时请填「图标 URL」。"
527
711
  },
528
712
  {
@@ -574,26 +758,26 @@ const ke = h({
574
758
  { key: "paddingTop", label: "外边距", type: "spacing" }
575
759
  ],
576
760
  toMjml: (e) => {
577
- const t = S(e), o = D(e.iconSize, e.iconBorderRadius ?? 999), l = C(e.iconSpacing, 10), n = `align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" border-radius="${o}" inner-padding="${l}px" padding="${t}"`, i = I(e).filter((a) => {
761
+ const t = C(e), o = G(e.iconSize, e.iconBorderRadius ?? 999), l = B(e.iconSpacing, 10), n = `align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" border-radius="${o}" inner-padding="${l}px" padding="${t}"`, i = _(e).filter((a) => {
578
762
  var d;
579
763
  return (d = a.href) == null ? void 0 : d.trim();
580
764
  }), r = {
581
765
  labelFontSize: Number(e.labelFontSize ?? 13),
582
766
  labelFontWeight: k(String(e.labelFontWeight ?? "400")),
583
767
  labelColor: String(e.labelColor ?? "#333333")
584
- }, c = J(i, r);
768
+ }, c = q(i, r);
585
769
  return c.trim() ? `<mj-social ${n}>
586
770
  ${c}
587
771
  </mj-social>` : `<mj-social ${n}></mj-social>`;
588
772
  },
589
773
  renderPreview: (e) => {
590
774
  var d;
591
- const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, o = Math.max(8, Math.min(48, t)), l = k(e.labelFontWeight), n = ((d = e.labelColor) == null ? void 0 : d.trim()) || "#333333", i = C(e.iconSpacing, 10), r = G(e.align), c = I(e).filter((s) => {
775
+ const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, o = Math.max(8, Math.min(48, t)), l = k(e.labelFontWeight), n = ((d = e.labelColor) == null ? void 0 : d.trim()) || "#333333", i = B(e.iconSpacing, 10), r = J(e.align), c = _(e).filter((s) => {
592
776
  var g;
593
777
  return (g = s.href) == null ? void 0 : g.trim();
594
778
  }).map((s) => {
595
779
  var f;
596
- const g = ((f = s.label) == null ? void 0 : f.trim()) ?? "", u = U({
780
+ const g = ((f = s.label) == null ? void 0 : f.trim()) ?? "", u = D({
597
781
  network: s.network,
598
782
  iconSize: e.iconSize,
599
783
  iconBorderRadius: e.iconBorderRadius ?? 999,
@@ -605,10 +789,10 @@ ${c}
605
789
  return `<span style="display:inline-flex;align-items:center;gap:6px;"><a href="${p(
606
790
  s.href
607
791
  )}" style="display:inline-flex;align-items:center;text-decoration:none;line-height:0;">${u}</a>${y}</span>`;
608
- }).join(""), a = S(e);
792
+ }).join(""), a = C(e);
609
793
  return `<div style="display:flex;flex-wrap:wrap;justify-content:${r};align-items:center;gap:${i}px;padding:${a};">${c || '<span style="color:#9ca3af;font-size:12px;">请填写链接 URL</span>'}</div>`;
610
794
  }
611
- }), ye = h({
795
+ }), Pe = h({
612
796
  type: "social-group",
613
797
  name: "社交组",
614
798
  category: "content",
@@ -635,7 +819,7 @@ ${c}
635
819
  key: "elements",
636
820
  label: "社交链接",
637
821
  type: "socialLinkList",
638
- options: pe,
822
+ options: Se,
639
823
  help: "每行:平台、链接、可选标签文字、自定义图标 URL、图标背景色。标签的字号/字重/颜色在下方统一设置。"
640
824
  },
641
825
  {
@@ -687,26 +871,26 @@ ${c}
687
871
  { key: "paddingTop", label: "外边距", type: "spacing" }
688
872
  ],
689
873
  toMjml: (e) => {
690
- const t = S(e), o = D(e.iconSize, e.iconBorderRadius ?? 999), l = C(e.iconSpacing, 10), n = `align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" border-radius="${o}" inner-padding="${l}px" padding="${t}"`, i = e.elements.filter((a) => {
874
+ const t = C(e), o = G(e.iconSize, e.iconBorderRadius ?? 999), l = B(e.iconSpacing, 10), n = `align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" border-radius="${o}" inner-padding="${l}px" padding="${t}"`, i = e.elements.filter((a) => {
691
875
  var d;
692
876
  return (d = a.href) == null ? void 0 : d.trim();
693
877
  }), r = {
694
878
  labelFontSize: Number(e.labelFontSize ?? 13),
695
879
  labelFontWeight: k(String(e.labelFontWeight ?? "400")),
696
880
  labelColor: String(e.labelColor ?? "#333333")
697
- }, c = J(i, r);
881
+ }, c = q(i, r);
698
882
  return c.trim() ? `<mj-social ${n}>
699
883
  ${c}
700
884
  </mj-social>` : `<mj-social ${n}></mj-social>`;
701
885
  },
702
886
  renderPreview: (e) => {
703
887
  var d;
704
- const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, o = Math.max(8, Math.min(48, t)), l = k(e.labelFontWeight), n = ((d = e.labelColor) == null ? void 0 : d.trim()) || "#333333", i = C(e.iconSpacing, 10), r = G(e.align), c = e.elements.filter((s) => {
888
+ const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, o = Math.max(8, Math.min(48, t)), l = k(e.labelFontWeight), n = ((d = e.labelColor) == null ? void 0 : d.trim()) || "#333333", i = B(e.iconSpacing, 10), r = J(e.align), c = e.elements.filter((s) => {
705
889
  var g;
706
890
  return (g = s.href) == null ? void 0 : g.trim();
707
891
  }).map((s) => {
708
892
  var f;
709
- const g = ((f = s.label) == null ? void 0 : f.trim()) ?? "", u = U({
893
+ const g = ((f = s.label) == null ? void 0 : f.trim()) ?? "", u = D({
710
894
  network: s.network,
711
895
  iconSize: e.iconSize,
712
896
  iconBorderRadius: e.iconBorderRadius ?? 999,
@@ -718,10 +902,10 @@ ${c}
718
902
  return `<span style="display:inline-flex;align-items:center;gap:6px;"><a href="${p(
719
903
  s.href
720
904
  )}" style="display:inline-flex;align-items:center;text-decoration:none;line-height:0;">${u}</a>${y}</span>`;
721
- }).join(""), a = S(e);
905
+ }).join(""), a = C(e);
722
906
  return `<div style="display:flex;flex-wrap:wrap;justify-content:${r};align-items:center;gap:${i}px;padding:${a};">${c || '<span style="color:#9ca3af;font-size:12px;">请添加社交链接</span>'}</div>`;
723
907
  }
724
- }), $e = h({
908
+ }), Fe = h({
725
909
  type: "spacer",
726
910
  name: "间距",
727
911
  category: "content",
@@ -730,13 +914,13 @@ ${c}
730
914
  schema: [{ key: "height", label: "高度 (px)", type: "number", min: 1, max: 200 }],
731
915
  toMjml: (e) => `<mj-spacer height="${e.height}px" />`,
732
916
  renderPreview: (e) => `<div style="height:${e.height}px;line-height:${e.height}px;"></div>`
733
- }), v = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), N = "输入文本…", we = h({
917
+ }), v = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), O = "输入文本…", je = h({
734
918
  type: "text",
735
919
  name: "文本",
736
920
  category: "content",
737
921
  icon: b.text,
738
922
  defaultProps: {
739
- content: '<p style="margin:0;">在此处输入文本。<strong>双击</strong>进入编辑模式,<em>选中文字</em>会出现工具条;支持变量 {{user.name}}</p>',
923
+ content: "<p>双击进入编辑...</p>",
740
924
  align: "left",
741
925
  color: "",
742
926
  fontSize: "",
@@ -804,247 +988,75 @@ ${c}
804
988
  mode: "rich",
805
989
  multiline: !0,
806
990
  propKey: "content",
807
- placeholder: N
991
+ placeholder: O
808
992
  },
809
993
  toMjml: (e) => {
810
994
  const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, o = e.fontFamily ? ` font-family="${v(e.fontFamily)}"` : "", l = String(e.fontWeight ?? "").trim(), n = l ? ` font-weight="${v(k(l))}"` : "", i = String(e.lineHeight ?? "").trim(), r = i ? ` line-height="${v(i)}"` : "", c = String(e.color ?? "").trim(), a = c ? ` color="${v(c)}"` : "", d = String(e.fontSize ?? "").trim(), s = d ? ` font-size="${v(d)}"` : "";
811
995
  return `<mj-text align="${e.align}"${a}${s}${r}${o}${n} padding="${t}">${e.content}</mj-text>`;
812
996
  },
813
997
  renderPreview: (e) => {
814
- const t = e.fontFamily ? `font-family:${e.fontFamily};` : "", o = String(e.fontWeight ?? "").trim(), l = o ? `font-weight:${k(o)};` : "", n = String(e.lineHeight ?? "").trim(), i = n ? `line-height:${n};` : "line-height:normal;", r = String(e.color ?? "").trim(), c = r ? `color:${r};` : "", a = String(e.fontSize ?? "").trim(), d = a ? `font-size:${a};` : "", s = oe(e.content), g = s ? " is-empty" : "", u = s ? ` data-placeholder="${N}"` : "";
998
+ const t = e.fontFamily ? `font-family:${e.fontFamily};` : "", o = String(e.fontWeight ?? "").trim(), l = o ? `font-weight:${k(o)};` : "", n = String(e.lineHeight ?? "").trim(), i = n ? `line-height:${n};` : "", r = String(e.color ?? "").trim(), c = r ? `color:${r};` : "", a = String(e.fontSize ?? "").trim(), d = a ? `font-size:${a};` : "", s = oe(e.content), g = s ? " is-empty" : "", u = s ? ` data-placeholder="${O}"` : "";
815
999
  return `<div class="sm-text-content${g}"${u} style="text-align:${e.align};${c}${d}${l}${i}${t}padding:${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px;">${e.content}</div>`;
816
1000
  }
817
- }), ve = {
818
- align: "blocks.field.align",
819
- textAlign: "blocks.field.textAlign",
820
- verticalAlign: "blocks.field.verticalAlign",
821
- color: "blocks.field.color",
822
- textColor: "blocks.field.textColor",
823
- backgroundColor: "blocks.field.backgroundColor",
824
- backgroundUrl: "blocks.field.backgroundUrl",
825
- height: "blocks.field.heightPx",
826
- width: "blocks.field.width",
827
- thickness: "blocks.field.thicknessPx",
828
- paddingTop: "blocks.field.padding",
829
- text: "blocks.field.text",
830
- href: "blocks.field.link",
831
- src: "blocks.field.imageUrl",
832
- alt: "blocks.field.alt",
833
- fontSize: "blocks.field.fontSize",
834
- fontFamily: "blocks.field.fontFamily",
835
- fontWeight: "blocks.field.fontWeight",
836
- lineHeight: "blocks.field.lineHeight",
837
- html: "blocks.field.html",
838
- borderRadius: "blocks.field.borderRadius",
839
- innerPaddingV: "blocks.field.buttonInnerPaddingV",
840
- innerPaddingH: "blocks.field.buttonInnerPaddingH",
841
- elements: "blocks.field.socialLinks",
842
- labelFontSize: "blocks.field.labelFontSize",
843
- labelFontWeight: "blocks.field.labelFontWeight",
844
- labelColor: "blocks.field.labelColor",
845
- iconSize: "blocks.field.iconSize",
846
- iconBorderRadius: "blocks.field.iconRadius",
847
- iconSpacing: "blocks.field.iconSpacing",
848
- companyName: "blocks.field.companyName",
849
- address: "blocks.field.address",
850
- unsubscribeText: "blocks.field.unsubscribeText",
851
- unsubscribeHref: "blocks.field.unsubscribeLink"
852
- }, Se = {
853
- button: {
854
- backgroundColor: "blocks.field.backgroundColor",
855
- color: "blocks.field.textColor",
856
- width: "blocks.field.width"
857
- },
858
- divider: {
859
- width: "blocks.field.widthPercentOrPx",
860
- paddingTop: "blocks.field.topMargin",
861
- paddingBottom: "blocks.field.bottomMargin"
862
- },
863
- hero: {
864
- backgroundColor: "blocks.field.backgroundPlaceholderColor",
865
- height: "blocks.field.areaHeightPx",
866
- content: "blocks.field.bodyHtml"
867
- },
868
- html: {
869
- paddingTop: "blocks.field.padding"
870
- },
871
- image: {
872
- href: "blocks.field.href",
873
- width: "blocks.field.widthPx"
874
- },
875
- logo: {
876
- src: "blocks.field.logoImage",
877
- href: "blocks.field.websiteLink",
878
- width: "blocks.field.widthPx"
879
- },
880
- text: {
881
- content: "blocks.field.contentHtml"
882
- }
883
- }, W = {
884
- button: { width: "blocks.help.buttonWidth" },
885
- hero: {
886
- backgroundColor: "blocks.help.imageFallbackColor",
887
- content: "blocks.help.canvasEditRecommendedShort"
888
- },
889
- html: { html: "blocks.help.htmlOnly" },
890
- image: { height: "blocks.help.imageAutoHeight" },
891
- "social-group": {
892
- elements: "blocks.help.socialLinks",
893
- iconBorderRadius: "blocks.help.iconRadius",
894
- iconSpacing: "blocks.help.iconSpacing"
895
- },
896
- social: {
897
- elements: "blocks.help.bizSocialLinks",
898
- iconBorderRadius: "blocks.help.iconRadius",
899
- iconSpacing: "blocks.help.bizIconSpacing"
900
- },
901
- text: {
902
- content: "blocks.help.canvasEditRecommended",
903
- lineHeight: "blocks.help.globalLineHeight"
904
- }
905
- }, _ = {
906
- button: { width: "blocks.placeholder.buttonWidth" },
907
- image: { alt: "blocks.field.imageDescription" },
908
- text: {
909
- color: "blocks.field.inheritGlobalPlaceholder",
910
- fontFamily: "blocks.field.inheritGlobalPlaceholder"
911
- }
912
- }, Ce = {
913
- button: "blocks.field.buttonTextPlaceholder",
914
- hero: "blocks.field.heroPlaceholder",
915
- html: "blocks.field.htmlPlaceholder",
916
- text: "blocks.field.textPlaceholder"
917
- }, Be = {
918
- button: { text: "blocks.button.defaultText" },
919
- hero: { content: "blocks.hero.defaultContent" },
920
- html: { html: "blocks.html.defaultHtml" },
921
- text: { content: "blocks.text.defaultContent" },
922
- footer: {
923
- companyName: "blocks.footer.defaultCompanyName",
924
- address: "blocks.footer.defaultAddress",
925
- unsubscribeText: "blocks.footer.defaultUnsubscribeText"
926
- }
927
- };
928
- function B(e, t) {
929
- return e.map((o) => ze(o, t));
930
- }
931
- function ze(e, t) {
932
- const o = Y(e.type), l = `blocks.${o}.name`, n = t(l), i = Te(o, e, t);
933
- return {
934
- ...e,
935
- name: n === l ? e.name : n,
936
- defaultProps: Le(e, t),
937
- schema: e.schema.map((r) => Me(o, r, t)),
938
- renderPreview: Pe(e, i),
939
- inlineEditable: e.inlineEditable ? {
940
- ...e.inlineEditable,
941
- placeholder: i
942
- } : void 0
943
- };
944
- }
945
- function Le(e, t) {
946
- const o = { ...e.defaultProps }, l = Be[Y(e.type)] ?? {};
947
- for (const [n, i] of Object.entries(l))
948
- o[n] = t(i);
949
- return o;
950
- }
951
- function Me(e, t, o) {
952
- var n, i, r, c;
953
- const l = ((n = Se[e]) == null ? void 0 : n[t.key]) ?? ve[t.key];
954
- return {
955
- ...t,
956
- label: l ? o(l) : t.label,
957
- placeholder: (i = _[e]) != null && i[t.key] ? o(_[e][t.key]) : t.placeholder,
958
- help: (r = W[e]) != null && r[t.key] ? o(W[e][t.key]) : t.help,
959
- options: (c = t.options) == null ? void 0 : c.map((a) => ({
960
- ...a,
961
- label: Re(a, o)
962
- }))
963
- };
964
- }
965
- function Re(e, t) {
966
- return e.value === "left" ? t("common.left") : e.value === "center" ? t("common.center") : e.value === "right" ? t("common.right") : e.value === "top" ? t("blocks.option.top") : e.value === "middle" ? t("blocks.option.middle") : e.value === "bottom" ? t("blocks.option.bottom") : e.value === "" ? t("common.inheritGlobal") : e.label;
967
- }
968
- function Te(e, t, o) {
969
- var n;
970
- const l = Ce[e];
971
- return l ? o(l) : (n = t.inlineEditable) == null ? void 0 : n.placeholder;
972
- }
973
- function Pe(e, t) {
974
- var n;
975
- if (!e.renderPreview || !((n = e.inlineEditable) != null && n.placeholder) || !t)
976
- return e.renderPreview;
977
- const o = O(e.inlineEditable.placeholder), l = O(t);
978
- return (i, r) => e.renderPreview(i, r).replaceAll(
979
- `data-placeholder="${o}"`,
980
- `data-placeholder="${l}"`
981
- );
982
- }
983
- function O(e) {
984
- return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
985
- }
986
- function Y(e) {
987
- return e.startsWith("custom:") ? e.slice(7) : e;
988
- }
989
- const X = [
990
- we,
1001
+ }), X = [
1002
+ je,
991
1003
  ce,
992
- se,
993
- ye,
1004
+ ke,
1005
+ Pe,
994
1006
  ae,
995
1007
  ne,
996
1008
  ie,
997
- $e
998
- ], Z = [de, ke, re];
999
- function M(e = {}) {
1009
+ Fe
1010
+ ], Z = [ye, Te, re];
1011
+ function R(e = {}) {
1000
1012
  return e.t ?? le(e).t;
1001
1013
  }
1002
- function Fe(e = {}) {
1003
- return B(X, M(e));
1014
+ function Ee(e = {}) {
1015
+ return S(X, R(e));
1004
1016
  }
1005
- function je(e = {}) {
1006
- return B(Z, M(e));
1017
+ function Ae(e = {}) {
1018
+ return S(Z, R(e));
1007
1019
  }
1008
- function Ee(e = {}) {
1009
- const t = M(e);
1020
+ function He(e = {}) {
1021
+ const t = R(e);
1010
1022
  return [
1011
- ...B(X, t),
1012
- ...B(Z, t)
1023
+ ...S(X, t),
1024
+ ...S(Z, t)
1013
1025
  ];
1014
1026
  }
1015
- const He = Fe(), Ie = je(), Ne = Ee();
1027
+ const Ie = Ee(), We = Ae(), _e = He();
1016
1028
  export {
1017
- pe as SOCIAL_NETWORK_OPTIONS,
1018
- Ne as allBlocks,
1019
- He as builtinBlocks,
1029
+ Se as SOCIAL_NETWORK_OPTIONS,
1030
+ _e as allBlocks,
1031
+ Ie as builtinBlocks,
1020
1032
  ne as buttonBlock,
1021
- Ee as createAllBlocks,
1022
- Fe as createBuiltinBlocks,
1023
- je as createExampleCustomBlocks,
1033
+ He as createAllBlocks,
1034
+ Ee as createBuiltinBlocks,
1035
+ Ae as createExampleCustomBlocks,
1024
1036
  ie as dividerBlock,
1025
1037
  p as escAttr,
1026
- be as escMjmlText,
1027
- Ie as exampleCustomBlocks,
1028
- G as flexJustifyFromAlign,
1038
+ Be as escMjmlText,
1039
+ We as exampleCustomBlocks,
1040
+ J as flexJustifyFromAlign,
1029
1041
  re as footerBlock,
1030
1042
  ae as heroBlock,
1031
1043
  ce as htmlBlock,
1032
- se as imageBlock,
1033
- ze as localizeBlockDefinition,
1034
- B as localizeBlockDefinitions,
1035
- de as logoBlock,
1036
- fe as mjSocialDefaultIconSrc,
1037
- K as mjSocialElementName,
1038
- J as mjSocialElementsLines,
1039
- S as paddingQuad,
1040
- U as renderSocialIconPreviewHtml,
1041
- ke as socialBlock,
1042
- ye as socialGroupBlock,
1043
- xe as socialIconBorderRadiusCss,
1044
- D as socialIconBorderRadiusMjml,
1045
- C as socialIconSpacingPx,
1046
- V as socialMeta,
1047
- $e as spacerBlock,
1048
- we as textBlock
1044
+ ke as imageBlock,
1045
+ he as localizeBlockDefinition,
1046
+ S as localizeBlockDefinitions,
1047
+ ye as logoBlock,
1048
+ Re as mjSocialDefaultIconSrc,
1049
+ V as mjSocialElementName,
1050
+ q as mjSocialElementsLines,
1051
+ C as paddingQuad,
1052
+ D as renderSocialIconPreviewHtml,
1053
+ Te as socialBlock,
1054
+ Pe as socialGroupBlock,
1055
+ Me as socialIconBorderRadiusCss,
1056
+ G as socialIconBorderRadiusMjml,
1057
+ B as socialIconSpacingPx,
1058
+ U as socialMeta,
1059
+ Fe as spacerBlock,
1060
+ je as textBlock
1049
1061
  };
1050
1062
  //# sourceMappingURL=index.js.map