mail-editor-pancake 0.0.0 → 0.0.8

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 (45) hide show
  1. package/README.md +79 -6
  2. package/package.json +1 -1
  3. package/packages/blocks/dist/index.d.ts +55 -3
  4. package/packages/blocks/dist/index.js +267 -208
  5. package/packages/blocks/dist/index.js.map +1 -1
  6. package/packages/blocks/node_modules/.bin/resolve +21 -0
  7. package/packages/blocks/package.json +1 -0
  8. package/packages/blocks/src/button.ts +1 -0
  9. package/packages/blocks/src/hero.ts +2 -0
  10. package/packages/blocks/src/image.ts +1 -0
  11. package/packages/blocks/src/index.ts +19 -2
  12. package/packages/blocks/src/logo.ts +1 -0
  13. package/packages/blocks/src/social.ts +47 -22
  14. package/packages/blocks/src/socialGroup.ts +49 -22
  15. package/packages/blocks/src/socialShared.ts +39 -2
  16. package/packages/blocks/src/text.ts +25 -19
  17. package/packages/blocks/tsconfig.json +0 -3
  18. package/packages/blocks/vite.config.ts +2 -0
  19. package/packages/core/dist/index.d.ts +90 -7
  20. package/packages/core/dist/index.js +2505 -1462
  21. package/packages/core/dist/index.js.map +1 -1
  22. package/packages/core/dist/style.css +1 -1
  23. package/packages/core/src/editor/Canvas.ts +107 -53
  24. package/packages/core/src/editor/ColorPickerPopover.ts +291 -0
  25. package/packages/core/src/editor/Editor.ts +129 -8
  26. package/packages/core/src/editor/ExportModal.ts +2 -1
  27. package/packages/core/src/editor/FocusBreadcrumb.ts +120 -0
  28. package/packages/core/src/editor/ImageGalleryModal.ts +3 -3
  29. package/packages/core/src/editor/InlineEditor.ts +308 -66
  30. package/packages/core/src/editor/LeftPanel.ts +1 -2
  31. package/packages/core/src/editor/PreviewModal.ts +77 -7
  32. package/packages/core/src/editor/RichTextToolbar.ts +66 -44
  33. package/packages/core/src/editor/RightPanel.ts +773 -171
  34. package/packages/core/src/editor/SourceView.ts +2 -1
  35. package/packages/core/src/editor/Topbar.ts +150 -5
  36. package/packages/core/src/editor/styles.css +644 -81
  37. package/packages/core/src/index.ts +18 -1
  38. package/packages/core/src/renderer/mjml.ts +2 -1
  39. package/packages/core/src/store/store.ts +44 -3
  40. package/packages/core/src/types.ts +34 -3
  41. package/packages/core/src/utils/fontWeightSteps.ts +31 -0
  42. package/packages/core/src/utils/lockedMjml.ts +2 -1
  43. package/packages/core/src/utils/richTextCommand.ts +30 -0
  44. package/packages/core/src/utils/sectionLayout.ts +13 -0
  45. package/playground/vanilla/src/main.ts +1 -1
@@ -1,5 +1,5 @@
1
- import { defineBlock as d, blockButtonWidthCss as F, docContentWidthCss as L, mjRawEmailTableWrap as W, mjRawCellTypographyFromStyles as E } from "@simple-mail/core";
2
- const s = {
1
+ import { defineBlock as h, blockButtonWidthCss as A, docContentWidthCss as H, mjRawEmailTableWrap as _, mjRawCellTypographyFromStyles as G, normalizeFontWeightStep as k, FONT_WEIGHT_STEP_OPTIONS as L } from "@simple-mail/core";
2
+ const m = {
3
3
  html: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="3.5" y="4" width="17" height="16" rx="2" stroke="currentColor" stroke-width="1.5" fill="none"/><path d="M8 8.5l3 3.5-3 3.5M16 8.5l-3 3.5 3 3.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>',
4
4
  text: '<svg width="24" height="24" viewBox="0 0 24 24"><path d="M5 6h14M5 10h14M5 14h10M5 18h8" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" fill="none"/></svg>',
5
5
  image: '<svg width="24" height="24" viewBox="0 0 24 24"><rect x="3.5" y="5" width="17" height="14" rx="2" stroke="currentColor" stroke-width="1.6" fill="none"/><circle cx="9" cy="10" r="1.5" fill="currentColor"/><path d="M4 18l5-5 4 4 3-3 4 4" stroke="currentColor" stroke-width="1.6" fill="none" stroke-linecap="round" stroke-linejoin="round"/></svg>',
@@ -11,11 +11,11 @@ const s = {
11
11
  social: '<svg width="24" height="24" viewBox="0 0 24 24"><circle cx="6" cy="12" r="2.5" stroke="currentColor" stroke-width="1.4" fill="none"/><circle cx="12" cy="12" r="2.5" stroke="currentColor" stroke-width="1.4" fill="none"/><circle cx="18" cy="12" r="2.5" stroke="currentColor" stroke-width="1.4" fill="none"/></svg>',
12
12
  footer: '<svg width="24" height="24" viewBox="0 0 24 24"><rect x="3.5" y="5" width="17" height="10" rx="1.5" stroke="currentColor" stroke-width="1.4" fill="none"/><path d="M5 18h14" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>',
13
13
  socialGroup: '<svg width="24" height="24" viewBox="0 0 24 24" fill="none"><rect x="3" y="5" width="18" height="14" rx="2" stroke="currentColor" stroke-width="1.5"/><circle cx="8" cy="12" r="2" stroke="currentColor" stroke-width="1.4"/><circle cx="12" cy="12" r="2" stroke="currentColor" stroke-width="1.4"/><circle cx="16" cy="12" r="2" stroke="currentColor" stroke-width="1.4"/></svg>'
14
- }, y = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), N = d({
14
+ }, $ = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), q = h({
15
15
  type: "button",
16
16
  name: "按钮",
17
17
  category: "content",
18
- icon: s.button,
18
+ icon: m.button,
19
19
  defaultProps: {
20
20
  text: "立即查看",
21
21
  href: "https://example.com",
@@ -43,6 +43,7 @@ const s = {
43
43
  key: "align",
44
44
  label: "对齐",
45
45
  type: "select",
46
+ selectVariant: "segmented",
46
47
  options: [
47
48
  { label: "左", value: "left" },
48
49
  { label: "居中", value: "center" },
@@ -68,26 +69,26 @@ const s = {
68
69
  placeholder: "按钮文字"
69
70
  },
70
71
  toMjml: (e) => {
71
- const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, l = `${e.innerPaddingV}px ${e.innerPaddingH}px`, o = F(e.width), n = o ? ` width="${y(o)}"` : "";
72
- return `<mj-button href="${y(e.href)}" background-color="${y(
72
+ const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, o = `${e.innerPaddingV}px ${e.innerPaddingH}px`, n = A(e.width), i = n ? ` width="${$(n)}"` : "";
73
+ return `<mj-button href="${$(e.href)}" background-color="${$(
73
74
  e.backgroundColor
74
- )}" color="${y(e.color)}" border-radius="${e.borderRadius}px" font-size="${y(
75
+ )}" color="${$(e.color)}" border-radius="${e.borderRadius}px" font-size="${$(
75
76
  e.fontSize
76
- )}" align="${e.align}" padding="${t}" inner-padding="${l}"${n}>${y(
77
+ )}" align="${e.align}" padding="${t}" inner-padding="${o}"${i}>${$(
77
78
  e.text
78
79
  )}</mj-button>`;
79
80
  },
80
81
  renderPreview: (e) => {
81
- const t = F(e.width), l = t ? `width:${t};max-width:100%;box-sizing:border-box;` : "";
82
+ const t = A(e.width), o = t ? `width:${t};max-width:100%;box-sizing:border-box;` : "";
82
83
  return `<div style="padding:${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px;text-align:${e.align};">
83
- <a href="${y(e.href)}" style="display:inline-block;background:${e.backgroundColor};border-radius:${e.borderRadius}px;padding:${e.innerPaddingV}px ${e.innerPaddingH}px;text-decoration:none;font-size:${e.fontSize};line-height:1.2;${l}"><span class="sm-button-text" style="color:${e.color}">${y(e.text)}</span></a>
84
+ <a href="${$(e.href)}" style="display:inline-block;background:${e.backgroundColor};border-radius:${e.borderRadius}px;padding:${e.innerPaddingV}px ${e.innerPaddingH}px;text-decoration:none;font-size:${e.fontSize};line-height:1.2;${o}"><span class="sm-button-text" style="color:${e.color}">${$(e.text)}</span></a>
84
85
  </div>`;
85
86
  }
86
- }), R = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), O = d({
87
+ }), E = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), K = h({
87
88
  type: "divider",
88
89
  name: "分隔线",
89
90
  category: "content",
90
- icon: s.divider,
91
+ icon: m.divider,
91
92
  defaultProps: {
92
93
  color: "#e6e8ec",
93
94
  width: "100%",
@@ -102,15 +103,15 @@ const s = {
102
103
  { key: "paddingTop", label: "上边距", type: "number", min: 0, max: 80 },
103
104
  { key: "paddingBottom", label: "下边距", type: "number", min: 0, max: 80 }
104
105
  ],
105
- toMjml: (e) => `<mj-divider border-color="${R(e.color)}" border-width="${e.thickness}px" width="${R(
106
+ toMjml: (e) => `<mj-divider border-color="${E(e.color)}" border-width="${e.thickness}px" width="${E(
106
107
  e.width
107
108
  )}" padding="${e.paddingTop}px 0px ${e.paddingBottom}px 0px" />`,
108
109
  renderPreview: (e) => `<div style="padding:${e.paddingTop}px 0 ${e.paddingBottom}px 0;"><div style="border-top:${e.thickness}px solid ${e.color};width:${e.width};margin:0 auto;"></div></div>`
109
- }), g = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), U = d({
110
+ }), b = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), J = h({
110
111
  type: "custom:footer",
111
112
  name: "页脚",
112
113
  category: "custom",
113
- icon: s.footer,
114
+ icon: m.footer,
114
115
  defaultProps: {
115
116
  companyName: "你的公司",
116
117
  address: "上海市某区某路某号",
@@ -125,21 +126,21 @@ const s = {
125
126
  { key: "unsubscribeHref", label: "退订链接", type: "url" },
126
127
  { key: "textColor", label: "文字颜色", type: "color" }
127
128
  ],
128
- toMjml: (e) => `<mj-text align="center" color="${g(e.textColor)}" font-size="12px" line-height="1.6" padding="8px 0px 8px 0px">
129
- ${g(e.companyName)}<br />
130
- ${g(e.address)}<br />
131
- <a href="${g(e.unsubscribeHref)}" style="color:${g(e.textColor)};">${g(e.unsubscribeText)}</a>
129
+ toMjml: (e) => `<mj-text align="center" color="${b(e.textColor)}" font-size="12px" line-height="1.6" padding="8px 0px 8px 0px">
130
+ ${b(e.companyName)}<br />
131
+ ${b(e.address)}<br />
132
+ <a href="${b(e.unsubscribeHref)}" style="color:${b(e.textColor)};">${b(e.unsubscribeText)}</a>
132
133
  </mj-text>`,
133
134
  renderPreview: (e) => `<div style="padding:8px 0;text-align:center;font-size:12px;line-height:1.6;color:${e.textColor};">
134
- ${g(e.companyName)}<br/>
135
- ${g(e.address)}<br/>
136
- <a href="${g(e.unsubscribeHref)}" style="color:${e.textColor};">${g(e.unsubscribeText)}</a>
135
+ ${b(e.companyName)}<br/>
136
+ ${b(e.address)}<br/>
137
+ <a href="${b(e.unsubscribeHref)}" style="color:${e.textColor};">${b(e.unsubscribeText)}</a>
137
138
  </div>`
138
- }), v = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), I = d({
139
+ }), C = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), X = h({
139
140
  type: "hero",
140
141
  name: "Hero 大图",
141
142
  category: "content",
142
- icon: s.hero,
143
+ icon: m.hero,
143
144
  defaultProps: {
144
145
  backgroundUrl: "https://placehold.co/600x320/312e81/c4b5fd/png?text=Hero+Background",
145
146
  backgroundColor: "#1e1b4b",
@@ -161,6 +162,7 @@ const s = {
161
162
  key: "verticalAlign",
162
163
  label: "文字垂直位置",
163
164
  type: "select",
165
+ selectVariant: "segmented",
164
166
  options: [
165
167
  { label: "靠上", value: "top" },
166
168
  { label: "居中", value: "middle" },
@@ -171,6 +173,7 @@ const s = {
171
173
  key: "textAlign",
172
174
  label: "文字水平对齐",
173
175
  type: "select",
176
+ selectVariant: "segmented",
174
177
  options: [
175
178
  { label: "左", value: "left" },
176
179
  { label: "居中", value: "center" },
@@ -194,31 +197,31 @@ const s = {
194
197
  placeholder: "编写覆盖在图片上的文案…"
195
198
  },
196
199
  toMjml: (e, t) => {
197
- const l = L(t.doc.meta.width), o = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, n = `${e.height}px`;
200
+ const o = H(t.doc.meta.width), n = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, i = `${e.height}px`;
198
201
  return `<mj-hero
199
202
  mode="fixed-height"
200
- height="${n}"
201
- background-width="${l}"
202
- background-height="${n}"
203
- background-url="${v(e.backgroundUrl)}"
204
- background-color="${v(e.backgroundColor)}"
205
- padding="${o}"
203
+ height="${i}"
204
+ background-width="${o}"
205
+ background-height="${i}"
206
+ background-url="${C(e.backgroundUrl)}"
207
+ background-color="${C(e.backgroundColor)}"
208
+ padding="${n}"
206
209
  vertical-align="${e.verticalAlign}"
207
210
  >
208
211
  <mj-text
209
212
  align="${e.textAlign}"
210
- color="${v(e.textColor)}"
213
+ color="${C(e.textColor)}"
211
214
  padding="0"
212
215
  >${e.content}</mj-text>
213
216
  </mj-hero>`;
214
217
  },
215
218
  renderPreview: (e, t) => {
216
- const l = L(t.doc.meta.width), o = e.verticalAlign === "top" ? "flex-start" : e.verticalAlign === "bottom" ? "flex-end" : "center", n = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, r = v(e.backgroundUrl);
219
+ const o = H(t.doc.meta.width), n = e.verticalAlign === "top" ? "flex-start" : e.verticalAlign === "bottom" ? "flex-end" : "center", i = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, r = C(e.backgroundUrl);
217
220
  return `<div
218
221
  style="
219
222
  box-sizing:border-box;
220
223
  width:100%;
221
- max-width:${l};
224
+ max-width:${o};
222
225
  min-height:${e.height}px;
223
226
  margin:0 auto;
224
227
  background-image:linear-gradient(to bottom,rgba(0,0,0,0.25),rgba(0,0,0,0.35)),url(${r});
@@ -226,10 +229,10 @@ const s = {
226
229
  background-position:center;
227
230
  background-color:${e.backgroundColor};
228
231
  display:flex;
229
- align-items:${o};
232
+ align-items:${n};
230
233
  justify-content:${e.textAlign === "right" ? "flex-end" : e.textAlign === "center" ? "center" : "flex-start"};
231
- padding:${n};
232
- color:${v(e.textColor)};
234
+ padding:${i};
235
+ color:${C(e.textColor)};
233
236
  overflow:hidden;
234
237
  border-radius:2px;
235
238
  "
@@ -239,17 +242,17 @@ const s = {
239
242
  style="
240
243
  width:100%;
241
244
  text-align:${e.textAlign};
242
- color:${v(e.textColor)};
245
+ color:${C(e.textColor)};
243
246
  text-shadow:0 1px 2px rgba(0,0,0,0.45);
244
247
  "
245
248
  >${e.content}</div>
246
249
  </div>`;
247
250
  }
248
- }), q = d({
251
+ }), D = h({
249
252
  type: "html",
250
253
  name: "HTML",
251
254
  category: "content",
252
- icon: s.html,
255
+ icon: m.html,
253
256
  defaultProps: {
254
257
  html: '<p style="margin:0;">在此写入任意 HTML,将经 <strong>mj-raw</strong> 原样输出到邮件。支持变量 {{user.name}}</p>',
255
258
  paddingTop: 8,
@@ -274,15 +277,15 @@ const s = {
274
277
  placeholder: "输入 HTML…"
275
278
  },
276
279
  toMjml: (e, t) => {
277
- const l = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`;
278
- return W(l, e.html, E(t.doc.styles));
280
+ const o = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`;
281
+ return _(o, e.html, G(t.doc.styles));
279
282
  },
280
283
  renderPreview: (e) => `<div class="sm-html-content" style="padding:${`${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`};min-height:1em;">${e.html}</div>`
281
- }), C = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), _ = d({
284
+ }), M = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), Y = h({
282
285
  type: "image",
283
286
  name: "图片",
284
287
  category: "content",
285
- icon: s.image,
288
+ icon: m.image,
286
289
  defaultProps: {
287
290
  src: "https://placehold.co/600x240/EEF2FF/4F46E5/png?text=600x240",
288
291
  alt: "",
@@ -312,6 +315,7 @@ const s = {
312
315
  key: "align",
313
316
  label: "对齐",
314
317
  type: "select",
318
+ selectVariant: "segmented",
315
319
  options: [
316
320
  { label: "左", value: "left" },
317
321
  { label: "居中", value: "center" },
@@ -321,20 +325,20 @@ const s = {
321
325
  { key: "paddingTop", label: "内边距", type: "spacing" }
322
326
  ],
323
327
  toMjml: (e) => {
324
- const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, l = e.href ? ` href="${C(e.href)}"` : "", o = ` alt="${C(e.alt || "")}"`, n = e.height != null && e.height > 0 ? ` height="${e.height}px"` : "";
325
- return `<mj-image src="${C(e.src)}"${o}${l} width="${e.width}px"${n} align="${e.align}" padding="${t}" />`;
328
+ const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, o = e.href ? ` href="${M(e.href)}"` : "", n = ` alt="${M(e.alt || "")}"`, i = e.height != null && e.height > 0 ? ` height="${e.height}px"` : "";
329
+ return `<mj-image src="${M(e.src)}"${n}${o} width="${e.width}px"${i} align="${e.align}" padding="${t}" />`;
326
330
  },
327
331
  renderPreview: (e) => {
328
- const t = e.align === "center" ? "margin:0 auto;" : e.align === "right" ? "margin-left:auto;" : "", l = e.height != null && e.height > 0 ? e.height : 0, o = l > 0 ? `width:${e.width}px;height:${l}px;object-fit:cover;object-position:center;` : `width:${e.width}px;height:auto;`;
329
- return `<div style="padding:${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px;text-align:${e.align};"><img src="${C(
332
+ const t = e.align === "center" ? "margin:0 auto;" : e.align === "right" ? "margin-left:auto;" : "", o = e.height != null && e.height > 0 ? e.height : 0, n = o > 0 ? `width:${e.width}px;height:${o}px;object-fit:cover;object-position:center;` : `width:${e.width}px;height:auto;`;
333
+ return `<div style="padding:${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px;text-align:${e.align};"><img src="${M(
330
334
  e.src
331
- )}" alt="${C(e.alt)}" style="display:block;${t}max-width:100%;${o}border:0;outline:none;" /></div>`;
335
+ )}" alt="${M(e.alt)}" style="display:block;${t}max-width:100%;${n}border:0;outline:none;" /></div>`;
332
336
  }
333
- }), T = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), K = d({
337
+ }), R = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), Z = h({
334
338
  type: "custom:logo",
335
339
  name: "公司 Logo",
336
340
  category: "custom",
337
- icon: s.logo,
341
+ icon: m.logo,
338
342
  defaultProps: {
339
343
  src: "https://placehold.co/240x60/1f2328/ffffff/png?text=YOUR+LOGO",
340
344
  href: "https://example.com",
@@ -349,6 +353,7 @@ const s = {
349
353
  key: "align",
350
354
  label: "对齐",
351
355
  type: "select",
356
+ selectVariant: "segmented",
352
357
  options: [
353
358
  { label: "左", value: "left" },
354
359
  { label: "居中", value: "center" },
@@ -356,25 +361,25 @@ const s = {
356
361
  ]
357
362
  }
358
363
  ],
359
- toMjml: (e) => `<mj-image src="${T(e.src)}" href="${T(e.href)}" width="${e.width}px" align="${e.align}" alt="logo" padding="8px 0px 8px 0px" />`,
364
+ toMjml: (e) => `<mj-image src="${R(e.src)}" href="${R(e.href)}" width="${e.width}px" align="${e.align}" alt="logo" padding="8px 0px 8px 0px" />`,
360
365
  renderPreview: (e) => {
361
366
  const t = e.align === "center" ? "margin:0 auto;" : e.align === "right" ? "margin-left:auto;" : "";
362
- return `<div style="padding:8px 0;text-align:${e.align};"><img src="${T(
367
+ return `<div style="padding:8px 0;text-align:${e.align};"><img src="${R(
363
368
  e.src
364
369
  )}" alt="logo" style="display:block;${t}width:${e.width}px;max-width:100%;height:auto;" /></div>`;
365
370
  }
366
371
  });
367
- function G(e) {
372
+ function Q(e) {
368
373
  const t = e.trim();
369
- return t === "ig" ? "instagram" : t === "rabbit" || t === "tiktok" ? "web" : t;
374
+ return t === "ig" ? "instagram" : t === "rabbit" || t === "tiktok" || t === "reddit" ? "web" : t;
370
375
  }
371
- const V = [
376
+ const ee = [
372
377
  { label: "X", value: "x" },
373
378
  { label: "Rabbit", value: "rabbit" },
374
379
  { label: "Facebook", value: "facebook" },
375
380
  { label: "TikTok", value: "tiktok" },
376
381
  { label: "Instagram", value: "ig" }
377
- ], X = [
382
+ ], te = [
378
383
  { label: "微信", value: "wechat" },
379
384
  { label: "微博", value: "weibo" },
380
385
  { label: "X", value: "x" },
@@ -383,8 +388,9 @@ const V = [
383
388
  { label: "Facebook", value: "facebook" },
384
389
  { label: "Instagram", value: "instagram" },
385
390
  { label: "YouTube", value: "youtube" },
391
+ { label: "Reddit", value: "reddit" },
386
392
  { label: "网页", value: "web" }
387
- ], D = {
393
+ ], oe = {
388
394
  wechat: { color: "#1AAD19", preview: "信" },
389
395
  weibo: { color: "#E6162D", preview: "微" },
390
396
  x: { color: "#000000", preview: "X" },
@@ -394,63 +400,85 @@ const V = [
394
400
  instagram: { color: "#E4405F", preview: "◎" },
395
401
  ig: { color: "#E4405F", preview: "◎" },
396
402
  youtube: { color: "#FF0000", preview: "▶" },
403
+ reddit: { color: "#FF4500", preview: "r" },
397
404
  tiktok: { color: "#000000", preview: "♪" },
398
405
  rabbit: { color: "#FF2442", preview: "R" },
399
406
  website: { color: "#6b7280", preview: "◇" },
400
407
  web: { color: "#6b7280", preview: "◇" }
401
- }, a = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), J = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
402
- function B(e) {
403
- return D[e] ?? { color: "#6b7280", preview: "·" };
408
+ }, p = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), ne = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
409
+ function P(e) {
410
+ return oe[e] ?? { color: "#6b7280", preview: "·" };
404
411
  }
405
- function j(e) {
412
+ function T(e) {
406
413
  return `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`;
407
414
  }
408
- function A(e, t) {
409
- var p, m;
410
- const l = t.labelFontSize > 0 ? t.labelFontSize : 13, o = Math.max(8, Math.min(48, l)), n = ((p = t.labelFontWeight) == null ? void 0 : p.trim()) || "normal", r = ((m = t.labelColor) == null ? void 0 : m.trim()) || "#333333", h = a(n);
411
- return e.map((i) => {
412
- var u, f, M;
413
- const c = B(i.network), z = ((u = i.backgroundColor) == null ? void 0 : u.trim()) || c.color, b = [
414
- `name="${a(G(i.network))}"`,
415
- `href="${a(i.href)}"`,
416
- `background-color="${a(z)}"`,
417
- `color="${a(r)}"`,
418
- `font-size="${o}px"`,
419
- `font-weight="${h}"`
420
- ].join(" "), k = (f = i.iconSrc) == null ? void 0 : f.trim(), w = k ? `${b} src="${a(k)}"` : b, x = ((M = i.label) == null ? void 0 : M.trim()) ?? "";
421
- return x ? ` <mj-social-element ${w}>
422
- ${J(x)}
423
- </mj-social-element>` : ` <mj-social-element ${w} />`;
415
+ function N(e, t) {
416
+ const o = Math.max(1, Number(e) || 28), n = Number(t);
417
+ if (!Number.isFinite(n) || n <= 0) return "0px";
418
+ const i = o / 2;
419
+ return n >= 999 || n >= i ? "999px" : `${Math.min(n, o)}px`;
420
+ }
421
+ function V(e, t) {
422
+ const o = Math.max(1, Number(e) || 28), n = Number(t);
423
+ if (!Number.isFinite(n) || n <= 0) return "0";
424
+ const i = o / 2;
425
+ return n >= 999 || n >= i ? "50%" : `${Math.min(n, o)}px`;
426
+ }
427
+ function F(e, t = 10) {
428
+ const o = Number(e);
429
+ return !Number.isFinite(o) || o < 0 ? t : Math.min(64, Math.round(o));
430
+ }
431
+ function I(e) {
432
+ return e === "right" ? "flex-end" : e === "left" ? "flex-start" : "center";
433
+ }
434
+ function O(e, t) {
435
+ var a;
436
+ const o = t.labelFontSize > 0 ? t.labelFontSize : 13, n = Math.max(8, Math.min(48, o)), i = k(t.labelFontWeight), r = ((a = t.labelColor) == null ? void 0 : a.trim()) || "#333333", d = p(i);
437
+ return e.map((l) => {
438
+ var v, S, y;
439
+ const c = P(l.network), u = ((v = l.backgroundColor) == null ? void 0 : v.trim()) || c.color, g = [
440
+ `name="${p(Q(l.network))}"`,
441
+ `href="${p(l.href)}"`,
442
+ `background-color="${p(u)}"`,
443
+ `color="${p(r)}"`,
444
+ `font-size="${n}px"`,
445
+ `font-weight="${d}"`
446
+ ].join(" "), w = (S = l.iconSrc) == null ? void 0 : S.trim(), x = w ? `${g} src="${p(w)}"` : g, f = ((y = l.label) == null ? void 0 : y.trim()) ?? "";
447
+ return f ? ` <mj-social-element ${x}>
448
+ ${ne(f)}
449
+ </mj-social-element>` : ` <mj-social-element ${x} />`;
424
450
  }).join(`
425
451
  `);
426
452
  }
427
- const H = [
453
+ const U = [
428
454
  { network: "x", href: "https://x.com/" },
429
455
  { network: "rabbit", href: "https://example.com" },
430
456
  { network: "facebook", href: "https://facebook.com/" },
431
457
  { network: "tiktok", href: "https://www.tiktok.com/" },
432
458
  { network: "ig", href: "https://instagram.com/" }
433
459
  ];
434
- function P(e) {
435
- var l;
436
- if ((l = e.elements) != null && l.length) return e.elements;
460
+ function W(e) {
461
+ var o;
462
+ if ((o = e.elements) != null && o.length) return e.elements;
437
463
  const t = e.links;
438
- return Array.isArray(t) && t.length ? t.map((o) => ({
439
- network: String(o.network ?? "web"),
440
- href: String(o.href ?? "")
441
- })) : H;
464
+ return Array.isArray(t) && t.length ? t.map((n) => ({
465
+ network: String(n.network ?? "web"),
466
+ href: String(n.href ?? "")
467
+ })) : U;
442
468
  }
443
- const Y = d({
469
+ const ie = h({
444
470
  type: "custom:social",
445
471
  name: "社交链接",
446
472
  category: "custom",
447
- icon: s.social,
473
+ icon: m.social,
448
474
  defaultProps: {
449
- elements: H,
475
+ elements: U,
450
476
  align: "center",
451
477
  iconSize: 28,
478
+ iconBorderRadius: 999,
479
+ iconSpacing: 10,
452
480
  labelFontSize: 13,
453
- labelFontWeight: "normal",
481
+ labelFontWeight: "400",
454
482
  labelColor: "#333333",
455
483
  paddingTop: 8,
456
484
  paddingRight: 0,
@@ -462,7 +490,7 @@ const Y = d({
462
490
  key: "elements",
463
491
  label: "社交链接",
464
492
  type: "socialLinkList",
465
- options: V,
493
+ options: ee,
466
494
  help: "平台:X、Rabbit、Facebook、TikTok、Instagram (ig)。可填标签、自定义图标 URL。MJML 侧 Rabbit/TikTok 使用 web 占位图标,需要品牌图时请填「图标 URL」。"
467
495
  },
468
496
  {
@@ -477,22 +505,15 @@ const Y = d({
477
505
  key: "labelFontWeight",
478
506
  label: "标签字重",
479
507
  type: "select",
480
- options: [
481
- { label: "较细 (300)", value: "300" },
482
- { label: "常规", value: "normal" },
483
- { label: "400", value: "400" },
484
- { label: "500", value: "500" },
485
- { label: "600", value: "600" },
486
- { label: "700", value: "700" },
487
- { label: "粗体", value: "bold" },
488
- { label: "更粗 (800)", value: "800" }
489
- ]
508
+ selectVariant: "segmented",
509
+ options: [...L]
490
510
  },
491
511
  { key: "labelColor", label: "标签颜色", type: "color" },
492
512
  {
493
513
  key: "align",
494
514
  label: "对齐",
495
515
  type: "select",
516
+ selectVariant: "segmented",
496
517
  options: [
497
518
  { label: "左", value: "left" },
498
519
  { label: "居中", value: "center" },
@@ -500,44 +521,62 @@ const Y = d({
500
521
  ]
501
522
  },
502
523
  { key: "iconSize", label: "图标尺寸 (px)", type: "number", min: 16, max: 64 },
524
+ {
525
+ key: "iconBorderRadius",
526
+ label: "图标圆角 (px)",
527
+ type: "number",
528
+ min: 0,
529
+ max: 999,
530
+ step: 1,
531
+ help: "0 为方形直角;较大值(如 999)为圆形(默认)。"
532
+ },
533
+ {
534
+ key: "iconSpacing",
535
+ label: "图标间距 (px)",
536
+ type: "number",
537
+ min: 0,
538
+ max: 64,
539
+ step: 1,
540
+ help: "图标之间的间隔(MJML inner-padding)。"
541
+ },
503
542
  { key: "paddingTop", label: "外边距", type: "spacing" }
504
543
  ],
505
544
  toMjml: (e) => {
506
- const t = j(e), l = P(e).filter((r) => {
507
- var h;
508
- return (h = r.href) == null ? void 0 : h.trim();
509
- }), o = {
545
+ const t = T(e), o = N(e.iconSize, e.iconBorderRadius ?? 999), n = F(e.iconSpacing, 10), i = `align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" border-radius="${o}" inner-padding="${n}px" padding="${t}"`, r = W(e).filter((l) => {
546
+ var c;
547
+ return (c = l.href) == null ? void 0 : c.trim();
548
+ }), d = {
510
549
  labelFontSize: Number(e.labelFontSize ?? 13),
511
- labelFontWeight: String(e.labelFontWeight ?? "normal"),
550
+ labelFontWeight: k(String(e.labelFontWeight ?? "400")),
512
551
  labelColor: String(e.labelColor ?? "#333333")
513
- }, n = A(l, o);
514
- return n.trim() ? `<mj-social align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" padding="${t}">
515
- ${n}
516
- </mj-social>` : `<mj-social align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" padding="${t}"></mj-social>`;
552
+ }, a = O(r, d);
553
+ return a.trim() ? `<mj-social ${i}>
554
+ ${a}
555
+ </mj-social>` : `<mj-social ${i}></mj-social>`;
517
556
  },
518
557
  renderPreview: (e) => {
519
- var p, m;
520
- const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, l = Math.max(8, Math.min(48, t)), o = ((p = e.labelFontWeight) == null ? void 0 : p.trim()) || "normal", n = ((m = e.labelColor) == null ? void 0 : m.trim()) || "#333333", r = P(e).filter((i) => {
521
- var c;
522
- return (c = i.href) == null ? void 0 : c.trim();
523
- }).map((i) => {
524
- var x, u, f;
525
- const c = B(i.network), z = ((x = i.backgroundColor) == null ? void 0 : x.trim()) || c.color, $ = ((u = i.label) == null ? void 0 : u.trim()) ?? "", b = (f = i.iconSrc) == null ? void 0 : f.trim(), k = b ? `<img src="${a(b)}" alt="" style="width:${e.iconSize}px;height:${e.iconSize}px;object-fit:contain;border-radius:3px;flex-shrink:0;" />` : `<span style="display:inline-flex;width:${e.iconSize}px;height:${e.iconSize}px;border-radius:50%;background:${z};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(
558
+ var u;
559
+ const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, o = Math.max(8, Math.min(48, t)), n = k(e.labelFontWeight), i = ((u = e.labelColor) == null ? void 0 : u.trim()) || "#333333", r = V(e.iconSize, e.iconBorderRadius ?? 999), d = F(e.iconSpacing, 10), a = I(e.align), l = W(e).filter((s) => {
560
+ var g;
561
+ return (g = s.href) == null ? void 0 : g.trim();
562
+ }).map((s) => {
563
+ var y, z, j;
564
+ const g = P(s.network), w = ((y = s.backgroundColor) == null ? void 0 : y.trim()) || g.color, x = ((z = s.label) == null ? void 0 : z.trim()) ?? "", f = (j = s.iconSrc) == null ? void 0 : j.trim(), v = f ? `<img src="${p(f)}" alt="" style="width:${e.iconSize}px;height:${e.iconSize}px;object-fit:cover;border-radius:${r};flex-shrink:0;" />` : `<span style="display:inline-flex;width:${e.iconSize}px;height:${e.iconSize}px;border-radius:${r};background:${w};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(
526
565
  e.iconSize / 2
527
- )}px;font-weight:600;flex-shrink:0;">${c.preview}</span>`, w = $ ? `<span style="margin-left:6px;font-size:${l}px !important;font-weight:${o};color:${a(
528
- n
529
- )} !important;line-height:1.2;">${a($)}</span>` : "";
530
- return `<span style="display:inline-flex;align-items:center;margin:0 6px;vertical-align:middle;"><a href="${a(
531
- i.href
532
- )}" style="display:inline-flex;align-items:center;text-decoration:none;line-height:0;">${k}</a>${w}</span>`;
533
- }).join("");
534
- return `<div style="padding:${j(e)};text-align:${e.align};">${r || '<span style="color:#9ca3af;font-size:12px;">请填写链接 URL</span>'}</div>`;
566
+ )}px;font-weight:600;flex-shrink:0;overflow:hidden;">${g.preview}</span>`, S = x ? `<span style="font-size:${o}px !important;font-weight:${n};color:${p(
567
+ i
568
+ )} !important;line-height:1.2;">${p(x)}</span>` : "";
569
+ return `<span style="display:inline-flex;align-items:center;gap:6px;"><a href="${p(
570
+ s.href
571
+ )}" style="display:inline-flex;align-items:center;text-decoration:none;line-height:0;">${v}</a>${S}</span>`;
572
+ }).join(""), c = T(e);
573
+ return `<div style="display:flex;flex-wrap:wrap;justify-content:${a};align-items:center;gap:${d}px;padding:${c};">${l || '<span style="color:#9ca3af;font-size:12px;">请填写链接 URL</span>'}</div>`;
535
574
  }
536
- }), Z = d({
575
+ }), le = h({
537
576
  type: "social-group",
538
577
  name: "社交组",
539
578
  category: "content",
540
- icon: s.socialGroup,
579
+ icon: m.socialGroup,
541
580
  defaultProps: {
542
581
  elements: [
543
582
  { network: "weibo", href: "https://weibo.com" },
@@ -545,8 +584,10 @@ ${n}
545
584
  ],
546
585
  align: "center",
547
586
  iconSize: 28,
587
+ iconBorderRadius: 999,
588
+ iconSpacing: 10,
548
589
  labelFontSize: 13,
549
- labelFontWeight: "normal",
590
+ labelFontWeight: "400",
550
591
  labelColor: "#333333",
551
592
  paddingTop: 8,
552
593
  paddingRight: 0,
@@ -558,7 +599,7 @@ ${n}
558
599
  key: "elements",
559
600
  label: "社交链接",
560
601
  type: "socialLinkList",
561
- options: X,
602
+ options: te,
562
603
  help: "每行:平台、链接、可选标签文字、自定义图标 URL、图标背景色。标签的字号/字重/颜色在下方统一设置。"
563
604
  },
564
605
  {
@@ -573,22 +614,15 @@ ${n}
573
614
  key: "labelFontWeight",
574
615
  label: "标签字重",
575
616
  type: "select",
576
- options: [
577
- { label: "较细 (300)", value: "300" },
578
- { label: "常规", value: "normal" },
579
- { label: "400", value: "400" },
580
- { label: "500", value: "500" },
581
- { label: "600", value: "600" },
582
- { label: "700", value: "700" },
583
- { label: "粗体", value: "bold" },
584
- { label: "更粗 (800)", value: "800" }
585
- ]
617
+ selectVariant: "segmented",
618
+ options: [...L]
586
619
  },
587
620
  { key: "labelColor", label: "标签颜色", type: "color" },
588
621
  {
589
622
  key: "align",
590
623
  label: "对齐",
591
624
  type: "select",
625
+ selectVariant: "segmented",
592
626
  options: [
593
627
  { label: "左", value: "left" },
594
628
  { label: "居中", value: "center" },
@@ -596,60 +630,78 @@ ${n}
596
630
  ]
597
631
  },
598
632
  { key: "iconSize", label: "图标尺寸 (px)", type: "number", min: 16, max: 64 },
633
+ {
634
+ key: "iconBorderRadius",
635
+ label: "图标圆角 (px)",
636
+ type: "number",
637
+ min: 0,
638
+ max: 999,
639
+ step: 1,
640
+ help: "0 为方形直角;填较大值(如 999)或与尺寸一半相当时为圆形(默认圆形)。"
641
+ },
642
+ {
643
+ key: "iconSpacing",
644
+ label: "图标间距 (px)",
645
+ type: "number",
646
+ min: 0,
647
+ max: 64,
648
+ step: 1,
649
+ help: "每个图标周围的留白,横向即图标之间的间隔(MJML inner-padding)。"
650
+ },
599
651
  { key: "paddingTop", label: "外边距", type: "spacing" }
600
652
  ],
601
653
  toMjml: (e) => {
602
- const t = j(e), l = e.elements.filter((r) => {
603
- var h;
604
- return (h = r.href) == null ? void 0 : h.trim();
605
- }), o = {
654
+ const t = T(e), o = N(e.iconSize, e.iconBorderRadius ?? 999), n = F(e.iconSpacing, 10), i = `align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" border-radius="${o}" inner-padding="${n}px" padding="${t}"`, r = e.elements.filter((l) => {
655
+ var c;
656
+ return (c = l.href) == null ? void 0 : c.trim();
657
+ }), d = {
606
658
  labelFontSize: Number(e.labelFontSize ?? 13),
607
- labelFontWeight: String(e.labelFontWeight ?? "normal"),
659
+ labelFontWeight: k(String(e.labelFontWeight ?? "400")),
608
660
  labelColor: String(e.labelColor ?? "#333333")
609
- }, n = A(l, o);
610
- return n.trim() ? `<mj-social align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" padding="${t}">
611
- ${n}
612
- </mj-social>` : `<mj-social align="${e.align}" icon-size="${e.iconSize}px" mode="horizontal" padding="${t}"></mj-social>`;
661
+ }, a = O(r, d);
662
+ return a.trim() ? `<mj-social ${i}>
663
+ ${a}
664
+ </mj-social>` : `<mj-social ${i}></mj-social>`;
613
665
  },
614
666
  renderPreview: (e) => {
615
- var p, m;
616
- const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, l = Math.max(8, Math.min(48, t)), o = ((p = e.labelFontWeight) == null ? void 0 : p.trim()) || "normal", n = ((m = e.labelColor) == null ? void 0 : m.trim()) || "#333333", r = e.elements.filter((i) => {
617
- var c;
618
- return (c = i.href) == null ? void 0 : c.trim();
619
- }).map((i) => {
620
- var x, u, f;
621
- const c = B(i.network), z = ((x = i.backgroundColor) == null ? void 0 : x.trim()) || c.color, $ = ((u = i.label) == null ? void 0 : u.trim()) ?? "", b = (f = i.iconSrc) == null ? void 0 : f.trim(), k = b ? `<img src="${a(b)}" alt="" style="width:${e.iconSize}px;height:${e.iconSize}px;object-fit:contain;border-radius:3px;flex-shrink:0;" />` : `<span style="display:inline-flex;width:${e.iconSize}px;height:${e.iconSize}px;border-radius:50%;background:${z};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(
667
+ var u;
668
+ const t = e.labelFontSize != null && e.labelFontSize > 0 ? e.labelFontSize : 13, o = Math.max(8, Math.min(48, t)), n = k(e.labelFontWeight), i = ((u = e.labelColor) == null ? void 0 : u.trim()) || "#333333", r = V(e.iconSize, e.iconBorderRadius ?? 999), d = F(e.iconSpacing, 10), a = I(e.align), l = e.elements.filter((s) => {
669
+ var g;
670
+ return (g = s.href) == null ? void 0 : g.trim();
671
+ }).map((s) => {
672
+ var y, z, j;
673
+ const g = P(s.network), w = ((y = s.backgroundColor) == null ? void 0 : y.trim()) || g.color, x = ((z = s.label) == null ? void 0 : z.trim()) ?? "", f = (j = s.iconSrc) == null ? void 0 : j.trim(), v = f ? `<img src="${p(f)}" alt="" style="width:${e.iconSize}px;height:${e.iconSize}px;object-fit:cover;border-radius:${r};flex-shrink:0;" />` : `<span style="display:inline-flex;width:${e.iconSize}px;height:${e.iconSize}px;border-radius:${r};background:${w};color:#fff;align-items:center;justify-content:center;font-size:${Math.round(
622
674
  e.iconSize / 2
623
- )}px;font-weight:600;flex-shrink:0;">${c.preview}</span>`, w = $ ? `<span style="margin-left:6px;font-size:${l}px !important;font-weight:${o};color:${a(
624
- n
625
- )} !important;line-height:1.2;">${a($)}</span>` : "";
626
- return `<span style="display:inline-flex;align-items:center;margin:0 6px;vertical-align:middle;"><a href="${a(
627
- i.href
628
- )}" style="display:inline-flex;align-items:center;text-decoration:none;line-height:0;">${k}</a>${w}</span>`;
629
- }).join("");
630
- return `<div style="padding:${j(e)};text-align:${e.align};">${r || '<span style="color:#9ca3af;font-size:12px;">请添加社交链接</span>'}</div>`;
675
+ )}px;font-weight:600;flex-shrink:0;overflow:hidden;">${g.preview}</span>`, S = x ? `<span style="font-size:${o}px !important;font-weight:${n};color:${p(
676
+ i
677
+ )} !important;line-height:1.2;">${p(x)}</span>` : "";
678
+ return `<span style="display:inline-flex;align-items:center;gap:6px;"><a href="${p(
679
+ s.href
680
+ )}" style="display:inline-flex;align-items:center;text-decoration:none;line-height:0;">${v}</a>${S}</span>`;
681
+ }).join(""), c = T(e);
682
+ return `<div style="display:flex;flex-wrap:wrap;justify-content:${a};align-items:center;gap:${d}px;padding:${c};">${l || '<span style="color:#9ca3af;font-size:12px;">请添加社交链接</span>'}</div>`;
631
683
  }
632
- }), Q = d({
684
+ }), re = h({
633
685
  type: "spacer",
634
686
  name: "间距",
635
687
  category: "content",
636
- icon: s.spacer,
688
+ icon: m.spacer,
637
689
  defaultProps: { height: 24 },
638
690
  schema: [{ key: "height", label: "高度 (px)", type: "number", min: 1, max: 200 }],
639
691
  toMjml: (e) => `<mj-spacer height="${e.height}px" />`,
640
692
  renderPreview: (e) => `<div style="height:${e.height}px;line-height:${e.height}px;"></div>`
641
- }), S = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), ee = d({
693
+ }), B = (e) => e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;"), ae = h({
642
694
  type: "text",
643
695
  name: "文本",
644
696
  category: "content",
645
- icon: s.text,
697
+ icon: m.text,
646
698
  defaultProps: {
647
699
  content: '<p style="margin:0;">在此处输入文本。<strong>双击</strong>进入编辑模式,<em>选中文字</em>会出现工具条;支持变量 {{user.name}}</p>',
648
700
  align: "left",
649
- color: "#433f3f",
650
- fontSize: "16px",
701
+ color: "",
702
+ fontSize: "",
651
703
  fontFamily: "",
652
- fontWeight: "normal",
704
+ fontWeight: "",
653
705
  lineHeight: "",
654
706
  paddingTop: 8,
655
707
  paddingRight: 0,
@@ -659,27 +711,25 @@ ${n}
659
711
  schema: [
660
712
  {
661
713
  key: "align",
662
- label: "默认对齐",
714
+ label: "对齐",
663
715
  type: "select",
716
+ selectVariant: "segmented",
664
717
  options: [
665
718
  { label: "左", value: "left" },
666
719
  { label: "居中", value: "center" },
667
720
  { label: "右", value: "right" }
668
721
  ]
669
722
  },
670
- { key: "color", label: "默认颜色", type: "color" },
671
- { key: "fontSize", label: "默认字号", type: "text", placeholder: "14px" },
723
+ { key: "color", label: "颜色", type: "color", placeholder: "继承全局" },
724
+ { key: "fontSize", label: "字号", type: "text", inheritGlobal: !0 },
672
725
  { key: "fontFamily", label: "字体", type: "text", placeholder: "继承全局" },
673
726
  {
674
727
  key: "fontWeight",
675
728
  label: "字重",
676
729
  type: "select",
677
- options: [
678
- { label: "常规 400", value: "normal" },
679
- { label: "中等 500", value: "500" },
680
- { label: "半粗 600", value: "600" },
681
- { label: "加粗 700", value: "bold" }
682
- ]
730
+ selectVariant: "segmented",
731
+ inheritGlobal: !0,
732
+ options: [...L]
683
733
  },
684
734
  {
685
735
  key: "lineHeight",
@@ -717,39 +767,48 @@ ${n}
717
767
  placeholder: "输入文本…"
718
768
  },
719
769
  toMjml: (e) => {
720
- const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, l = e.fontFamily ? ` font-family="${S(e.fontFamily)}"` : "", o = e.fontWeight && e.fontWeight !== "normal" ? ` font-weight="${e.fontWeight}"` : "", n = String(e.lineHeight ?? "").trim(), r = n ? ` line-height="${S(n)}"` : "";
721
- return `<mj-text align="${e.align}" color="${S(e.color)}" font-size="${S(
722
- e.fontSize
723
- )}"${r}${l}${o} padding="${t}">${e.content}</mj-text>`;
770
+ const t = `${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px`, o = e.fontFamily ? ` font-family="${B(e.fontFamily)}"` : "", n = String(e.fontWeight ?? "").trim(), i = n ? ` font-weight="${B(k(n))}"` : "", r = String(e.lineHeight ?? "").trim(), d = r ? ` line-height="${B(r)}"` : "", a = String(e.color ?? "").trim(), l = a ? ` color="${B(a)}"` : "", c = String(e.fontSize ?? "").trim(), u = c ? ` font-size="${B(c)}"` : "";
771
+ return `<mj-text align="${e.align}"${l}${u}${d}${o}${i} padding="${t}">${e.content}</mj-text>`;
724
772
  },
725
773
  renderPreview: (e) => {
726
- const t = e.fontFamily ? `font-family:${e.fontFamily};` : "", l = e.fontWeight && e.fontWeight !== "normal" ? `font-weight:${e.fontWeight};` : "", o = String(e.lineHeight ?? "").trim(), n = o ? `line-height:${o};` : "line-height:normal;";
727
- return `<div class="sm-text-content" style="text-align:${e.align};color:${e.color};font-size:${e.fontSize};${n}${t}${l}padding:${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px;">${e.content}</div>`;
774
+ const t = e.fontFamily ? `font-family:${e.fontFamily};` : "", o = String(e.fontWeight ?? "").trim(), n = o ? `font-weight:${k(o)};` : "", i = String(e.lineHeight ?? "").trim(), r = i ? `line-height:${i};` : "line-height:normal;", d = String(e.color ?? "").trim(), a = d ? `color:${d};` : "", l = String(e.fontSize ?? "").trim(), c = l ? `font-size:${l};` : "";
775
+ return `<div class="sm-text-content" style="text-align:${e.align};${a}${c}${n}${r}${t}padding:${e.paddingTop}px ${e.paddingRight}px ${e.paddingBottom}px ${e.paddingLeft}px;">${e.content}</div>`;
728
776
  }
729
- }), te = [
730
- ee,
777
+ }), ce = [
778
+ ae,
779
+ D,
780
+ Y,
781
+ le,
782
+ X,
731
783
  q,
732
- _,
733
- Z,
734
- I,
735
- N,
736
- O,
737
- Q
738
- ], le = [K, Y, U], ne = [...te, ...le];
784
+ K,
785
+ re
786
+ ], se = [Z, ie, J], ge = [...ce, ...se];
739
787
  export {
740
- ne as allBlocks,
741
- te as builtinBlocks,
742
- N as buttonBlock,
743
- O as dividerBlock,
744
- le as exampleCustomBlocks,
745
- U as footerBlock,
746
- I as heroBlock,
747
- q as htmlBlock,
748
- _ as imageBlock,
749
- K as logoBlock,
750
- Y as socialBlock,
751
- Z as socialGroupBlock,
752
- Q as spacerBlock,
753
- ee as textBlock
788
+ te as SOCIAL_NETWORK_OPTIONS,
789
+ ge as allBlocks,
790
+ ce as builtinBlocks,
791
+ q as buttonBlock,
792
+ K as dividerBlock,
793
+ p as escAttr,
794
+ ne as escMjmlText,
795
+ se as exampleCustomBlocks,
796
+ I as flexJustifyFromAlign,
797
+ J as footerBlock,
798
+ X as heroBlock,
799
+ D as htmlBlock,
800
+ Y as imageBlock,
801
+ Z as logoBlock,
802
+ Q as mjSocialElementName,
803
+ O as mjSocialElementsLines,
804
+ T as paddingQuad,
805
+ ie as socialBlock,
806
+ le as socialGroupBlock,
807
+ V as socialIconBorderRadiusCss,
808
+ N as socialIconBorderRadiusMjml,
809
+ F as socialIconSpacingPx,
810
+ P as socialMeta,
811
+ re as spacerBlock,
812
+ ae as textBlock
754
813
  };
755
814
  //# sourceMappingURL=index.js.map