mail-editor-pancake 0.0.9 → 0.1.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 (42) hide show
  1. package/README.md +461 -303
  2. package/package.json +2 -2
  3. package/packages/blocks/dist/index.js +153 -150
  4. package/packages/blocks/dist/index.js.map +1 -1
  5. package/packages/blocks/src/html.ts +11 -3
  6. package/packages/blocks/src/text.ts +8 -3
  7. package/packages/core/dist/index.d.ts +220 -10
  8. package/packages/core/dist/index.js +3963 -2250
  9. package/packages/core/dist/index.js.map +1 -1
  10. package/packages/core/dist/style.css +1 -1
  11. package/packages/core/package.json +1 -1
  12. package/packages/core/src/editor/BlockCodeModal.ts +84 -2
  13. package/packages/core/src/editor/Canvas.ts +182 -26
  14. package/packages/core/src/editor/Editor.ts +414 -68
  15. package/packages/core/src/editor/ExportModal.ts +1 -1
  16. package/packages/core/src/editor/ImportDocModal.ts +129 -0
  17. package/packages/core/src/editor/InlineEditor.ts +238 -24
  18. package/packages/core/src/editor/LeftPanel.ts +55 -14
  19. package/packages/core/src/editor/Modal.ts +20 -1
  20. package/packages/core/src/editor/PreviewModal.ts +2 -2
  21. package/packages/core/src/editor/RichTextToolbar.ts +125 -18
  22. package/packages/core/src/editor/RightPanel.ts +165 -7
  23. package/packages/core/src/editor/Topbar.ts +306 -132
  24. package/packages/core/src/editor/VariablePickerPanel.ts +145 -0
  25. package/packages/core/src/editor/styles.css +410 -52
  26. package/packages/core/src/index.ts +32 -2
  27. package/packages/core/src/renderer/index.ts +9 -1
  28. package/packages/core/src/renderer/mjml.ts +4 -5
  29. package/packages/core/src/store/store.ts +13 -2
  30. package/packages/core/src/types.ts +65 -2
  31. package/packages/core/src/utils/docClipboard.ts +89 -0
  32. package/packages/core/src/utils/dynamicVariantHtml.ts +45 -0
  33. package/packages/core/src/utils/dynamicVariantKey.ts +24 -0
  34. package/packages/core/src/utils/dynamicVariantSection.ts +98 -0
  35. package/packages/core/src/utils/emailListStyles.ts +188 -0
  36. package/packages/core/src/utils/inlineListEditing.ts +774 -0
  37. package/packages/core/src/utils/lockedMjml.ts +146 -12
  38. package/packages/core/src/utils/modalSize.ts +27 -0
  39. package/packages/core/src/utils/richHtmlEmpty.ts +43 -0
  40. package/packages/core/src/utils/sectionLayout.ts +2 -2
  41. package/packages/core/src/variables/index.ts +3 -4
  42. package/playground/vanilla/src/main.ts +26 -1
@@ -1,3 +1,14 @@
1
+ /**
2
+ * 编译后为带 `dynamicVariantKey` 的 Section 根节点写入 `data-dv="{key}"`,供宿主 DOM 抽取。
3
+ */
4
+ export declare function annotateDynamicVariantHtmlAttributes(html: string, doc: EmailDoc): string;
5
+
6
+ /**
7
+ * 向富文本 HTML 末尾「行内」追加内容,避免落在 `</p>` 外产生换行。
8
+ * 无块级标签时包一层 `<p style="margin:0;">`。
9
+ */
10
+ export declare function appendInlineToRichHtml(html: string, insert: string): string;
11
+
1
12
  /**
2
13
  * Block 是注册表驱动的:所有内置/自定义组件都遵循同一个数据形状。
3
14
  * 渲染、属性面板、代码模式三方都从注册表读取该 type 的定义。
@@ -22,8 +33,10 @@ export declare interface BlockDefinition<P extends object = Record<string, unkno
22
33
  type: string;
23
34
  /** 显示名(左栏) */
24
35
  name: string;
25
- /** 分类,用于左栏分组 */
36
+ /** 分类,用于左栏分组与定制块角标 */
26
37
  category: 'content' | 'custom';
38
+ /** 左栏卡片悬停提示;未设时 custom 类块使用 UI 默认后缀 */
39
+ paletteTooltip?: string;
27
40
  /** 16x16 SVG 字符串 */
28
41
  icon: string;
29
42
  /** 默认 props(拖入时使用) */
@@ -49,7 +62,14 @@ export declare interface BlockDefinition<P extends object = Record<string, unkno
49
62
  * 用于「组合模板」:画布内仅为通用 image/text 等,便于逐项修改。
50
63
  * 文档里不会出现本定义的 `type`,仅作左栏入口;若需提供请返回内置块的实例。
51
64
  */
52
- expandPaletteDrop?: (createBlock: (type: string) => Block) => Block[];
65
+ expandPaletteDrop?: (createBlock: (type: string) => Block) => Block[] | PaletteDropResult;
66
+ }
67
+
68
+ declare interface BlockPaddingBox {
69
+ top: number;
70
+ right: number;
71
+ bottom: number;
72
+ left: number;
53
73
  }
54
74
 
55
75
  export declare interface BlockSchemaField {
@@ -111,17 +131,28 @@ declare interface ColumnAttrs {
111
131
 
112
132
  export declare function createSection(layout: SectionLayout): Section;
113
133
 
114
- /** 无后端 sample 时按 kind / label 生成预览用示例值(仅预览弹窗等场景) */
134
+ /** 无显式 sample 时保留 Mustache 占位符;仅当宿主传入 sample 才用于可选的示例替换。 */
115
135
  export declare function defaultVariableSample(v: Pick<Variable, 'key' | 'label' | 'kind' | 'sample'>): string;
116
136
 
117
137
  /** 工厂函数,便于外部以函数式风格定义组件。 */
118
138
  export declare function defineBlock<P extends object>(def: BlockDefinition<P>): BlockDefinition<P>;
119
139
 
140
+ export declare const DOC_CLIPBOARD_FORMAT_VERSION: 1;
141
+
142
+ /** 剪贴板 / 文件 interchange 信封标识 */
143
+ export declare const DOC_CLIPBOARD_KIND: "simple-mail/doc";
144
+
120
145
  /** 文档变更通知来源(右栏等可按来源决定是否保留焦点) */
121
146
  declare type DocChangedDetail = {
122
147
  source: 'mutate' | 'history' | 'replace';
123
148
  };
124
149
 
150
+ export declare interface DocClipboardEnvelope {
151
+ kind: typeof DOC_CLIPBOARD_KIND;
152
+ formatVersion: typeof DOC_CLIPBOARD_FORMAT_VERSION;
153
+ doc: EmailDoc;
154
+ }
155
+
125
156
  /**
126
157
  * 内容区 / 按钮等「布局宽度」解析:数字与无单位数字按 px;支持显式 `px` 与 `%`。
127
158
  */
@@ -136,6 +167,13 @@ export declare function docContentWidthCss(raw: unknown): string;
136
167
  */
137
168
  export declare function docToMjml(doc: EmailDoc, registry: Registry): string;
138
169
 
170
+ /**
171
+ * 导出 HTML 上标记动态变量组合的宿主约定属性名(值为 `Section.attrs.dynamicVariantKey`)。
172
+ */
173
+ export declare const DYNAMIC_VARIANT_HTML_ATTR = "data-dv";
174
+
175
+ export declare function dynamicVariantPlaceholder(key: string): string;
176
+
139
177
  export declare interface EditorEvents {
140
178
  change: {
141
179
  doc: EmailDoc;
@@ -230,6 +268,45 @@ export declare interface EditorUiOptions {
230
268
  hideTopbarClearCanvas?: boolean;
231
269
  /** 为 true 时隐藏顶栏「重置内容」按钮。 */
232
270
  hideTopbarResetContent?: boolean;
271
+ /** 为 true 时隐藏顶栏「复制设计稿」「导入设计稿」按钮。 */
272
+ hideTopbarDocClipboard?: boolean;
273
+ /** 为 true 时隐藏顶栏「插入变量」按钮(由宿主在编辑器外提供时可用)。 */
274
+ hideTopbarInsertVariable?: boolean;
275
+ /**
276
+ * 为 true 时顶栏默认可切换为仅图标(文案收入 `title` / `aria-label`),适合窄屏或嵌入宿主。
277
+ * 默认 false;嵌入场景可在宿主侧设为 true。
278
+ */
279
+ topbarCompact?: boolean;
280
+ /**
281
+ * 顶栏按钮文案展示策略(在 `topbarCompact === true` 时生效)。
282
+ * - `auto`(默认):仅图标;根节点进入浏览器全屏或宽度 ≥ `topbarCompactMinWidth` 时展示文案。
283
+ * - `never`:始终仅图标(含全屏与宽屏)。
284
+ * - `always`:始终展示图标旁文案(等同不启用紧凑顶栏)。
285
+ */
286
+ topbarLabels?: 'always' | 'never' | 'auto';
287
+ /**
288
+ * `topbarLabels: 'auto'` 时,根节点宽度不低于该值(px)则展示顶栏文案。默认 1200。
289
+ */
290
+ topbarCompactMinWidth?: number;
291
+ /**
292
+ * @deprecated 左栏已合并为单组,请用 `paletteBlockGroupTitle`。
293
+ * 仍兼容:仅 `content` 键会作为合并后分组标题的回退。
294
+ */
295
+ blockCategoryLabels?: Partial<Record<BlockDefinition['category'], string>>;
296
+ /** 左栏合并后的组件分组标题,默认「组件」。 */
297
+ paletteBlockGroupTitle?: string;
298
+ /** custom 类块无 `paletteTooltip` 时拼入 title 的说明后缀。 */
299
+ customPaletteTooltipSuffix?: string;
300
+ /**
301
+ * 仍注册、渲染、可被 palette 展开引用,但不显示在左栏的 block type(如组合块内部用的 divider)。
302
+ */
303
+ hiddenPaletteBlockTypes?: string[];
304
+ /**
305
+ * 为 true 时:右栏 Section 可配置「动态变量名」、画布展示动态变量节标识,
306
+ * 左栏拖入带 `sectionAttrs.dynamicVariantKey` 的组合块会创建动态变量 Section。
307
+ * 默认 false;宿主(如后管)按需开启。已写入文档的 key 仍会在导出时生效。
308
+ */
309
+ enableDynamicVariantKey?: boolean;
233
310
  }
234
311
 
235
312
  /**
@@ -256,6 +333,22 @@ export declare interface EmailMeta {
256
333
  width: number | string;
257
334
  }
258
335
 
336
+ /**
337
+ * 将带 `dynamicVariantKey` 的 Section 从全文 HTML 中替换为占位符,并返回各 key 的编译 HTML。
338
+ * 优先使用导出 HTML 上的 `data-dv="{key}"` 标记。
339
+ */
340
+ export declare function extractDynamicVariantSlots(html: string, doc: EmailDoc, registry: Registry): ExtractDynamicVariantSlotsResult;
341
+
342
+ export declare interface ExtractDynamicVariantSlotsResult {
343
+ html: string;
344
+ variants: Record<string, string>;
345
+ }
346
+
347
+ /**
348
+ * 从锁定 MJML 片段提取可在画布内渲染的 HTML;无法识别时返回 null(回退源码视图)。
349
+ */
350
+ export declare function extractPreviewHtmlFromLockedMjml(lockedMjml: string): string | null;
351
+
259
352
  export declare function findBlockLocation(doc: EmailDoc, blockId: string): {
260
353
  section: Section;
261
354
  columnIndex: number;
@@ -283,6 +376,9 @@ export declare interface GalleryItem {
283
376
  title?: string;
284
377
  }
285
378
 
379
+ /** 本节导出后替换为 `{{dynamicVariantKey}}`,内容由宿主写入 dynamicVariant */
380
+ export declare function getSectionDynamicVariantKey(section: Section): string | undefined;
381
+
286
382
  export declare interface GlobalStyles {
287
383
  backgroundColor: string;
288
384
  contentBackgroundColor: string;
@@ -294,8 +390,16 @@ export declare interface GlobalStyles {
294
390
  linkColor: string;
295
391
  /** 无单位倍数(如 1.25)或固定值(如 24px) */
296
392
  lineHeight: string;
393
+ /**
394
+ * 未单独设置缩进的列表使用的全局左缩进(px)。
395
+ * 不设时等价于内置默认 24px。
396
+ */
397
+ listIndentDefaultPx?: number;
297
398
  }
298
399
 
400
+ /** HTML 块内容是否误含 MJML 标签(应只写 HTML,MJML 标签在 mj-raw 内不会被编译)。 */
401
+ export declare function htmlContainsMjmlTags(html: string): boolean;
402
+
299
403
  export declare interface ImageAssetsHandlers {
300
404
  /**
301
405
  * 用户点击右侧「上传」并选择本地文件。宿主完成上传后返回 **绝对 HTTPS URL**。
@@ -371,6 +475,17 @@ declare interface InlineEditableConfig<P extends object = Record<string, unknown
371
475
  placeholder?: string;
372
476
  }
373
477
 
478
+ export declare function isDynamicVariantSection(section: Section): boolean;
479
+
480
+ export declare function isMultiColumnLayout(layout: SectionLayout): layout is MultiColumnLayout;
481
+
482
+ /**
483
+ * 富文本是否「完全无内容」。
484
+ * 空格、&nbsp;、换行(<br>)均视为有效内容;仅空串或空标签壳子算空。
485
+ */
486
+ export declare function isRichHtmlEffectivelyEmpty(html: string): boolean;
487
+
488
+ /** @deprecated 使用 isMultiColumnLayout */
374
489
  export declare function isTwoColumnLayout(layout: SectionLayout): layout is TwoColumnLayout;
375
490
 
376
491
  declare type Listener = (detail?: DocChangedDetail) => void;
@@ -401,6 +516,10 @@ export declare class MailEditor {
401
516
  private sourceView;
402
517
  private toolbar;
403
518
  private body;
519
+ /** 浮层(变量列表、toast),避免挂到 grid 的 .sm-root 上被挤成窄条 */
520
+ private overlayLayer;
521
+ /** design 态右栏变量列表:未固定时点击外部收起 */
522
+ private variablePickerOutsideClick;
404
523
  private changeTimer;
405
524
  /** 显式品牌色时覆盖 CSS 变量;未设置则由 styles 按 light/dark 使用默认紫/靛 */
406
525
  private accentColorOverride;
@@ -410,16 +529,25 @@ export declare class MailEditor {
410
529
  private presetContentDoc;
411
530
  /** 宿主通过 setVariables 注入的列表;setValue 恢复文档后仍会写回,避免被 doc JSON 里的空数组覆盖 */
412
531
  private configuredVariables;
532
+ private importDocModal;
533
+ private topbarLayoutObserver;
534
+ private topbarLayoutRaf;
413
535
  private systemThemeMq;
414
536
  private readonly _onSystemThemeMqChange;
415
537
  private readonly _onFullscreenChange;
416
538
  /** design 态 Esc:块 → 父级 Section → 文档级面板(邮件设置或版式/全局样式,取决于 `ui.hideMailMeta`) */
417
539
  private _mailEscHandler;
418
540
  /**
419
- * 文档级撤销/重做(捕获阶段):焦点在右栏 input/CodeMirror 内时,冒泡到 root 的监听太晚,
420
- * 浏览器会先处理控件内撤销;仅在 store 仍有历史时拦截并走全局 undo/redo。
541
+ * 文档级撤销/重做(捕获阶段)。
542
+ * - 画布内联 contenteditable:交给浏览器撤销文字,不走 store。
543
+ * - 右栏 input / CodeMirror:控件自带撤销,不走 store。
544
+ * - 其余区域:在 store 有历史时拦截并 undo/redo 整份文档。
421
545
  */
422
546
  private _mailUndoRedoHandler;
547
+ /** 内联编辑、右栏表单等应使用控件/浏览器本地撤销,而非文档 history */
548
+ private _shouldDeferToLocalUndoRedo;
549
+ private _storeUndo;
550
+ private _storeRedo;
423
551
  constructor(opts: EditorOptions);
424
552
  setValue(doc: EmailDoc): void;
425
553
  getValue(): EmailDoc;
@@ -428,7 +556,10 @@ export declare class MailEditor {
428
556
  * 会提交内联编辑并清空选中。
429
557
  */
430
558
  clearCanvas(): void;
431
- /** 将画布恢复为构造时 `presetDoc`(或 `initialDoc`)对应的预置内容。 */
559
+ /**
560
+ * 将画布恢复为 `presetDoc` 快照(未传时等同构造时的预置合并结果)。
561
+ * 记入撤销栈(⌘Z 可恢复);与 `setValue` 不同,不会清空 history。
562
+ */
432
563
  resetToPreset(): void;
433
564
  /** 更新「重置内容」的目标(例如宿主异步加载默认模板后)。 */
434
565
  setPresetDoc(partial: Partial<EmailDoc>): void;
@@ -461,6 +592,17 @@ export declare class MailEditor {
461
592
  export(opts?: {
462
593
  withSampleVariables?: boolean;
463
594
  }): RenderResult;
595
+ /**
596
+ * 将当前画布设计稿(EmailDoc JSON 信封)写入剪贴板,供另一实例「导入设计稿」使用。
597
+ */
598
+ copyDocDesign(): Promise<boolean>;
599
+ /** 打开导入设计稿对话框(从剪贴板或手动粘贴 JSON,覆盖当前画布)。 */
600
+ openImportDocDesign(): void;
601
+ /**
602
+ * 程序化导入设计稿(与对话框「应用」相同逻辑)。
603
+ * @returns 是否成功解析并应用
604
+ */
605
+ importDocDesignFromJson(raw: string): boolean;
464
606
  registerBlock<P extends object>(def: BlockDefinition<P>): void;
465
607
  setSelection(sel: Selection_2 | null): void;
466
608
  destroy(): void;
@@ -479,13 +621,33 @@ export declare class MailEditor {
479
621
  private _setMode;
480
622
  private _bindKeyboard;
481
623
  private _onChange;
482
- private _showVariablePopover;
624
+ private _unbindVariablePickerOutsideClick;
625
+ private _bindVariablePickerOutsideClick;
626
+ private _closeVariablePicker;
627
+ private _toggleVariablePanel;
628
+ private _dismissVariablePopover;
629
+ /** 源码模式无右栏时仍用浮层选择变量 */
630
+ private _toggleVariablePopover;
483
631
  private _showToast;
484
632
  private _insertImageVariable;
633
+ /**
634
+ * 按当前选中插入块:block → 其后;section → 该 section 首列末尾;无选中 → 文档最后一节首列末尾。
635
+ */
636
+ private _insertBlockRelativeToSelection;
637
+ /** 链接变量:写入图片/按钮等块的 `href`(MJML 可点击),而非 alt 或右栏纯文本。 */
638
+ private _tryApplyLinkVariableToken;
639
+ private _schemaUrlPropKey;
640
+ private _setBlockUrlProp;
485
641
  /** 在焦点处插入文本或 HTML;失败时返回 false */
486
642
  private _insertAtFocus;
643
+ private _ensureImportDocModal;
644
+ private _applyImportedDoc;
487
645
  private _showExport;
488
646
  private _showPreview;
647
+ private _topbarLayoutContext;
648
+ private _syncTopbarLayout;
649
+ private _bindTopbarLayoutWatch;
650
+ private _unbindTopbarLayoutWatch;
489
651
  private _bindFullscreen;
490
652
  private _unbindFullscreen;
491
653
  private _toggleFullscreen;
@@ -516,9 +678,17 @@ export declare function mjRawCellTypographyFromStyles(s: GlobalStyles): MjRawCel
516
678
  */
517
679
  export declare function mjRawEmailTableWrap(paddingCss: string, cellInnerHtml: string, typo: MjRawCellTypography): string;
518
680
 
681
+ /** 多列 Section 的列布局(左栏拖入默认 `1-1`,右栏可切换列数/比例) */
682
+ export declare const MULTI_COLUMN_LAYOUTS: readonly ["1-1", "1-2", "2-1", "1-1-1"];
683
+
684
+ export declare type MultiColumnLayout = (typeof MULTI_COLUMN_LAYOUTS)[number];
685
+
519
686
  /** 将任意历史写法映射到最近一档(normal→400,bold→700 等) */
520
687
  export declare function normalizeFontWeightStep(raw: string | undefined | null): FontWeightStep;
521
688
 
689
+ /** 提交前:完全无内容时统一为 '' */
690
+ export declare function normalizeRichHtmlForCommit(html: string): string;
691
+
522
692
  /** 规范化 Variable(补 kind、sample) */
523
693
  export declare function normalizeVariable(v: Variable): Variable;
524
694
 
@@ -535,6 +705,17 @@ export declare interface OpenImageGalleryModalOptions {
535
705
  onClose?: () => void;
536
706
  }
537
707
 
708
+ /** 左栏组合拖入:可附带新建 Section 的 attrs(如 meta 扩展袋) */
709
+ export declare interface PaletteDropResult {
710
+ blocks: Block[];
711
+ sectionAttrs?: Partial<SectionAttrs>;
712
+ }
713
+
714
+ /**
715
+ * 解析剪贴板或手动粘贴的 JSON。支持信封格式与裸 `EmailDoc`(version: '1')。
716
+ */
717
+ export declare function parseDocClipboard(raw: string): EmailDoc | null;
718
+
538
719
  /** 右栏输入解析存库:纯整数可存 number,其它存 string */
539
720
  export declare function parseMetaWidthFromUserInput(input: string): number | string;
540
721
 
@@ -552,6 +733,9 @@ export declare function pruneEmptySections(draft: EmailDoc): void;
552
733
  */
553
734
  export declare function pruneSectionIfEmpty(draft: EmailDoc, sectionId: string): void;
554
735
 
736
+ /** 导入前重生成 section / column / block id,避免与当前文档冲突。 */
737
+ export declare function regenerateDocIds(doc: EmailDoc): EmailDoc;
738
+
555
739
  /**
556
740
  * 组件注册表。所有内置/自定义组件都通过 `defineBlock` 注册进来;
557
741
  * 渲染、属性面板、左栏拖拽源、组件级代码模式四方都从这里读取。
@@ -582,7 +766,8 @@ declare interface RenderOptions {
582
766
  /** 渲染引擎,目前仅 'mjml';'table' 预留作将来直输 table HTML。 */
583
767
  engine?: RenderEngine;
584
768
  /**
585
- * 是否把 {{var}} 替换为示例值。设计态画布预览传 true,导出原始 HTML 传 false。
769
+ * 是否把 {{var}} 替换为变量的 sample 值。
770
+ * 设计态预览默认不替换,保持占位符;仅当变量显式配置了 sample 且调用方传 true 时才替换。
586
771
  */
587
772
  withSampleVariables?: boolean;
588
773
  }
@@ -595,12 +780,24 @@ declare interface RenderResult {
595
780
  }[];
596
781
  }
597
782
 
783
+ /** 仅编译某一 Section,返回邮件 body 内 HTML 片段 */
784
+ export declare function renderSectionBodyHtml(doc: EmailDoc, sectionId: string, registry: Registry): string;
785
+
598
786
  /**
599
787
  * 用 sample 值替换 `{{var.name}}` 占位符。仅做最简单的字符串替换,
600
788
  * 不做任何沙箱式表达式求值(邮件场景里下游模板引擎会再处理一次)。
601
789
  */
602
790
  export declare function replaceVariables(text: string, vars: Variable[]): string;
603
791
 
792
+ /** 锁定块在画布上的渲染结果:preview 为 WYSIWYG HTML,source 为无法解析时的源码回退。 */
793
+ export declare function resolveLockedMjmlCanvasContent(lockedMjml: string, padding: BlockPaddingBox): {
794
+ mode: 'preview';
795
+ html: string;
796
+ } | {
797
+ mode: 'source';
798
+ source: string;
799
+ };
800
+
604
801
  export declare interface Section {
605
802
  id: string;
606
803
  type: 'section';
@@ -629,10 +826,21 @@ export declare interface SectionAttrs {
629
826
  * 本节内容区最大宽度(窄于邮件 `meta.width` 时居中)。支持 `480`、`480px`、`90%`;留空则与邮件同宽。
630
827
  */
631
828
  width?: string | number;
829
+ /**
830
+ * 动态变量组合:设置后本节编译结果在导出时替换为 `{{dynamicVariantKey}}`;
831
+ * 具体存贮与业务含义由宿主处理(如券包 couponGroup)。
832
+ */
833
+ dynamicVariantKey?: string;
834
+ /**
835
+ * 宿主扩展元数据;编辑器不解释、不参与 MJML 编译,仅随 EmailDoc 序列化。
836
+ */
837
+ meta?: Record<string, unknown>;
632
838
  }
633
839
 
634
840
  export declare type SectionLayout = '1' | '1-1' | '1-2' | '2-1' | '1-1-1';
635
841
 
842
+ export declare function sectionMjClassName(sectionId: string): string;
843
+
636
844
  export declare function sectionWidthInputString(raw: unknown): string;
637
845
 
638
846
  declare type Selection_2 = {
@@ -648,7 +856,9 @@ export { Selection_2 as Selection }
648
856
 
649
857
  declare type SelectionListener = () => void;
650
858
 
651
- /** 仅更新 layout 字段;两列间切换时列数不变,列内块按列下标保留 */
859
+ export declare function serializeDocClipboard(doc: EmailDoc): string;
860
+
861
+ /** 更新 layout;列数变化时增删列,被删列内块并入最后一列 */
652
862
  export declare function setSectionLayout(section: Section, layout: SectionLayout): void;
653
863
 
654
864
  /**
@@ -690,7 +900,7 @@ export declare class Store {
690
900
  /** 从 Mustache token 提取 key,如 `{{username}}` → `username` */
691
901
  export declare function tokenToVariableKey(token: string): string;
692
902
 
693
- /** 两列 Section 的列宽比例(左栏拖入默认 `1-1`,右栏可改为 `1-2` / `2-1`) */
903
+ /** @deprecated 使用 MULTI_COLUMN_LAYOUTS */
694
904
  export declare const TWO_COLUMN_LAYOUTS: readonly ["1-1", "1-2", "2-1"];
695
905
 
696
906
  export declare type TwoColumnLayout = (typeof TWO_COLUMN_LAYOUTS)[number];