mail-editor-pancake 0.0.7 → 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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/registry/registry.ts","../src/utils/contentWidth.ts","../src/utils/dom.ts","../src/utils/fontWeightSteps.ts","../src/utils/lockedMjml.ts","../src/renderer/mjml.ts","../src/renderer/index.ts","../src/utils/id.ts","../src/store/store.ts","../src/utils/html.ts","../src/editor/Modal.ts","../src/editor/BlockCodeModal.ts","../src/editor/InlineEditor.ts","../src/editor/Canvas.ts","../src/editor/ExportModal.ts","../src/editor/LeftPanel.ts","../src/editor/PreviewModal.ts","../src/editor/RichTextToolbar.ts","../src/socialDefaults.ts","../src/editor/ImageGalleryModal.ts","../src/editor/RightPanel.ts","../src/editor/SourceView.ts","../src/utils/accentColor.ts","../src/editor/Topbar.ts","../src/editor/Editor.ts"],"sourcesContent":["import type { Block, BlockDefinition } from '../types';\n\n/**\n * 组件注册表。所有内置/自定义组件都通过 `defineBlock` 注册进来;\n * 渲染、属性面板、左栏拖拽源、组件级代码模式四方都从这里读取。\n */\nexport class Registry {\n private map = new Map<string, BlockDefinition<any>>();\n\n register<P extends object>(def: BlockDefinition<P>) {\n if (this.map.has(def.type)) {\n console.warn(`[simple-mail] block type 重复注册: ${def.type},后注册的会覆盖前者`);\n }\n this.map.set(def.type, def as BlockDefinition<any>);\n return this;\n }\n\n get(type: string): BlockDefinition | undefined {\n return this.map.get(type);\n }\n\n /** 必须能找到,否则抛出。渲染/属性面板都用它,未注册即 bug。 */\n require(type: string): BlockDefinition {\n const def = this.map.get(type);\n if (!def) throw new Error(`[simple-mail] 未注册的 block type: ${type}`);\n return def;\n }\n\n list(): BlockDefinition[] {\n return [...this.map.values()];\n }\n\n byCategory(category: BlockDefinition['category']): BlockDefinition[] {\n return this.list().filter((d) => d.category === category);\n }\n\n /** 用注册表里的默认 props 创建一个新 block 实例。 */\n createBlock(type: string): Block {\n const def = this.require(type);\n return {\n id: cryptoRandomId(),\n type,\n props: structuredClone(def.defaultProps),\n };\n }\n}\n\nfunction cryptoRandomId() {\n const ts = Date.now().toString(36).slice(-4);\n const rand = Math.floor(Math.random() * 36 ** 4)\n .toString(36)\n .padStart(4, '0');\n return `blk_${ts}${rand}`;\n}\n\n/** 工厂函数,便于外部以函数式风格定义组件。 */\nexport function defineBlock<P extends object>(def: BlockDefinition<P>): BlockDefinition<P> {\n return def;\n}\n","/**\n * 内容区 / 按钮等「布局宽度」解析:数字与无单位数字按 px;支持显式 `px` 与 `%`。\n */\n\nfunction coerceCssWidth(raw: unknown): string | undefined {\n if (raw == null || raw === '') return undefined;\n if (typeof raw === 'number' && Number.isFinite(raw)) {\n const n = Math.round(raw);\n return n > 0 ? `${n}px` : undefined;\n }\n const s = String(raw).trim();\n if (!s) return undefined;\n if (/^\\d+(\\.\\d+)?%$/.test(s)) return s;\n if (/^\\d+(\\.\\d+)?px$/i.test(s)) return s.replace(/px$/i, 'px');\n if (/^\\d+(\\.\\d+)?$/.test(s)) return `${s}px`;\n return undefined;\n}\n\n/** 邮件 `meta.width` → CSS / mj-body 可用的宽度(非法则 600px) */\nexport function docContentWidthCss(raw: unknown): string {\n return coerceCssWidth(raw) ?? '600px';\n}\n\n/** 右栏输入解析存库:纯整数可存 number,其它存 string */\nexport function parseMetaWidthFromUserInput(input: string): number | string {\n const t = input.trim();\n if (!t) return 600;\n if (/^\\d+(\\.\\d+)?%$/.test(t)) return t;\n if (/^\\d+(\\.\\d+)?px$/i.test(t)) return t.replace(/PX$/i, 'px');\n if (/^\\d+$/.test(t)) return Number(t);\n if (/^\\d+\\.\\d+$/.test(t)) return `${t}px`;\n return t;\n}\n\nexport function metaWidthInputString(raw: unknown): string {\n if (raw == null) return '600';\n if (typeof raw === 'number' && Number.isFinite(raw)) return String(raw);\n return String(raw);\n}\n\n/** 按钮 / Section 等:可选宽度,空或 auto 表示不限制 */\nexport function blockButtonWidthCss(raw: unknown): string | undefined {\n if (raw == null) return undefined;\n const s = String(raw).trim();\n if (!s || s.toLowerCase() === 'auto') return undefined;\n return coerceCssWidth(s);\n}\n\n/** Section 右栏输入;空字符串表示清除宽度 */\nexport function parseSectionWidthFromUserInput(input: string): string | number | undefined {\n const t = input.trim();\n if (!t) return undefined;\n if (/^\\d+(\\.\\d+)?%$/.test(t)) return t;\n if (/^\\d+(\\.\\d+)?px$/i.test(t)) return t.replace(/PX$/i, 'px');\n if (/^\\d+$/.test(t)) return Number(t);\n if (/^\\d+\\.\\d+$/.test(t)) return `${t}px`;\n return t;\n}\n\nexport function sectionWidthInputString(raw: unknown): string {\n if (raw == null || raw === '') return '';\n if (typeof raw === 'number' && Number.isFinite(raw)) return String(raw);\n return String(raw);\n}\n","/** 极简 DOM 创建工具,避免引入 hyperscript 等额外依赖。 */\n\ntype Attrs = Record<string, string | number | boolean | EventListener | undefined | null>;\n\nexport function h<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Attrs = {},\n children: (Node | string | null | undefined | false)[] = [],\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n if (v == null || v === false) continue;\n if (k === 'class') el.className = String(v);\n else if (k === 'style') el.setAttribute('style', String(v));\n else if (k === 'html') el.innerHTML = String(v);\n else if (k.startsWith('on') && typeof v === 'function') {\n el.addEventListener(k.slice(2).toLowerCase(), v as EventListener);\n } else if (typeof v === 'boolean') {\n if (v) el.setAttribute(k, '');\n } else {\n el.setAttribute(k, String(v));\n }\n }\n for (const child of children) {\n if (child == null || child === false) continue;\n el.appendChild(typeof child === 'string' ? document.createTextNode(child) : child);\n }\n return el;\n}\n\nexport function clear(el: HTMLElement) {\n while (el.firstChild) el.removeChild(el.firstChild);\n}\n\nexport function escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nexport function escapeAttr(s: string): string {\n return escapeHtml(s);\n}\n","/** 全局与各组件字重:固定五档,便于右栏平铺或步进滑块 */\nexport const FONT_WEIGHT_STEP_VALUES = ['300', '400', '500', '600', '700'] as const;\nexport type FontWeightStep = (typeof FONT_WEIGHT_STEP_VALUES)[number];\n\nexport const FONT_WEIGHT_STEP_OPTIONS: { label: string; value: string }[] = FONT_WEIGHT_STEP_VALUES.map(\n (v) => ({ label: v, value: v }),\n);\n\n/** 将任意历史写法映射到最近一档(normal→400,bold→700 等) */\nexport function normalizeFontWeightStep(raw: string | undefined | null): FontWeightStep {\n const s = String(raw ?? '400').trim().toLowerCase();\n if (s === '' || s === 'normal' || s === 'regular') return '400';\n if (s === 'bold' || s === 'bolder') return '700';\n if (s === 'lighter') return '300';\n const match = /^(\\d+)(\\.\\d+)?$/.exec(s);\n if (match) {\n const n = parseInt(match[1], 10);\n const steps = [300, 400, 500, 600, 700];\n let best: FontWeightStep = '400';\n let bestD = Infinity;\n for (const st of steps) {\n const d = Math.abs(n - st);\n if (d < bestD) {\n bestD = d;\n best = String(st) as FontWeightStep;\n }\n }\n return best;\n }\n return '400';\n}\n","import type { GlobalStyles } from '../types';\nimport { normalizeFontWeightStep } from './fontWeightSteps';\n\n/**\n * mj-column 编译结果外层会有 `font-size:0`(多列 inline-block 间距技巧),\n * mj-raw 内若未在祖先上重置字号,li/p 等会继承 0 导致「看不见」。\n * 在包裹 td 上对齐邮件全局正文样式即可规避。\n */\nexport interface MjRawCellTypography {\n fontSize: string;\n lineHeight: string;\n color: string;\n fontFamily: string;\n fontWeight: string;\n}\n\nexport function mjRawCellTypographyFromStyles(s: GlobalStyles): MjRawCellTypography {\n return {\n fontSize: (s.fontSize || '16px').trim(),\n lineHeight: (s.lineHeight || '1.25').trim(),\n color: (s.color || '#433f3f').trim(),\n fontFamily: (s.fontFamily || 'sans-serif').trim(),\n fontWeight: normalizeFontWeightStep(s.fontWeight),\n };\n}\n\n/** style=\"...\" 为双引号属性,避免值内双引号破坏解析 */\nfunction cssForDoubleQuotedAttr(value: string): string {\n return value.replace(/\"/g, \"'\").replace(/\\s+/g, ' ').trim();\n}\n\nfunction buildMjRawTdStyle(paddingCss: string, typo: MjRawCellTypography): string {\n const fontSize = cssForDoubleQuotedAttr(typo.fontSize);\n const lineHeight = cssForDoubleQuotedAttr(typo.lineHeight);\n const color = cssForDoubleQuotedAttr(typo.color);\n const fontFamily = cssForDoubleQuotedAttr(typo.fontFamily);\n const fontWeight = cssForDoubleQuotedAttr(typo.fontWeight);\n return `padding:${paddingCss};font-size:${fontSize};line-height:${lineHeight};color:${color};font-family:${fontFamily};font-weight:${fontWeight}`;\n}\n\n/**\n * mj-column 编译结果是表格布局,列内若用 mj-raw 直接输出 div/ul 等块级 HTML,\n * 会变成非法 table 子节点,浏览器/邮件里常表现为整块空白。\n * 用 presentation table + 单格 td 包住用户 HTML,与 mj-text 等组件结构一致。\n */\nexport function mjRawEmailTableWrap(\n paddingCss: string,\n cellInnerHtml: string,\n typo: MjRawCellTypography,\n): string {\n const tdStyle = buildMjRawTdStyle(paddingCss, typo);\n return `<mj-raw>\n<table role=\"presentation\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n <tbody>\n <tr>\n <td style=\"${tdStyle}\">\n ${cellInnerHtml}\n </td>\n </tr>\n </tbody>\n</table>\n</mj-raw>`;\n}\n\n/**\n * 锁定片段插入 mj-column 时的规范化。\n *\n * mj-column 内只允许 mj-* 节点(或 mj-raw 包一层 HTML)。\n * 用户若在「编辑组件代码」里只保存了 `<ul>...</ul>` 等裸 HTML,直接下发会导致 MJML 编译失败、预览空白。\n */\nexport function wrapLockedMjmlForMjColumn(fragment: string, typo: MjRawCellTypography): string {\n const lead = fragment.trimStart();\n if (!lead) return '<mj-raw><!-- empty --></mj-raw>';\n if (/^<mj-/i.test(lead)) return fragment;\n const t = fragment.trim();\n // 无 props 上下文,内边距交给 0;用户可在片段内自行写 padding\n return mjRawEmailTableWrap('0', t, typo);\n}\n\n/** 旧版 HTML 块/锁定片段只有 mj-raw 包 div 或裸标签,编译进列后表格结构非法;统一包一层 presentation table。 */\nexport function normalizeHtmlBlockLockedMjmlForCompile(\n fragment: string,\n paddingCss: string,\n typo: MjRawCellTypography,\n): string {\n const raw = fragment.trim();\n const mj = raw.match(/^<mj-raw\\b[^>]*>([\\s\\S]*)<\\/mj-raw\\s*>$/i);\n if (!mj) return fragment;\n let inner = mj[1].trim();\n const divStrip = inner.match(/^\\s*<div\\b[^>]*style=\"[^\"]*\"[^>]*>([\\s\\S]*)<\\/div>\\s*$/i);\n if (divStrip) inner = divStrip[1].trim();\n if (/^\\s*<table\\b/i.test(inner)) return raw;\n return mjRawEmailTableWrap(paddingCss, inner, typo);\n}\n\n/** HTML 块锁定:画布上优先渲染可读效果,而非转义后的 MJML 源码字符串。 */\nexport function htmlFragmentForLockedHtmlBlockCanvas(\n lockedMjml: string,\n padding: { top: number; right: number; bottom: number; left: number },\n): string {\n const raw = lockedMjml.trim();\n const mjMatch = raw.match(/^<mj-raw\\b[^>]*>([\\s\\S]*)<\\/mj-raw\\s*>$/i);\n const pad = `${padding.top}px ${padding.right}px ${padding.bottom}px ${padding.left}px`;\n if (mjMatch) {\n const body = mjMatch[1].trim();\n return body || `<div style=\"padding:${pad};color:#9ca3af;font-size:13px;\">(无内容)</div>`;\n }\n const bare = raw;\n if (!bare) return `<div style=\"padding:${pad};color:#9ca3af;font-size:13px;\">(无内容)</div>`;\n return `<div style=\"padding:${pad}\">${bare}</div>`;\n}\n","import type { Registry } from '../registry/registry';\nimport type { Column, EmailDoc, RenderContext, Section, SectionLayout } from '../types';\nimport { blockButtonWidthCss, docContentWidthCss } from '../utils/contentWidth';\nimport { escapeAttr } from '../utils/dom';\nimport { normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport {\n mjRawCellTypographyFromStyles,\n normalizeHtmlBlockLockedMjmlForCompile,\n wrapLockedMjmlForMjColumn,\n} from '../utils/lockedMjml';\n\n/**\n * Schema → MJML 字符串。\n *\n * 不直接编译成 HTML——HTML 编译交给 `mjml-browser`,\n * 这一层只负责把数据模型翻译成 MJML 语义化标签。\n */\nexport function docToMjml(doc: EmailDoc, registry: Registry): string {\n const ctx: RenderContext = { doc, engine: 'mjml' };\n const attrs = doc.styles;\n\n const sections = doc.sections.map((s) => sectionToMjml(s, registry, ctx)).join('\\n');\n\n return `<mjml>\n <mj-head>\n <mj-title>${escapeAttr(doc.meta.subject || '')}</mj-title>\n ${doc.meta.preheader ? `<mj-preview>${escapeAttr(doc.meta.preheader)}</mj-preview>` : ''}\n <mj-attributes>\n <mj-all font-family=\"${escapeAttr(attrs.fontFamily)}\" />\n <mj-text font-size=\"${escapeAttr(attrs.fontSize)}\" font-weight=\"${escapeAttr(normalizeFontWeightStep(attrs.fontWeight))}\" color=\"${escapeAttr(attrs.color)}\" line-height=\"${escapeAttr(attrs.lineHeight ?? '1.25')}\" />\n <mj-class name=\"link\" color=\"${escapeAttr(attrs.linkColor)}\" />\n </mj-attributes>\n <mj-style>\n a { color: ${escapeAttr(attrs.linkColor)}; }\n${sectionWidthConstraintCss(doc)}\n </mj-style>\n </mj-head>\n <mj-body background-color=\"${escapeAttr(attrs.backgroundColor)}\" width=\"${escapeAttr(docContentWidthCss(doc.meta.width))}\">\n${sections}\n </mj-body>\n</mjml>`;\n}\n\nfunction sectionMjClassName(sectionId: string): string {\n return `sm-sec-${sectionId.replace(/[^a-zA-Z0-9_-]/g, '_')}`;\n}\n\n/** 为设置了宽度的 Section 生成 max-width 规则(css-class 挂在 mj-section 上) */\nfunction sectionWidthConstraintCss(doc: EmailDoc): string {\n return doc.sections\n .map((s) => {\n const w = blockButtonWidthCss(s.attrs.width);\n if (!w) return '';\n const cls = sectionMjClassName(s.id);\n return ` .${cls} { max-width: ${w} !important; width: 100% !important; margin-left: auto !important; margin-right: auto !important; }`;\n })\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction sectionToMjml(section: Section, registry: Registry, ctx: RenderContext): string {\n const a = section.attrs;\n const padding = [a.paddingTop, a.paddingRight, a.paddingBottom, a.paddingLeft]\n .map((v) => `${v ?? 0}px`)\n .join(' ');\n const bg = a.backgroundColor ? ` background-color=\"${escapeAttr(a.backgroundColor)}\"` : '';\n const secW = blockButtonWidthCss(a.width);\n const secCls = secW ? ` css-class=\"${escapeAttr(sectionMjClassName(section.id))}\"` : '';\n const widths = layoutWidths(section.layout);\n const gapPx = Math.max(0, section.attrs.columnGap ?? 0);\n\n const columns = section.columns\n .map((col, i) =>\n columnToMjml(col, widths[i], i, section.columns.length, gapPx, registry, ctx),\n )\n .join('\\n');\n\n /** 多列 + 显式开启时包 mj-group,阻止小屏列堆叠(MJML 官方语义) */\n const multiCol = section.columns.length > 1;\n const grouped =\n multiCol && section.attrs.preserveColumnsOnMobile === true\n ? ` <mj-group>\\n${indent(columns, 2)}\\n </mj-group>`\n : columns;\n\n return ` <mj-section padding=\"${padding}\"${bg}${secCls}>\n${grouped}\n </mj-section>`;\n}\n\nfunction columnToMjml(\n column: Column,\n width: string,\n columnIndex: number,\n columnCount: number,\n columnGapPx: number,\n registry: Registry,\n ctx: RenderContext,\n): string {\n const a = column.attrs;\n const va = a.verticalAlign ? ` vertical-align=\"${a.verticalAlign}\"` : '';\n const bg = a.backgroundColor ? ` background-color=\"${escapeAttr(a.backgroundColor)}\"` : '';\n\n let gapPad = '';\n if (columnCount > 1 && columnGapPx > 0) {\n const half = columnGapPx / 2;\n const pl = columnIndex > 0 ? `${half}px` : '0px';\n const pr = columnIndex < columnCount - 1 ? `${half}px` : '0px';\n gapPad = ` padding=\"0px ${pr} 0px ${pl}\"`;\n }\n\n const rawTypo = mjRawCellTypographyFromStyles(ctx.doc.styles);\n const blocks = column.blocks\n .map((b) => {\n if (b.lockedMjml) {\n let frag = wrapLockedMjmlForMjColumn(b.lockedMjml, rawTypo);\n if (b.type === 'html') {\n const p = b.props as {\n paddingTop?: number;\n paddingRight?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n };\n const pad = `${Number(p.paddingTop ?? 8)}px ${Number(p.paddingRight ?? 0)}px ${Number(p.paddingBottom ?? 8)}px ${Number(p.paddingLeft ?? 0)}px`;\n frag = normalizeHtmlBlockLockedMjmlForCompile(frag, pad, rawTypo);\n }\n return indent(frag, 8);\n }\n const def = registry.require(b.type);\n return indent(def.toMjml(b.props, ctx), 8);\n })\n .join('\\n');\n\n return ` <mj-column width=\"${width}\"${va}${bg}${gapPad}>\n${blocks || ' <!-- empty column -->'}\n </mj-column>`;\n}\n\nfunction layoutWidths(layout: SectionLayout): string[] {\n // 内容宽度 600,给到百分比即可,让 MJML 自己处理像素分配\n const parts = layout.split('-').map(Number);\n const total = parts.reduce((s, x) => s + x, 0);\n return parts.map((p) => `${((p / total) * 100).toFixed(2)}%`);\n}\n\nfunction indent(text: string, n: number): string {\n const pad = ' '.repeat(n);\n return text\n .split('\\n')\n .map((l) => (l ? pad + l : l))\n .join('\\n');\n}\n","import mjmlCompile from 'mjml-browser';\nimport type { EmailDoc, RenderEngine, Variable } from '../types';\nimport type { Registry } from '../registry/registry';\nimport { docToMjml } from './mjml';\n\nexport interface RenderResult {\n mjml: string;\n html: string;\n errors: { message: string }[];\n}\n\nexport interface RenderOptions {\n /** 渲染引擎,目前仅 'mjml';'table' 预留作将来直输 table HTML。 */\n engine?: RenderEngine;\n /**\n * 是否把 {{var}} 替换为示例值。设计态画布预览传 true,导出原始 HTML 传 false。\n */\n withSampleVariables?: boolean;\n}\n\nexport function renderDoc(\n doc: EmailDoc,\n registry: Registry,\n opts: RenderOptions = {},\n): RenderResult {\n const engine: RenderEngine = opts.engine ?? 'mjml';\n\n if (engine !== 'mjml') {\n // 预留:将来可在此分支实现纯 table 输出。\n throw new Error(`渲染引擎暂未实现: ${engine}`);\n }\n\n const mjml = docToMjml(doc, registry);\n\n const compiled = mjmlCompile(mjml, {\n validationLevel: 'soft',\n keepComments: false,\n });\n\n let html = compiled.html;\n if (opts.withSampleVariables) {\n html = replaceVariables(html, doc.variables);\n }\n\n return {\n mjml,\n html,\n errors: (compiled.errors || []).map((e: any) => ({\n message: e.formattedMessage ?? e.message ?? String(e),\n })),\n };\n}\n\n/**\n * 用 sample 值替换 `{{var.name}}` 占位符。仅做最简单的字符串替换,\n * 不做任何沙箱式表达式求值(邮件场景里下游模板引擎会再处理一次)。\n */\nexport function replaceVariables(text: string, vars: Variable[]): string {\n if (!vars.length) return text;\n return text.replace(/\\{\\{\\s*([^}\\s]+)\\s*\\}\\}/g, (raw, key) => {\n const v = vars.find((x) => x.key === key);\n if (v && v.sample != null) return v.sample;\n return raw;\n });\n}\n","let _counter = 0;\n\n/**\n * 生成短 ID。无需密码学强度——仅用于文档内引用。\n * 使用 base36 + 自增计数,保证同 doc 内单调,便于 diff 调试。\n */\nexport function uid(prefix = 'id'): string {\n _counter += 1;\n const ts = Date.now().toString(36).slice(-4);\n const rand = Math.floor(Math.random() * 36 ** 3)\n .toString(36)\n .padStart(3, '0');\n return `${prefix}_${ts}${rand}${_counter.toString(36)}`;\n}\n","import type { Block, Column, EmailDoc, Section, SectionLayout, Selection } from '../types';\nimport { uid } from '../utils/id';\n\n/** 文档变更通知来源(右栏等可按来源决定是否保留焦点) */\nexport type DocChangedDetail = { source: 'mutate' | 'history' | 'replace' };\n\ntype Listener = (detail?: DocChangedDetail) => void;\ntype SelectionListener = () => void;\n\n/**\n * 极小的不可变 store + 发布订阅 + history。\n * 所有变更都通过 `update(fn)` 走结构化克隆,保证:\n * - 引用不可变(外部 memo/diff 友好)\n * - 变更原子(一个 update 一条 history)\n */\nexport class Store {\n private _doc: EmailDoc;\n private _selection: Selection | null = null;\n private _listeners: Set<Listener> = new Set();\n private _selectionListeners: Set<SelectionListener> = new Set();\n private _past: EmailDoc[] = [];\n private _future: EmailDoc[] = [];\n private _historyLimit = 100;\n\n constructor(initial: EmailDoc) {\n this._doc = initial;\n }\n\n get doc(): EmailDoc {\n return this._doc;\n }\n\n get selection(): Selection | null {\n return this._selection;\n }\n\n subscribe(fn: Listener): () => void {\n this._listeners.add(fn);\n return () => this._listeners.delete(fn);\n }\n\n subscribeSelection(fn: SelectionListener): () => void {\n this._selectionListeners.add(fn);\n return () => this._selectionListeners.delete(fn);\n }\n\n setSelection(sel: Selection | null) {\n this._selection = sel;\n this._selectionListeners.forEach((l) => l());\n }\n\n /**\n * 应用一次变更。`mutator` 收到一份可直接修改的 draft(结构化克隆得来)。\n * 修改完毕后用新对象替换当前 doc,并把旧 doc 入历史。\n */\n update(mutator: (draft: EmailDoc) => void, opts: { silent?: boolean } = {}) {\n const draft = structuredClone(this._doc);\n mutator(draft);\n this._past.push(this._doc);\n if (this._past.length > this._historyLimit) this._past.shift();\n this._future = [];\n this._doc = draft;\n if (!opts.silent) this._notify('mutate');\n }\n\n /** 替换整个文档(如外部 setValue),会清空 history。 */\n replace(doc: EmailDoc) {\n this._past = [];\n this._future = [];\n this._doc = doc;\n this._notify('replace');\n }\n\n undo(): boolean {\n const prev = this._past.pop();\n if (!prev) return false;\n this._future.push(this._doc);\n this._doc = prev;\n this._notify('history');\n return true;\n }\n\n redo(): boolean {\n const next = this._future.pop();\n if (!next) return false;\n this._past.push(this._doc);\n this._doc = next;\n this._notify('history');\n return true;\n }\n\n canUndo() {\n return this._past.length > 0;\n }\n\n canRedo() {\n return this._future.length > 0;\n }\n\n private _notify(source: DocChangedDetail['source']) {\n const detail: DocChangedDetail = { source };\n this._listeners.forEach((l) => l(detail));\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* 便捷的查询/变更助手 */\n/* -------------------------------------------------------------------------- */\n\nexport function findSection(doc: EmailDoc, sectionId: string): Section | undefined {\n return doc.sections.find((s) => s.id === sectionId);\n}\n\nexport function findBlockLocation(\n doc: EmailDoc,\n blockId: string,\n): { section: Section; columnIndex: number; block: Block } | undefined {\n for (const section of doc.sections) {\n for (let i = 0; i < section.columns.length; i += 1) {\n const col = section.columns[i];\n const blk = col.blocks.find((b) => b.id === blockId);\n if (blk) return { section, columnIndex: i, block: blk };\n }\n }\n return undefined;\n}\n\n/**\n * 从文档中移除「每一列都没有任何 Block」的 Section。\n * 在内容块被删除或拖走后调用,可与 `autoWrapSection` 搭配,避免唯一块离场后仍残留空壳;\n * 不会在用户仅点击「添加 Section」时单独触发,因此未拖入内容的空布局仍会保留在画布上。\n */\nexport function pruneEmptySections(draft: EmailDoc) {\n draft.sections = draft.sections.filter((sec) =>\n sec.columns.some((col) => col.blocks.length > 0),\n );\n}\n\nexport function createSection(layout: SectionLayout): Section {\n const colCount = layout.split('-').length;\n const columns: Column[] = Array.from({ length: colCount }, () => ({\n id: uid('col'),\n attrs: {},\n blocks: [],\n }));\n return {\n id: uid('sec'),\n type: 'section',\n layout,\n attrs: {\n /** 默认左右 16:版心内边距由节承担;上下 0 由内容块堆叠节奏(常见 8)控制 */\n paddingTop: 0,\n paddingRight: 16,\n paddingBottom: 0,\n paddingLeft: 16,\n },\n columns,\n };\n}\n","/**\n * 极轻量 HTML 格式化器(约 50 行)。\n *\n * 不追求 100% 通用,但对邮件 HTML(table 嵌套、inline style、无脚本)非常稳定:\n * - 按 `<` 切 token,识别开标签 / 闭标签 / 自闭合 / 注释 / DOCTYPE\n * - 维护 depth 控制缩进\n * - void 元素与 self-closing 不增加 depth\n * - <pre> / <textarea> 内的换行不二次处理(保留原样)\n */\nexport function prettyHtml(html: string, indent = ' '): string {\n if (!html) return '';\n const VOID = new Set([\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n ]);\n const PRESERVE = new Set(['pre', 'textarea', 'script', 'style']);\n\n const tokens = html.match(/<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<![^>]*>|<\\/?[^<>]+>|[^<]+/g) ?? [];\n let depth = 0;\n let preserveStack: string[] = [];\n const out: string[] = [];\n const pad = (n: number) => indent.repeat(Math.max(0, n));\n\n for (const raw of tokens) {\n const tok = raw;\n const inPreserve = preserveStack.length > 0;\n\n if (tok.startsWith('<!--') || tok.startsWith('<![')) {\n if (inPreserve) out.push(tok);\n else out.push(pad(depth) + tok.trim());\n continue;\n }\n if (tok.startsWith('<!')) {\n out.push(tok.trim());\n continue;\n }\n\n if (tok.startsWith('</')) {\n const tag = (tok.match(/^<\\/([\\w-]+)/) ?? [])[1]?.toLowerCase();\n if (preserveStack[preserveStack.length - 1] === tag) {\n preserveStack.pop();\n out.push(tok);\n continue;\n }\n depth = Math.max(0, depth - 1);\n out.push(pad(depth) + tok.trim());\n continue;\n }\n\n if (tok.startsWith('<')) {\n const tag = (tok.match(/^<([\\w-]+)/) ?? [])[1]?.toLowerCase();\n const selfClosing = tok.endsWith('/>') || (tag && VOID.has(tag));\n if (inPreserve) {\n out.push(tok);\n if (tag && PRESERVE.has(tag) && !selfClosing) preserveStack.push(tag);\n continue;\n }\n out.push(pad(depth) + tok.trim());\n if (tag && !selfClosing) {\n if (PRESERVE.has(tag)) preserveStack.push(tag);\n else depth += 1;\n }\n continue;\n }\n\n // 文本\n if (inPreserve) {\n out.push(tok);\n } else {\n const txt = tok.replace(/\\s+/g, ' ').trim();\n if (txt) out.push(pad(depth) + txt);\n }\n }\n\n return out.join('\\n');\n}\n","import { h } from '../utils/dom';\n\n/**\n * 极简 Modal:遮罩 + 居中卡片 + header/body/footer 三段。\n * - 自带 Esc / 点遮罩 关闭\n * - 不锁 body scroll(邮件编辑器场景内通常已经接管了高度)\n * - 不依赖框架,保持 vanilla\n */\nexport interface ModalOptions {\n title: string;\n /** 卡片宽度 / 高度。可传 'auto' / px / % */\n width?: string;\n height?: string;\n /** 自定义类名,便于覆盖样式(如 sm-modal--preview) */\n className?: string;\n /** 关闭回调;用户取消、Esc、点遮罩时触发 */\n onClose?: () => void;\n}\n\nexport class Modal {\n el: HTMLElement;\n private mask: HTMLElement;\n private card: HTMLElement;\n private headerEl: HTMLElement;\n private bodyEl: HTMLElement;\n private footerEl: HTMLElement;\n private opts: ModalOptions;\n private keydownHandler?: (e: KeyboardEvent) => void;\n\n constructor(opts: ModalOptions) {\n this.opts = opts;\n\n this.mask = h('div', {\n class: 'sm-modal__mask',\n onclick: (e: Event) => {\n if (e.target === this.mask) this._handleClose();\n },\n });\n\n this.headerEl = h('header', { class: 'sm-modal__header' });\n this.bodyEl = h('div', { class: 'sm-modal__body' });\n this.footerEl = h('footer', { class: 'sm-modal__footer' });\n\n this.card = h(\n 'div',\n {\n class: `sm-modal__card ${opts.className ?? ''}`,\n style: [\n opts.width ? `width:${opts.width};` : '',\n opts.height ? `height:${opts.height};` : '',\n ].join(''),\n },\n [this.headerEl, this.bodyEl, this.footerEl],\n );\n\n this.mask.append(this.card);\n this.el = this.mask;\n\n this._renderHeader();\n }\n\n open(parent: HTMLElement = document.body) {\n parent.append(this.el);\n this.keydownHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') this._handleClose();\n };\n document.addEventListener('keydown', this.keydownHandler);\n requestAnimationFrame(() => this.el.classList.add('is-open'));\n }\n\n close() {\n this._handleClose();\n }\n\n setTitle(title: string) {\n this.opts.title = title;\n this._renderHeader();\n }\n\n /** body 容器直接给外部填充 */\n get body(): HTMLElement {\n return this.bodyEl;\n }\n\n /** footer 容器直接给外部填充按钮等 */\n get footer(): HTMLElement {\n return this.footerEl;\n }\n\n /** 在 header 右侧追加自定义工具按钮 */\n appendHeaderTool(el: HTMLElement) {\n const tools = this.headerEl.querySelector('.sm-modal__header-tools');\n tools?.append(el);\n }\n\n private _renderHeader() {\n this.headerEl.innerHTML = '';\n const title = h('div', { class: 'sm-modal__title' }, [this.opts.title]);\n const tools = h('div', { class: 'sm-modal__header-tools' });\n const closeBtn = h(\n 'button',\n {\n class: 'sm-modal__close',\n type: 'button',\n title: '关闭 Esc',\n onclick: () => this._handleClose(),\n },\n [iconClose()],\n );\n this.headerEl.append(title, tools, closeBtn);\n }\n\n private _handleClose() {\n if (this.keydownHandler) document.removeEventListener('keydown', this.keydownHandler);\n this.el.classList.remove('is-open');\n setTimeout(() => this.el.remove(), 180);\n this.opts.onClose?.();\n }\n}\n\nfunction iconClose(): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '16');\n el.setAttribute('height', '16');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML =\n '<path d=\"M5 5l10 10M15 5L5 15\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>';\n return el;\n}\n","import { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport { EditorState } from '@codemirror/state';\nimport type { Registry } from '../registry/registry';\nimport { findBlockLocation } from '../store/store';\nimport type { Store } from '../store/store';\nimport { h } from '../utils/dom';\nimport { prettyHtml } from '../utils/html';\nimport { Modal } from './Modal';\n\nexport interface BlockCodeModalOptions {\n store: Store;\n registry: Registry;\n /** 须落在 MailEditor `.sm-root` 子树内,才能继承 `--sm-code-bg` 等变量 */\n mountParent: HTMLElement;\n}\n\n/**\n * 画布内快速编辑单个 Block 的 MJML:与右栏「代码」Tab 行为一致(写入 lockedMjml)。\n */\nexport class BlockCodeModal {\n private opts: BlockCodeModalOptions;\n private modal: Modal;\n private editorHost: HTMLElement;\n private cm: EditorView | null = null;\n private blockId: string | null = null;\n\n constructor(opts: BlockCodeModalOptions) {\n this.opts = opts;\n this.modal = new Modal({\n title: '编辑组件代码',\n className: 'sm-modal--block-code',\n width: 'min(720px, 92vw)',\n height: 'min(560px, 85vh)',\n onClose: () => this._destroyCm(),\n });\n this.editorHost = h('div', { class: 'sm-export__editor' });\n this.modal.body.append(this.editorHost);\n\n const beautifyBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: () => this._beautify() },\n ['美化'],\n );\n const saveBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onclick: () => this._saveAndClose(),\n },\n ['保存'],\n );\n this.modal.footer.append(beautifyBtn, saveBtn);\n }\n\n open(blockId: string, componentLabel: string) {\n const doc = this.opts.store.doc;\n const loc = findBlockLocation(doc, blockId);\n if (!loc) return;\n\n this._destroyCm();\n this.blockId = blockId;\n const block = loc.block;\n const def = this.opts.registry.get(block.type);\n const initial =\n block.lockedMjml ??\n (def ? def.toMjml(block.props as Record<string, unknown>, { doc, engine: 'mjml' }) : '');\n\n this.modal.setTitle(`编辑组件代码 · ${componentLabel}`);\n this.cm = new EditorView({\n parent: this.editorHost,\n state: EditorState.create({\n doc: initial,\n extensions: [basicSetup, cmHtml()],\n }),\n });\n this.modal.open(this.opts.mountParent);\n }\n\n destroy() {\n this._destroyCm();\n if (this.modal.el.parentElement) this.modal.close();\n }\n\n private _beautify() {\n if (!this.cm) return;\n const text = prettyHtml(this.cm.state.doc.toString());\n this.cm.dispatch({\n changes: { from: 0, to: this.cm.state.doc.length, insert: text },\n });\n }\n\n private _saveAndClose() {\n if (!this.cm || !this.blockId) return;\n const text = this.cm.state.doc.toString();\n const id = this.blockId;\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, id);\n if (l) l.block.lockedMjml = text;\n });\n this.modal.close();\n }\n\n private _destroyCm() {\n if (this.cm) {\n this.cm.destroy();\n this.cm = null;\n }\n this.blockId = null;\n }\n}\n","/**\n * 把任意 DOM 元素临时变成 contenteditable,并暴露提交/取消/选区事件。\n *\n * 设计要点:\n * - 不直接同步到 store。编辑过程中只在本地累积,提交(blur / Esc / 单行 Enter)时一次性回调,\n * 避免每次按键都触发画布全量重渲染导致光标丢失。\n * - mode=plain 时仅取 textContent,并在 paste/keydown 上拦截换行;\n * mode=rich 时保留 inline HTML,但会在提交时做一次清理(白名单标签 + inline style);\n * mode=html 时提交原始 innerHTML(用于 mj-raw 等),不挂富文本浮动条。\n * - 选区变化通过 `onSelectionChange` 实时回调,便于浮动工具条同步按钮状态/位置。\n */\nexport interface InlineEditorOptions {\n el: HTMLElement;\n initialValue: string;\n mode: 'rich' | 'plain' | 'html';\n multiline: boolean;\n placeholder?: string;\n onCommit: (value: string) => void;\n onCancel: () => void;\n onSelectionChange?: (state: SelectionState | null) => void;\n}\n\nexport interface SelectionState {\n hasSelection: boolean;\n rect: DOMRect | null;\n /** queryCommandState 的若干常用值,用于工具条按钮高亮 */\n formats: {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n unorderedList: boolean;\n orderedList: boolean;\n align: 'left' | 'center' | 'right' | 'justify' | null;\n link: string | null;\n foreColor: string | null;\n fontSize: string | null;\n fontName: string | null;\n };\n}\n\nexport class InlineEditor {\n private opts: InlineEditorOptions;\n private el: HTMLElement;\n private listeners: Array<() => void> = [];\n private committed = false;\n private originalContent: string;\n /** 防止 selectionchange 在我们 destroy 之后还回调 */\n private alive = true;\n /**\n * 上一次\"用户在编辑区内\"时的有效选区。\n * 当用户去工具条点 select / input 时焦点会离开 contenteditable,\n * execCommand 在那种状态下会哑火——必须先 focus 回来,再恢复选区,再执行命令。\n */\n private savedRange: Range | null = null;\n /** 富文本工具条控件会抢走焦点,此时 getSelection 已不在编辑区内;保留上一帧状态避免工具条整栏收起。 */\n private lastSelectionState: SelectionState | null = null;\n\n constructor(opts: InlineEditorOptions) {\n this.opts = opts;\n this.el = opts.el;\n this.originalContent = this.el.innerHTML;\n this._mount();\n }\n\n /** 立即提交并销毁。 */\n commit() {\n if (this.committed) return;\n this.committed = true;\n const value =\n this.opts.mode === 'plain'\n ? (this.el.textContent ?? '').replace(/\\s+\\n/g, '\\n').trim()\n : this.opts.mode === 'html'\n ? this.el.innerHTML\n : sanitizeRichHtml(this.el.innerHTML);\n this.opts.onCommit(value);\n this.destroy(false);\n }\n\n /** 放弃编辑、还原 DOM 并销毁。 */\n cancel() {\n if (this.committed) return;\n this.committed = true;\n this.el.innerHTML = this.originalContent;\n this.opts.onCancel();\n this.destroy(false);\n }\n\n destroy(restore = true) {\n if (!this.alive) return;\n this.alive = false;\n this.listeners.forEach((off) => off());\n this.listeners = [];\n this.el.removeAttribute('contenteditable');\n this.el.classList.remove('sm-inline-editing');\n if (restore && !this.committed) this.el.innerHTML = this.originalContent;\n }\n\n /**\n * 保存当前在编辑区内的选区。Toolbar 在 mousedown(capture)阶段调用:\n * 在浏览器把焦点切到 select/input 之前抢先存档。\n */\n saveSelection() {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (!this.el.contains(range.startContainer) || !this.el.contains(range.endContainer)) return;\n this.savedRange = range.cloneRange();\n }\n\n /** 直接对当前选区执行命令(供 Toolbar 调用)。 */\n exec(command: string, value?: string) {\n this._ensureFocus();\n this._restoreSelection();\n // 列表:Chrome 等在 styleWithCSS=true 下 insertOrderedList / insertUnorderedList 常失灵,需退回 HTML 列表标签\n const isListCmd = command === 'insertOrderedList' || command === 'insertUnorderedList';\n document.execCommand('styleWithCSS', false, isListCmd ? ('false' as any) : ('true' as any));\n document.execCommand(command, false, value);\n // 命令执行后选区可能已经变化(例如插入链接会扩展),刷新存档\n this.saveSelection();\n this._emitSelection();\n }\n\n /**\n * 设置或移除超链接:已有 &lt;a&gt; 则改 href;否则 createLink。\n * (仅用 createLink 在链接内需改 URL 时浏览器行为不一致。)\n */\n setLink(url: string) {\n this._ensureFocus();\n this._restoreSelection();\n const trimmed = url.trim();\n if (!trimmed) {\n document.execCommand('unlink');\n this.saveSelection();\n this._emitSelection();\n return;\n }\n const safe = /^https?:|^mailto:|^tel:|^\\{\\{/i.test(trimmed) ? trimmed : `https://${trimmed}`;\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const anchor = findAncestorAnchor(sel.anchorNode, this.el);\n if (anchor) {\n anchor.setAttribute('href', safe);\n if (!anchor.getAttribute('rel')) anchor.setAttribute('rel', 'noopener');\n } else {\n document.execCommand('styleWithCSS', false, 'true' as any);\n document.execCommand('createLink', false, safe);\n }\n this.saveSelection();\n this._emitSelection();\n }\n\n /** 在当前光标处插入纯文本(供\"插入变量\"使用)。 */\n insertText(text: string) {\n this._ensureFocus();\n this._restoreSelection();\n document.execCommand('insertText', false, text);\n this.saveSelection();\n }\n\n /** Toolbar 关闭某个面板/控件后调用,把选区还给编辑区,方便用户继续输入。 */\n refocus() {\n this._ensureFocus();\n this._restoreSelection();\n }\n\n /** 内联编辑根节点(如 `.sm-text-content`)的盒模型矩形,供富文本条贴在正文区域外沿定位 */\n getAnchorRect(): DOMRect {\n return this.el.getBoundingClientRect();\n }\n\n private _restoreSelection() {\n if (!this.savedRange) return;\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(this.savedRange);\n }\n\n /* -------------------------------- 内部 ---------------------------------- */\n\n private _mount() {\n const { el, mode, multiline, placeholder } = this.opts;\n el.setAttribute('contenteditable', 'true');\n el.classList.add('sm-inline-editing');\n if (placeholder) el.setAttribute('data-placeholder', placeholder);\n\n if (this.opts.initialValue) {\n el.innerHTML =\n mode === 'plain' ? escapeHtml(this.opts.initialValue) : this.opts.initialValue;\n }\n\n // 初始聚焦并把光标移到末尾,便于\"双击 → 直接输入\"\n requestAnimationFrame(() => {\n el.focus();\n placeCaretAtEnd(el);\n });\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.cancel();\n return;\n }\n if (e.key === 'Enter') {\n if (!multiline) {\n e.preventDefault();\n this.commit();\n return;\n }\n // 多行下,回车默认会插入 <div> / <br>。强制 <br>,避免出现各种奇怪嵌套。\n e.preventDefault();\n document.execCommand('insertLineBreak');\n }\n };\n const onBlur = () => {\n // 给点钟摆余地,避免点击工具条按钮时立刻提交\n setTimeout(() => {\n if (!this.alive) return;\n const active = document.activeElement;\n if (active && (active === el || el.contains(active))) return;\n if (active && (active as HTMLElement).closest?.('.sm-floating-toolbar')) return;\n this.commit();\n }, 0);\n };\n const onPaste = (e: ClipboardEvent) => {\n if (mode !== 'plain') return;\n e.preventDefault();\n const text = e.clipboardData?.getData('text/plain') ?? '';\n const safe = multiline ? text : text.replace(/\\r?\\n/g, ' ');\n document.execCommand('insertText', false, safe);\n };\n const onSelChange = () => {\n if (!this.alive) return;\n this.saveSelection();\n this._emitSelection();\n };\n\n const linkInsideEditing = (t: EventTarget | null): HTMLAnchorElement | null => {\n if (!(t instanceof Element)) return null;\n const a = t.closest('a');\n if (!a || !el.contains(a)) return null;\n const href = a.getAttribute('href');\n if (href == null || href === '' || href === '#') return null;\n return a;\n };\n\n /** Chrome:contenteditable 里的 <a href> 仍会在 mousedown/click 时导航;阻止后用手动 caret 对齐点击处 */\n const onLinkMouseDown = (e: MouseEvent) => {\n if ((mode !== 'rich' && mode !== 'html') || e.button !== 0) return;\n if (!linkInsideEditing(e.target)) return;\n e.preventDefault();\n placeCaretAtClientPoint(el, e.clientX, e.clientY);\n };\n\n const stopLinkActivate = (e: MouseEvent) => {\n if (mode !== 'rich' && mode !== 'html') return;\n if (!linkInsideEditing(e.target)) return;\n e.preventDefault();\n };\n\n el.addEventListener('keydown', onKeyDown);\n el.addEventListener('blur', onBlur);\n el.addEventListener('paste', onPaste);\n document.addEventListener('selectionchange', onSelChange);\n el.addEventListener('input', onSelChange);\n el.addEventListener('mouseup', onSelChange);\n if (mode === 'rich' || mode === 'html') {\n el.addEventListener('mousedown', onLinkMouseDown, true);\n el.addEventListener('click', stopLinkActivate, true);\n el.addEventListener('auxclick', stopLinkActivate, true);\n }\n\n this.listeners.push(\n () => el.removeEventListener('keydown', onKeyDown),\n () => el.removeEventListener('blur', onBlur),\n () => el.removeEventListener('paste', onPaste),\n () => document.removeEventListener('selectionchange', onSelChange),\n () => el.removeEventListener('input', onSelChange),\n () => el.removeEventListener('mouseup', onSelChange),\n ...(mode === 'rich' || mode === 'html'\n ? [\n () => el.removeEventListener('mousedown', onLinkMouseDown, true),\n () => el.removeEventListener('click', stopLinkActivate, true),\n () => el.removeEventListener('auxclick', stopLinkActivate, true),\n ]\n : []),\n );\n }\n\n private _ensureFocus() {\n if (document.activeElement !== this.el) {\n this.el.focus();\n }\n }\n\n private _emitSelection() {\n if (!this.opts.onSelectionChange) return;\n if (this.opts.mode === 'plain' || this.opts.mode === 'html') {\n this.opts.onSelectionChange(null); // plain / 原始 HTML 不挂富文本浮动条\n return;\n }\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) {\n this._emitSelectionOrKeepToolbar(null);\n return;\n }\n if (!this.el.contains(sel.anchorNode)) {\n this._emitSelectionOrKeepToolbar(null);\n return;\n }\n const range = sel.getRangeAt(0);\n const rect = sel.isCollapsed ? this._caretRect(range) : range.getBoundingClientRect();\n\n const align: SelectionState['formats']['align'] = document.queryCommandState('justifyCenter')\n ? 'center'\n : document.queryCommandState('justifyRight')\n ? 'right'\n : document.queryCommandState('justifyFull')\n ? 'justify'\n : 'left';\n\n const link = (() => {\n const a = findAncestorAnchor(sel.anchorNode, this.el);\n return a?.getAttribute('href') ?? null;\n })();\n\n const state: SelectionState = {\n hasSelection: true,\n rect,\n formats: {\n bold: document.queryCommandState('bold'),\n italic: document.queryCommandState('italic'),\n underline: document.queryCommandState('underline'),\n strikethrough: document.queryCommandState('strikeThrough'),\n unorderedList: document.queryCommandState('insertUnorderedList'),\n orderedList: document.queryCommandState('insertOrderedList'),\n align,\n link,\n foreColor: safeQueryValue('foreColor'),\n fontSize: safeQueryValue('fontSize'),\n fontName: safeQueryValue('fontName'),\n },\n };\n this.lastSelectionState = state;\n this.opts.onSelectionChange(state);\n }\n\n /** 焦点在浮动工具条上时沿用上一帧选区,避免点开链接框 / 颜色等控件后工具条消失。 */\n private _emitSelectionOrKeepToolbar(fallback: null) {\n if (\n fallback === null &&\n this.lastSelectionState &&\n document.activeElement?.closest?.('.sm-floating-toolbar')\n ) {\n this.opts.onSelectionChange?.(this.lastSelectionState);\n return;\n }\n if (fallback === null) this.lastSelectionState = null;\n this.opts.onSelectionChange?.(fallback);\n }\n\n private _caretRect(range: Range): DOMRect | null {\n const rects = range.getClientRects();\n if (rects.length) return rects[0];\n // 折叠选区在空段落上时 rects 为空,造一个零宽 range 拿到位置\n const tmp = range.cloneRange();\n tmp.collapse(true);\n const span = document.createElement('span');\n span.appendChild(document.createTextNode('\\u200b'));\n tmp.insertNode(span);\n const r = span.getBoundingClientRect();\n span.remove();\n return r;\n }\n}\n\n/* ----------------------------- helpers ----------------------------- */\n\nfunction findAncestorAnchor(node: Node | null, root: HTMLElement): HTMLAnchorElement | null {\n while (node && node !== root) {\n if (node.nodeType === 1 && (node as HTMLElement).tagName === 'A') {\n return node as HTMLAnchorElement;\n }\n node = node.parentNode;\n }\n return null;\n}\n\nfunction placeCaretAtEnd(el: HTMLElement) {\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\n/** 在视口坐标处设置折叠选区(用于拦截 <a> 默认行为后补回放光标) */\nfunction placeCaretAtClientPoint(root: HTMLElement, clientX: number, clientY: number): boolean {\n const doc = root.ownerDocument;\n const d = doc as Document & {\n caretRangeFromPoint?: (x: number, y: number) => Range | null;\n caretPositionFromPoint?: (x: number, y: number) => { offsetNode: Node; offset: number } | null;\n };\n let range: Range | null = null;\n if (d.caretRangeFromPoint) {\n range = d.caretRangeFromPoint(clientX, clientY);\n } else if (d.caretPositionFromPoint) {\n const pos = d.caretPositionFromPoint(clientX, clientY);\n if (pos?.offsetNode) {\n range = doc.createRange();\n try {\n range.setStart(pos.offsetNode, pos.offset);\n range.collapse(true);\n } catch {\n range = null;\n }\n }\n }\n if (!range || !root.contains(range.startContainer)) return false;\n const sel = doc.getSelection();\n if (!sel) return false;\n sel.removeAllRanges();\n sel.addRange(range);\n return true;\n}\n\nfunction safeQueryValue(cmd: string): string | null {\n try {\n const v = document.queryCommandValue(cmd);\n return v ? v : null;\n } catch {\n return null;\n }\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/**\n * 邮件 HTML 必须只用一组保守的标签 + inline style。\n * 这里做一次轻量清理:\n * - 白名单标签:保留 a/b/strong/i/em/u/s/strike/span/br/p/div/ul/ol/li/h1-h6/font\n * - 标准化:<b> -> <strong>,<i> -> <em>,<font color> -> <span style=\"color:..\">\n * - 属性白名单:href / target / rel / style / class(保留邮件常见属性)\n */\nexport function sanitizeRichHtml(html: string): string {\n const tpl = document.createElement('template');\n tpl.innerHTML = html;\n walk(tpl.content);\n return tpl.innerHTML;\n\n function walk(root: Node) {\n const toRemove: Element[] = [];\n const all = (root as ParentNode).querySelectorAll('*');\n all.forEach((el) => {\n const tag = el.tagName.toLowerCase();\n // <font color=\"...\" size=\"...\" face=\"...\"> → 转成 span style\n if (tag === 'font') {\n const span = document.createElement('span');\n const color = el.getAttribute('color');\n const size = el.getAttribute('size');\n const face = el.getAttribute('face');\n const styles: string[] = [el.getAttribute('style') ?? ''];\n if (color) styles.push(`color:${color}`);\n if (size) styles.push(`font-size:${fontSizeFromLegacy(size)}`);\n if (face) styles.push(`font-family:${face}`);\n const cleaned = styles.filter(Boolean).join(';');\n if (cleaned) span.setAttribute('style', cleaned);\n while (el.firstChild) span.appendChild(el.firstChild);\n el.parentNode?.replaceChild(span, el);\n return;\n }\n // 标签级白名单\n const allowed = [\n 'a',\n 'b',\n 'strong',\n 'i',\n 'em',\n 'u',\n 's',\n 'strike',\n 'span',\n 'br',\n 'p',\n 'div',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n ];\n if (!allowed.includes(tag)) {\n toRemove.push(el);\n return;\n }\n // 属性白名单\n const allowedAttrs = ['href', 'target', 'rel', 'style', 'class'];\n [...el.attributes].forEach((attr) => {\n if (!allowedAttrs.includes(attr.name.toLowerCase())) {\n el.removeAttribute(attr.name);\n }\n });\n // 链接安全\n if (tag === 'a') {\n const href = el.getAttribute('href') ?? '';\n if (/^javascript:/i.test(href)) el.setAttribute('href', '#');\n if (!el.getAttribute('rel')) el.setAttribute('rel', 'noopener');\n }\n });\n toRemove.forEach((el) => {\n while (el.firstChild) el.parentNode?.insertBefore(el.firstChild, el);\n el.remove();\n });\n }\n}\n\nfunction fontSizeFromLegacy(size: string): string {\n // 旧 <font size=\"1..7\"> → px 近似\n const map: Record<string, string> = {\n '1': '10px',\n '2': '12px',\n '3': '14px',\n '4': '16px',\n '5': '20px',\n '6': '24px',\n '7': '32px',\n };\n return map[size] ?? size;\n}\n","import Sortable from 'sortablejs';\nimport type { Registry } from '../registry/registry';\nimport {\n createSection,\n findBlockLocation,\n findSection,\n pruneEmptySections,\n type Store,\n} from '../store/store';\nimport type { Block, Column, EmailDoc, RenderContext, Section, SectionLayout } from '../types';\nimport { blockButtonWidthCss, docContentWidthCss } from '../utils/contentWidth';\nimport { normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport { clear, escapeHtml, h } from '../utils/dom';\nimport { htmlFragmentForLockedHtmlBlockCanvas } from '../utils/lockedMjml';\nimport { BlockCodeModal } from './BlockCodeModal';\nimport { InlineEditor, type SelectionState } from './InlineEditor';\nimport type { RichTextToolbar } from './RichTextToolbar';\n\nexport interface CanvasOptions {\n store: Store;\n registry: Registry;\n /** 富文本工具条由 Editor 主类创建,Canvas 只负责调用 attach/detach/update */\n toolbar: RichTextToolbar;\n /** 是否允许 Block 落到 sections 之间空白处时自动裹一列 Section */\n autoWrapSection: boolean;\n /**\n * 为 true 时:点击中栏灰色衬底、白底画布上未落到 Section/块的空白、空文档提示区等会提交内联编辑并清空选中。\n * 默认不绑定(由 MailEditor 的 clearSelectionOnCanvasMargin 控制)。\n */\n clearSelectionOnCanvasMargin?: boolean;\n /**\n * 画布内弹层(如「编辑组件代码」)挂接到此节点,以继承 `.sm-root` 上的主题 CSS 变量。\n * 应传入 MailEditor 根节点;若挂到 `document.body`,`var(--sm-code-bg)` 等会失效,弹框背景会变透明。\n */\n layerRoot: HTMLElement;\n}\n\n/**\n * 画布。负责:\n * 1. 根据 doc 渲染轻量预览 DOM(非真实邮件 HTML)\n * 2. 选中态/悬浮态/工具条\n * 3. SortableJS 两级拖拽(仅 hover 显示的拖拽 handle 触发):\n * - 顶层(sections 组):Section 列表纵向排序,并接收左栏布局拖入\n * - 列内(blocks 组):Block 列表纵向排序,并接收左栏内容/自定义拖入\n * 4. 双击 Block 进入\"内联编辑\"——文本类直接富文本编辑,按钮文字单行编辑\n * 5. 设计画布内所有 <a href> 拦截默认行为,避免误跳转;真实跳转仅在「预览」iframe 中可用。\n *\n * 关键约束:所有数据变更走 store.update(),UI 通过 subscribe 全量重渲染。\n * 内联编辑是例外:编辑期间不再每次输入都 update,避免 contenteditable 因重渲染丢光标。\n */\nexport class Canvas {\n el: HTMLElement;\n private inner: HTMLElement;\n private addBar: HTMLElement;\n private opts: CanvasOptions;\n private sortableRefs: Sortable[] = [];\n /** 正在内联编辑的 block id;进入时画布不会被 store 触发的重渲染干扰它 */\n private editingBlockId: string | null = null;\n private inlineEditor: InlineEditor | null = null;\n /** 当 store 在编辑期间触发了 change(外部调用之类),延迟到编辑结束再重渲染 */\n private pendingRender = false;\n /** 设计模式下禁用画布内超链接导航(预览弹框 iframe 不在此 DOM 内,不受影响) */\n private linkNavSuppression = new AbortController();\n private blockCodeModal: BlockCodeModal;\n\n constructor(opts: CanvasOptions) {\n this.opts = opts;\n this.el = h('div', { class: 'sm-canvas-wrap' });\n this.inner = h('div', { class: 'sm-canvas' });\n this.addBar = this._renderAddBar();\n this.el.append(this.inner, this.addBar);\n this.blockCodeModal = new BlockCodeModal({\n store: opts.store,\n registry: opts.registry,\n mountParent: opts.layerRoot,\n });\n\n this._bindDesignModeLinkSuppression();\n if (opts.clearSelectionOnCanvasMargin) {\n this._bindClearSelectionOnCanvasWhitespace();\n this._bindClearSelectionOnCanvasMargin();\n }\n\n this.inner.addEventListener('dblclick', (e: MouseEvent) => {\n this._onEmptyCanvasDblClick(e);\n });\n\n this._render();\n\n opts.store.subscribe(() => {\n if (this.editingBlockId) {\n this.pendingRender = true;\n return;\n }\n this._render();\n });\n opts.store.subscribeSelection(() => this._syncSelection());\n }\n\n setWidth(width: number) {\n this.inner.style.maxWidth = `${width}px`;\n }\n\n /** 暴露给 Editor,用于\"插入变量\"等外部交互直接写入到当前富文本光标处。 */\n get currentInlineEditor(): InlineEditor | null {\n return this.inlineEditor;\n }\n\n /** 强制提交并退出当前内联编辑(切换源码模式、destroy 前等场景) */\n commitInlineEdit() {\n this.inlineEditor?.commit();\n }\n\n destroy() {\n this.linkNavSuppression.abort();\n this._exitEditing(false);\n this._destroySortables();\n this.blockCodeModal.destroy();\n }\n\n /**\n * 点击画布白底上未落到 Section 内的区域(如 min-height 下方留白、空文档提示)时清空选中,\n * Section/Block 上的点击会在冒泡到此前被 stopPropagation,不会误清。\n */\n private _bindClearSelectionOnCanvasWhitespace() {\n this.inner.addEventListener('click', (e: MouseEvent) => {\n const t = e.target;\n if (!(t instanceof Node)) return;\n const el = t instanceof Element ? t : t.parentElement;\n if (!el) return;\n if (el === this.inner || el.closest('.sm-empty-doc')) {\n this.commitInlineEdit();\n this.opts.store.setSelection(null);\n }\n });\n }\n\n /** 点击中栏灰色衬底(非白底画布、非底部添加 Section 条)时取消选中 */\n private _bindClearSelectionOnCanvasMargin() {\n this.el.addEventListener('click', (e: MouseEvent) => {\n const t = e.target;\n if (!(t instanceof Node)) return;\n if (!this.el.contains(t)) return;\n if (this.inner.contains(t)) return;\n if (this.addBar.contains(t)) return;\n this.commitInlineEdit();\n this.opts.store.setSelection(null);\n });\n }\n\n /** 捕获阶段拦截 <a href>,防止 Chrome 等在画布预览 DOM 上触发跳转(含未进入内联编辑时点到按钮块链接) */\n private _bindDesignModeLinkSuppression() {\n const opts = { capture: true, signal: this.linkNavSuppression.signal } as const;\n const stop = (e: MouseEvent) => {\n if (!(e.target instanceof Element)) return;\n const a = e.target.closest('a');\n if (!a || !this.inner.contains(a)) return;\n if (!a.hasAttribute('href')) return;\n e.preventDefault();\n };\n this.inner.addEventListener('mousedown', stop, opts);\n this.inner.addEventListener('click', stop, opts);\n this.inner.addEventListener('auxclick', stop, opts);\n }\n\n /* -------------------------------- 渲染 ---------------------------------- */\n\n private _render() {\n this._destroySortables();\n clear(this.inner);\n\n const { doc } = this.opts.store;\n this.inner.style.maxWidth = docContentWidthCss(doc.meta.width);\n this.inner.style.background = doc.styles.contentBackgroundColor;\n this.inner.style.fontFamily = doc.styles.fontFamily;\n this.inner.style.fontSize = doc.styles.fontSize;\n this.inner.style.fontWeight = normalizeFontWeightStep(doc.styles.fontWeight);\n this.inner.style.color = doc.styles.color;\n this.inner.style.lineHeight = doc.styles.lineHeight ?? '1.25';\n this.inner.style.setProperty('--sm-editor-link-color', doc.styles.linkColor);\n\n if (!doc.sections.length) {\n this.inner.append(\n h('div', { class: 'sm-empty-doc' }, [\n '从左侧拖入布局开始,或直接双击开始 ✦',\n ]),\n );\n } else {\n for (let si = 0; si < doc.sections.length; si++) {\n this.inner.append(this._renderSection(doc.sections[si], doc, si));\n }\n }\n\n // 顶层 Sortable:负责 Section 排序。\n // put 规则随 autoWrapSection 切换:\n // - autoWrapSection=true:同时接收 sections 与 blocks(block 落到这里时由 path B/C 自动套壳)\n // - autoWrapSection=false:仅接收 sections(block 落不下来,SortableJS 会显示禁止)\n // pull:false 始终:Section 不允许被拖到 column 里(保持四层模型)\n const topPut: string[] = this.opts.autoWrapSection ? ['sections', 'blocks'] : ['sections'];\n const top = Sortable.create(this.inner, {\n group: { name: 'sections', pull: false, put: topPut },\n animation: 150,\n handle: '.sm-section__handle',\n draggable: '.sm-section',\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n onAdd: (e) => this._handleSectionAdd(e),\n onUpdate: (e) => this._handleSectionMove(e),\n });\n this.sortableRefs.push(top);\n\n this._syncSelection();\n }\n\n private _renderSection(section: Section, doc: EmailDoc, sectionIndex: number) {\n const a = section.attrs;\n const padding = `${a.paddingTop ?? 0}px ${a.paddingRight ?? 0}px ${\n a.paddingBottom ?? 0\n }px ${a.paddingLeft ?? 0}px`;\n\n const layoutShort = layoutHumanLabel(section.layout);\n const sectionChip = `区块 ${sectionIndex + 1} · ${layoutShort}`;\n\n const sw = blockButtonWidthCss(a.width);\n const box =\n sw != null ? `max-width:${sw};width:100%;margin-left:auto;margin-right:auto;box-sizing:border-box;` : '';\n\n const wrap = h('div', {\n class: 'sm-section',\n 'data-id': section.id,\n title: `${sectionChip}。子组件铺满列内时:按 Esc 或 Alt+点击块可选中本节。`,\n style: `padding:${padding};${a.backgroundColor ? `background:${a.backgroundColor};` : ''}${box}`,\n });\n\n const toolbar = h('div', { class: 'sm-section__toolbar' }, [\n h('span', { class: 'sm-section__toolbar-label', title: sectionChip }, [sectionChip]),\n h('div', { class: 'sm-section__toolbar-actions' }, [\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-section__handle',\n type: 'button',\n title: '拖拽排序',\n onmousedown: (e: Event) => e.stopPropagation(),\n },\n [iconDrag()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '复制',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._duplicateSection(section.id);\n },\n },\n [iconCopy()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-tool-btn--danger',\n type: 'button',\n title: '删除',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._removeSection(section.id);\n },\n },\n [iconTrash()],\n ),\n ]),\n ]);\n\n const cols = h('div', {\n class: 'sm-section__columns',\n style: layoutFlexStyle(section.layout, section.attrs.columnGap),\n });\n\n section.columns.forEach((col, i) => {\n cols.append(this._renderColumn(section, col, i, doc));\n });\n\n wrap.append(toolbar, cols);\n\n wrap.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.sm-block')) return;\n e.stopPropagation();\n this.opts.store.setSelection({ kind: 'section', sectionId: section.id });\n });\n\n return wrap;\n }\n\n private _renderColumn(\n section: Section,\n column: Column,\n columnIndex: number,\n doc: EmailDoc,\n ): HTMLElement {\n const isEmpty = column.blocks.length === 0;\n const colEl = h('div', {\n class: `sm-column ${isEmpty ? 'is-empty' : ''}`,\n 'data-section-id': section.id,\n 'data-column-index': String(columnIndex),\n style: `flex:${layoutFlexValue(section.layout, columnIndex)};${\n column.attrs.backgroundColor ? `background:${column.attrs.backgroundColor};` : ''\n }${column.attrs.verticalAlign ? `align-self:${vaToFlex(column.attrs.verticalAlign)};` : ''}`,\n });\n\n for (const block of column.blocks) {\n colEl.append(this._renderBlock(section, columnIndex, block, doc));\n }\n\n if (isEmpty) {\n colEl.addEventListener('dblclick', (e: MouseEvent) => {\n if ((e.target as HTMLElement).closest('.sm-block')) return;\n e.preventDefault();\n e.stopPropagation();\n this._insertEmptyTextAndEdit(section.id, columnIndex);\n });\n }\n\n // 列内 Sortable:负责块排序,并且:\n // - put: ['blocks'] 接受外来 block(同 group)\n // - pull: true(默认) 允许把内部 block 拖出到其他列 / 或顶层(自动裹一列)\n // - handle 限制为 .sm-block__handle:点选/编辑文本不会误触拖拽\n const sortable = Sortable.create(colEl, {\n group: { name: 'blocks', put: ['blocks'] },\n animation: 150,\n draggable: '.sm-block',\n handle: '.sm-block__handle',\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n onAdd: (e) => this._handleBlockAdd(e, section.id, columnIndex),\n onUpdate: (e) => this._handleBlockMove(e, section.id, columnIndex),\n onRemove: () => {\n /* DOM 调整由 store 重渲染负责;这里不处理。\n 源 column 把 block 拖出后,store 会被 onAdd 同步从源数组里移除该 block。 */\n },\n });\n this.sortableRefs.push(sortable);\n\n return colEl;\n }\n\n private _renderBlock(\n section: Section,\n columnIndex: number,\n block: Block,\n doc: EmailDoc,\n ): HTMLElement {\n const ctx: RenderContext = { doc, engine: 'mjml' };\n const def = this.opts.registry.get(block.type);\n let inner = '';\n if (block.lockedMjml) {\n if (block.type === 'html') {\n const p = block.props as {\n paddingTop?: number;\n paddingRight?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n };\n const frag = htmlFragmentForLockedHtmlBlockCanvas(block.lockedMjml, {\n top: Number(p.paddingTop ?? 8),\n right: Number(p.paddingRight ?? 0),\n bottom: Number(p.paddingBottom ?? 8),\n left: Number(p.paddingLeft ?? 0),\n });\n inner = `<div class=\"sm-html-content\">${frag}</div>`;\n } else {\n inner = `<div style=\"padding:8px;color:#92400e;background:#fffbeb;border:1px dashed #f59e0b;font-family:monospace;font-size:11px;white-space:pre-wrap;\">${escapeHtml(\n block.lockedMjml,\n )}</div>`;\n }\n } else if (def?.renderPreview) {\n inner = def.renderPreview(block.props as any, ctx);\n } else if (def) {\n inner = `<div style=\"padding:16px;color:#6b7280;background:#f9fafb;border:1px dashed #d1d5db;text-align:center;\">${escapeHtml(\n def.name,\n )}</div>`;\n } else {\n inner = `<div style=\"padding:8px;color:#dc2626;\">未知组件: ${escapeHtml(block.type)}</div>`;\n }\n\n const displayName = def?.name ?? block.type;\n\n const el = h('div', {\n class: `sm-block ${block.lockedMjml ? 'is-locked' : ''}`,\n 'data-id': block.id,\n 'data-section-id': section.id,\n 'data-column-index': String(columnIndex),\n });\n\n // 内容容器:renderPreview 输出放这里,便于精确定位 inlineEditable selector\n const content = h('div', { class: 'sm-block__content', html: inner });\n\n // 块工具条:hover 仅名称;选中 / 编辑中显示全部按钮;贴在块顶边之上不压内容\n const blockToolbar = h('div', { class: 'sm-block__toolbar' }, [\n h('span', { class: 'sm-block__toolbar-name', title: displayName }, [displayName]),\n h('div', { class: 'sm-block__toolbar-actions' }, [\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-block__handle',\n type: 'button',\n title: '拖拽排序',\n onmousedown: (e: Event) => e.stopPropagation(),\n onclick: (e: Event) => e.stopPropagation(),\n },\n [iconDrag()],\n ),\n def?.inlineEditable && !block.lockedMjml\n ? h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '编辑文本',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._enterEditing(block);\n },\n },\n [iconEdit()],\n )\n : null,\n h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '编辑组件代码',\n onclick: (e: Event) => {\n e.stopPropagation();\n this.blockCodeModal.open(block.id, displayName);\n },\n },\n [iconCode()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '复制',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._duplicateBlock(block.id);\n },\n },\n [iconCopy()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-tool-btn--danger',\n type: 'button',\n title: '删除',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._removeBlock(block.id);\n },\n },\n [iconTrash()],\n ),\n ]),\n ]);\n\n el.append(blockToolbar, content);\n\n el.addEventListener('click', (e) => {\n if (this.editingBlockId === block.id) return; // 编辑中不抢焦点\n /** Alt(mac Option):穿透选中父级 Section,解决单列内边距为 0 时块铺满无法点到 Section */\n if (e.altKey) {\n e.stopPropagation();\n this.opts.store.setSelection({ kind: 'section', sectionId: section.id });\n return;\n }\n e.stopPropagation();\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: section.id,\n columnIndex,\n blockId: block.id,\n });\n });\n\n if (def?.inlineEditable && !block.lockedMjml) {\n el.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n this._enterEditing(block);\n });\n }\n\n return el;\n }\n\n private _renderAddBar(): HTMLElement {\n const layouts: { layout: SectionLayout; label: string }[] = [\n { layout: '1', label: '一列' },\n { layout: '1-1', label: '两列' },\n { layout: '1-2', label: '1:2' },\n { layout: '2-1', label: '2:1' },\n { layout: '1-1-1', label: '三列' },\n ];\n const bar = h('div', { class: 'sm-add-section-bar' }, [h('span', {}, ['+ 添加 Section:'])]);\n for (const l of layouts) {\n bar.append(\n h(\n 'button',\n {\n class: 'sm-add-section-bar__btn',\n type: 'button',\n onclick: () =>\n this.opts.store.update((d) => {\n d.sections.push(createSection(l.layout));\n }),\n },\n [l.label],\n ),\n );\n }\n return bar;\n }\n\n /* ----------------------------- 内联编辑 -------------------------------- */\n\n /** 空文档时:在画布白底区域双击,插入一列 Section + 空文本并进入编辑 */\n private _onEmptyCanvasDblClick(e: MouseEvent) {\n if (this.opts.store.doc.sections.length > 0) return;\n const t = e.target as HTMLElement | null;\n if (!t || !this.inner.contains(t)) return;\n e.preventDefault();\n e.stopPropagation();\n this._bootstrapEmptyDocWithText();\n }\n\n /** 无任何 Section 时:创建单栏布局并放入空正文块,再进入内联编辑 */\n private _bootstrapEmptyDocWithText() {\n const reg = this.opts.registry;\n if (!reg.get('text')?.inlineEditable) return;\n this.opts.store.update((d) => {\n if (d.sections.length > 0) return;\n const newBlock = reg.createBlock('text');\n (newBlock.props as { content: string }).content = '';\n const section = createSection('1');\n section.columns[0].blocks.push(newBlock);\n d.sections.push(section);\n });\n\n const doc = this.opts.store.doc;\n const firstBlock = doc.sections[0]?.columns[0]?.blocks[0];\n if (!firstBlock) return;\n\n requestAnimationFrame(() => {\n const loc = findBlockLocation(this.opts.store.doc, firstBlock.id);\n if (loc) this._enterEditing(loc.block);\n });\n }\n\n /** 空列双击:插入正文组件(content 为空)并直接进入编辑 */\n private _insertEmptyTextAndEdit(sectionId: string, columnIndex: number) {\n const reg = this.opts.registry;\n if (!reg.get('text')?.inlineEditable) return;\n const newBlock = reg.createBlock('text');\n (newBlock.props as { content: string }).content = '';\n\n this.opts.store.update((d) => {\n const sec = findSection(d, sectionId);\n if (!sec) return;\n const col = sec.columns[columnIndex];\n if (!col || col.blocks.length > 0) return;\n col.blocks.push(newBlock);\n });\n\n requestAnimationFrame(() => {\n const loc = findBlockLocation(this.opts.store.doc, newBlock.id);\n if (loc) this._enterEditing(loc.block);\n });\n }\n\n private _enterEditing(block: Block) {\n if (this.editingBlockId === block.id) return;\n this._exitEditing(true);\n\n const def = this.opts.registry.get(block.type);\n if (!def?.inlineEditable) return;\n\n const blockEl = this.inner.querySelector(\n `.sm-block[data-id=\"${cssEscape(block.id)}\"]`,\n ) as HTMLElement | null;\n const contentRoot = blockEl?.querySelector('.sm-block__content') as HTMLElement | null;\n if (!contentRoot) return;\n\n const target = (\n def.inlineEditable.selector\n ? contentRoot.querySelector(def.inlineEditable.selector)\n : contentRoot.firstElementChild\n ) as HTMLElement | null;\n if (!target) return;\n\n this.editingBlockId = block.id;\n blockEl?.classList.add('is-editing');\n\n const initial =\n def.inlineEditable.mode === 'plain'\n ? String((block.props as any)[def.inlineEditable.propKey] ?? '')\n : String((block.props as any)[def.inlineEditable.propKey] ?? '');\n\n this.inlineEditor = new InlineEditor({\n el: target,\n initialValue: initial,\n mode: def.inlineEditable.mode,\n multiline: !!def.inlineEditable.multiline,\n placeholder: def.inlineEditable.placeholder,\n onCommit: (value) => {\n const propKey = def.inlineEditable!.propKey;\n const editingId = block.id;\n this._exitEditing(false);\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, editingId);\n if (loc) (loc.block.props as any)[propKey] = value;\n });\n },\n onCancel: () => this._exitEditing(true),\n onSelectionChange: (state: SelectionState | null) => {\n this.opts.toolbar.update(state);\n },\n });\n\n if (def.inlineEditable.mode === 'rich') {\n this.opts.toolbar.attach(this.inlineEditor);\n }\n\n // 选中该 block,便于属性面板同步\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: blockEl!.getAttribute('data-section-id')!,\n columnIndex: Number(blockEl!.getAttribute('data-column-index')),\n blockId: block.id,\n });\n }\n\n /** restoreUI=true:编辑器自身恢复原 DOM(取消场景);false:保留新内容(提交场景,等待 store 回写后重渲染) */\n private _exitEditing(restoreUI: boolean) {\n if (!this.editingBlockId) return;\n const id = this.editingBlockId;\n this.editingBlockId = null;\n if (this.inlineEditor) {\n this.inlineEditor.destroy(restoreUI);\n this.inlineEditor = null;\n }\n this.opts.toolbar.detach();\n const blockEl = this.inner.querySelector(\n `.sm-block[data-id=\"${cssEscape(id)}\"]`,\n ) as HTMLElement | null;\n blockEl?.classList.remove('is-editing');\n\n if (this.pendingRender) {\n this.pendingRender = false;\n this._render();\n }\n }\n\n /* -------------------------------- 拖拽 ---------------------------------- */\n\n private _blocksFromPaletteDrop(blockType: string): Block[] {\n const def = this.opts.registry.get(blockType);\n if (def?.expandPaletteDrop) {\n return def.expandPaletteDrop((t) => this.opts.registry.createBlock(t));\n }\n return [this.opts.registry.createBlock(blockType)];\n }\n\n private _handleSectionAdd(e: Sortable.SortableEvent) {\n const item = e.item;\n const layout = item.getAttribute('data-layout') as SectionLayout | null;\n const blockType = item.getAttribute('data-block-type');\n const fromBlockId = item.getAttribute('data-id');\n const sourceGroup = item.getAttribute('data-source-group');\n const newIndex = e.newIndex ?? 0;\n\n // 路径 A:左栏布局卡片\n if (layout) {\n item.parentElement?.removeChild(item);\n this.opts.store.update((d) => {\n d.sections.splice(newIndex, 0, createSection(layout));\n });\n return;\n }\n\n // 路径 B:左栏内容/自定义卡片拖到 sections 之间 → 自动裹一列 Section\n if (sourceGroup === 'blocks' && blockType) {\n item.parentElement?.removeChild(item);\n const blocks = this._blocksFromPaletteDrop(blockType);\n const newSection = createSection('1');\n newSection.columns[0].blocks.splice(newIndex, 0, ...blocks);\n this.opts.store.update((d) => {\n d.sections.splice(newIndex, 0, newSection);\n });\n const head = blocks[0];\n if (head) {\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: newSection.id,\n columnIndex: 0,\n blockId: head.id,\n });\n }\n return;\n }\n\n // 路径 C:从某个已有 column 把 block 拖到 sections 之间 → 自动裹一列 Section\n if (fromBlockId) {\n item.parentElement?.removeChild(item);\n const newSection = createSection('1');\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, fromBlockId);\n if (!loc) return;\n const fromCol = loc.section.columns[loc.columnIndex];\n const idx = fromCol.blocks.findIndex((b) => b.id === fromBlockId);\n if (idx < 0) return;\n const [moved] = fromCol.blocks.splice(idx, 1);\n newSection.columns[0].blocks.push(moved);\n // 注意:newIndex 是 SortableJS 把 item 放进 DOM 后看到的索引;\n // 由于来源 column 内的 block 不属于 inner 的直接子节点,\n // newIndex 在 inner 的可视位置上是准确的。\n d.sections.splice(newIndex, 0, newSection);\n pruneEmptySections(d);\n });\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: newSection.id,\n columnIndex: 0,\n blockId: fromBlockId,\n });\n }\n }\n\n private _handleSectionMove(e: Sortable.SortableEvent) {\n const oldIndex = e.oldIndex ?? 0;\n const newIndex = e.newIndex ?? 0;\n if (oldIndex === newIndex) return;\n this.opts.store.update((d) => {\n const [moved] = d.sections.splice(oldIndex, 1);\n d.sections.splice(newIndex, 0, moved);\n });\n }\n\n private _handleBlockAdd(e: Sortable.SortableEvent, sectionId: string, columnIndex: number) {\n const item = e.item;\n const newIndex = e.newIndex ?? 0;\n const sourceGroup = item.getAttribute('data-source-group');\n const blockType = item.getAttribute('data-block-type');\n const fromBlockId = item.getAttribute('data-id');\n\n if (sourceGroup === 'blocks' && blockType) {\n item.parentElement?.removeChild(item);\n const blocks = this._blocksFromPaletteDrop(blockType);\n this.opts.store.update((d) => {\n const sec = d.sections.find((s) => s.id === sectionId);\n if (!sec) return;\n sec.columns[columnIndex]?.blocks.splice(newIndex, 0, ...blocks);\n });\n const head = blocks[0];\n if (head) {\n this.opts.store.setSelection({\n kind: 'block',\n sectionId,\n columnIndex,\n blockId: head.id,\n });\n }\n return;\n }\n\n if (fromBlockId) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, fromBlockId);\n if (!loc) return;\n const fromCol = loc.section.columns[loc.columnIndex];\n const idx = fromCol.blocks.findIndex((b) => b.id === fromBlockId);\n if (idx < 0) return;\n const [moved] = fromCol.blocks.splice(idx, 1);\n const targetSec = d.sections.find((s) => s.id === sectionId);\n targetSec?.columns[columnIndex]?.blocks.splice(newIndex, 0, moved);\n pruneEmptySections(d);\n });\n }\n }\n\n private _handleBlockMove(e: Sortable.SortableEvent, sectionId: string, columnIndex: number) {\n const oldIndex = e.oldIndex ?? 0;\n const newIndex = e.newIndex ?? 0;\n if (oldIndex === newIndex) return;\n this.opts.store.update((d) => {\n const sec = d.sections.find((s) => s.id === sectionId);\n const col = sec?.columns[columnIndex];\n if (!col) return;\n const [moved] = col.blocks.splice(oldIndex, 1);\n col.blocks.splice(newIndex, 0, moved);\n });\n }\n\n /* -------------------------------- 操作 ---------------------------------- */\n\n private _removeSection(id: string) {\n this.opts.store.update((d) => {\n d.sections = d.sections.filter((s) => s.id !== id);\n });\n this.opts.store.setSelection(null);\n }\n\n private _duplicateSection(id: string) {\n this.opts.store.update((d) => {\n const idx = d.sections.findIndex((s) => s.id === id);\n if (idx < 0) return;\n const clone = structuredClone(d.sections[idx]);\n clone.id = `${clone.id}_c${Date.now().toString(36)}`;\n clone.columns = clone.columns.map((c) => ({\n ...c,\n id: `${c.id}_c${Date.now().toString(36)}`,\n blocks: c.blocks.map((b) => ({ ...b, id: `${b.id}_c${Date.now().toString(36)}` })),\n }));\n d.sections.splice(idx + 1, 0, clone);\n });\n }\n\n private _removeBlock(id: string) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, id);\n if (!loc) return;\n const col = loc.section.columns[loc.columnIndex];\n col.blocks = col.blocks.filter((b) => b.id !== id);\n pruneEmptySections(d);\n });\n this.opts.store.setSelection(null);\n }\n\n private _duplicateBlock(id: string) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, id);\n if (!loc) return;\n const col = loc.section.columns[loc.columnIndex];\n const idx = col.blocks.findIndex((b) => b.id === id);\n if (idx < 0) return;\n const clone = structuredClone(col.blocks[idx]);\n clone.id = `${clone.id}_c${Date.now().toString(36)}`;\n col.blocks.splice(idx + 1, 0, clone);\n });\n }\n\n private _syncSelection() {\n const sel = this.opts.store.selection;\n this.inner.querySelectorAll('.is-selected').forEach((el) => el.classList.remove('is-selected'));\n if (!sel) return;\n if (sel.kind === 'section') {\n this.inner\n .querySelector(`.sm-section[data-id=\"${cssEscape(sel.sectionId)}\"]`)\n ?.classList.add('is-selected');\n } else {\n this.inner\n .querySelector(`.sm-block[data-id=\"${cssEscape(sel.blockId)}\"]`)\n ?.classList.add('is-selected');\n }\n }\n\n private _destroySortables() {\n for (const s of this.sortableRefs) s.destroy();\n this.sortableRefs = [];\n }\n}\n\n/* ---------------------------------- utils --------------------------------- */\n\nconst LAYOUT_LABELS: Record<SectionLayout, string> = {\n '1': '一列',\n '1-1': '两列',\n '1-2': '1:2',\n '2-1': '2:1',\n '1-1-1': '三列',\n};\n\nfunction layoutHumanLabel(layout: SectionLayout): string {\n return LAYOUT_LABELS[layout] ?? layout;\n}\n\nfunction layoutFlexStyle(_layout: SectionLayout, columnGap?: number): string {\n const gap =\n columnGap != null && columnGap > 0 ? `gap:${Math.min(columnGap, 200)}px;` : '';\n return `display:flex;flex-wrap:nowrap;width:100%;${gap}`;\n}\n\nfunction layoutFlexValue(layout: SectionLayout, index: number): string {\n const parts = layout.split('-').map(Number);\n const total = parts.reduce((s, x) => s + x, 0);\n const ratio = parts[index] ?? 1;\n return `${ratio} 1 0;min-width:0;width:${((ratio / total) * 100).toFixed(2)}%`;\n}\n\nfunction vaToFlex(va: 'top' | 'middle' | 'bottom'): string {\n return va === 'top' ? 'flex-start' : va === 'bottom' ? 'flex-end' : 'center';\n}\n\nfunction cssEscape(s: string): string {\n if (typeof CSS !== 'undefined' && CSS.escape) return CSS.escape(s);\n return s.replace(/[^\\w-]/g, '\\\\$&');\n}\n\nfunction svg(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '12');\n el.setAttribute('height', '12');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML = inner;\n return el;\n}\nfunction iconDrag() {\n return svg(\n '<circle cx=\"7\" cy=\"5\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"13\" cy=\"5\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"7\" cy=\"10\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"13\" cy=\"10\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"7\" cy=\"15\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"13\" cy=\"15\" r=\"1.4\" fill=\"currentColor\"/>',\n );\n}\nfunction iconCopy() {\n return svg(\n '<rect x=\"6\" y=\"6\" width=\"10\" height=\"10\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><path d=\"M4 12V5a1 1 0 011-1h7\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/>',\n );\n}\nfunction iconTrash() {\n return svg(\n '<path d=\"M5 6h10M8 6V4h4v2M6 6l1 10h6l1-10\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\" stroke-linejoin=\"round\"/>',\n );\n}\nfunction iconEdit() {\n return svg(\n '<path d=\"M4 14l8-8 2 2-8 8H4v-2z\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\" stroke-linejoin=\"round\"/>',\n );\n}\nfunction iconCode() {\n return svg(\n '<path d=\"M7 7l-3 3 3 3M13 7l3 3-3 3\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n );\n}\n","import { EditorState } from '@codemirror/state';\nimport { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport type { Registry } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport type { Store } from '../store/store';\nimport { prettyHtml } from '../utils/html';\nimport { h } from '../utils/dom';\nimport { Modal } from './Modal';\n\nexport interface ExportModalOptions {\n store: Store;\n registry: Registry;\n /** 替换 {{var}} 为 sample 值 */\n withSampleVariables?: boolean;\n}\n\n/**\n * 导出 HTML 弹框:\n * - body 用 CodeMirror 只读展示当前文档编译产物\n * - footer:复制、美化、下载 三个动作\n */\nexport class ExportModal {\n private opts: ExportModalOptions;\n private modal: Modal;\n private cm: EditorView | null = null;\n private current: string = '';\n\n constructor(opts: ExportModalOptions) {\n this.opts = opts;\n this.modal = new Modal({\n title: '导出 HTML',\n className: 'sm-modal--export',\n width: 'min(960px, 96vw)',\n height: 'min(720px, 88vh)',\n onClose: () => this._destroyCm(),\n });\n\n const editorHost = h('div', { class: 'sm-export__editor' });\n this.modal.body.append(editorHost);\n\n const copyBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: () => this._copy() },\n ['复制 HTML'],\n );\n const beautifyBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: () => this._beautify() },\n ['美化'],\n );\n const downloadBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onclick: () => this._download(),\n },\n ['下载 .html'],\n );\n this.modal.footer.append(copyBtn, beautifyBtn, downloadBtn);\n\n // 初始化 CodeMirror(在 open 时填充 doc)\n this.cm = new EditorView({\n parent: editorHost,\n state: EditorState.create({\n doc: '',\n extensions: [basicSetup, cmHtml(), EditorState.readOnly.of(true)],\n }),\n });\n }\n\n open(parent?: HTMLElement) {\n this._compile();\n this.modal.open(parent);\n }\n\n private _compile() {\n const result = renderDoc(this.opts.store.doc, this.opts.registry, {\n withSampleVariables: this.opts.withSampleVariables ?? true,\n });\n this.current = result.html;\n this._setText(result.html);\n }\n\n private _setText(text: string) {\n if (!this.cm) return;\n this.cm.dispatch({\n changes: { from: 0, to: this.cm.state.doc.length, insert: text },\n });\n }\n\n private async _copy() {\n try {\n await navigator.clipboard.writeText(this.current);\n this._toast('已复制到剪贴板');\n } catch {\n const ta = document.createElement('textarea');\n ta.value = this.current;\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n this._toast('已复制');\n }\n }\n\n private _beautify() {\n this.current = prettyHtml(this.current);\n this._setText(this.current);\n }\n\n private _download() {\n const blob = new Blob([this.current], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `email-${Date.now()}.html`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n }\n\n private _toast(text: string) {\n const t = h('div', { class: 'sm-toast' }, [text]);\n this.modal.body.append(t);\n requestAnimationFrame(() => t.classList.add('is-visible'));\n setTimeout(() => {\n t.classList.remove('is-visible');\n setTimeout(() => t.remove(), 200);\n }, 1400);\n }\n\n private _destroyCm() {\n this.cm?.destroy();\n this.cm = null;\n }\n}\n","import Sortable from 'sortablejs';\nimport type { Registry } from '../registry/registry';\nimport type { BlockDefinition, SectionLayout } from '../types';\nimport { clear, h } from '../utils/dom';\n\nexport interface LeftPanelOptions {\n registry: Registry;\n}\n\ninterface LayoutCard {\n layout: SectionLayout;\n name: string;\n icon: string;\n}\n\nconst LAYOUT_CARDS: LayoutCard[] = [\n { layout: '1', name: '一列', icon: layoutSvg([1]) },\n { layout: '1-1', name: '两列', icon: layoutSvg([1, 1]) },\n { layout: '1-2', name: '1:2', icon: layoutSvg([1, 2]) },\n { layout: '2-1', name: '2:1', icon: layoutSvg([2, 1]) },\n { layout: '1-1-1', name: '三列', icon: layoutSvg([1, 1, 1]) },\n];\n\n/**\n * 左栏分两类:\n * - 布局(layout):决定 Section 结构,拖入到画布顶层(group: 'sections')\n * - 内容/自定义:作为 Block,拖入到 Column 中(group: 'blocks')\n *\n * 通过 SortableJS 的 group + clone + sort:false 实现。\n * 这两个组分开,画布顶层只接 'sections',列内只接 'blocks',\n * 严格两层拖拽,禁止跨级别——这是解决 GrapesJS 嵌套混乱的核心。\n */\nexport class LeftPanel {\n el: HTMLElement;\n private opts: LeftPanelOptions;\n\n constructor(opts: LeftPanelOptions) {\n this.opts = opts;\n this.el = h('aside', { class: 'sm-panel sm-panel--left' });\n this._render();\n }\n\n refresh() {\n this._render();\n }\n\n private _render() {\n clear(this.el);\n const content = this.opts.registry.byCategory('content');\n const custom = this.opts.registry.byCategory('custom');\n\n const wrap = h('div', { class: 'sm-blocks' });\n\n wrap.append(this._renderLayoutGroup());\n if (content.length) wrap.append(this._renderBlockGroup('内容', content));\n if (custom.length) wrap.append(this._renderBlockGroup('自定义', custom));\n\n this.el.append(wrap);\n }\n\n private _renderLayoutGroup(): HTMLElement {\n const grid = h('div', { class: 'sm-blocks__grid' });\n for (const c of LAYOUT_CARDS) {\n grid.append(\n h(\n 'div',\n {\n class: 'sm-block-card',\n 'data-source-group': 'sections',\n 'data-layout': c.layout,\n title: c.name,\n },\n [\n h('span', { class: 'sm-block-card__icon', html: c.icon }),\n h('span', { class: 'sm-block-card__name' }, [c.name]),\n ],\n ),\n );\n }\n Sortable.create(grid, {\n group: { name: 'sections', pull: 'clone', put: false },\n sort: false,\n animation: 120,\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n });\n return h('section', { class: 'sm-blocks__group' }, [\n h('div', { class: 'sm-panel__title' }, ['布局']),\n grid,\n ]);\n }\n\n private _renderBlockGroup(title: string, defs: BlockDefinition[]): HTMLElement {\n const grid = h('div', { class: 'sm-blocks__grid' });\n for (const def of defs) {\n grid.append(\n h(\n 'div',\n {\n class: 'sm-block-card',\n 'data-source-group': 'blocks',\n 'data-block-type': def.type,\n title: def.name,\n },\n [\n h('span', { class: 'sm-block-card__icon', html: def.icon }),\n h('span', { class: 'sm-block-card__name' }, [def.name]),\n ],\n ),\n );\n }\n Sortable.create(grid, {\n group: { name: 'blocks', pull: 'clone', put: false },\n sort: false,\n animation: 120,\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n });\n return h('section', { class: 'sm-blocks__group' }, [\n h('div', { class: 'sm-panel__title' }, [title]),\n grid,\n ]);\n }\n}\n\nfunction layoutSvg(parts: number[]): string {\n const total = parts.reduce((s, x) => s + x, 0);\n const w = 24;\n const gap = 1;\n const innerW = w - gap * (parts.length - 1);\n let x = 0;\n const rects = parts\n .map((p) => {\n const rw = (p / total) * innerW;\n const rect = `<rect x=\"${x}\" y=\"6\" width=\"${rw.toFixed(\n 2,\n )}\" height=\"12\" fill=\"currentColor\" opacity=\"0.8\" rx=\"1\"/>`;\n x += rw + gap;\n return rect;\n })\n .join('');\n return `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">${rects}</svg>`;\n}\n","import type { Registry } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport type { Store } from '../store/store';\nimport { h } from '../utils/dom';\nimport { Modal } from './Modal';\n\nexport type PreviewDevice = 'pc' | 'pad' | 'phone';\n\ninterface DeviceSpec {\n width: number;\n label: string;\n}\n\nconst DEVICES: Record<PreviewDevice, DeviceSpec> = {\n pc: { width: 800, label: 'PC' },\n pad: { width: 640, label: 'Pad' },\n phone: { width: 375, label: 'Phone' },\n};\n\nexport interface PreviewModalOptions {\n store: Store;\n registry: Registry;\n}\n\n/**\n * 预览弹框:用 iframe 渲染真实 mjml 编译产物。\n * 通过 srcdoc 写入 HTML,避免跨域;用变量 sample 值替换占位符,所见即所得。\n * 三个设备宽度切换:800 / 640 / 375,按邮件常见宽度档位。\n */\nexport class PreviewModal {\n private opts: PreviewModalOptions;\n private modal: Modal;\n private device: PreviewDevice = 'pc';\n private iframe: HTMLIFrameElement;\n private viewport: HTMLElement;\n private deviceBtns: Record<PreviewDevice, HTMLButtonElement> = {} as any;\n private iframeRo?: ResizeObserver;\n private layoutRaf: number | null = null;\n private onWinResize?: () => void;\n\n constructor(opts: PreviewModalOptions) {\n this.opts = opts;\n this.modal = new Modal({\n title: '预览邮件',\n className: 'sm-modal--preview',\n width: 'min(960px, calc(100vw - 32px))',\n /** 高度随 iframe 内容测量,见 _fitPreviewHeight;不超过屏高由 CSS max-height 约束 */\n onClose: () => this._teardownLayoutHooks(),\n });\n\n this.iframe = h('iframe', {\n class: 'sm-preview__frame',\n sandbox: 'allow-same-origin',\n title: 'preview',\n }) as HTMLIFrameElement;\n this.iframe.addEventListener('load', () => {\n this._bindIframeResizeObserver();\n this._scheduleFitPreviewHeight();\n });\n\n this.viewport = h('div', { class: 'sm-preview__viewport' }, [this.iframe]);\n this.modal.body.classList.add('sm-modal__body--center');\n this.modal.body.append(this.viewport);\n\n // 设备切换工具条放在 header 右侧\n const switcher = h('div', { class: 'sm-segmented' });\n (['pc', 'pad', 'phone'] as PreviewDevice[]).forEach((d) => {\n const btn = h(\n 'button',\n {\n class: `sm-segmented__item ${d === this.device ? 'sm-segmented__item--active' : ''}`,\n type: 'button',\n onclick: () => this.setDevice(d),\n },\n [iconForDevice(d), DEVICES[d].label],\n ) as HTMLButtonElement;\n this.deviceBtns[d] = btn;\n switcher.append(btn);\n });\n this.modal.appendHeaderTool(switcher);\n }\n\n open(parent?: HTMLElement) {\n this._render();\n this.setDevice(this.device);\n this.modal.open(parent);\n this.onWinResize = () => this._scheduleFitPreviewHeight();\n window.addEventListener('resize', this.onWinResize);\n }\n\n setDevice(d: PreviewDevice) {\n this.device = d;\n const spec = DEVICES[d];\n this.viewport.style.setProperty('--sm-preview-w', `${spec.width}px`);\n for (const k of Object.keys(this.deviceBtns) as PreviewDevice[]) {\n this.deviceBtns[k].classList.toggle('sm-segmented__item--active', k === d);\n }\n requestAnimationFrame(() =>\n requestAnimationFrame(() => this._scheduleFitPreviewHeight()),\n );\n }\n\n private _render() {\n const result = renderDoc(this.opts.store.doc, this.opts.registry, {\n withSampleVariables: true,\n });\n // 用 srcdoc 而非 src=blob:,避免 about:srcdoc 偶发的相对资源问题\n this.iframe.srcdoc = result.html;\n }\n\n /** 标题栏 + body 上下 padding + 与视口的小间距 */\n private static readonly VIEWPORT_RESERVED_Y = 112;\n\n private _scheduleFitPreviewHeight() {\n if (this.layoutRaf != null) cancelAnimationFrame(this.layoutRaf);\n this.layoutRaf = requestAnimationFrame(() => {\n this.layoutRaf = null;\n this._fitPreviewHeight();\n });\n }\n\n private _fitPreviewHeight() {\n if (!this.iframe.isConnected) return;\n try {\n const doc = this.iframe.contentDocument;\n const root = doc?.documentElement;\n const body = doc?.body;\n if (!root || !body) return;\n const raw = Math.max(root.scrollHeight, body.scrollHeight);\n const maxPx = Math.max(\n 240,\n window.innerHeight - PreviewModal.VIEWPORT_RESERVED_Y,\n );\n const minPx = 200;\n const next = Math.min(Math.max(Math.ceil(raw), minPx), maxPx);\n this.viewport.style.height = `${next}px`;\n } catch {\n /* srcdoc 同域,极端情况下忽略 */\n }\n }\n\n private _bindIframeResizeObserver() {\n this.iframeRo?.disconnect();\n try {\n const doc = this.iframe.contentDocument;\n const body = doc?.body;\n if (!body || typeof ResizeObserver === 'undefined') return;\n this.iframeRo = new ResizeObserver(() => this._scheduleFitPreviewHeight());\n this.iframeRo.observe(body);\n const html = doc.documentElement;\n if (html) this.iframeRo.observe(html);\n } catch {\n /* ignore */\n }\n }\n\n private _teardownLayoutHooks() {\n if (this.onWinResize) {\n window.removeEventListener('resize', this.onWinResize);\n this.onWinResize = undefined;\n }\n this.iframeRo?.disconnect();\n this.iframeRo = undefined;\n if (this.layoutRaf != null) {\n cancelAnimationFrame(this.layoutRaf);\n this.layoutRaf = null;\n }\n }\n}\n\nfunction iconForDevice(d: PreviewDevice): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '14');\n el.setAttribute('height', '14');\n el.setAttribute('viewBox', '0 0 20 20');\n if (d === 'pc')\n el.innerHTML =\n '<rect x=\"2\" y=\"4\" width=\"16\" height=\"11\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><path d=\"M7 18h6\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/>';\n else if (d === 'pad')\n el.innerHTML =\n '<rect x=\"4\" y=\"2\" width=\"12\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"10\" cy=\"16\" r=\"0.6\" fill=\"currentColor\"/>';\n else\n el.innerHTML =\n '<rect x=\"6\" y=\"2\" width=\"8\" height=\"16\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"10\" cy=\"16\" r=\"0.6\" fill=\"currentColor\"/>';\n return el;\n}\n","import { h } from '../utils/dom';\nimport type { InlineEditor, SelectionState } from './InlineEditor';\n\n/**\n * 富文本浮动工具条。\n *\n * 关键设计:\n * - 工具条挂在 editor root 上,跨 block 实例复用;切换编辑对象时调用 attach()。\n * - **mousedown 在工具条任意位置时(capture 阶段)先调用 editor.saveSelection()**:\n * 在浏览器把焦点切到 select/input 之前抢先把选区存到 InlineEditor,\n * 后续 exec 时会自动 focus 回 contenteditable + 恢复选区——这是\n * \"切字体/字号/颜色失灵\"问题的根本修复。\n * - 按钮全部 mousedown.preventDefault:不抢焦点;select/color/url 这些\n * 必须 takeFocus 的控件不能 preventDefault,但因为 mousedown 已经存档了选区,\n * onChange/onClick 时调 exec 即可。\n * - 定位:贴在当前内联编辑根节点(正文容器)**上沿外**,不跟随选区以免压住文字;顶栏贴顶时落到下沿外。\n */\nexport interface RichTextToolbarOptions {\n /** 工具条的定位上下文:rect 是相对该容器计算的 */\n positionRoot: HTMLElement;\n}\n\nconst FONT_FAMILIES = [\n { label: '默认', value: '' },\n { label: 'Inter', value: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif' },\n { label: '苹方/PingFang', value: '\"PingFang SC\", \"Helvetica Neue\", Arial, sans-serif' },\n { label: '微软雅黑', value: '\"Microsoft YaHei\", \"Segoe UI\", sans-serif' },\n { label: '宋体', value: 'SimSun, \"Songti SC\", serif' },\n { label: 'Helvetica', value: '\"Helvetica Neue\", Arial, sans-serif' },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Courier', value: '\"Courier New\", monospace' },\n];\n\nconst FONT_SIZES = ['12px', '13px', '14px', '15px', '16px', '18px', '20px', '24px', '28px', '32px'];\n\nconst FONT_WEIGHTS = [\n { label: '常规', value: '400' },\n { label: '中等', value: '500' },\n { label: '半粗', value: '600' },\n { label: '加粗', value: '700' },\n];\n\nexport class RichTextToolbar {\n el: HTMLElement;\n private opts: RichTextToolbarOptions;\n private editor: InlineEditor | null = null;\n private btns: Record<string, HTMLButtonElement> = {};\n private selectFontFamily!: HTMLSelectElement;\n private selectFontSize!: HTMLSelectElement;\n private selectFontWeight!: HTMLSelectElement;\n private inputColor!: HTMLInputElement;\n private inputBgColor!: HTMLInputElement;\n private inputLink!: HTMLInputElement;\n private linkPanel!: HTMLElement;\n /** 最近一次选区推断出的链接,供打开面板时预填 */\n private lastLinkHref: string | null = null;\n\n constructor(opts: RichTextToolbarOptions) {\n this.opts = opts;\n this.el = h('div', { class: 'sm-floating-toolbar', role: 'toolbar' });\n this._build();\n this.hide();\n opts.positionRoot.append(this.el);\n\n // 关键:用 capture 阶段在所有控件之前抢先 save selection\n this.el.addEventListener(\n 'mousedown',\n () => {\n this.editor?.saveSelection();\n },\n true,\n );\n }\n\n attach(editor: InlineEditor) {\n this.editor = editor;\n }\n\n detach() {\n this.editor = null;\n this.hide();\n }\n\n show() {\n this.el.classList.add('is-visible');\n }\n\n hide() {\n this.el.classList.remove('is-visible');\n this.linkPanel.classList.remove('is-visible');\n }\n\n /** 由 InlineEditor 推选区状态进来 */\n update(state: SelectionState | null) {\n if (!state || !this.editor) {\n this.hide();\n return;\n }\n this.show();\n\n const f = state.formats;\n this._setActive('bold', f.bold);\n this._setActive('italic', f.italic);\n this._setActive('underline', f.underline);\n this._setActive('strikethrough', f.strikethrough);\n this._setActive('ul', f.unorderedList);\n this._setActive('ol', f.orderedList);\n this._setActive('alignLeft', f.align === 'left');\n this._setActive('alignCenter', f.align === 'center');\n this._setActive('alignRight', f.align === 'right');\n\n const hasLink = !!f.link;\n this.lastLinkHref = f.link;\n this.btns.unlink.style.display = hasLink ? '' : 'none';\n\n if (f.foreColor) {\n const hex = rgbToHex(f.foreColor);\n if (hex) this.inputColor.value = hex;\n }\n if (f.fontName) this.selectFontFamily.value = matchFamily(f.fontName);\n if (f.fontSize) {\n const px = f.fontSize.match(/\\d+px/)?.[0];\n if (px && FONT_SIZES.includes(px)) this.selectFontSize.value = px;\n }\n\n const ed = this.editor;\n requestAnimationFrame(() => {\n if (!this.editor || ed !== this.editor || !this.el.classList.contains('is-visible')) return;\n this._positionForAnchor(ed.getAnchorRect());\n });\n }\n\n destroy() {\n this.el.remove();\n }\n\n /* -------------------------------- 内部 ---------------------------------- */\n\n private _build() {\n const sep = () => h('div', { class: 'sm-floating-toolbar__sep' });\n\n // 这些按钮 mousedown.preventDefault 阻止抢焦点;点击时直接 exec\n const exec = (cmd: string, val?: string) => () => this.editor?.exec(cmd, val);\n\n this.btns.bold = this._btn('B', '加粗 ⌘B', exec('bold'), { fontWeight: '700' });\n this.btns.italic = this._btn('I', '斜体 ⌘I', exec('italic'), { fontStyle: 'italic' });\n this.btns.underline = this._btn('U', '下划线 ⌘U', exec('underline'), {\n textDecoration: 'underline',\n });\n this.btns.strikethrough = this._btn('S', '删除线', exec('strikeThrough'), {\n textDecoration: 'line-through',\n });\n\n this.btns.alignLeft = this._iconBtn(\n svgIcon(\n '<path d=\"M3 5h14M3 9h10M3 13h14M3 17h10\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '左对齐',\n exec('justifyLeft'),\n );\n this.btns.alignCenter = this._iconBtn(\n svgIcon(\n '<path d=\"M3 5h14M5 9h10M3 13h14M5 17h10\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '居中',\n exec('justifyCenter'),\n );\n this.btns.alignRight = this._iconBtn(\n svgIcon(\n '<path d=\"M3 5h14M7 9h10M3 13h14M7 17h10\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '右对齐',\n exec('justifyRight'),\n );\n\n this.btns.ul = this._iconBtn(\n svgIcon(\n '<circle cx=\"4\" cy=\"6\" r=\"1.2\" fill=\"currentColor\"/><circle cx=\"4\" cy=\"10\" r=\"1.2\" fill=\"currentColor\"/><circle cx=\"4\" cy=\"14\" r=\"1.2\" fill=\"currentColor\"/><path d=\"M8 6h9M8 10h9M8 14h9\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '无序列表',\n exec('insertUnorderedList'),\n );\n this.btns.ol = this._iconBtn(\n svgIcon(\n '<text x=\"2\" y=\"8\" font-size=\"6\" font-weight=\"600\" fill=\"currentColor\">1</text><text x=\"2\" y=\"14\" font-size=\"6\" font-weight=\"600\" fill=\"currentColor\">2</text><path d=\"M8 6h9M8 12h9\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '有序列表',\n exec('insertOrderedList'),\n );\n\n // 字体:select 不能 preventDefault(否则下拉打不开);mousedown(capture) 已存档选区\n this.selectFontFamily = h('select', {\n class: 'sm-floating-toolbar__select',\n title: '字体',\n onchange: (e: Event) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v) this.editor?.exec('fontName', v);\n else this.editor?.exec('removeFormat');\n },\n });\n for (const f of FONT_FAMILIES) {\n const opt = document.createElement('option');\n opt.value = f.value;\n opt.textContent = f.label;\n this.selectFontFamily.append(opt);\n }\n\n // 字号\n this.selectFontSize = h('select', {\n class: 'sm-floating-toolbar__select',\n title: '字号',\n onchange: (e: Event) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v) this._wrapStyle('font-size', v);\n },\n });\n {\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = '字号';\n this.selectFontSize.append(placeholder);\n }\n for (const px of FONT_SIZES) {\n const opt = document.createElement('option');\n opt.value = px;\n opt.textContent = px;\n this.selectFontSize.append(opt);\n }\n\n // 字重\n this.selectFontWeight = h('select', {\n class: 'sm-floating-toolbar__select',\n title: '字重',\n onchange: (e: Event) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v) this._wrapStyle('font-weight', v);\n },\n });\n {\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = '字重';\n this.selectFontWeight.append(placeholder);\n }\n for (const w of FONT_WEIGHTS) {\n const opt = document.createElement('option');\n opt.value = w.value;\n opt.textContent = w.label;\n this.selectFontWeight.append(opt);\n }\n\n // 文字颜色\n this.inputColor = h('input', {\n class: 'sm-floating-toolbar__color',\n type: 'color',\n title: '文字颜色',\n value: '#433f3f',\n oninput: (e: Event) => this.editor?.exec('foreColor', (e.target as HTMLInputElement).value),\n }) as HTMLInputElement;\n\n // 文字背景色\n this.inputBgColor = h('input', {\n class: 'sm-floating-toolbar__color',\n type: 'color',\n title: '文字背景色',\n value: '#fff7e6',\n oninput: (e: Event) => this.editor?.exec('hiliteColor', (e.target as HTMLInputElement).value),\n }) as HTMLInputElement;\n\n // 链接:插入链接(无链接时显示)\n this.btns.link = this._iconBtn(\n svgIcon(\n '<path d=\"M9 11.5l1.5 1.5a3.5 3.5 0 005-5l-2-2a3.5 3.5 0 00-5 0M11 8.5L9.5 7a3.5 3.5 0 00-5 5l2 2a3.5 3.5 0 005 0\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n ),\n '插入或编辑链接',\n () => this._toggleLinkPanel(),\n );\n\n // 取消链接(有链接时显示)\n this.btns.unlink = this._iconBtn(\n svgIcon(\n '<path d=\"M9 11.5l1.5 1.5a3.5 3.5 0 005-5l-2-2\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M3 3l14 14\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '取消链接',\n exec('unlink'),\n );\n\n // 清除格式:图标改为 Tx,避免被误认为\"关闭工具条\"\n this.btns.clear = this._iconBtn(\n svgIcon(\n '<text x=\"2\" y=\"14\" font-size=\"11\" font-weight=\"700\" fill=\"currentColor\">T</text><text x=\"11\" y=\"9\" font-size=\"7\" font-weight=\"700\" fill=\"currentColor\">x</text><path d=\"M11 11l5 5M16 11l-5 5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/>',\n ),\n '清除格式',\n exec('removeFormat'),\n );\n\n this.linkPanel = h('div', { class: 'sm-floating-toolbar__link-panel' });\n this.inputLink = h('input', {\n class: 'sm-input',\n type: 'url',\n placeholder: 'https://...',\n onkeydown: ((e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === 'Enter') {\n ke.preventDefault();\n this._applyLink();\n } else if (ke.key === 'Escape') {\n ke.preventDefault();\n this.linkPanel.classList.remove('is-visible');\n this.editor?.refocus();\n }\n }) as EventListener,\n }) as HTMLInputElement;\n const applyLinkBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onmousedown: (e: Event) => e.preventDefault(),\n onclick: () => this._applyLink(),\n },\n ['确定'],\n );\n this.linkPanel.append(this.inputLink, applyLinkBtn);\n\n this.el.append(\n this._group([this.btns.bold, this.btns.italic, this.btns.underline, this.btns.strikethrough]),\n sep(),\n this._group([this.selectFontFamily, this.selectFontSize, this.selectFontWeight]),\n sep(),\n this._group([this.inputColor, this.inputBgColor]),\n sep(),\n this._group([this.btns.alignLeft, this.btns.alignCenter, this.btns.alignRight]),\n sep(),\n this._group([this.btns.ul, this.btns.ol]),\n sep(),\n this._group([this.btns.link, this.btns.unlink, this.btns.clear]),\n this.linkPanel,\n );\n }\n\n private _toggleLinkPanel() {\n const opening = !this.linkPanel.classList.contains('is-visible');\n this.linkPanel.classList.toggle('is-visible');\n if (this.linkPanel.classList.contains('is-visible')) {\n if (opening) {\n this.inputLink.value = this.lastLinkHref ?? '';\n }\n requestAnimationFrame(() => this.inputLink.focus());\n } else {\n this.editor?.refocus();\n }\n }\n\n private _applyLink() {\n if (!this.editor) return;\n const url = this.inputLink.value.trim();\n this.editor.setLink(url);\n this.linkPanel.classList.remove('is-visible');\n this.inputLink.value = '';\n }\n\n private _wrapStyle(prop: string, value: string) {\n if (!this.editor) return;\n // execCommand 没有\"任意 inline style\"命令;自己处理:把存档选区的内容包到一个 span。\n this.editor.refocus(); // focus + restoreSelection\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (range.collapsed) return; // 没选中文字,无意义\n const span = document.createElement('span');\n span.setAttribute('style', `${prop}:${value};`);\n try {\n span.appendChild(range.extractContents());\n range.insertNode(span);\n // 选中 span 内容方便连续操作\n const newRange = document.createRange();\n newRange.selectNodeContents(span);\n sel.removeAllRanges();\n sel.addRange(newRange);\n this.editor.saveSelection();\n } catch {\n // 跨节点结构复杂时 extractContents 偶尔抛错,忽略并保持原样\n }\n }\n\n /**\n * 相对 `positionRoot` 定位:默认贴在**正文容器**上沿上方,避免压在选区文字上;\n * 若顶端空间不足则贴在容器下沿下方。\n */\n private _positionForAnchor(anchor: DOMRect) {\n const rootRect = this.opts.positionRoot.getBoundingClientRect();\n const gap = 6;\n const bar = this.el.getBoundingClientRect();\n const tw = bar.width || this.el.offsetWidth;\n const th = bar.height || this.el.offsetHeight || 40;\n\n let top = anchor.top - rootRect.top - th - gap;\n if (top < 8) {\n top = anchor.bottom - rootRect.top + gap;\n }\n\n const left = Math.max(\n 8,\n Math.min(\n anchor.left - rootRect.left + anchor.width / 2 - tw / 2,\n rootRect.width - tw - 8,\n ),\n );\n\n this.el.style.top = `${top}px`;\n this.el.style.left = `${left}px`;\n }\n\n private _setActive(key: string, on: boolean) {\n this.btns[key]?.classList.toggle('is-active', on);\n }\n\n private _btn(\n text: string,\n title: string,\n onClick: () => void,\n style: Partial<CSSStyleDeclaration> = {},\n ): HTMLButtonElement {\n const b = h(\n 'button',\n {\n class: 'sm-floating-toolbar__btn',\n type: 'button',\n title,\n onmousedown: (e: Event) => e.preventDefault(),\n onclick: onClick,\n },\n [text],\n ) as HTMLButtonElement;\n Object.assign(b.style, style);\n return b;\n }\n\n private _iconBtn(icon: SVGElement, title: string, onClick: () => void): HTMLButtonElement {\n return h(\n 'button',\n {\n class: 'sm-floating-toolbar__btn',\n type: 'button',\n title,\n onmousedown: (e: Event) => e.preventDefault(),\n onclick: onClick,\n },\n [icon],\n ) as HTMLButtonElement;\n }\n\n private _group(children: HTMLElement[]): HTMLElement {\n return h('div', { class: 'sm-floating-toolbar__group' }, children);\n }\n}\n\nfunction svgIcon(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '14');\n el.setAttribute('height', '14');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML = inner;\n return el;\n}\n\nfunction matchFamily(name: string): string {\n const lower = name.toLowerCase().replace(/['\"]/g, '').split(',')[0].trim();\n for (const f of FONT_FAMILIES) {\n if (!f.value) continue;\n if (f.value.toLowerCase().includes(lower)) return f.value;\n }\n return '';\n}\n\nfunction rgbToHex(rgb: string): string | null {\n if (rgb.startsWith('#')) return rgb;\n const m = rgb.match(/rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/i);\n if (!m) return null;\n const toHex = (n: string) => Number(n).toString(16).padStart(2, '0');\n return `#${toHex(m[1])}${toHex(m[2])}${toHex(m[3])}`;\n}\n","/** 与 blocks 中社交图标预设背景一致;core 不可依赖 blocks,供属性面板展示默认背景色 */\nexport function defaultSocialIconBackground(network: string): string {\n const m: Record<string, string> = {\n wechat: '#1AAD19',\n weibo: '#E6162D',\n x: '#000000',\n linkedin: '#0A66C2',\n github: '#181717',\n facebook: '#1877F2',\n instagram: '#E4405F',\n ig: '#E4405F',\n youtube: '#FF0000',\n tiktok: '#000000',\n rabbit: '#FF2442',\n website: '#6b7280',\n web: '#6b7280',\n };\n return m[network] ?? '#6b7280';\n}\n","import type { GalleryItem, ImageGalleryAdapter } from './imageAssets';\nimport { Modal } from './Modal';\nimport { clear, h } from '../utils/dom';\n\nexport interface OpenImageGalleryModalOptions {\n adapter: ImageGalleryAdapter;\n onPick: (url: string) => void;\n /** 挂载父节点,默认 `document.body` */\n parent?: HTMLElement;\n onClose?: () => void;\n}\n\n/**\n * 打开内置图库弹层:搜索、分页、选图插入;可选「链接添加」「上传到图库」「删除」由 adapter 决定。\n */\nexport function openImageGalleryModal(opts: OpenImageGalleryModalOptions): void {\n const { adapter, onPick, parent = document.body, onClose } = opts;\n\n const modal = new Modal({\n title: '图库',\n width: 'min(760px, 94vw)',\n height: 'min(580px, 88vh)',\n className: 'sm-modal--gallery',\n onClose,\n });\n\n const wrap = h('div', { class: 'sm-gallery-modal' });\n\n let query = '';\n let page = 0;\n let hasMore = false;\n let loading = false;\n let selected: GalleryItem | null = null;\n\n const errEl = h('div', {\n class: 'sm-gallery-modal__error',\n style: 'display:none',\n role: 'alert',\n });\n\n const searchInp = h('input', {\n class: 'sm-input sm-gallery-modal__search',\n type: 'search',\n placeholder: '搜索…',\n 'aria-label': '搜索图片',\n });\n\n let debounceId: ReturnType<typeof setTimeout> | null = null;\n searchInp.addEventListener('input', () => {\n if (debounceId) clearTimeout(debounceId);\n debounceId = setTimeout(() => {\n query = (searchInp as HTMLInputElement).value;\n void loadFirst();\n }, 320);\n });\n\n const gridEl = h('div', { class: 'sm-gallery-modal__grid' });\n\n const loadMoreBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-gallery-modal__loadmore',\n type: 'button',\n style: 'display:none',\n onclick: () => {\n if (!hasMore || loading) return;\n void loadPage(page + 1, true);\n },\n },\n ['加载更多'],\n ) as HTMLButtonElement;\n\n const confirmBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n disabled: true,\n onclick: () => finishPick(),\n },\n ['插入'],\n ) as HTMLButtonElement;\n\n function setError(msg: string | null) {\n if (msg) {\n errEl.textContent = msg;\n errEl.style.display = '';\n } else {\n errEl.textContent = '';\n errEl.style.display = 'none';\n }\n }\n\n function syncSelectionStyles() {\n const cells = gridEl.querySelectorAll('.sm-gallery-modal__cell');\n cells.forEach((c) => {\n const id = (c as HTMLElement).dataset.id;\n c.classList.toggle('is-selected', !!selected && id === selected.id);\n });\n }\n\n function renderCells(items: GalleryItem[], append: boolean) {\n if (!append) clear(gridEl);\n if (items.length === 0 && !append) {\n gridEl.append(\n h('div', { class: 'sm-gallery-modal__empty' }, [\n '暂无图片,可上传、添加链接或更换搜索条件',\n ]),\n );\n loadMoreBtn.style.display = hasMore ? '' : 'none';\n return;\n }\n for (const it of items) {\n const thumb = it.thumbnailUrl || it.url;\n const cellWrap = h('div', { class: 'sm-gallery-modal__cell-wrap' });\n const cell = h(\n 'button',\n {\n type: 'button',\n class: 'sm-gallery-modal__cell',\n title: it.title || it.url,\n 'data-id': it.id,\n onclick: () => {\n selected = it;\n syncSelectionStyles();\n confirmBtn.disabled = false;\n },\n ondblclick: (e: Event) => {\n e.preventDefault();\n selected = it;\n finishPick();\n },\n },\n [],\n );\n const img = h('img', {\n class: 'sm-gallery-modal__thumb',\n alt: '',\n loading: 'lazy',\n decoding: 'async',\n }) as HTMLImageElement;\n img.src = thumb;\n img.onerror = () => {\n img.style.opacity = '0.72';\n };\n const cap = h('div', { class: 'sm-gallery-modal__caption' }, [\n it.title?.trim() ? it.title : '图片',\n ]);\n cell.append(img, cap);\n cellWrap.append(cell);\n\n if (adapter.deleteItem) {\n const delBtn = h(\n 'button',\n {\n type: 'button',\n class: 'sm-gallery-modal__cell-delete',\n title: '从图库删除',\n onclick: async (e: Event) => {\n e.preventDefault();\n e.stopPropagation();\n if (!window.confirm('确定从图库中删除这张图片?')) return;\n try {\n await adapter.deleteItem!(it.id);\n if (selected?.id === it.id) {\n selected = null;\n confirmBtn.disabled = true;\n }\n await loadFirst();\n } catch (err) {\n setError(err instanceof Error ? err.message : '删除失败');\n }\n },\n },\n ['×'],\n );\n cellWrap.append(delBtn);\n }\n\n gridEl.append(cellWrap);\n }\n loadMoreBtn.style.display = hasMore ? '' : 'none';\n }\n\n async function loadPage(p: number, append: boolean) {\n if (loading) return;\n loading = true;\n loadMoreBtn.disabled = true;\n setError(null);\n try {\n const res = await adapter.listItems({ query, page: p });\n hasMore = res.hasMore;\n page = p;\n renderCells(res.items, append);\n } catch (e) {\n setError(e instanceof Error ? e.message : '加载失败');\n } finally {\n loading = false;\n loadMoreBtn.disabled = false;\n }\n }\n\n async function loadFirst() {\n page = 0;\n selected = null;\n confirmBtn.disabled = true;\n clear(gridEl);\n await loadPage(0, false);\n syncSelectionStyles();\n }\n\n function finishPick() {\n if (!selected?.url?.trim()) return;\n onPick(selected.url.trim());\n modal.close();\n }\n\n /** 搜索、链接、添加、上传同一行(窄屏可换行) */\n const toolbar = h('div', { class: 'sm-gallery-modal__toolbar' });\n const toolRow = h('div', { class: 'sm-gallery-modal__toolbar-row' });\n toolRow.append(searchInp);\n\n if (adapter.addByUrl) {\n const urlInp = h('input', {\n class: 'sm-input sm-gallery-modal__addurl-input',\n type: 'url',\n placeholder: '图片链接 https://…',\n }) as HTMLInputElement;\n const addBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-gallery-modal__toolbar-action',\n type: 'button',\n onclick: async () => {\n const u = urlInp.value.trim();\n if (!u) return;\n try {\n await adapter.addByUrl!(u);\n urlInp.value = '';\n await loadFirst();\n } catch (e) {\n setError(e instanceof Error ? e.message : '添加失败');\n }\n },\n },\n ['添加'],\n );\n toolRow.append(urlInp, addBtn);\n }\n\n if (adapter.uploadFile) {\n const fileInp = h('input', {\n type: 'file',\n accept: 'image/*',\n class: 'sm-gallery-modal__file',\n });\n fileInp.addEventListener('change', async () => {\n const f = (fileInp as HTMLInputElement).files?.[0];\n (fileInp as HTMLInputElement).value = '';\n if (!f) return;\n try {\n await adapter.uploadFile!(f);\n await loadFirst();\n } catch (e) {\n setError(e instanceof Error ? e.message : '上传失败');\n }\n });\n const upBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-gallery-modal__toolbar-action',\n type: 'button',\n onclick: () => fileInp.click(),\n },\n ['上传'],\n );\n toolRow.append(upBtn, fileInp);\n }\n\n toolbar.append(toolRow);\n\n const scrollArea = h('div', { class: 'sm-gallery-modal__scroll' }, [gridEl, loadMoreBtn]);\n\n wrap.append(toolbar, errEl, scrollArea);\n\n modal.body.append(wrap);\n modal.footer.append(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary',\n type: 'button',\n onclick: () => modal.close(),\n },\n ['取消'],\n ),\n confirmBtn,\n );\n\n modal.open(parent);\n void loadFirst();\n}\n","import { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport { EditorState } from '@codemirror/state';\nimport type { Registry } from '../registry/registry';\nimport { findBlockLocation, findSection, type Store, type DocChangedDetail } from '../store/store';\nimport type {\n Block,\n BlockSchemaField,\n EditorUiOptions,\n EmailDoc,\n Section,\n} from '../types';\nimport { defaultSocialIconBackground } from '../socialDefaults';\nimport { clear, h } from '../utils/dom';\nimport { metaWidthInputString, parseMetaWidthFromUserInput, parseSectionWidthFromUserInput, sectionWidthInputString } from '../utils/contentWidth';\nimport { FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport type { ImageAssetsHandlers, ImageFieldContext } from './imageAssets';\nimport { openImageGalleryModal } from './ImageGalleryModal';\n\n/** 与社交组 block 中每行元素结构一致(core 不依赖 blocks) */\ntype SocialLinkRow = {\n network: string;\n href: string;\n label?: string;\n iconSrc?: string;\n backgroundColor?: string;\n};\n\n/** 宽度滑块:解析右栏当前字符串 */\nfunction classifyLayoutWidth(raw: string): 'auto' | 'px' | '%' | 'custom' {\n const t = (raw ?? '').trim();\n if (!t || t.toLowerCase() === 'auto') return 'auto';\n if (/^\\d+(\\.\\d+)?%$/.test(t)) return '%';\n if (/^\\d+(\\.\\d+)?px$/i.test(t)) return 'px';\n if (/^\\d+(\\.\\d+)?$/.test(t)) return 'px';\n return 'custom';\n}\n\nfunction layoutWidthNumeric(raw: string, mode: 'px' | '%'): number {\n const t = (raw ?? '').trim();\n if (!t) return mode === '%' ? 100 : 280;\n const m = t.match(/^(\\d+(\\.\\d+)?)/);\n const n = m ? parseFloat(m[1]) : mode === '%' ? 100 : 280;\n if (mode === '%') return Math.min(100, Math.max(1, Math.round(n)));\n return Math.min(1200, Math.max(1, Math.round(n)));\n}\n\nexport interface RightPanelOptions {\n store: Store;\n registry: Registry;\n /**\n * 可选。配置后,schema 中 `type: 'image'` 的字段会显示「上传 / 图床」按钮并调用对应回调。\n */\n imageAssets?: ImageAssetsHandlers;\n /** 与 MailEditor.opts.ui 对齐 */\n ui?: EditorUiOptions;\n}\n\ntype RightTab = 'props' | 'code';\n\n/**\n * 右栏:选中 Section/Block 时显示对应配置;未选中显示文档级配置(标题/宽度/全局样式)。\n * Block 选中时多一个\"代码\"Tab,可编辑该 Block 的 MJML 片段(CodeMirror)。\n */\nexport class RightPanel {\n el: HTMLElement;\n private opts: RightPanelOptions;\n private currentTab: RightTab = 'props';\n private codeView: EditorView | null = null;\n\n private _preferSliderControls(): boolean {\n return this.opts.ui?.preferSliderControls === true;\n }\n\n private _hideMailMeta(): boolean {\n return this.opts.ui?.hideMailMeta === true;\n }\n\n constructor(opts: RightPanelOptions) {\n this.opts = opts;\n this.el = h('aside', { class: 'sm-panel sm-panel--right' });\n this._render();\n opts.store.subscribe((detail?: DocChangedDetail) => {\n if (detail?.source === 'history') {\n this._renderPreservingFieldFocus();\n return;\n }\n if (detail?.source === 'replace') {\n this._render();\n return;\n }\n // update() 每打一字符都会 notify;整栏 clear 会拆掉输入框导致失焦\n if (this._shouldSkipRenderBecauseFocused()) return;\n this._render();\n });\n opts.store.subscribeSelection(() => {\n this.currentTab = 'props';\n this._render();\n });\n }\n\n /** 焦点在右栏可编辑控件上时不要整栏重渲染(避免输入/CodeMirror 失焦) */\n private _shouldSkipRenderBecauseFocused(): boolean {\n const ae = document.activeElement as HTMLElement | null;\n if (!ae || !this.el.contains(ae)) return false;\n if (ae.closest('.cm-editor')) return true;\n const tag = ae.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;\n return false;\n }\n\n /** undo/redo 后整栏重绘,但尽量回到同一输入框与光标位置 */\n private _renderPreservingFieldFocus() {\n const ae = document.activeElement as HTMLElement | null;\n let token: string | null = null;\n let selStart = 0;\n let selEnd = 0;\n if (ae && this.el.contains(ae)) {\n token = ae.getAttribute('data-sm-focus');\n if (\n token &&\n (ae instanceof HTMLInputElement || ae instanceof HTMLTextAreaElement)\n ) {\n selStart = ae.selectionStart ?? 0;\n selEnd = ae.selectionEnd ?? 0;\n }\n }\n this._render();\n if (!token) return;\n const next = this._findFocusEl(token);\n next?.focus();\n if (next instanceof HTMLInputElement || next instanceof HTMLTextAreaElement) {\n const len = next.value.length;\n next.setSelectionRange(Math.min(selStart, len), Math.min(selEnd, len));\n }\n }\n\n private _findFocusEl(token: string): HTMLElement | null {\n for (const el of this.el.querySelectorAll('[data-sm-focus]')) {\n if ((el as HTMLElement).getAttribute('data-sm-focus') === token) return el as HTMLElement;\n }\n return null;\n }\n\n private _render() {\n this._destroyCodeView();\n clear(this.el);\n\n const sel = this.opts.store.selection;\n const doc = this.opts.store.doc;\n\n if (!sel) {\n this.el.append(this._renderDocForm(doc));\n return;\n }\n\n if (sel.kind === 'section') {\n const section = findSection(doc, sel.sectionId);\n if (!section) return;\n this.el.append(this._renderSectionForm(section));\n return;\n }\n\n // block\n const loc = findBlockLocation(doc, sel.blockId);\n if (!loc) {\n const tabs = h('div', { class: 'sm-tabs' }, [\n this._tabBtn('props', '属性'),\n this._tabBtn('code', '代码'),\n ]);\n this.el.append(tabs);\n this.el.append(\n h('div', { class: 'sm-empty-form' }, ['该组件可能已被删除,请重新选中画布中的块。']),\n );\n return;\n }\n const def = this.opts.registry.get(loc.block.type);\n\n const tabs = h('div', { class: 'sm-tabs' }, [\n this._tabBtn('props', '属性'),\n this._tabBtn('code', '代码'),\n ]);\n this.el.append(tabs);\n\n if (this.currentTab === 'props') {\n if (loc.block.lockedMjml) {\n this.el.append(\n h('div', { class: 'sm-empty-form' }, [\n '该组件已被代码模式锁定。',\n h('div', { style: 'margin-top:8px;' }, [\n h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: () => {\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, loc.block.id);\n if (l) delete l.block.lockedMjml;\n });\n },\n },\n ['恢复为属性模式'],\n ),\n ]),\n ]),\n );\n } else if (def) {\n this.el.append(this._renderBlockForm(loc.block, def.schema));\n } else {\n this.el.append(\n h('div', { class: 'sm-empty-form' }, [`未注册的组件: ${loc.block.type}`]),\n );\n }\n } else {\n this.el.append(this._renderBlockCodeView(loc.block));\n }\n }\n\n private _tabBtn(tab: RightTab, label: string) {\n return h(\n 'button',\n {\n class: `sm-tabs__item ${this.currentTab === tab ? 'sm-tabs__item--active' : ''}`,\n type: 'button',\n onclick: () => {\n this.currentTab = tab;\n this._render();\n },\n },\n [label],\n );\n }\n\n /* ------------------------------ 文档级表单 ------------------------------- */\n\n private _renderDocForm(doc: EmailDoc): HTMLElement {\n const hideMeta = this._hideMailMeta();\n const rows: HTMLElement[] = [];\n if (!hideMeta) {\n rows.push(\n h('div', { class: 'sm-panel__title' }, ['邮件设置']),\n this._textField('主题', doc.meta.subject, (v) =>\n this.opts.store.update((d) => {\n d.meta.subject = v;\n }),\n '',\n 'doc:meta.subject',\n ),\n this._textField('Preheader', doc.meta.preheader ?? '', (v) =>\n this.opts.store.update((d) => {\n d.meta.preheader = v;\n }),\n '',\n 'doc:meta.preheader',\n ),\n );\n } else {\n rows.push(h('div', { class: 'sm-panel__title' }, ['版式']));\n }\n rows.push(\n this._textField(\n '内容宽度',\n metaWidthInputString(doc.meta.width),\n (v) =>\n this.opts.store.update((d) => {\n d.meta.width = parseMetaWidthFromUserInput(v);\n }),\n '如 600、600px、100%',\n 'doc:meta.width',\n ),\n h('div', { class: 'sm-panel__title' }, ['全局样式']),\n this._colorField(\n '页面背景',\n doc.styles.backgroundColor,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.backgroundColor = v;\n }),\n 'doc:styles.backgroundColor',\n ),\n this._colorField(\n '内容背景',\n doc.styles.contentBackgroundColor,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.contentBackgroundColor = v;\n }),\n 'doc:styles.contentBackgroundColor',\n ),\n this._textField(\n '字体',\n doc.styles.fontFamily,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.fontFamily = v;\n }),\n '',\n 'doc:styles.fontFamily',\n ),\n this._docFontSizeField(\n doc.styles.fontSize,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.fontSize = v;\n }),\n 'doc:styles.fontSize',\n ),\n this._docFontWeightField(\n doc.styles.fontWeight ?? '400',\n (v) =>\n this.opts.store.update((d) => {\n d.styles.fontWeight = v;\n }),\n 'doc:styles.fontWeight',\n ),\n this._textField(\n '行高',\n doc.styles.lineHeight ?? '1.25',\n (v) =>\n this.opts.store.update((d) => {\n d.styles.lineHeight = v;\n }),\n '如 1.25 或 24px',\n 'doc:styles.lineHeight',\n ),\n this._colorField(\n '正文颜色',\n doc.styles.color,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.color = v;\n }),\n 'doc:styles.color',\n ),\n this._colorField(\n '链接颜色',\n doc.styles.linkColor,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.linkColor = v;\n }),\n 'doc:styles.linkColor',\n ),\n );\n return h('form', { class: 'sm-form', onsubmit: (e: Event) => e.preventDefault() }, rows);\n }\n\n /* ------------------------------ Section 表单 ----------------------------- */\n\n private _renderSectionForm(section: Section): HTMLElement {\n const a = section.attrs;\n return h('form', { class: 'sm-form', onsubmit: (e: Event) => e.preventDefault() }, [\n h('div', { class: 'sm-panel__title' }, ['Section 设置']),\n this._colorField(\n '背景色',\n a.backgroundColor ?? '',\n (v) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.backgroundColor = v || undefined;\n }),\n `section:${section.id}:attrs.bg`,\n ),\n this._layoutWidthField(\n '区域宽度',\n sectionWidthInputString(a.width),\n (v) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.width = parseSectionWidthFromUserInput(v);\n }),\n `section:${section.id}:attrs.width`,\n '留空=与邮件同宽;自适应等价于清空宽度',\n ),\n this._spacingField(\n '内边距',\n [a.paddingTop, a.paddingRight, a.paddingBottom, a.paddingLeft],\n (vals) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (!s) return;\n [s.attrs.paddingTop, s.attrs.paddingRight, s.attrs.paddingBottom, s.attrs.paddingLeft] =\n vals;\n }),\n `section:${section.id}:attrs.pad`,\n [0, 0, 0, 0],\n ),\n section.layout !== '1'\n ? this._numberField(\n '列间距 (px)',\n a.columnGap ?? 0,\n 0,\n 64,\n (v) => {\n const g = Math.max(0, Math.min(64, Math.round(v)));\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.columnGap = g > 0 ? g : undefined;\n });\n },\n 1,\n `section:${section.id}:attrs.columnGap`,\n )\n : null,\n section.layout !== '1'\n ? this._switchField(\n '小屏仍并排显示多列(可能字很窄)',\n !!a.preserveColumnsOnMobile,\n (checked) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.preserveColumnsOnMobile = checked || undefined;\n }),\n '开启后 MJML 会生成 mj-group,移动端预览/导出与默认「小屏堆叠列」行为不同。',\n `section:${section.id}:attrs.preserveMobile`,\n )\n : null,\n ]);\n }\n\n /* ------------------------------- Block 表单 ----------------------------- */\n\n private _renderBlockForm(block: Block, schema: BlockSchemaField[]): HTMLElement {\n const form = h('form', { class: 'sm-form', onsubmit: (e: Event) => e.preventDefault() });\n for (const field of schema) {\n form.append(this._field(field, block));\n }\n return form;\n }\n\n private _updateBlock(blockId: string, key: string, value: unknown) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, blockId);\n if (!loc) return;\n (loc.block.props as any)[key] = value;\n });\n }\n\n private _field(field: BlockSchemaField, block: Block): HTMLElement {\n const blockId = block.id;\n const fp = `block:${blockId}:${field.key}`;\n const def = this.opts.registry.get(block.type);\n const defaults = def?.defaultProps as Record<string, unknown> | undefined;\n const raw = (block.props as Record<string, unknown>)[field.key];\n const value: unknown =\n raw !== undefined && raw !== null ? raw : defaults?.[field.key];\n const onChange = (v: any) => this._updateBlock(blockId, field.key, v);\n\n switch (field.type) {\n case 'textarea':\n return this._textareaField(field.label, String(value ?? ''), onChange, field.help, fp);\n case 'number':\n return this._numberField(\n field.label,\n Number(value ?? 0),\n field.min ?? 0,\n field.max ?? 9999,\n onChange,\n field.step ?? 1,\n fp,\n );\n case 'color':\n return this._colorField(field.label, String(value ?? ''), onChange, fp);\n case 'select': {\n const isFw = field.key === 'fontWeight' || field.key === 'labelFontWeight';\n const displayVal = isFw ? normalizeFontWeightStep(String(value ?? '')) : String(value ?? '');\n const opts = isFw ? FONT_WEIGHT_STEP_OPTIONS : (field.options ?? []);\n if (isFw || field.selectVariant === 'segmented') {\n return this._segmentedSelectField(field.label, displayVal, opts, onChange, fp);\n }\n return this._selectField(field.label, displayVal, opts, onChange, fp);\n }\n case 'switch':\n return this._switchField(field.label, !!value, onChange, field.help, fp);\n case 'image':\n return this._imageField(\n field.label,\n String(value ?? ''),\n onChange,\n field.placeholder ?? 'https://',\n fp,\n { blockId, propKey: field.key },\n );\n case 'url':\n case 'text': {\n if (field.key === 'width' && this._preferSliderControls()) {\n const el = this._layoutWidthField(\n field.label,\n String(value ?? ''),\n (v) => onChange(v),\n fp,\n field.help,\n );\n if (field.placeholder && !field.help) {\n el.append(h('div', { class: 'sm-field__help' }, [field.placeholder]));\n }\n return el;\n }\n if (field.key === 'fontSize' && this._preferSliderControls()) {\n const el = this._fontSizeSliderField(\n field.label,\n String(value ?? ''),\n (v) => onChange(v),\n fp,\n field.help,\n );\n if (field.placeholder && !field.help) {\n el.append(h('div', { class: 'sm-field__help' }, [field.placeholder]));\n }\n return el;\n }\n const row = this._textField(\n field.label,\n String(value ?? ''),\n onChange,\n field.placeholder ?? '',\n fp,\n );\n if (field.help) row.append(h('div', { class: 'sm-field__help' }, [field.help]));\n return row;\n }\n case 'spacing': {\n /** 与各 block 约定:四边分别存 paddingTop / paddingRight / paddingBottom / paddingLeft */\n const p = block.props as Record<string, unknown>;\n const quad = [\n Number(p.paddingTop ?? 0),\n Number(p.paddingRight ?? 0),\n Number(p.paddingBottom ?? 0),\n Number(p.paddingLeft ?? 0),\n ];\n const def = this.opts.registry.get(block.type);\n const dp = def?.defaultProps as Record<string, unknown> | undefined;\n const resetQuad: [number, number, number, number] = [\n Number(dp?.paddingTop ?? 0),\n Number(dp?.paddingRight ?? 0),\n Number(dp?.paddingBottom ?? 0),\n Number(dp?.paddingLeft ?? 0),\n ];\n return this._spacingField(field.label, quad, (vals) => {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, blockId);\n if (!loc) return;\n const pr = loc.block.props as Record<string, number>;\n [pr.paddingTop, pr.paddingRight, pr.paddingBottom, pr.paddingLeft] = vals;\n });\n }, `${fp}:pad`, resetQuad);\n }\n case 'socialLinkList': {\n const rows = Array.isArray(value)\n ? (value as SocialLinkRow[])\n : Array.isArray(defaults?.[field.key])\n ? (defaults[field.key] as SocialLinkRow[])\n : [];\n return this._socialLinkListField(\n field.label,\n rows,\n field.options ?? [],\n blockId,\n field.key,\n field.help,\n fp,\n );\n }\n default:\n return h('div');\n }\n }\n\n /**\n * 社交组:每行含平台、链接、可选标签/图标 URL/图标背景色。\n * 注意:右栏在输入框聚焦时会跳过整栏 _render(),故更新 elements 必须在 store.update 内\n * 读取当前 props 再合并,禁止依赖闭包里的 items 快照(否则改一行会覆盖其它行已编辑未重绘的数据)。\n */\n private _socialLinkListField(\n label: string,\n items: SocialLinkRow[],\n networkOptions: { label: string; value: string }[],\n blockId: string,\n elementsKey: string,\n help: string | undefined,\n focusPrefix: string,\n ): HTMLElement {\n const firstVal = networkOptions[0]?.value ?? 'weibo';\n const wrap = h('div', { class: 'sm-field' });\n wrap.append(h('label', { class: 'sm-field__label' }, [label]));\n\n const listEl = h('div', { class: 'sm-social-link-list' });\n\n const patchElements = (mutate: (rows: SocialLinkRow[]) => SocialLinkRow[]) => {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, blockId);\n if (!loc) return;\n const props = loc.block.props as Record<string, unknown>;\n const raw = props[elementsKey];\n const cur: SocialLinkRow[] = Array.isArray(raw)\n ? (raw as SocialLinkRow[]).map((x) => ({ ...x }))\n : [];\n props[elementsKey] = mutate(cur);\n });\n };\n\n const syncItem = (index: number, patch: Partial<SocialLinkRow>) => {\n patchElements((rows) =>\n rows.map((x, i) => (i === index ? { ...x, ...patch } : x)),\n );\n };\n\n const removeAt = (index: number) => {\n patchElements((rows) => rows.filter((_, i) => i !== index));\n };\n\n for (let i = 0; i < items.length; i++) {\n const rowData = items[i];\n const rowWrap = h('div', { class: 'sm-social-link-list__row' });\n const mainRow = h('div', { class: 'sm-social-link-list__row-main' });\n const sel = h('select', {\n class: 'sm-select sm-social-link-list__network',\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:net` } : {}),\n onchange: (e: Event) =>\n syncItem(i, { network: (e.target as HTMLSelectElement).value }),\n });\n for (const o of networkOptions) {\n const opt = document.createElement('option');\n opt.value = o.value;\n opt.textContent = o.label;\n if (o.value === rowData.network) opt.selected = true;\n sel.append(opt);\n }\n if (!networkOptions.some((o) => o.value === rowData.network) && rowData.network) {\n const opt = document.createElement('option');\n opt.value = rowData.network;\n opt.textContent = rowData.network;\n opt.selected = true;\n sel.insertBefore(opt, sel.firstChild);\n }\n const inp = h('input', {\n class: 'sm-input sm-social-link-list__href',\n type: 'url',\n placeholder: 'https://',\n value: rowData.href,\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:href` } : {}),\n oninput: (e: Event) => syncItem(i, { href: (e.target as HTMLInputElement).value }),\n });\n const rm = h(\n 'button',\n {\n class: 'sm-social-link-list__remove',\n type: 'button',\n title: '删除',\n onclick: () => removeAt(i),\n },\n ['×'],\n );\n mainRow.append(sel, inp, rm);\n rowWrap.append(mainRow);\n\n const extras = h('div', { class: 'sm-social-link-list__row-extras' });\n const bgResolved = defaultSocialIconBackground(rowData.network);\n const bgStored = rowData.backgroundColor?.trim();\n const bgDisplay =\n bgStored && bgStored.startsWith('#') ? bgStored : bgResolved;\n extras.append(\n h('input', {\n class: 'sm-input sm-social-link-list__label',\n type: 'text',\n placeholder: '标签文字(可选)',\n value: rowData.label ?? '',\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:label` } : {}),\n oninput: (e: Event) => syncItem(i, { label: (e.target as HTMLInputElement).value }),\n }),\n h('input', {\n class: 'sm-input sm-social-link-list__iconsrc',\n type: 'url',\n placeholder: '图标 URL(可选)',\n value: rowData.iconSrc ?? '',\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:icon` } : {}),\n oninput: (e: Event) => syncItem(i, { iconSrc: (e.target as HTMLInputElement).value }),\n }),\n h('input', {\n class: 'sm-social-link-list__color sm-social-link-list__color--compact',\n type: 'color',\n title: '图标背景色',\n value: bgDisplay.length >= 4 ? bgDisplay : bgResolved,\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:bg` } : {}),\n oninput: (e: Event) =>\n syncItem(i, { backgroundColor: (e.target as HTMLInputElement).value }),\n }),\n );\n rowWrap.append(extras);\n\n listEl.append(rowWrap);\n }\n\n const addBtn = h(\n 'button',\n {\n class: 'sm-btn sm-social-link-list__add',\n type: 'button',\n onclick: () =>\n patchElements((rows) => [\n ...rows,\n {\n network: firstVal,\n href: 'https://',\n label: '',\n iconSrc: '',\n },\n ]),\n },\n ['+ 添加社交链接'],\n );\n\n wrap.append(listEl, addBtn);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n /* --------------------------------- 控件 --------------------------------- */\n\n private _textField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n placeholder = '',\n focusToken?: string,\n ) {\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('input', {\n class: 'sm-input',\n type: 'text',\n value,\n placeholder,\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n }),\n ]);\n }\n\n /** `type: 'image'`:URL 输入 + 可选上传、图床(由 `imageAssets` 注入) */\n private _imageField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n placeholder: string,\n focusToken: string | undefined,\n ids: Pick<ImageFieldContext, 'blockId' | 'propKey'>,\n ): HTMLElement {\n const assets = this.opts.imageAssets;\n const showUploadBtn = !!assets?.uploadImage && assets.showUpload !== false;\n const showGalleryBtn =\n assets?.showGallery === true &&\n (!!assets.imageGallery || !!assets.pickImageFromGallery);\n const hasAssetCallbacks = !!(\n assets?.uploadImage ||\n assets?.pickImageFromGallery ||\n assets?.imageGallery\n );\n const hasAnyPickerBtn = showUploadBtn || showGalleryBtn;\n\n const row = h('div', { class: 'sm-image-field__row' });\n const urlInp = h('input', {\n class: 'sm-input sm-image-field__url',\n type: 'url',\n value,\n placeholder,\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n });\n const getCtx = (): ImageFieldContext => ({\n blockId: ids.blockId,\n propKey: ids.propKey,\n currentUrl: urlInp.value,\n });\n row.append(urlInp);\n\n const applyUrl = (url: string) => {\n const t = url.trim();\n if (!t) return;\n onChange(t);\n urlInp.value = t;\n };\n\n const runAsync = (p: Promise<string | null | void>, labelErr: string) => {\n p.catch((e) => {\n console.error(`[simple-mail] ${labelErr}`, e);\n });\n };\n\n if (showUploadBtn) {\n const fileInp = h('input', {\n type: 'file',\n accept: 'image/*',\n class: 'sm-image-field__file',\n onchange: (e: Event) => {\n const el = e.target as HTMLInputElement;\n const f = el.files?.[0];\n el.value = '';\n if (!f) return;\n runAsync(\n assets.uploadImage!(f, getCtx()).then((url) => applyUrl(String(url))),\n 'uploadImage',\n );\n },\n });\n row.append(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-image-field__btn',\n type: 'button',\n title: '上传本地图片',\n onclick: () => fileInp.click(),\n },\n ['上传'],\n ),\n );\n row.append(fileInp);\n }\n\n if (showGalleryBtn) {\n row.append(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-image-field__btn',\n type: 'button',\n title: '从图库选择',\n onclick: () => {\n if (assets.imageGallery) {\n openImageGalleryModal({\n adapter: assets.imageGallery,\n onPick: (url) => applyUrl(url),\n });\n return;\n }\n if (assets.pickImageFromGallery) {\n runAsync(\n assets.pickImageFromGallery(getCtx()).then((url) => {\n if (url != null && String(url).trim()) applyUrl(String(url));\n }),\n 'pickImageFromGallery',\n );\n }\n },\n },\n ['图床'],\n ),\n );\n }\n\n let helpBody: string;\n if (hasAnyPickerBtn) {\n const bits: string[] = ['可手输 URL'];\n if (showUploadBtn) bits.push('或使用「上传」');\n if (showGalleryBtn) bits.push('或使用「图床」');\n helpBody = `${bits.join(';')}。`;\n } else if (hasAssetCallbacks) {\n helpBody =\n '已传入 imageAssets:上传默认显示(提供 uploadImage 且未设 showUpload:false);图库需 showGallery:true,可使用内置 imageGallery 或自管 pickImageFromGallery。仍可手输 URL。';\n } else {\n helpBody =\n '在 MailEditor 的 imageAssets 中配置 uploadImage、内置 imageGallery 或 pickImageFromGallery 等;未配置时仅支持手输 URL。';\n }\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n row,\n h('div', { class: 'sm-field__help' }, [helpBody]),\n ]);\n }\n private _textareaField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n help?: string,\n focusToken?: string,\n ) {\n const ta = h('textarea', {\n class: 'sm-textarea',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLTextAreaElement).value),\n });\n ta.value = value;\n return h(\n 'div',\n { class: 'sm-field' },\n [\n h('label', { class: 'sm-field__label' }, [label]),\n ta,\n help ? h('div', { class: 'sm-field__help' }, [help]) : null,\n ],\n );\n }\n private _numberField(\n label: string,\n value: number,\n min: number,\n max: number,\n onChange: (v: number) => void,\n step = 1,\n focusToken?: string,\n ) {\n const snap = (n: number) => {\n const c = Math.min(max, Math.max(min, n));\n if (!step || step <= 0) return c;\n const k = Math.round((c - min) / step);\n return Number((min + k * step).toPrecision(12));\n };\n\n if (!this._preferSliderControls()) {\n const inp = h('input', {\n class: 'sm-input',\n type: 'number',\n value: String(value),\n min,\n max,\n step,\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const commitPlain = () => {\n const t = inp.value.trim();\n const fb = snap(value);\n if (t === '') {\n inp.value = String(fb);\n onChange(fb);\n return;\n }\n const v = Number(t);\n const s = snap(Number.isNaN(v) ? fb : v);\n inp.value = String(s);\n onChange(s);\n };\n\n /** min>0 时中途输入会被 snap 打断(如想输入 16 会先变成 10),仅失焦/Enter 提交 */\n if (min > 0) {\n inp.addEventListener('blur', commitPlain);\n inp.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') inp.blur();\n });\n } else {\n inp.addEventListener('input', () => {\n const t = inp.value.trim();\n if (t === '') return;\n const v = Number(t);\n if (Number.isNaN(v)) return;\n onChange(snap(v));\n });\n inp.addEventListener('blur', commitPlain);\n inp.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') commitPlain();\n });\n }\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n inp,\n ]);\n }\n\n const v0 = snap(value);\n const range = h('input', {\n type: 'range',\n min,\n max,\n step,\n value: String(v0),\n }) as HTMLInputElement;\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min,\n max,\n step,\n value: String(v0),\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const syncFromSlider = (n: number) => {\n const s = snap(n);\n range.value = String(s);\n num.value = String(s);\n onChange(s);\n };\n\n range.addEventListener('input', () => {\n syncFromSlider(Number(range.value));\n });\n\n num.addEventListener('input', () => {\n const t = num.value.trim();\n if (t === '') return;\n const raw = Number(t);\n if (Number.isNaN(raw)) return;\n range.value = String(snap(raw));\n });\n\n num.addEventListener('blur', () => {\n const t = num.value.trim();\n const fb = snap(Number(range.value));\n if (t === '') {\n syncFromSlider(fb);\n return;\n }\n const raw = Number(t);\n if (Number.isNaN(raw)) {\n syncFromSlider(fb);\n return;\n }\n syncFromSlider(raw);\n });\n\n num.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('div', { class: 'sm-field__slider-row' }, [range, num]),\n ]);\n }\n private _colorField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n focusPrefix?: string,\n ) {\n const pickToken = focusPrefix ? `${focusPrefix}:pick` : undefined;\n const textToken = focusPrefix ? `${focusPrefix}:text` : undefined;\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('div', { class: 'sm-color-row' }, [\n h('input', {\n type: 'color',\n value: value || '#ffffff',\n ...(pickToken ? { 'data-sm-focus': pickToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n }),\n h('input', {\n class: 'sm-input',\n type: 'text',\n value,\n placeholder: '#ffffff',\n ...(textToken ? { 'data-sm-focus': textToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n }),\n ]),\n ]);\n }\n private _selectField(\n label: string,\n value: string,\n options: { label: string; value: string }[],\n onChange: (v: string) => void,\n focusToken?: string,\n ) {\n const sel = h('select', {\n class: 'sm-select',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n onchange: (e: Event) => onChange((e.target as HTMLSelectElement).value),\n });\n for (const o of options) {\n const opt = document.createElement('option');\n opt.value = o.value;\n opt.textContent = o.label;\n if (o.value === value) opt.selected = true;\n sel.append(opt);\n }\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n sel,\n ]);\n }\n\n /** select 平铺:与顶栏 sm-segmented 视觉一致,占满右栏宽度 */\n private _segmentedSelectField(\n label: string,\n value: string,\n options: { label: string; value: string }[],\n onChange: (v: string) => void,\n focusToken?: string,\n ) {\n const group = h('div', {\n class: 'sm-segmented sm-segmented--fill',\n role: 'group',\n 'aria-label': label,\n });\n for (const o of options) {\n const active = o.value === value;\n group.append(\n h(\n 'button',\n {\n type: 'button',\n class: `sm-segmented__item${active ? ' sm-segmented__item--active' : ''}`,\n 'aria-pressed': active ? 'true' : 'false',\n title: o.label,\n ...(focusToken ? { 'data-sm-focus': `${focusToken}:${o.value}` } : {}),\n onclick: () => onChange(o.value),\n },\n [o.label],\n ),\n );\n }\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n group,\n ]);\n }\n private _switchField(\n label: string,\n value: boolean,\n onChange: (v: boolean) => void,\n help?: string,\n focusToken?: string,\n ): HTMLElement {\n const row = h('label', {\n class: 'sm-field',\n style: 'flex-direction:row;align-items:center;gap:8px;',\n }, [\n h('input', {\n type: 'checkbox',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n onchange: (e: Event) => onChange((e.target as HTMLInputElement).checked),\n ...(value ? { checked: true } : {}),\n } as any),\n h('span', { class: 'sm-field__label' }, [label]),\n ]);\n if (!help) return row;\n return h('div', { class: 'sm-field', style: 'flex-direction:column;align-items:flex-start;gap:6px;' }, [\n row,\n h('div', { class: 'sm-field__help' }, [help]),\n ]);\n }\n private _spacingField(\n label: string,\n [t, r, b, l]: (number | undefined)[],\n onChange: (vals: number[]) => void,\n focusPrefix?: string,\n resetQuad?: [number, number, number, number],\n ) {\n const titles = ['上', '右', '下', '左'];\n const clampPad = (n: number) => Math.max(0, Math.min(200, Math.round(n)));\n\n /** 右栏聚焦时会跳过整栏重绘,闭包里的 t/r/b/l 会过时;用同一数组累积四边,避免改一边再改另一边时覆盖。 */\n const current: number[] = [\n clampPad(Number(t ?? 0)),\n clampPad(Number(r ?? 0)),\n clampPad(Number(b ?? 0)),\n clampPad(Number(l ?? 0)),\n ];\n const emit = () => onChange([...current]);\n\n const makePlain = (v: number | undefined, idx: number) => {\n const inp = h('input', {\n class: 'sm-input',\n type: 'number',\n min: 0,\n max: 200,\n value: String(v ?? 0),\n title: titles[idx],\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:${idx}` } : {}),\n }) as HTMLInputElement;\n inp.addEventListener('input', () => {\n const t = inp.value.trim();\n if (t === '') return;\n const raw = Number(t);\n if (Number.isNaN(raw)) return;\n current[idx] = clampPad(raw);\n emit();\n });\n inp.addEventListener('blur', () => {\n const t = inp.value.trim();\n if (t === '') {\n inp.value = String(current[idx]);\n return;\n }\n const raw = Number(t);\n const c = clampPad(Number.isNaN(raw) ? current[idx] : raw);\n inp.value = String(c);\n current[idx] = c;\n emit();\n });\n inp.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') inp.blur();\n });\n return inp;\n };\n\n const makeSliderRow = (v: number | undefined, idx: number) => {\n const cur = clampPad(v ?? 0);\n const range = h('input', {\n type: 'range',\n min: 0,\n max: 200,\n step: 1,\n value: String(cur),\n title: titles[idx],\n }) as HTMLInputElement;\n\n range.addEventListener('input', () => {\n const c = clampPad(Number(range.value));\n current[idx] = c;\n num.value = String(c);\n emit();\n });\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min: 0,\n max: 200,\n value: String(cur),\n title: titles[idx],\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:${idx}` } : {}),\n }) as HTMLInputElement;\n\n num.addEventListener('input', () => {\n const t = num.value.trim();\n if (t === '') return;\n const rawN = Number(t);\n if (Number.isNaN(rawN)) return;\n const c = clampPad(rawN);\n range.value = String(c);\n current[idx] = c;\n emit();\n });\n\n num.addEventListener('blur', () => {\n const t = num.value.trim();\n if (t === '') {\n num.value = String(current[idx]);\n range.value = String(current[idx]);\n return;\n }\n const rawN = Number(t);\n const c = clampPad(Number.isNaN(rawN) ? current[idx] : rawN);\n num.value = String(c);\n range.value = String(c);\n current[idx] = c;\n emit();\n });\n\n num.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n return h('div', { class: 'sm-spacing-row' }, [\n h('span', { class: 'sm-spacing-row__axis' }, [titles[idx]]),\n range,\n num,\n ]);\n };\n\n return h('div', { class: 'sm-field' }, [\n h('div', { class: 'sm-spacing-field__label-row' }, [\n h('label', { class: 'sm-field__label' }, [`${label}(上/右/下/左)`]),\n resetQuad\n ? h(\n 'button',\n {\n type: 'button',\n class: 'sm-btn sm-btn--ghost sm-spacing-field__reset',\n onclick: () => {\n const next = resetQuad.map((n) => clampPad(Number(n)));\n for (let i = 0; i < 4; i++) current[i] = next[i];\n onChange([...current]);\n },\n },\n ['恢复默认'],\n )\n : null,\n ]),\n this._preferSliderControls()\n ? h(\n 'div',\n { class: 'sm-spacing-rows' },\n [0, 1, 2, 3].map((idx) => makeSliderRow([t, r, b, l][idx], idx)),\n )\n : h(\n 'div',\n { class: 'sm-spacing-grid' },\n [0, 1, 2, 3].map((idx) => makePlain([t, r, b, l][idx], idx)),\n ),\n ]);\n }\n\n private _snapFontSizeToPx(value: string): number {\n const t = (value ?? '').trim();\n const m = t.match(/^(\\d+(\\.\\d+)?)/);\n if (m) return Math.min(48, Math.max(10, Math.round(parseFloat(m[1]))));\n return 16;\n }\n\n private _fontSizeSliderField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n focusToken: string,\n help?: string,\n ) {\n if (!this._preferSliderControls()) {\n return this._textField(label, value ?? '', onChange, '', focusToken);\n }\n const min = 10;\n const max = 48;\n const step = 1;\n const snap = (n: number) => Math.min(max, Math.max(min, Math.round(n)));\n const px = snap(this._snapFontSizeToPx(value ?? ''));\n\n const range = h('input', {\n type: 'range',\n min,\n max,\n step,\n value: String(px),\n }) as HTMLInputElement;\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min,\n max,\n step,\n value: String(px),\n 'data-sm-focus': focusToken,\n }) as HTMLInputElement;\n\n range.addEventListener('input', () => {\n const s = snap(Number(range.value));\n num.value = String(s);\n onChange(`${s}px`);\n });\n\n num.addEventListener('input', () => {\n const t = num.value.trim();\n if (t === '') return;\n const rawN = Number(t);\n if (Number.isNaN(rawN)) return;\n range.value = String(snap(rawN));\n });\n\n num.addEventListener('blur', () => {\n const t = num.value.trim();\n const fb = snap(Number(range.value));\n if (t === '') {\n const r = fb;\n num.value = String(r);\n range.value = String(r);\n onChange(`${r}px`);\n return;\n }\n const rawN = Number(t);\n const s = snap(Number.isNaN(rawN) ? fb : rawN);\n num.value = String(s);\n range.value = String(s);\n onChange(`${s}px`);\n });\n\n num.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n const wrap = h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('div', { class: 'sm-field__slider-row' }, [range, num]),\n ]);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n private _docFontSizeField(value: string, onChange: (v: string) => void, focusToken: string) {\n return this._fontSizeSliderField(\n '字号',\n value,\n onChange,\n focusToken,\n '滑块与数字均以 px 写入(如 16px)',\n );\n }\n\n private _layoutWidthField(\n label: string,\n raw: string,\n onChange: (v: string) => void,\n focusToken: string,\n help?: string,\n ) {\n if (!this._preferSliderControls()) {\n const tf = this._textField(label, raw, onChange, '', focusToken);\n if (help) tf.append(h('div', { class: 'sm-field__help' }, [help]));\n return tf;\n }\n\n const kind = classifyLayoutWidth(raw);\n if (kind === 'custom') {\n const wrap = h('div', { class: 'sm-field' });\n wrap.append(h('label', { class: 'sm-field__label' }, [label]));\n wrap.append(\n h('div', { class: 'sm-field__help' }, [\n '当前值为自定义写法,请直接编辑;清空后可选「自适应」再用滑块。',\n ]),\n );\n wrap.append(\n h('input', {\n class: 'sm-input',\n type: 'text',\n value: raw,\n placeholder: '如 480px、90%',\n 'data-sm-focus': focusToken,\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n }),\n );\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n const mode: 'auto' | 'px' | '%' = kind;\n const max = mode === '%' ? 100 : 1200;\n const min = 1;\n const displayN = mode === 'auto' ? 280 : layoutWidthNumeric(raw, mode === '%' ? '%' : 'px');\n\n const clampW = (n: number) => Math.max(min, Math.min(max, Math.round(n)));\n\n const range = h('input', {\n type: 'range',\n min,\n max,\n step: 1,\n value: String(displayN),\n disabled: mode === 'auto',\n }) as HTMLInputElement;\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min,\n max,\n step: 1,\n value: String(displayN),\n disabled: mode === 'auto',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const emitW = (c: number) => {\n const v = clampW(c);\n range.value = String(v);\n num.value = String(v);\n onChange(mode === '%' ? `${v}%` : `${v}px`);\n };\n\n range.addEventListener('input', () => {\n if (mode === 'auto') return;\n emitW(Number(range.value));\n });\n\n num.addEventListener('input', () => {\n if (mode === 'auto') return;\n const t = num.value.trim();\n if (t === '') return;\n const rawN = Number(t);\n if (Number.isNaN(rawN)) return;\n range.value = String(clampW(rawN));\n });\n\n num.addEventListener('blur', () => {\n if (mode === 'auto') return;\n const t = num.value.trim();\n const fb = clampW(Number(range.value));\n if (t === '') {\n emitW(fb);\n return;\n }\n const rawN = Number(t);\n emitW(Number.isNaN(rawN) ? fb : rawN);\n });\n\n num.addEventListener('keydown', (e) => {\n if (mode === 'auto') return;\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n const sliderRow = h(\n 'div',\n { class: `sm-width-field__slider-row ${mode === 'auto' ? 'is-disabled' : ''}` },\n [range, num],\n );\n\n const modesWrap = h('div', { class: 'sm-segmented sm-segmented--wrap sm-width-field__modes' });\n const addModeBtn = (m: 'auto' | 'px' | '%', text: string) => {\n modesWrap.append(\n h(\n 'button',\n {\n type: 'button',\n class: `sm-segmented__item ${mode === m ? 'sm-segmented__item--active' : ''}`,\n onclick: () => {\n if (m === 'auto') onChange('');\n else if (m === 'px') onChange(`${layoutWidthNumeric(raw, 'px')}px`);\n else onChange(`${layoutWidthNumeric(raw, '%')}%`);\n },\n },\n [text],\n ),\n );\n };\n addModeBtn('auto', '自适应');\n addModeBtn('px', 'px');\n addModeBtn('%', '%');\n\n const wrap = h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n modesWrap,\n sliderRow,\n ]);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n private _docFontWeightField(value: string, onChange: (v: string) => void, focusToken: string) {\n const cur = normalizeFontWeightStep(value);\n return this._segmentedSelectField('字重', cur, FONT_WEIGHT_STEP_OPTIONS, onChange, focusToken);\n }\n\n private _renderBlockCodeView(block: Block): HTMLElement {\n const def = this.opts.registry.get(block.type);\n const initial =\n block.lockedMjml ??\n (def ? def.toMjml(block.props as any, { doc: this.opts.store.doc, engine: 'mjml' }) : '');\n\n const wrap = h('div', { class: 'sm-code-pane' });\n\n const header = h('div', { class: 'sm-code-pane__header' }, [\n h('div', { class: 'sm-code-pane__title' }, ['编辑组件 MJML 源码']),\n ]);\n\n const editorHost = h('div', { class: 'sm-code' });\n\n const view = new EditorView({\n parent: editorHost,\n state: EditorState.create({\n doc: initial,\n extensions: [basicSetup, cmHtml()],\n }),\n });\n this.codeView = view;\n\n const actions = h('div', { class: 'sm-code-pane__header' }, [\n h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: () => {\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, block.id);\n if (l) delete l.block.lockedMjml;\n });\n },\n },\n ['恢复默认'],\n ),\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onclick: () => {\n const text = view.state.doc.toString();\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, block.id);\n if (l) l.block.lockedMjml = text;\n });\n },\n },\n ['保存为锁定 MJML'],\n ),\n ]);\n\n wrap.append(\n header,\n editorHost,\n h('div', { class: 'sm-field__help' }, [\n '保存后该组件将以这段 MJML 直接输出,属性面板会被禁用,可点\"恢复默认\"取消锁定。',\n ]),\n actions,\n );\n return wrap;\n }\n\n private _destroyCodeView() {\n if (this.codeView) {\n this.codeView.destroy();\n this.codeView = null;\n }\n }\n}\n","import { EditorState } from '@codemirror/state';\nimport { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport type { Registry } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport type { Store } from '../store/store';\nimport { clear, h } from '../utils/dom';\n\nexport interface SourceViewOptions {\n store: Store;\n registry: Registry;\n}\n\ntype SourceTab = 'mjml' | 'html';\n\n/**\n * 文档级源码视图:只读地展示当前文档编译出的 MJML 与 HTML。\n *\n * 本期不支持把源码直接回写到数据模型——MJML/HTML 反推 doc 风险大且不必要,\n * 用户若需要直接写源码,可在右栏对单个 Block 走\"组件级代码模式\"。\n */\nexport class SourceView {\n el: HTMLElement;\n private opts: SourceViewOptions;\n private currentTab: SourceTab = 'mjml';\n private body: HTMLElement;\n private cm: EditorView | null = null;\n\n constructor(opts: SourceViewOptions) {\n this.opts = opts;\n this.el = h('div', { class: 'sm-doc-source' });\n this.body = h('div', { class: 'sm-doc-source__body' });\n this._render();\n opts.store.subscribe(() => {\n if (this._isVisible()) this._renderEditor();\n });\n }\n\n /**\n * 设计态运行时 SourceView 不在 DOM,`store.subscribe` 里的 `_renderEditor()` 全部被跳过,\n * CodeMirror 里仍是构造函数那一刻的快照。**切到「源码」模式后必须手动调一次**,\n * 否则会看到空文档 / 旧文档,但「导出」「预览」「MJML→HTML」却一直是当前 doc ——这正是用户报告的错位。\n */\n refreshDoc() {\n this._renderEditor();\n }\n\n private _isVisible(): boolean {\n return this.el.isConnected && (this.el.offsetParent !== null || this.el.getClientRects().length > 0);\n }\n\n private _render() {\n clear(this.el);\n const bar = h('div', { class: 'sm-doc-source__bar' }, [\n this._tabBtn('mjml', 'MJML'),\n this._tabBtn('html', 'HTML(编译产物)'),\n h('div', { class: 'sm-topbar__spacer' }),\n h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: () => this._copy(),\n },\n ['复制'],\n ),\n ]);\n this.el.append(bar, this.body);\n this._renderEditor();\n }\n\n private _tabBtn(tab: SourceTab, label: string) {\n return h(\n 'button',\n {\n class: `sm-segmented__item ${tab === this.currentTab ? 'sm-segmented__item--active' : ''}`,\n type: 'button',\n onclick: () => {\n this.currentTab = tab;\n this._render();\n },\n },\n [label],\n );\n }\n\n private _renderEditor() {\n this._destroyCm();\n clear(this.body);\n const result = renderDoc(this.opts.store.doc, this.opts.registry, {\n withSampleVariables: false,\n });\n const text = this.currentTab === 'mjml' ? result.mjml : result.html;\n this.cm = new EditorView({\n parent: this.body,\n state: EditorState.create({\n doc: text,\n extensions: [basicSetup, cmHtml(), EditorState.readOnly.of(true)],\n }),\n });\n }\n\n private async _copy() {\n if (!this.cm) return;\n const text = this.cm.state.doc.toString();\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n const ta = document.createElement('textarea');\n ta.value = text;\n document.body.appendChild(ta);\n ta.select();\n document.execCommand('copy');\n document.body.removeChild(ta);\n }\n }\n\n private _destroyCm() {\n if (this.cm) {\n this.cm.destroy();\n this.cm = null;\n }\n }\n\n destroy() {\n this._destroyCm();\n }\n}\n","/**\n * 邮件编辑器品牌/主题色:写入 .sm-root 的 --sm-primary / --sm-primary-soft。\n */\n\n/** 合法则规范为 #RRGGBB(大写),否则 null */\nexport function normalizeAccentHex(input: string): string | null {\n const t = input.trim();\n if (!t) return null;\n const h = t.replace(/^#/, '');\n if (/^[0-9a-fA-F]{3}$/.test(h)) {\n return `#${(h[0] + h[0] + h[1] + h[1] + h[2] + h[2]).toUpperCase()}`;\n }\n if (/^[0-9a-fA-F]{6}$/.test(h)) {\n return `#${h.toUpperCase()}`;\n }\n return null;\n}\n\n/** 由 getComputedStyle 得到的 rgb(...) / rgba(...) 转 #rrggbb */\nexport function rgbCssToHex(rgb: string): string | null {\n const m = rgb.trim().match(/^rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n if (!m) return null;\n const h = (n: string) => Number(n).toString(16).padStart(2, '0');\n return `#${h(m[1])}${h(m[2])}${h(m[3])}`;\n}\n\n/**\n * 与浅色/深色界面配套的浅底强调色(选区、滑块 accent 等)。\n */\nexport function accentPrimarySoftRgba(primaryHex: string, isDarkChrome: boolean): string {\n const hex = normalizeAccentHex(primaryHex);\n if (!hex) return isDarkChrome ? 'rgba(129, 140, 248, 0.18)' : 'rgba(79, 70, 229, 0.12)';\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n const a = isDarkChrome ? 0.22 : 0.14;\n return `rgba(${r},${g},${b},${a})`;\n}\n","import type { Store } from '../store/store';\nimport { normalizeAccentHex, rgbCssToHex } from '../utils/accentColor';\nimport { h, clear } from '../utils/dom';\nimport type { EditorTheme } from './theme';\n\nexport type EditorMode = 'design' | 'source';\n\nexport interface TopbarOptions {\n store: Store;\n mode: EditorMode;\n theme: EditorTheme;\n /** 用于读取解析后的 `--sm-primary`,同步到原生 color 输入 */\n accentPickerRoot?: HTMLElement;\n /** 为 true 时在顶栏显示主题色拾取器(需同时提供 `onAccentChange`) */\n showAccentColorPicker?: boolean;\n onAccentChange?: (hex: string) => void;\n onThemeChange: (t: EditorTheme) => void;\n onModeChange: (m: EditorMode) => void;\n onUndo: () => void;\n onRedo: () => void;\n /** 清空画布选中并回到右栏「邮件设置 / 全局样式」 */\n onMailSettings: () => void;\n onInsertVariable: (anchor: HTMLElement) => void;\n onPreview: () => void;\n onExport: () => void;\n /** 切换编辑器根节点浏览器全屏(由 Editor 实现 Fullscreen API) */\n onFullscreenToggle?: () => void;\n /** 为 false 时不展示全屏按钮(也可用 `ui.hideTopbarFullscreen`) */\n showFullscreenButton?: boolean;\n /** 为 false 时不展示「邮件设置」按钮(也可用 `ui.hideTopbarMailSettings`) */\n showMailSettingsButton?: boolean;\n /** 为 false 时不渲染左侧产品标题 */\n showTitle?: boolean;\n}\n\nexport class Topbar {\n el: HTMLElement;\n private opts: TopbarOptions;\n private undoBtn!: HTMLButtonElement;\n private redoBtn!: HTMLButtonElement;\n private themeButtons!: Record<EditorTheme, HTMLButtonElement>;\n private modeButtons: Record<EditorMode, HTMLButtonElement> = {} as any;\n private accentInput?: HTMLInputElement;\n private fullscreenBtn?: HTMLButtonElement;\n\n constructor(opts: TopbarOptions) {\n this.opts = opts;\n this.el = h('header', { class: 'sm-topbar' });\n this._render();\n opts.store.subscribe(() => this._sync());\n this._sync();\n }\n\n setMode(m: EditorMode) {\n this.opts.mode = m;\n for (const k of ['design', 'source'] as EditorMode[]) {\n this.modeButtons[k].classList.toggle('sm-segmented__item--active', k === m);\n }\n }\n\n syncTheme(t: EditorTheme) {\n this.opts.theme = t;\n for (const k of ['light', 'dark', 'system'] as const) {\n const on = k === t;\n this.themeButtons[k].classList.toggle('sm-segmented__item--active', on);\n this.themeButtons[k].setAttribute('aria-pressed', on ? 'true' : 'false');\n }\n }\n\n /** 根据 `.sm-root` 上计算后的 `--sm-primary` 更新拾取器显示(无拾取器或未挂 root 时忽略) */\n syncAccentPicker() {\n if (!this.accentInput || !this.opts.accentPickerRoot) return;\n const raw = getComputedStyle(this.opts.accentPickerRoot).getPropertyValue('--sm-primary').trim();\n const base = normalizeAccentHex(raw) || rgbCssToHex(raw);\n if (!base) return;\n const norm = normalizeAccentHex(base);\n if (!norm) return;\n const forInput = `#${norm.slice(1).toLowerCase()}`;\n if (this.accentInput.value.toLowerCase() !== forInput) this.accentInput.value = forInput;\n }\n\n /** 与 document fullscreen 状态同步图标与 aria(按钮不存在时忽略) */\n setFullscreenActive(active: boolean) {\n const btn = this.fullscreenBtn;\n if (!btn) return;\n btn.replaceChildren(active ? iconFullscreenExit() : iconFullscreenEnter());\n btn.title = active ? '退出全屏' : '全屏';\n btn.setAttribute('aria-label', active ? '退出全屏' : '全屏');\n btn.setAttribute('aria-pressed', active ? 'true' : 'false');\n }\n\n private _render() {\n clear(this.el);\n\n const segmented = h('div', { class: 'sm-segmented' });\n const designBtn = h(\n 'button',\n {\n class: 'sm-segmented__item sm-segmented__item--active',\n type: 'button',\n onclick: () => this.opts.onModeChange('design'),\n },\n ['设计'],\n );\n const sourceBtn = h(\n 'button',\n {\n class: 'sm-segmented__item',\n type: 'button',\n onclick: () => this.opts.onModeChange('source'),\n },\n ['源码'],\n );\n segmented.append(designBtn, sourceBtn);\n this.modeButtons = { design: designBtn, source: sourceBtn };\n\n const themeSeg = h('div', {\n class: 'sm-segmented sm-topbar__theme-seg',\n role: 'group',\n 'aria-label': '界面主题',\n });\n const themeBtn = (theme: EditorTheme, title: string, icon: SVGElement) =>\n h(\n 'button',\n {\n class: 'sm-segmented__item sm-topbar__theme-btn',\n type: 'button',\n title,\n 'aria-pressed': theme === this.opts.theme ? 'true' : 'false',\n onclick: () => this.opts.onThemeChange(theme),\n },\n [icon],\n ) as HTMLButtonElement;\n this.themeButtons = {\n light: themeBtn('light', '浅色', iconSun()),\n dark: themeBtn('dark', '深色', iconMoon()),\n system: themeBtn('system', '跟随系统', iconThemeAuto()),\n };\n themeSeg.append(this.themeButtons.light, this.themeButtons.dark, this.themeButtons.system);\n\n const themeGroupKids: Node[] = [themeSeg];\n if (this.opts.showAccentColorPicker && this.opts.onAccentChange) {\n const inputEl = h('input', {\n type: 'color',\n class: 'sm-topbar__accent-input',\n 'aria-label': '主题色',\n title: '主题色',\n value: '#4f46e5',\n }) as HTMLInputElement;\n inputEl.addEventListener('input', () => this.opts.onAccentChange!(inputEl.value));\n this.accentInput = inputEl;\n themeGroupKids.push(h('div', { class: 'sm-topbar__accent' }, [inputEl]));\n } else {\n this.accentInput = undefined;\n }\n\n this.undoBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '撤销 ⌘Z',\n onclick: this.opts.onUndo,\n },\n [iconUndo(), '撤销'],\n );\n this.redoBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '重做 ⌘⇧Z',\n onclick: this.opts.onRedo,\n },\n [iconRedo(), '重做'],\n );\n\n const insertVar = h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: (e: Event) => this.opts.onInsertVariable(e.currentTarget as HTMLElement),\n },\n ['{{ }} 插入变量'],\n );\n\n const previewBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: this.opts.onPreview },\n [iconEye(), '预览'],\n );\n\n const exportBtn = h(\n 'button',\n { class: 'sm-btn sm-btn--primary', type: 'button', onclick: this.opts.onExport },\n ['导出 HTML'],\n );\n\n const showMailSettings = this.opts.showMailSettingsButton !== false;\n const trailingGroup: HTMLElement[] = [];\n if (showMailSettings) {\n trailingGroup.push(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '邮件主题、宽度与全局样式',\n onclick: () => this.opts.onMailSettings(),\n },\n ['邮件设置'],\n ),\n );\n }\n trailingGroup.push(insertVar, previewBtn, exportBtn);\n\n const showFs =\n this.opts.showFullscreenButton !== false &&\n typeof this.opts.onFullscreenToggle === 'function';\n const fsGroup =\n showFs &&\n h('div', { class: 'sm-topbar__group' }, [\n (this.fullscreenBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost sm-topbar__icon-btn',\n type: 'button',\n title: '全屏',\n 'aria-label': '全屏',\n 'aria-pressed': 'false',\n onclick: () => this.opts.onFullscreenToggle!(),\n },\n [iconFullscreenEnter()],\n ) as HTMLButtonElement),\n ]);\n if (!showFs) this.fullscreenBtn = undefined;\n\n const headKids: HTMLElement[] = [];\n if (this.opts.showTitle !== false) {\n headKids.push(h('div', { class: 'sm-topbar__title' }, ['Simple Mail Editor']));\n }\n\n this.el.append(\n ...headKids,\n h('div', { class: 'sm-topbar__group' }, [segmented]),\n h('div', { class: 'sm-topbar__group sm-topbar__theme-group' }, themeGroupKids),\n h('div', { class: 'sm-topbar__group' }, [this.undoBtn, this.redoBtn]),\n ...(fsGroup ? [fsGroup] : []),\n h('div', { class: 'sm-topbar__spacer' }),\n h('div', { class: 'sm-topbar__group' }, trailingGroup),\n );\n\n this.setMode(this.opts.mode);\n this.syncTheme(this.opts.theme);\n }\n\n private _sync() {\n this.undoBtn.disabled = !this.opts.store.canUndo();\n this.redoBtn.disabled = !this.opts.store.canRedo();\n }\n}\n\nfunction iconUndo(): SVGElement {\n return svg(\n '<path d=\"M9 14l-4-4 4-4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5 10h7a4 4 0 010 8h-1\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconRedo(): SVGElement {\n return svg(\n '<path d=\"M11 14l4-4-4-4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 10H8a4 4 0 000 8h1\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconEye(): SVGElement {\n return svg(\n '<path d=\"M2 10s3-5 8-5 8 5 8 5-3 5-8 5-8-5-8-5z\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><circle cx=\"10\" cy=\"10\" r=\"2.4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\n );\n}\n/** 进入全屏:四角向外 */\nfunction iconFullscreenEnter(): SVGElement {\n return svg(\n '<path d=\"M6 4H4v2M14 4h2v2M6 16H4v-2M14 16h2v-2M4 6V4h2M16 6V4h-2M4 14v2h2M16 14v2h-2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\n/** 退出全屏:四角向内 */\nfunction iconFullscreenExit(): SVGElement {\n return svg(\n '<path d=\"M8 4v4H4M12 4v4h4M8 16v-4H4M12 16v-4h4M4 8h4v4H4M16 8h-4v4h4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconSun(): SVGElement {\n return svgTheme(\n '<circle cx=\"10\" cy=\"10\" r=\"3.2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M10 3.5V5M10 15v1.5M16.5 10H15M5 10H3.5M14.1 5.9 13 7M7 13 5.9 14.1M14.1 14.1 13 13M7 7 5.9 5.9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconMoon(): SVGElement {\n return svgTheme(\n '<path d=\"M8.5 4.2a5.8 5.8 0 100 11.3 4.8 4.8 0 01-1.3-11.3z\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linejoin=\"round\"/>',\n );\n}\n/** 显示器:表示跟随系统外观 */\nfunction iconThemeAuto(): SVGElement {\n return svgTheme(\n '<path d=\"M5 5.5h10c.8 0 1.5.7 1.5 1.5v6c0 .8-.7 1.5-1.5 1.5H5c-.8 0-1.5-.7-1.5-1.5v-6c0-.8.7-1.5 1.5-1.5z\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M8 16h4M10 14.2V16\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>',\n );\n}\nfunction svg(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '14');\n el.setAttribute('height', '14');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML = inner;\n return el;\n}\nfunction svgTheme(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '15');\n el.setAttribute('height', '15');\n el.setAttribute('viewBox', '0 0 20 20');\n el.setAttribute('aria-hidden', 'true');\n el.innerHTML = inner;\n return el;\n}\n","import { Registry, defineBlock } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport { Store, pruneEmptySections } from '../store/store';\nimport type {\n BlockDefinition,\n EditorUiOptions,\n EmailDoc,\n RenderEngine,\n Selection,\n Variable,\n} from '../types';\nimport { clear, h } from '../utils/dom';\nimport { Canvas } from './Canvas';\nimport { ExportModal } from './ExportModal';\nimport { LeftPanel } from './LeftPanel';\nimport { PreviewModal } from './PreviewModal';\nimport { RichTextToolbar } from './RichTextToolbar';\nimport { RightPanel } from './RightPanel';\nimport { SourceView } from './SourceView';\nimport { Topbar, type EditorMode } from './Topbar';\nimport type { EditorTheme } from './theme';\nimport type { ImageAssetsHandlers } from './imageAssets';\nimport { accentPrimarySoftRgba, normalizeAccentHex } from '../utils/accentColor';\n\nimport './styles.css';\n\nexport interface EditorOptions {\n /** 挂载点 */\n container: HTMLElement;\n /** 初始文档;不传时使用空文档 */\n initialDoc?: Partial<EmailDoc>;\n /** 自定义组件定义(除内置组件之外) */\n blocks?: BlockDefinition<any>[];\n /** 渲染引擎,目前仅 'mjml'。预留 'table' 切换 */\n engine?: RenderEngine;\n /**\n * 把 Block 拖到 sections 之间的空白处时,是否自动包一个一列 Section。\n * - true(默认):宽容,运营即使没瞄准列也能落下,自动加壳\n * - false:严格,只允许拖到现有列内;落到顶层会被 SortableJS 显示为禁止\n */\n autoWrapSection?: boolean;\n /**\n * 为 true 时:点击中栏灰色衬底、画布内空白(未点到 Section/块)等会提交内联编辑并清空选中,\n * 右栏回到文档级面板(邮件设置 / 版式与全局样式;若 `ui.hideMailMeta` 则仅版式与全局样式)。\n * 默认 false;需要「点空白取消选中」的宿主再设为 true。\n */\n clearSelectionOnCanvasMargin?: boolean;\n /** 文档变更回调(防抖发出) */\n onChange?: (doc: EmailDoc) => void;\n /**\n * 品牌/主题色(#RRGGBB),映射为界面上的 --sm-primary / --sm-primary-soft(强调、选区、主按钮等)。\n * 不传则使用 styles 里与 light/dark/system 配套的默认紫/靛。\n */\n accentColor?: string;\n /** 为 true 时在顶栏显示主题色拾取(原生 color 控件);默认 false,仅通过 accentColor / setAccentColor 由宿主控制也可 */\n showAccentColorPicker?: boolean;\n /**\n * 编辑器外框主题。`system` 随 `prefers-color-scheme`;邮件画布仍默认白纸以便预览成品。\n * @default 'light'\n */\n theme?: EditorTheme;\n /**\n * 可选。为 `type: 'image'` 提供上传 / 图床;`showUpload` 默认 true(有 uploadImage 时),`showGallery` 默认 false。\n */\n imageAssets?: ImageAssetsHandlers;\n /** 右栏控件形态等可选 UI 偏好。 */\n ui?: EditorUiOptions;\n}\n\n/**\n * 编辑器主类。所有外部能力都通过它暴露。\n *\n * 使用示例(vanilla):\n * const editor = new MailEditor({\n * container: document.getElementById('app')!,\n * blocks: [/* 自定义组件 *\\/],\n * // imageAssets: { uploadImage, pickImageFromGallery, showGallery: true } // 可选,见 README\n * });\n * editor.setVariables([{ key: 'user.name', label: '用户名', sample: '张三' }]);\n * editor.export(); // -> { mjml, html }\n */\nexport class MailEditor {\n readonly store: Store;\n readonly registry: Registry;\n private opts: EditorOptions;\n private root: HTMLElement;\n private theme: EditorTheme;\n private mode: EditorMode = 'design';\n private topbar!: Topbar;\n private leftPanel!: LeftPanel;\n private canvas!: Canvas;\n private rightPanel!: RightPanel;\n private sourceView!: SourceView;\n private toolbar!: RichTextToolbar;\n private body: HTMLElement;\n private changeTimer: number | null = null;\n /** 显式品牌色时覆盖 CSS 变量;未设置则由 styles 按 light/dark 使用默认紫/靛 */\n private accentColorOverride: string | undefined;\n private systemThemeMq: MediaQueryList | null = null;\n private readonly _onSystemThemeMqChange = () => {\n if (this.accentColorOverride) this._applyAccentVars();\n };\n\n private readonly _onFullscreenChange = () => {\n const el = smGetFullscreenElement();\n this.topbar?.setFullscreenActive(el === this.root);\n };\n\n /** design 态 Esc:块 → 父级 Section → 文档级面板(邮件设置或版式/全局样式,取决于 `ui.hideMailMeta`) */\n private _mailEscHandler = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (this.mode !== 'design') return;\n if (!this.store.selection) return;\n if (document.querySelector('.sm-modal__mask.is-open')) return;\n const t = e.target as HTMLElement | null;\n if (t?.closest?.('.sm-modal__mask')) return;\n const ae = document.activeElement as HTMLElement | null;\n if (ae && (ae.tagName === 'INPUT' || ae.tagName === 'TEXTAREA' || ae.isContentEditable)) return;\n if (ae && ae !== document.body && !this.root.contains(ae)) return;\n e.preventDefault();\n const sel = this.store.selection;\n if (sel.kind === 'block') {\n this.canvas.commitInlineEdit();\n this.store.setSelection({ kind: 'section', sectionId: sel.sectionId });\n return;\n }\n this._focusMailSettings();\n };\n\n /**\n * 文档级撤销/重做(捕获阶段):焦点在右栏 input/CodeMirror 内时,冒泡到 root 的监听太晚,\n * 浏览器会先处理控件内撤销;仅在 store 仍有历史时拦截并走全局 undo/redo。\n */\n private _mailUndoRedoHandler = (e: KeyboardEvent) => {\n const meta = e.metaKey || e.ctrlKey;\n if (!meta) return;\n const k = e.key.toLowerCase();\n if (k !== 'z') return;\n const t = e.target as Node | null;\n if (!t || !this.root.contains(t)) return;\n const undo = !e.shiftKey;\n const redo = e.shiftKey;\n if (undo && !this.store.canUndo()) return;\n if (redo && !this.store.canRedo()) return;\n e.preventDefault();\n if (undo) this.store.undo();\n else this.store.redo();\n };\n\n constructor(opts: EditorOptions) {\n this.opts = opts;\n this.registry = new Registry();\n\n // 注册外部 blocks\n if (opts.blocks) {\n for (const def of opts.blocks) this.registry.register(def);\n }\n\n const initialDoc = createDefaultDoc(opts.initialDoc);\n this.store = new Store(initialDoc);\n\n const initialAccent = normalizeAccentHex(this.opts.accentColor ?? '');\n if (\n this.opts.accentColor != null &&\n String(this.opts.accentColor).trim() !== '' &&\n !initialAccent\n ) {\n console.warn('[simple-mail] accentColor 无效,已忽略:', this.opts.accentColor);\n }\n this.accentColorOverride = initialAccent ?? undefined;\n\n this.theme = opts.theme ?? 'light';\n this.root = h('div', { class: 'sm-root' });\n this._applyThemeAttr();\n this.body = h('div', { class: 'sm-body' });\n opts.container.append(this.root);\n\n this._buildUI();\n this._bindKeyboard();\n this._bindFullscreen();\n\n this._applyAccentVars();\n this._refreshAccentMqBinding();\n this._syncTopbarAccentPicker();\n\n this.store.subscribe(() => this._onChange());\n }\n\n /* ------------------------------ Public API ------------------------------ */\n\n setValue(doc: EmailDoc) {\n this._blurRightPanelIfFocused();\n this.store.replace(doc);\n }\n\n getValue(): EmailDoc {\n return this.store.doc;\n }\n\n setVariables(vars: Variable[]) {\n this.store.update((d) => {\n d.variables = vars;\n });\n }\n\n getVariables(): Variable[] {\n return this.store.doc.variables;\n }\n\n /** 当前界面主题(`system` 不解析为 light/dark)。 */\n getTheme(): EditorTheme {\n return this.theme;\n }\n\n /** 切换界面主题;写入 `data-sm-theme`,顶栏选择器同步。 */\n setTheme(t: EditorTheme) {\n if (this.theme === t) return;\n this.theme = t;\n this._applyThemeAttr();\n this._applyAccentVars();\n this._refreshAccentMqBinding();\n this.topbar?.syncTheme(t);\n this._syncTopbarAccentPicker();\n }\n\n /**\n * 品牌/主题色(#RRGGBB)。传 null、undefined 或空字符串则恢复为 light/dark/system 下的 CSS 默认色。\n */\n setAccentColor(hex: string | null | undefined) {\n if (hex == null || String(hex).trim() === '') {\n this.accentColorOverride = undefined;\n } else {\n const n = normalizeAccentHex(String(hex));\n if (!n) {\n console.warn('[simple-mail] setAccentColor 无效,已忽略:', hex);\n return;\n }\n this.accentColorOverride = n;\n }\n this._applyAccentVars();\n this._refreshAccentMqBinding();\n this._syncTopbarAccentPicker();\n }\n\n /** 当前由选项或 setAccentColor 显式设置的品牌色;未覆盖时为 undefined。 */\n getAccentColor(): string | undefined {\n return this.accentColorOverride;\n }\n\n /** 导出 MJML 与编译后的 HTML。withSampleVariables=true 时把 {{var}} 替换为 sample 值用于预览。 */\n export(opts: { withSampleVariables?: boolean } = {}) {\n return renderDoc(this.store.doc, this.registry, {\n engine: this.opts.engine ?? 'mjml',\n withSampleVariables: opts.withSampleVariables ?? false,\n });\n }\n\n registerBlock<P extends object>(def: BlockDefinition<P>) {\n this.registry.register(def);\n this.leftPanel?.refresh();\n }\n\n setSelection(sel: Selection | null) {\n this.store.setSelection(sel);\n }\n\n destroy() {\n this._unbindFullscreen();\n this._unbindSystemThemeMqForAccent();\n if (this.changeTimer) window.clearTimeout(this.changeTimer);\n if (smGetFullscreenElement() === this.root) void smExitFullscreen();\n document.removeEventListener('keydown', this._mailEscHandler, true);\n document.removeEventListener('keydown', this._mailUndoRedoHandler, true);\n this.canvas?.destroy?.();\n this.sourceView?.destroy?.();\n this.toolbar?.destroy?.();\n this.root.remove();\n }\n\n /* -------------------------------- 私有 ---------------------------------- */\n\n private _applyThemeAttr() {\n this.root.setAttribute('data-sm-theme', this.theme);\n }\n\n private _chromeIsEffectivelyDark(): boolean {\n if (this.theme === 'dark') return true;\n if (this.theme === 'light') return false;\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n\n private _applyAccentVars() {\n if (!this.accentColorOverride) {\n this.root.style.removeProperty('--sm-primary');\n this.root.style.removeProperty('--sm-primary-soft');\n return;\n }\n const dark = this._chromeIsEffectivelyDark();\n this.root.style.setProperty('--sm-primary', this.accentColorOverride);\n this.root.style.setProperty('--sm-primary-soft', accentPrimarySoftRgba(this.accentColorOverride, dark));\n }\n\n private _unbindSystemThemeMqForAccent() {\n if (this.systemThemeMq) {\n this.systemThemeMq.removeEventListener('change', this._onSystemThemeMqChange);\n this.systemThemeMq = null;\n }\n }\n\n /** `system` 主题且存在品牌色覆盖时,随系统深浅刷新 --sm-primary-soft */\n private _refreshAccentMqBinding() {\n this._unbindSystemThemeMqForAccent();\n if (this.theme === 'system' && this.accentColorOverride) {\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n mq.addEventListener('change', this._onSystemThemeMqChange);\n this.systemThemeMq = mq;\n }\n }\n\n private _syncTopbarAccentPicker() {\n this.topbar?.syncAccentPicker();\n }\n\n private _buildUI() {\n this.topbar = new Topbar({\n store: this.store,\n mode: this.mode,\n theme: this.theme,\n accentPickerRoot: this.root,\n showAccentColorPicker: this.opts.showAccentColorPicker === true,\n onAccentChange: (hx) => this.setAccentColor(hx),\n onThemeChange: (t) => this.setTheme(t),\n onModeChange: (m) => this._setMode(m),\n onUndo: () => {\n this.store.undo();\n },\n onRedo: () => {\n this.store.redo();\n },\n onMailSettings: () => this._focusMailSettings(),\n showMailSettingsButton: this.opts.ui?.hideTopbarMailSettings !== true,\n showTitle: this.opts.ui?.hideTopbarTitle !== true,\n onInsertVariable: (anchor) => this._showVariablePopover(anchor),\n onPreview: () => this._showPreview(),\n onExport: () => this._showExport(),\n showFullscreenButton: this.opts.ui?.hideTopbarFullscreen !== true,\n onFullscreenToggle: () => void this._toggleFullscreen(),\n });\n\n this.toolbar = new RichTextToolbar({ positionRoot: this.root });\n this.leftPanel = new LeftPanel({ registry: this.registry });\n const autoWrap = this.opts.autoWrapSection !== false;\n this.root.classList.toggle('sm-allow-auto-wrap', autoWrap);\n this.canvas = new Canvas({\n store: this.store,\n registry: this.registry,\n toolbar: this.toolbar,\n autoWrapSection: autoWrap,\n clearSelectionOnCanvasMargin: this.opts.clearSelectionOnCanvasMargin === true,\n layerRoot: this.root,\n });\n this.rightPanel = new RightPanel({\n store: this.store,\n registry: this.registry,\n imageAssets: this.opts.imageAssets,\n ui: this.opts.ui,\n });\n this.sourceView = new SourceView({ store: this.store, registry: this.registry });\n\n this.body.append(this.leftPanel.el, this.canvas.el, this.rightPanel.el);\n this.root.append(this.topbar.el, this.body);\n }\n\n /** 撤销/替换文档前先失焦右栏,否则 RightPanel 会因「保留焦点」跳过重绘而仍显示旧值 */\n private _blurRightPanelIfFocused() {\n const ae = document.activeElement as HTMLElement | null;\n if (ae && this.rightPanel.el.contains(ae)) ae.blur();\n }\n\n /** 提交内联编辑并清空选中,右栏回到文档级面板 */\n private _focusMailSettings() {\n this.canvas.commitInlineEdit();\n this.store.setSelection(null);\n }\n\n private _setMode(m: EditorMode) {\n if (this.mode === m) return;\n if (m !== 'design') this.canvas.commitInlineEdit();\n this.mode = m;\n this.topbar.setMode(m);\n clear(this.body);\n if (m === 'design') {\n this.body.classList.remove('sm-body--source');\n this.body.style.removeProperty('grid-template-columns');\n this.body.append(this.leftPanel.el, this.canvas.el, this.rightPanel.el);\n } else {\n this.body.classList.add('sm-body--source');\n this.body.style.removeProperty('grid-template-columns');\n this.body.append(this.sourceView.el);\n // 见 SourceView.refreshDoc:设计态源码面板未挂载时不更新,否则会一直显示构造函数时的旧快照\n queueMicrotask(() => this.sourceView.refreshDoc());\n }\n }\n\n private _bindKeyboard() {\n this.root.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' || e.key === 'Backspace') {\n const tag = (e.target as HTMLElement).tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement).isContentEditable) {\n return;\n }\n const sel = this.store.selection;\n if (!sel) return;\n e.preventDefault();\n if (sel.kind === 'section') {\n this.store.update((d) => {\n d.sections = d.sections.filter((s) => s.id !== sel.sectionId);\n });\n this.store.setSelection(null);\n } else {\n this.store.update((d) => {\n const sec = d.sections.find((s) => s.id === sel.sectionId);\n if (!sec) return;\n const col = sec.columns[sel.columnIndex];\n if (!col) return;\n col.blocks = col.blocks.filter((b) => b.id !== sel.blockId);\n pruneEmptySections(d);\n });\n this.store.setSelection(null);\n }\n }\n });\n document.addEventListener('keydown', this._mailUndoRedoHandler, true);\n document.addEventListener('keydown', this._mailEscHandler, true);\n this.root.tabIndex = 0;\n }\n\n private _onChange() {\n if (!this.opts.onChange) return;\n if (this.changeTimer) window.clearTimeout(this.changeTimer);\n this.changeTimer = window.setTimeout(() => {\n this.opts.onChange?.(this.store.doc);\n this.changeTimer = null;\n }, 60) as unknown as number;\n }\n\n private _showVariablePopover(anchor: HTMLElement) {\n const vars = this.store.doc.variables;\n if (!vars.length) {\n alert('当前未配置变量。请先调用 editor.setVariables([...])');\n return;\n }\n const existing = this.root.querySelector('.sm-popover');\n if (existing) {\n existing.remove();\n return;\n }\n\n const pop = h('div', { class: 'sm-popover' });\n for (const v of vars) {\n pop.append(\n h(\n 'button',\n {\n class: 'sm-popover__item',\n type: 'button',\n onclick: () => {\n this._insertVariable(v);\n pop.remove();\n },\n },\n [\n h('span', { class: 'sm-popover__key' }, [`{{${v.key}}}`]),\n h('span', { class: 'sm-popover__label' }, [v.label]),\n ],\n ),\n );\n }\n\n const rect = anchor.getBoundingClientRect();\n const rootRect = this.root.getBoundingClientRect();\n pop.style.top = `${rect.bottom - rootRect.top + 4}px`;\n pop.style.left = `${rect.left - rootRect.left}px`;\n this.root.append(pop);\n\n const onDocClick = (ev: MouseEvent) => {\n if (!pop.contains(ev.target as Node) && ev.target !== anchor) {\n pop.remove();\n document.removeEventListener('click', onDocClick, true);\n }\n };\n setTimeout(() => document.addEventListener('click', onDocClick, true), 0);\n }\n\n private _insertVariable(v: Variable) {\n const sel = this.store.selection;\n const placeholder = `{{${v.key}}}`;\n\n // 最高优:正在画布内联编辑的富文本光标处\n const inline = this.canvas.currentInlineEditor;\n if (inline) {\n inline.insertText(placeholder);\n return;\n }\n\n // 次之:当前聚焦的 input/textarea(属性面板)\n const active = document.activeElement as HTMLInputElement | HTMLTextAreaElement | null;\n if (\n active &&\n (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA') &&\n this.root.contains(active)\n ) {\n const start = active.selectionStart ?? active.value.length;\n const end = active.selectionEnd ?? active.value.length;\n active.value = active.value.slice(0, start) + placeholder + active.value.slice(end);\n const ev = new Event('input', { bubbles: true });\n active.dispatchEvent(ev);\n return;\n }\n\n // 最次:选中 Block 时追加到该 block 的 inlineEditable 字段或第一个文本字段\n if (sel?.kind === 'block') {\n this.store.update((d) => {\n for (const s of d.sections) {\n for (const c of s.columns) {\n const b = c.blocks.find((x) => x.id === sel.blockId);\n if (!b) continue;\n const def = this.registry.get(b.type);\n const key =\n def?.inlineEditable?.propKey ??\n def?.schema.find((f) => f.type === 'text' || f.type === 'textarea')?.key;\n if (key) {\n const cur = String((b.props as any)[key] ?? '');\n (b.props as any)[key] = cur + placeholder;\n }\n }\n }\n });\n return;\n }\n\n alert('请先双击进入文本编辑、或聚焦一个输入框后再插入变量');\n }\n\n private _showExport() {\n // 切回设计模式时如果还在内联编辑,先把内容提交进 store\n this.canvas.commitInlineEdit();\n const modal = new ExportModal({\n store: this.store,\n registry: this.registry,\n withSampleVariables: true,\n });\n modal.open(this.root);\n }\n\n private _showPreview() {\n this.canvas.commitInlineEdit();\n const modal = new PreviewModal({\n store: this.store,\n registry: this.registry,\n });\n modal.open(this.root);\n }\n\n private _bindFullscreen() {\n if (this.opts.ui?.hideTopbarFullscreen === true) return;\n document.addEventListener('fullscreenchange', this._onFullscreenChange);\n document.addEventListener('webkitfullscreenchange', this._onFullscreenChange);\n this._onFullscreenChange();\n }\n\n private _unbindFullscreen() {\n document.removeEventListener('fullscreenchange', this._onFullscreenChange);\n document.removeEventListener('webkitfullscreenchange', this._onFullscreenChange);\n }\n\n private async _toggleFullscreen() {\n try {\n if (smGetFullscreenElement() === this.root) await smExitFullscreen();\n else await smRequestFullscreen(this.root);\n } catch (err) {\n console.warn('[simple-mail] 全屏不可用:', err);\n }\n }\n}\n\nfunction smGetFullscreenElement(): Element | null {\n const d = document as Document & { webkitFullscreenElement?: Element | null };\n return document.fullscreenElement ?? d.webkitFullscreenElement ?? null;\n}\n\nasync function smRequestFullscreen(el: HTMLElement): Promise<void> {\n const anyEl = el as HTMLElement & { webkitRequestFullscreen?: () => Promise<void> | void };\n if (typeof anyEl.requestFullscreen === 'function') await anyEl.requestFullscreen();\n else if (typeof anyEl.webkitRequestFullscreen === 'function') await anyEl.webkitRequestFullscreen();\n}\n\nasync function smExitFullscreen(): Promise<void> {\n const d = document as Document & { webkitExitFullscreen?: () => Promise<void> | void };\n if (typeof document.exitFullscreen === 'function') await document.exitFullscreen();\n else if (typeof d.webkitExitFullscreen === 'function') await d.webkitExitFullscreen();\n}\n\n/* ----------------------------- 默认空文档 ------------------------------- */\n\nfunction createDefaultDoc(partial?: Partial<EmailDoc>): EmailDoc {\n const mergedStyles = {\n backgroundColor: '#ffffff',\n contentBackgroundColor: '#ffffff',\n fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Microsoft YaHei\", sans-serif',\n fontSize: '16px',\n fontWeight: '400',\n color: '#433f3f',\n linkColor: '#ff5a00',\n lineHeight: '1.25',\n ...(partial?.styles ?? {}),\n };\n return {\n version: '1',\n meta: {\n subject: '一封新邮件',\n preheader: '',\n width: 600,\n ...(partial?.meta ?? {}),\n },\n variables: partial?.variables ?? [],\n styles: {\n ...mergedStyles,\n fontWeight: mergedStyles.fontWeight ?? '400',\n lineHeight: mergedStyles.lineHeight ?? '1.25',\n },\n sections: partial?.sections ?? [],\n };\n}\n\nexport { defineBlock };\n"],"names":["Registry","__publicField","def","type","category","d","cryptoRandomId","ts","rand","defineBlock","coerceCssWidth","raw","n","s","docContentWidthCss","parseMetaWidthFromUserInput","input","metaWidthInputString","blockButtonWidthCss","parseSectionWidthFromUserInput","sectionWidthInputString","h","tag","attrs","children","el","k","v","child","clear","escapeHtml","escapeAttr","FONT_WEIGHT_STEP_VALUES","FONT_WEIGHT_STEP_OPTIONS","normalizeFontWeightStep","match","steps","best","bestD","st","mjRawCellTypographyFromStyles","cssForDoubleQuotedAttr","value","buildMjRawTdStyle","paddingCss","typo","fontSize","lineHeight","color","fontFamily","fontWeight","mjRawEmailTableWrap","cellInnerHtml","wrapLockedMjmlForMjColumn","fragment","lead","t","normalizeHtmlBlockLockedMjmlForCompile","mj","inner","divStrip","htmlFragmentForLockedHtmlBlockCanvas","lockedMjml","padding","mjMatch","pad","bare","docToMjml","doc","registry","ctx","sections","sectionToMjml","sectionWidthConstraintCss","sectionMjClassName","sectionId","w","section","a","bg","secCls","widths","layoutWidths","gapPx","columns","col","i","columnToMjml","grouped","indent","column","width","columnIndex","columnCount","columnGapPx","va","gapPad","half","pl","rawTypo","blocks","b","frag","p","layout","parts","total","x","text","l","renderDoc","opts","engine","mjml","compiled","mjmlCompile","html","replaceVariables","e","vars","key","_counter","uid","prefix","Store","initial","fn","sel","mutator","draft","prev","next","source","detail","findSection","findBlockLocation","blockId","blk","pruneEmptySections","sec","createSection","colCount","prettyHtml","VOID","PRESERVE","tokens","depth","preserveStack","out","tok","inPreserve","_a","_b","selfClosing","txt","Modal","parent","title","tools","closeBtn","iconClose","BlockCodeModal","beautifyBtn","saveBtn","componentLabel","loc","block","EditorView","EditorState","basicSetup","cmHtml","id","InlineEditor","sanitizeRichHtml","restore","off","range","command","isListCmd","url","trimmed","safe","anchor","findAncestorAnchor","mode","multiline","placeholder","placeCaretAtEnd","onKeyDown","onBlur","active","onPaste","onSelChange","linkInsideEditing","href","onLinkMouseDown","placeCaretAtClientPoint","stopLinkActivate","rect","align","link","state","safeQueryValue","fallback","_d","_c","_f","_e","rects","tmp","span","r","node","root","clientX","clientY","pos","cmd","tpl","walk","toRemove","size","face","styles","fontSizeFromLegacy","cleaned","allowedAttrs","attr","Canvas","stop","si","topPut","top","Sortable","sectionIndex","layoutShort","layoutHumanLabel","sectionChip","sw","box","wrap","toolbar","iconDrag","iconCopy","iconTrash","cols","layoutFlexStyle","isEmpty","colEl","layoutFlexValue","vaToFlex","sortable","displayName","content","blockToolbar","iconEdit","iconCode","layouts","bar","reg","newBlock","firstBlock","blockEl","cssEscape","contentRoot","target","propKey","editingId","restoreUI","blockType","item","fromBlockId","sourceGroup","newIndex","newSection","head","fromCol","idx","moved","oldIndex","targetSec","clone","c","LAYOUT_LABELS","_layout","columnGap","index","ratio","svg","ExportModal","editorHost","copyBtn","downloadBtn","result","ta","blob","LAYOUT_CARDS","layoutSvg","LeftPanel","custom","grid","defs","gap","innerW","rw","DEVICES","_PreviewModal","switcher","btn","iconForDevice","spec","body","maxPx","PreviewModal","FONT_FAMILIES","FONT_SIZES","FONT_WEIGHTS","RichTextToolbar","editor","f","hasLink","hex","rgbToHex","matchFamily","px","ed","sep","exec","val","svgIcon","opt","ke","applyLinkBtn","opening","prop","newRange","rootRect","tw","th","left","on","onClick","style","icon","name","lower","rgb","m","toHex","defaultSocialIconBackground","network","openImageGalleryModal","adapter","onPick","onClose","modal","query","page","hasMore","loading","selected","errEl","searchInp","debounceId","loadFirst","gridEl","loadMoreBtn","loadPage","confirmBtn","finishPick","setError","msg","syncSelectionStyles","renderCells","items","append","it","thumb","cellWrap","cell","img","cap","delBtn","err","res","toolRow","urlInp","addBtn","u","fileInp","upBtn","scrollArea","classifyLayoutWidth","layoutWidthNumeric","RightPanel","ae","token","selStart","selEnd","len","tabs","tab","label","hideMeta","rows","vals","g","checked","schema","form","field","fp","defaults","onChange","isFw","displayVal","row","quad","dp","resetQuad","pr","networkOptions","elementsKey","help","focusPrefix","firstVal","listEl","patchElements","mutate","props","cur","syncItem","patch","removeAt","_","rowData","rowWrap","mainRow","o","inp","rm","extras","bgResolved","bgStored","bgDisplay","focusToken","ids","assets","showUploadBtn","showGalleryBtn","hasAssetCallbacks","hasAnyPickerBtn","getCtx","applyUrl","runAsync","labelErr","helpBody","bits","min","max","step","snap","commitPlain","fb","v0","num","syncFromSlider","pickToken","textToken","options","group","titles","clampPad","current","emit","makePlain","makeSliderRow","rawN","tf","kind","displayN","clampW","emitW","sliderRow","modesWrap","addModeBtn","header","view","actions","SourceView","normalizeAccentHex","rgbCssToHex","accentPrimarySoftRgba","primaryHex","isDarkChrome","Topbar","base","norm","forInput","iconFullscreenExit","iconFullscreenEnter","segmented","designBtn","sourceBtn","themeSeg","themeBtn","theme","iconSun","iconMoon","iconThemeAuto","themeGroupKids","inputEl","iconUndo","iconRedo","insertVar","previewBtn","iconEye","exportBtn","showMailSettings","trailingGroup","showFs","fsGroup","headKids","svgTheme","MailEditor","smGetFullscreenElement","undo","redo","initialDoc","createDefaultDoc","initialAccent","smExitFullscreen","dark","mq","hx","autoWrap","existing","pop","onDocClick","ev","inline","start","end","smRequestFullscreen","anyEl","partial","mergedStyles"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/registry/registry.ts","../src/utils/contentWidth.ts","../src/utils/dom.ts","../src/utils/fontWeightSteps.ts","../src/utils/lockedMjml.ts","../src/renderer/mjml.ts","../src/renderer/index.ts","../src/utils/id.ts","../src/store/store.ts","../src/utils/sectionLayout.ts","../src/utils/html.ts","../src/editor/Modal.ts","../src/editor/BlockCodeModal.ts","../src/utils/richTextCommand.ts","../src/utils/accentColor.ts","../src/editor/ColorPickerPopover.ts","../src/editor/InlineEditor.ts","../src/editor/Canvas.ts","../src/editor/ExportModal.ts","../src/editor/LeftPanel.ts","../src/editor/PreviewModal.ts","../src/editor/RichTextToolbar.ts","../src/socialDefaults.ts","../src/editor/FocusBreadcrumb.ts","../src/editor/ImageGalleryModal.ts","../src/editor/RightPanel.ts","../src/editor/SourceView.ts","../src/editor/Topbar.ts","../src/editor/Editor.ts"],"sourcesContent":["import type { Block, BlockDefinition } from '../types';\n\n/**\n * 组件注册表。所有内置/自定义组件都通过 `defineBlock` 注册进来;\n * 渲染、属性面板、左栏拖拽源、组件级代码模式四方都从这里读取。\n */\nexport class Registry {\n private map = new Map<string, BlockDefinition<any>>();\n\n register<P extends object>(def: BlockDefinition<P>) {\n if (this.map.has(def.type)) {\n console.warn(`[simple-mail] block type 重复注册: ${def.type},后注册的会覆盖前者`);\n }\n this.map.set(def.type, def as BlockDefinition<any>);\n return this;\n }\n\n get(type: string): BlockDefinition | undefined {\n return this.map.get(type);\n }\n\n /** 必须能找到,否则抛出。渲染/属性面板都用它,未注册即 bug。 */\n require(type: string): BlockDefinition {\n const def = this.map.get(type);\n if (!def) throw new Error(`[simple-mail] 未注册的 block type: ${type}`);\n return def;\n }\n\n list(): BlockDefinition[] {\n return [...this.map.values()];\n }\n\n byCategory(category: BlockDefinition['category']): BlockDefinition[] {\n return this.list().filter((d) => d.category === category);\n }\n\n /** 用注册表里的默认 props 创建一个新 block 实例。 */\n createBlock(type: string): Block {\n const def = this.require(type);\n return {\n id: cryptoRandomId(),\n type,\n props: structuredClone(def.defaultProps),\n };\n }\n}\n\nfunction cryptoRandomId() {\n const ts = Date.now().toString(36).slice(-4);\n const rand = Math.floor(Math.random() * 36 ** 4)\n .toString(36)\n .padStart(4, '0');\n return `blk_${ts}${rand}`;\n}\n\n/** 工厂函数,便于外部以函数式风格定义组件。 */\nexport function defineBlock<P extends object>(def: BlockDefinition<P>): BlockDefinition<P> {\n return def;\n}\n","/**\n * 内容区 / 按钮等「布局宽度」解析:数字与无单位数字按 px;支持显式 `px` 与 `%`。\n */\n\nfunction coerceCssWidth(raw: unknown): string | undefined {\n if (raw == null || raw === '') return undefined;\n if (typeof raw === 'number' && Number.isFinite(raw)) {\n const n = Math.round(raw);\n return n > 0 ? `${n}px` : undefined;\n }\n const s = String(raw).trim();\n if (!s) return undefined;\n if (/^\\d+(\\.\\d+)?%$/.test(s)) return s;\n if (/^\\d+(\\.\\d+)?px$/i.test(s)) return s.replace(/px$/i, 'px');\n if (/^\\d+(\\.\\d+)?$/.test(s)) return `${s}px`;\n return undefined;\n}\n\n/** 邮件 `meta.width` → CSS / mj-body 可用的宽度(非法则 600px) */\nexport function docContentWidthCss(raw: unknown): string {\n return coerceCssWidth(raw) ?? '600px';\n}\n\n/** 右栏输入解析存库:纯整数可存 number,其它存 string */\nexport function parseMetaWidthFromUserInput(input: string): number | string {\n const t = input.trim();\n if (!t) return 600;\n if (/^\\d+(\\.\\d+)?%$/.test(t)) return t;\n if (/^\\d+(\\.\\d+)?px$/i.test(t)) return t.replace(/PX$/i, 'px');\n if (/^\\d+$/.test(t)) return Number(t);\n if (/^\\d+\\.\\d+$/.test(t)) return `${t}px`;\n return t;\n}\n\nexport function metaWidthInputString(raw: unknown): string {\n if (raw == null) return '600';\n if (typeof raw === 'number' && Number.isFinite(raw)) return String(raw);\n return String(raw);\n}\n\n/** 按钮 / Section 等:可选宽度,空或 auto 表示不限制 */\nexport function blockButtonWidthCss(raw: unknown): string | undefined {\n if (raw == null) return undefined;\n const s = String(raw).trim();\n if (!s || s.toLowerCase() === 'auto') return undefined;\n return coerceCssWidth(s);\n}\n\n/** Section 右栏输入;空字符串表示清除宽度 */\nexport function parseSectionWidthFromUserInput(input: string): string | number | undefined {\n const t = input.trim();\n if (!t) return undefined;\n if (/^\\d+(\\.\\d+)?%$/.test(t)) return t;\n if (/^\\d+(\\.\\d+)?px$/i.test(t)) return t.replace(/PX$/i, 'px');\n if (/^\\d+$/.test(t)) return Number(t);\n if (/^\\d+\\.\\d+$/.test(t)) return `${t}px`;\n return t;\n}\n\nexport function sectionWidthInputString(raw: unknown): string {\n if (raw == null || raw === '') return '';\n if (typeof raw === 'number' && Number.isFinite(raw)) return String(raw);\n return String(raw);\n}\n","/** 极简 DOM 创建工具,避免引入 hyperscript 等额外依赖。 */\n\ntype Attrs = Record<string, string | number | boolean | EventListener | undefined | null>;\n\nexport function h<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Attrs = {},\n children: (Node | string | null | undefined | false)[] = [],\n): HTMLElementTagNameMap[K] {\n const el = document.createElement(tag);\n for (const [k, v] of Object.entries(attrs)) {\n if (v == null || v === false) continue;\n if (k === 'class') el.className = String(v);\n else if (k === 'style') el.setAttribute('style', String(v));\n else if (k === 'html') el.innerHTML = String(v);\n else if (k.startsWith('on') && typeof v === 'function') {\n el.addEventListener(k.slice(2).toLowerCase(), v as EventListener);\n } else if (typeof v === 'boolean') {\n if (v) el.setAttribute(k, '');\n } else {\n el.setAttribute(k, String(v));\n }\n }\n for (const child of children) {\n if (child == null || child === false) continue;\n el.appendChild(typeof child === 'string' ? document.createTextNode(child) : child);\n }\n return el;\n}\n\nexport function clear(el: HTMLElement) {\n while (el.firstChild) el.removeChild(el.firstChild);\n}\n\nexport function escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nexport function escapeAttr(s: string): string {\n return escapeHtml(s);\n}\n","/** 全局与各组件字重:固定五档,便于右栏平铺或步进滑块 */\nexport const FONT_WEIGHT_STEP_VALUES = ['300', '400', '500', '600', '700'] as const;\nexport type FontWeightStep = (typeof FONT_WEIGHT_STEP_VALUES)[number];\n\nexport const FONT_WEIGHT_STEP_OPTIONS: { label: string; value: string }[] = FONT_WEIGHT_STEP_VALUES.map(\n (v) => ({ label: v, value: v }),\n);\n\n/** 将任意历史写法映射到最近一档(normal→400,bold→700 等) */\nexport function normalizeFontWeightStep(raw: string | undefined | null): FontWeightStep {\n const s = String(raw ?? '400').trim().toLowerCase();\n if (s === '' || s === 'normal' || s === 'regular') return '400';\n if (s === 'bold' || s === 'bolder') return '700';\n if (s === 'lighter') return '300';\n const match = /^(\\d+)(\\.\\d+)?$/.exec(s);\n if (match) {\n const n = parseInt(match[1], 10);\n const steps = [300, 400, 500, 600, 700];\n let best: FontWeightStep = '400';\n let bestD = Infinity;\n for (const st of steps) {\n const d = Math.abs(n - st);\n if (d < bestD) {\n bestD = d;\n best = String(st) as FontWeightStep;\n }\n }\n return best;\n }\n return '400';\n}\n","import type { GlobalStyles } from '../types';\nimport { normalizeFontWeightStep } from './fontWeightSteps';\n\n/**\n * mj-column 编译结果外层会有 `font-size:0`(多列 inline-block 间距技巧),\n * mj-raw 内若未在祖先上重置字号,li/p 等会继承 0 导致「看不见」。\n * 在包裹 td 上对齐邮件全局正文样式即可规避。\n */\nexport interface MjRawCellTypography {\n fontSize: string;\n lineHeight: string;\n color: string;\n fontFamily: string;\n fontWeight: string;\n}\n\nexport function mjRawCellTypographyFromStyles(s: GlobalStyles): MjRawCellTypography {\n return {\n fontSize: (s.fontSize || '16px').trim(),\n lineHeight: (s.lineHeight || '1.25').trim(),\n color: (s.color || '#433f3f').trim(),\n fontFamily: (s.fontFamily || 'sans-serif').trim(),\n fontWeight: normalizeFontWeightStep(s.fontWeight),\n };\n}\n\n/** style=\"...\" 为双引号属性,避免值内双引号破坏解析 */\nfunction cssForDoubleQuotedAttr(value: string): string {\n return value.replace(/\"/g, \"'\").replace(/\\s+/g, ' ').trim();\n}\n\nfunction buildMjRawTdStyle(paddingCss: string, typo: MjRawCellTypography): string {\n const fontSize = cssForDoubleQuotedAttr(typo.fontSize);\n const lineHeight = cssForDoubleQuotedAttr(typo.lineHeight);\n const color = cssForDoubleQuotedAttr(typo.color);\n const fontFamily = cssForDoubleQuotedAttr(typo.fontFamily);\n const fontWeight = cssForDoubleQuotedAttr(typo.fontWeight);\n return `padding:${paddingCss};font-size:${fontSize};line-height:${lineHeight};color:${color};font-family:${fontFamily};font-weight:${fontWeight}`;\n}\n\n/**\n * mj-column 编译结果是表格布局,列内若用 mj-raw 直接输出 div/ul 等块级 HTML,\n * 会变成非法 table 子节点,浏览器/邮件里常表现为整块空白。\n * 用 presentation table + 单格 td 包住用户 HTML,与 mj-text 等组件结构一致。\n */\nexport function mjRawEmailTableWrap(\n paddingCss: string,\n cellInnerHtml: string,\n typo: MjRawCellTypography,\n): string {\n const tdStyle = buildMjRawTdStyle(paddingCss, typo);\n return `<mj-raw>\n<table role=\"presentation\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\">\n <tbody>\n <tr>\n <td style=\"${tdStyle}\">\n ${cellInnerHtml}\n </td>\n </tr>\n </tbody>\n</table>\n</mj-raw>`;\n}\n\n/**\n * 锁定片段插入 mj-column 时的规范化。\n *\n * mj-column 内只允许 mj-* 节点(或 mj-raw 包一层 HTML)。\n * 用户若在「编辑组件代码」里只保存了 `<ul>...</ul>` 等裸 HTML,直接下发会导致 MJML 编译失败、预览空白。\n */\nexport function wrapLockedMjmlForMjColumn(fragment: string, typo: MjRawCellTypography): string {\n const lead = fragment.trimStart();\n if (!lead) return '<mj-raw><!-- empty --></mj-raw>';\n if (/^<mj-/i.test(lead)) return fragment;\n const t = fragment.trim();\n // 无 props 上下文,内边距交给 0;用户可在片段内自行写 padding\n return mjRawEmailTableWrap('0', t, typo);\n}\n\n/** 旧版 HTML 块/锁定片段只有 mj-raw 包 div 或裸标签,编译进列后表格结构非法;统一包一层 presentation table。 */\nexport function normalizeHtmlBlockLockedMjmlForCompile(\n fragment: string,\n paddingCss: string,\n typo: MjRawCellTypography,\n): string {\n const raw = fragment.trim();\n const mj = raw.match(/^<mj-raw\\b[^>]*>([\\s\\S]*)<\\/mj-raw\\s*>$/i);\n if (!mj) return fragment;\n let inner = mj[1].trim();\n const divStrip = inner.match(/^\\s*<div\\b[^>]*style=\"[^\"]*\"[^>]*>([\\s\\S]*)<\\/div>\\s*$/i);\n if (divStrip) inner = divStrip[1].trim();\n if (/^\\s*<table\\b/i.test(inner)) return raw;\n return mjRawEmailTableWrap(paddingCss, inner, typo);\n}\n\n/** HTML 块锁定:画布上优先渲染可读效果,而非转义后的 MJML 源码字符串。 */\nexport function htmlFragmentForLockedHtmlBlockCanvas(\n lockedMjml: string,\n padding: { top: number; right: number; bottom: number; left: number },\n): string {\n const raw = lockedMjml.trim();\n const mjMatch = raw.match(/^<mj-raw\\b[^>]*>([\\s\\S]*)<\\/mj-raw\\s*>$/i);\n const pad = `${padding.top}px ${padding.right}px ${padding.bottom}px ${padding.left}px`;\n if (mjMatch) {\n const body = mjMatch[1].trim();\n return body || `<div style=\"padding:${pad};color:#9ca3af;font-size:13px;\">(无内容)</div>`;\n }\n const bare = raw;\n if (!bare) return `<div style=\"padding:${pad};color:#9ca3af;font-size:13px;\">(无内容)</div>`;\n return `<div style=\"padding:${pad}\">${bare}</div>`;\n}\n","import type { Registry } from '../registry/registry';\nimport type { Column, EmailDoc, RenderContext, Section, SectionLayout } from '../types';\nimport { blockButtonWidthCss, docContentWidthCss } from '../utils/contentWidth';\nimport { escapeAttr } from '../utils/dom';\nimport { normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport {\n mjRawCellTypographyFromStyles,\n normalizeHtmlBlockLockedMjmlForCompile,\n wrapLockedMjmlForMjColumn,\n} from '../utils/lockedMjml';\n\n/**\n * Schema → MJML 字符串。\n *\n * 不直接编译成 HTML——HTML 编译交给 `mjml-browser`,\n * 这一层只负责把数据模型翻译成 MJML 语义化标签。\n */\nexport function docToMjml(doc: EmailDoc, registry: Registry): string {\n const ctx: RenderContext = { doc, engine: 'mjml' };\n const attrs = doc.styles;\n\n const sections = doc.sections.map((s) => sectionToMjml(s, registry, ctx)).join('\\n');\n\n return `<mjml>\n <mj-head>\n <mj-title>${escapeAttr(doc.meta.subject || '')}</mj-title>\n ${doc.meta.preheader ? `<mj-preview>${escapeAttr(doc.meta.preheader)}</mj-preview>` : ''}\n <mj-attributes>\n <mj-all font-family=\"${escapeAttr(attrs.fontFamily)}\" />\n <mj-text font-size=\"${escapeAttr(attrs.fontSize)}\" font-weight=\"${escapeAttr(normalizeFontWeightStep(attrs.fontWeight))}\" color=\"${escapeAttr(attrs.color)}\" line-height=\"${escapeAttr(attrs.lineHeight ?? '1.25')}\" />\n <mj-class name=\"link\" color=\"${escapeAttr(attrs.linkColor)}\" />\n </mj-attributes>\n <mj-style>\n a { color: ${escapeAttr(attrs.linkColor)}; }\n${sectionWidthConstraintCss(doc)}\n </mj-style>\n </mj-head>\n <mj-body background-color=\"${escapeAttr(attrs.backgroundColor)}\" width=\"${escapeAttr(docContentWidthCss(doc.meta.width))}\">\n${sections}\n </mj-body>\n</mjml>`;\n}\n\nfunction sectionMjClassName(sectionId: string): string {\n return `sm-sec-${sectionId.replace(/[^a-zA-Z0-9_-]/g, '_')}`;\n}\n\n/** 为设置了宽度的 Section 生成 max-width 规则(css-class 挂在 mj-section 上) */\nfunction sectionWidthConstraintCss(doc: EmailDoc): string {\n return doc.sections\n .map((s) => {\n const w = blockButtonWidthCss(s.attrs.width);\n if (!w) return '';\n const cls = sectionMjClassName(s.id);\n return ` .${cls} { max-width: ${w} !important; width: 100% !important; margin-left: auto !important; margin-right: auto !important; }`;\n })\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction sectionToMjml(section: Section, registry: Registry, ctx: RenderContext): string {\n const a = section.attrs;\n const padding = [a.paddingTop, a.paddingRight, a.paddingBottom, a.paddingLeft]\n .map((v) => `${v ?? 0}px`)\n .join(' ');\n const bg = a.backgroundColor ? ` background-color=\"${escapeAttr(a.backgroundColor)}\"` : '';\n const secW = blockButtonWidthCss(a.width);\n const secCls = secW ? ` css-class=\"${escapeAttr(sectionMjClassName(section.id))}\"` : '';\n const widths = layoutWidths(section.layout);\n const gapPx = Math.max(0, section.attrs.columnGap ?? 0);\n\n const columns = section.columns\n .map((col, i) =>\n columnToMjml(col, widths[i], i, section.columns.length, gapPx, registry, ctx),\n )\n .join('\\n');\n\n /** 多列 + 显式开启时包 mj-group,阻止小屏列堆叠(MJML 官方语义) */\n const multiCol = section.columns.length > 1;\n const grouped =\n multiCol && section.attrs.preserveColumnsOnMobile === true\n ? ` <mj-group>\\n${indent(columns, 2)}\\n </mj-group>`\n : columns;\n\n return ` <mj-section padding=\"${padding}\"${bg}${secCls}>\n${grouped}\n </mj-section>`;\n}\n\nfunction columnToMjml(\n column: Column,\n width: string,\n columnIndex: number,\n columnCount: number,\n columnGapPx: number,\n registry: Registry,\n ctx: RenderContext,\n): string {\n const a = column.attrs;\n const va = a.verticalAlign ? ` vertical-align=\"${a.verticalAlign}\"` : '';\n const bg = a.backgroundColor ? ` background-color=\"${escapeAttr(a.backgroundColor)}\"` : '';\n\n let gapPad = '';\n if (columnCount > 1 && columnGapPx > 0) {\n const half = columnGapPx / 2;\n const pl = columnIndex > 0 ? `${half}px` : '0px';\n const pr = columnIndex < columnCount - 1 ? `${half}px` : '0px';\n gapPad = ` padding=\"0px ${pr} 0px ${pl}\"`;\n }\n\n const rawTypo = mjRawCellTypographyFromStyles(ctx.doc.styles);\n const blocks = column.blocks\n .map((b) => {\n if (b.lockedMjml) {\n let frag = wrapLockedMjmlForMjColumn(b.lockedMjml, rawTypo);\n if (b.type === 'html') {\n const p = b.props as {\n paddingTop?: number;\n paddingRight?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n };\n const pad = `${Number(p.paddingTop ?? 8)}px ${Number(p.paddingRight ?? 0)}px ${Number(p.paddingBottom ?? 8)}px ${Number(p.paddingLeft ?? 0)}px`;\n frag = normalizeHtmlBlockLockedMjmlForCompile(frag, pad, rawTypo);\n }\n return indent(frag, 8);\n }\n const def = registry.require(b.type);\n return indent(def.toMjml(b.props, ctx), 8);\n })\n .join('\\n');\n\n return ` <mj-column width=\"${width}\"${va}${bg}${gapPad}>\n${blocks || ' <!-- empty column -->'}\n </mj-column>`;\n}\n\nfunction layoutWidths(layout: SectionLayout): string[] {\n // 内容宽度 600,给到百分比即可,让 MJML 自己处理像素分配\n const parts = layout.split('-').map(Number);\n const total = parts.reduce((s, x) => s + x, 0);\n return parts.map((p) => `${((p / total) * 100).toFixed(2)}%`);\n}\n\nfunction indent(text: string, n: number): string {\n const pad = ' '.repeat(n);\n return text\n .split('\\n')\n .map((l) => (l ? pad + l : l))\n .join('\\n');\n}\n","import mjmlCompile from 'mjml-browser';\nimport type { EmailDoc, RenderEngine, Variable } from '../types';\nimport type { Registry } from '../registry/registry';\nimport { docToMjml } from './mjml';\n\nexport interface RenderResult {\n mjml: string;\n html: string;\n errors: { message: string }[];\n}\n\nexport interface RenderOptions {\n /** 渲染引擎,目前仅 'mjml';'table' 预留作将来直输 table HTML。 */\n engine?: RenderEngine;\n /**\n * 是否把 {{var}} 替换为示例值。设计态画布预览传 true,导出原始 HTML 传 false。\n */\n withSampleVariables?: boolean;\n}\n\nexport function renderDoc(\n doc: EmailDoc,\n registry: Registry,\n opts: RenderOptions = {},\n): RenderResult {\n const engine: RenderEngine = opts.engine ?? 'mjml';\n\n if (engine !== 'mjml') {\n // 预留:将来可在此分支实现纯 table 输出。\n throw new Error(`渲染引擎暂未实现: ${engine}`);\n }\n\n const mjml = docToMjml(doc, registry);\n\n const compiled = mjmlCompile(mjml, {\n validationLevel: 'soft',\n keepComments: false,\n });\n\n let html = compiled.html;\n if (opts.withSampleVariables) {\n html = replaceVariables(html, doc.variables);\n }\n\n return {\n mjml,\n html,\n errors: (compiled.errors || []).map((e: any) => ({\n message: e.formattedMessage ?? e.message ?? String(e),\n })),\n };\n}\n\n/**\n * 用 sample 值替换 `{{var.name}}` 占位符。仅做最简单的字符串替换,\n * 不做任何沙箱式表达式求值(邮件场景里下游模板引擎会再处理一次)。\n */\nexport function replaceVariables(text: string, vars: Variable[]): string {\n if (!vars.length) return text;\n return text.replace(/\\{\\{\\s*([^}\\s]+)\\s*\\}\\}/g, (raw, key) => {\n const v = vars.find((x) => x.key === key);\n if (v && v.sample != null) return v.sample;\n return raw;\n });\n}\n","let _counter = 0;\n\n/**\n * 生成短 ID。无需密码学强度——仅用于文档内引用。\n * 使用 base36 + 自增计数,保证同 doc 内单调,便于 diff 调试。\n */\nexport function uid(prefix = 'id'): string {\n _counter += 1;\n const ts = Date.now().toString(36).slice(-4);\n const rand = Math.floor(Math.random() * 36 ** 3)\n .toString(36)\n .padStart(3, '0');\n return `${prefix}_${ts}${rand}${_counter.toString(36)}`;\n}\n","import type { Block, Column, EmailDoc, Section, SectionLayout, Selection } from '../types';\nimport { uid } from '../utils/id';\n\n/** 文档变更通知来源(右栏等可按来源决定是否保留焦点) */\nexport type DocChangedDetail = { source: 'mutate' | 'history' | 'replace' };\n\ntype Listener = (detail?: DocChangedDetail) => void;\ntype SelectionListener = () => void;\n\n/**\n * 极小的不可变 store + 发布订阅 + history。\n * 所有变更都通过 `update(fn)` 走结构化克隆,保证:\n * - 引用不可变(外部 memo/diff 友好)\n * - 变更原子(一个 update 一条 history)\n */\nexport class Store {\n private _doc: EmailDoc;\n private _selection: Selection | null = null;\n private _listeners: Set<Listener> = new Set();\n private _selectionListeners: Set<SelectionListener> = new Set();\n private _past: EmailDoc[] = [];\n private _future: EmailDoc[] = [];\n private _historyLimit = 100;\n\n constructor(initial: EmailDoc) {\n this._doc = initial;\n }\n\n get doc(): EmailDoc {\n return this._doc;\n }\n\n get selection(): Selection | null {\n return this._selection;\n }\n\n subscribe(fn: Listener): () => void {\n this._listeners.add(fn);\n return () => this._listeners.delete(fn);\n }\n\n subscribeSelection(fn: SelectionListener): () => void {\n this._selectionListeners.add(fn);\n return () => this._selectionListeners.delete(fn);\n }\n\n setSelection(sel: Selection | null) {\n this._selection = sel;\n this._selectionListeners.forEach((l) => l());\n }\n\n /**\n * 应用一次变更。`mutator` 收到一份可直接修改的 draft(结构化克隆得来)。\n * 修改完毕后用新对象替换当前 doc,并把旧 doc 入历史。\n */\n update(mutator: (draft: EmailDoc) => void, opts: { silent?: boolean } = {}) {\n const draft = structuredClone(this._doc);\n mutator(draft);\n this._past.push(this._doc);\n if (this._past.length > this._historyLimit) this._past.shift();\n this._future = [];\n this._doc = draft;\n if (!opts.silent) this._notify('mutate');\n }\n\n /** 替换整个文档(如外部 setValue),会清空 history。 */\n replace(doc: EmailDoc) {\n this._past = [];\n this._future = [];\n this._doc = doc;\n this._notify('replace');\n }\n\n undo(): boolean {\n const prev = this._past.pop();\n if (!prev) return false;\n this._future.push(this._doc);\n this._doc = prev;\n this._notify('history');\n return true;\n }\n\n redo(): boolean {\n const next = this._future.pop();\n if (!next) return false;\n this._past.push(this._doc);\n this._doc = next;\n this._notify('history');\n return true;\n }\n\n canUndo() {\n return this._past.length > 0;\n }\n\n canRedo() {\n return this._future.length > 0;\n }\n\n private _notify(source: DocChangedDetail['source']) {\n const detail: DocChangedDetail = { source };\n this._listeners.forEach((l) => l(detail));\n }\n}\n\n/* -------------------------------------------------------------------------- */\n/* 便捷的查询/变更助手 */\n/* -------------------------------------------------------------------------- */\n\nexport function findSection(doc: EmailDoc, sectionId: string): Section | undefined {\n return doc.sections.find((s) => s.id === sectionId);\n}\n\nexport function findBlockLocation(\n doc: EmailDoc,\n blockId: string,\n): { section: Section; columnIndex: number; block: Block } | undefined {\n for (const section of doc.sections) {\n for (let i = 0; i < section.columns.length; i += 1) {\n const col = section.columns[i];\n const blk = col.blocks.find((b) => b.id === blockId);\n if (blk) return { section, columnIndex: i, block: blk };\n }\n }\n return undefined;\n}\n\n/**\n * 若指定 Section 的每一列都没有 Block,则从文档中移除该 Section。\n * 在内容块被删除或拖走后调用,可与 `autoWrapSection` 搭配,避免单列 Section 在唯一块离场后仍残留空壳;\n * 多列 Section 始终保留,便于继续向各列拖入内容。\n * 仅处理刚变空的 Section,不会误删用户事先添加、尚未拖入内容的空布局。\n */\nexport function pruneSectionIfEmpty(draft: EmailDoc, sectionId: string) {\n const sec = draft.sections.find((s) => s.id === sectionId);\n if (!sec) return;\n if (sec.columns.length > 1) return;\n const isEmpty = sec.columns.every((col) => col.blocks.length === 0);\n if (!isEmpty) return;\n draft.sections = draft.sections.filter((s) => s.id !== sectionId);\n}\n\n/** @deprecated 请改用 {@link pruneSectionIfEmpty},避免误删多个空 Section */\nexport function pruneEmptySections(draft: EmailDoc) {\n draft.sections = draft.sections.filter((sec) =>\n sec.columns.some((col) => col.blocks.length > 0),\n );\n}\n\n/** 两列 Section 的列宽比例(左栏拖入默认 `1-1`,右栏可改为 `1-2` / `2-1`) */\nexport const TWO_COLUMN_LAYOUTS = ['1-1', '1-2', '2-1'] as const;\nexport type TwoColumnLayout = (typeof TWO_COLUMN_LAYOUTS)[number];\n\nexport function isTwoColumnLayout(layout: SectionLayout): layout is TwoColumnLayout {\n return layout === '1-1' || layout === '1-2' || layout === '2-1';\n}\n\n/** 仅更新 layout 字段;两列间切换时列数不变,列内块按列下标保留 */\nexport function setSectionLayout(section: Section, layout: SectionLayout): void {\n const nextCols = layout.split('-').length;\n const curCols = section.columns.length;\n if (nextCols === curCols) {\n section.layout = layout;\n return;\n }\n if (nextCols > curCols) {\n for (let i = curCols; i < nextCols; i++) {\n section.columns.push({ id: uid('col'), attrs: {}, blocks: [] });\n }\n } else {\n const removed = section.columns.splice(nextCols);\n const last = section.columns[nextCols - 1];\n if (last) {\n for (const col of removed) last.blocks.push(...col.blocks);\n }\n }\n section.layout = layout;\n}\n\nexport function createSection(layout: SectionLayout): Section {\n const colCount = layout.split('-').length;\n const columns: Column[] = Array.from({ length: colCount }, () => ({\n id: uid('col'),\n attrs: {},\n blocks: [],\n }));\n return {\n id: uid('sec'),\n type: 'section',\n layout,\n attrs: {\n /** 默认左右 16:版心内边距由节承担;上下 0 由内容块堆叠节奏(常见 8)控制 */\n paddingTop: 0,\n paddingRight: 16,\n paddingBottom: 0,\n paddingLeft: 16,\n },\n columns,\n };\n}\n","import type { SectionLayout } from '../types';\n\nconst LAYOUT_LABELS: Record<SectionLayout, string> = {\n '1': '一列',\n '1-1': '两列',\n '1-2': '1:2',\n '2-1': '2:1',\n '1-1-1': '三列',\n};\n\nexport function layoutHumanLabel(layout: SectionLayout): string {\n return LAYOUT_LABELS[layout] ?? layout;\n}\n","/**\n * 极轻量 HTML 格式化器(约 50 行)。\n *\n * 不追求 100% 通用,但对邮件 HTML(table 嵌套、inline style、无脚本)非常稳定:\n * - 按 `<` 切 token,识别开标签 / 闭标签 / 自闭合 / 注释 / DOCTYPE\n * - 维护 depth 控制缩进\n * - void 元素与 self-closing 不增加 depth\n * - <pre> / <textarea> 内的换行不二次处理(保留原样)\n */\nexport function prettyHtml(html: string, indent = ' '): string {\n if (!html) return '';\n const VOID = new Set([\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n ]);\n const PRESERVE = new Set(['pre', 'textarea', 'script', 'style']);\n\n const tokens = html.match(/<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|<![^>]*>|<\\/?[^<>]+>|[^<]+/g) ?? [];\n let depth = 0;\n let preserveStack: string[] = [];\n const out: string[] = [];\n const pad = (n: number) => indent.repeat(Math.max(0, n));\n\n for (const raw of tokens) {\n const tok = raw;\n const inPreserve = preserveStack.length > 0;\n\n if (tok.startsWith('<!--') || tok.startsWith('<![')) {\n if (inPreserve) out.push(tok);\n else out.push(pad(depth) + tok.trim());\n continue;\n }\n if (tok.startsWith('<!')) {\n out.push(tok.trim());\n continue;\n }\n\n if (tok.startsWith('</')) {\n const tag = (tok.match(/^<\\/([\\w-]+)/) ?? [])[1]?.toLowerCase();\n if (preserveStack[preserveStack.length - 1] === tag) {\n preserveStack.pop();\n out.push(tok);\n continue;\n }\n depth = Math.max(0, depth - 1);\n out.push(pad(depth) + tok.trim());\n continue;\n }\n\n if (tok.startsWith('<')) {\n const tag = (tok.match(/^<([\\w-]+)/) ?? [])[1]?.toLowerCase();\n const selfClosing = tok.endsWith('/>') || (tag && VOID.has(tag));\n if (inPreserve) {\n out.push(tok);\n if (tag && PRESERVE.has(tag) && !selfClosing) preserveStack.push(tag);\n continue;\n }\n out.push(pad(depth) + tok.trim());\n if (tag && !selfClosing) {\n if (PRESERVE.has(tag)) preserveStack.push(tag);\n else depth += 1;\n }\n continue;\n }\n\n // 文本\n if (inPreserve) {\n out.push(tok);\n } else {\n const txt = tok.replace(/\\s+/g, ' ').trim();\n if (txt) out.push(pad(depth) + txt);\n }\n }\n\n return out.join('\\n');\n}\n","import { h } from '../utils/dom';\n\n/**\n * 极简 Modal:遮罩 + 居中卡片 + header/body/footer 三段。\n * - 自带 Esc / 点遮罩 关闭\n * - 不锁 body scroll(邮件编辑器场景内通常已经接管了高度)\n * - 不依赖框架,保持 vanilla\n */\nexport interface ModalOptions {\n title: string;\n /** 卡片宽度 / 高度。可传 'auto' / px / % */\n width?: string;\n height?: string;\n /** 自定义类名,便于覆盖样式(如 sm-modal--preview) */\n className?: string;\n /** 关闭回调;用户取消、Esc、点遮罩时触发 */\n onClose?: () => void;\n}\n\nexport class Modal {\n el: HTMLElement;\n private mask: HTMLElement;\n private card: HTMLElement;\n private headerEl: HTMLElement;\n private bodyEl: HTMLElement;\n private footerEl: HTMLElement;\n private opts: ModalOptions;\n private keydownHandler?: (e: KeyboardEvent) => void;\n\n constructor(opts: ModalOptions) {\n this.opts = opts;\n\n this.mask = h('div', {\n class: 'sm-modal__mask',\n onclick: (e: Event) => {\n if (e.target === this.mask) this._handleClose();\n },\n });\n\n this.headerEl = h('header', { class: 'sm-modal__header' });\n this.bodyEl = h('div', { class: 'sm-modal__body' });\n this.footerEl = h('footer', { class: 'sm-modal__footer' });\n\n this.card = h(\n 'div',\n {\n class: `sm-modal__card ${opts.className ?? ''}`,\n style: [\n opts.width ? `width:${opts.width};` : '',\n opts.height ? `height:${opts.height};` : '',\n ].join(''),\n },\n [this.headerEl, this.bodyEl, this.footerEl],\n );\n\n this.mask.append(this.card);\n this.el = this.mask;\n\n this._renderHeader();\n }\n\n open(parent: HTMLElement = document.body) {\n parent.append(this.el);\n this.keydownHandler = (e: KeyboardEvent) => {\n if (e.key === 'Escape') this._handleClose();\n };\n document.addEventListener('keydown', this.keydownHandler);\n requestAnimationFrame(() => this.el.classList.add('is-open'));\n }\n\n close() {\n this._handleClose();\n }\n\n setTitle(title: string) {\n this.opts.title = title;\n this._renderHeader();\n }\n\n /** body 容器直接给外部填充 */\n get body(): HTMLElement {\n return this.bodyEl;\n }\n\n /** footer 容器直接给外部填充按钮等 */\n get footer(): HTMLElement {\n return this.footerEl;\n }\n\n /** 在 header 右侧追加自定义工具按钮 */\n appendHeaderTool(el: HTMLElement) {\n const tools = this.headerEl.querySelector('.sm-modal__header-tools');\n tools?.append(el);\n }\n\n private _renderHeader() {\n this.headerEl.innerHTML = '';\n const title = h('div', { class: 'sm-modal__title' }, [this.opts.title]);\n const tools = h('div', { class: 'sm-modal__header-tools' });\n const closeBtn = h(\n 'button',\n {\n class: 'sm-modal__close',\n type: 'button',\n title: '关闭 Esc',\n onclick: () => this._handleClose(),\n },\n [iconClose()],\n );\n this.headerEl.append(title, tools, closeBtn);\n }\n\n private _handleClose() {\n if (this.keydownHandler) document.removeEventListener('keydown', this.keydownHandler);\n this.el.classList.remove('is-open');\n setTimeout(() => this.el.remove(), 180);\n this.opts.onClose?.();\n }\n}\n\nfunction iconClose(): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '16');\n el.setAttribute('height', '16');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML =\n '<path d=\"M5 5l10 10M15 5L5 15\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>';\n return el;\n}\n","import { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport { EditorState } from '@codemirror/state';\nimport type { Registry } from '../registry/registry';\nimport { findBlockLocation } from '../store/store';\nimport type { Store } from '../store/store';\nimport { h } from '../utils/dom';\nimport { prettyHtml } from '../utils/html';\nimport { Modal } from './Modal';\n\nexport interface BlockCodeModalOptions {\n store: Store;\n registry: Registry;\n /** 须落在 MailEditor `.sm-root` 子树内,才能继承 `--sm-code-bg` 等变量 */\n mountParent: HTMLElement;\n}\n\n/**\n * 画布内快速编辑单个 Block 的 MJML:与右栏「代码」Tab 行为一致(写入 lockedMjml)。\n */\nexport class BlockCodeModal {\n private opts: BlockCodeModalOptions;\n private modal: Modal;\n private editorHost: HTMLElement;\n private cm: EditorView | null = null;\n private blockId: string | null = null;\n\n constructor(opts: BlockCodeModalOptions) {\n this.opts = opts;\n this.modal = new Modal({\n title: '编辑组件代码',\n className: 'sm-modal--block-code',\n width: 'min(720px, 92vw)',\n height: 'min(560px, 85vh)',\n onClose: () => this._destroyCm(),\n });\n this.editorHost = h('div', { class: 'sm-export__editor' });\n this.modal.body.append(this.editorHost);\n\n const beautifyBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: () => this._beautify() },\n ['美化'],\n );\n const saveBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onclick: () => this._saveAndClose(),\n },\n ['保存'],\n );\n this.modal.footer.append(beautifyBtn, saveBtn);\n }\n\n open(blockId: string, componentLabel: string) {\n const doc = this.opts.store.doc;\n const loc = findBlockLocation(doc, blockId);\n if (!loc) return;\n\n this._destroyCm();\n this.blockId = blockId;\n const block = loc.block;\n const def = this.opts.registry.get(block.type);\n const initial =\n block.lockedMjml ??\n (def ? def.toMjml(block.props as Record<string, unknown>, { doc, engine: 'mjml' }) : '');\n\n this.modal.setTitle(`编辑组件代码 · ${componentLabel}`);\n this.cm = new EditorView({\n parent: this.editorHost,\n state: EditorState.create({\n doc: initial,\n extensions: [basicSetup, cmHtml()],\n }),\n });\n this.modal.open(this.opts.mountParent);\n }\n\n destroy() {\n this._destroyCm();\n if (this.modal.el.parentElement) this.modal.close();\n }\n\n private _beautify() {\n if (!this.cm) return;\n const text = prettyHtml(this.cm.state.doc.toString());\n this.cm.dispatch({\n changes: { from: 0, to: this.cm.state.doc.length, insert: text },\n });\n }\n\n private _saveAndClose() {\n if (!this.cm || !this.blockId) return;\n const text = this.cm.state.doc.toString();\n const id = this.blockId;\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, id);\n if (l) l.block.lockedMjml = text;\n });\n this.modal.close();\n }\n\n private _destroyCm() {\n if (this.cm) {\n this.cm.destroy();\n this.cm = null;\n }\n this.blockId = null;\n }\n}\n","/**\n * contenteditable 富文本仍依赖 Document.execCommand / queryCommand* 系列 API。\n * 浏览器与 TypeScript lib.dom 虽已标记 deprecated,但目前无等价替代;集中封装便于 IDE 消警与日后迁移。\n */\nexport interface RichTextDocument extends Document {\n execCommand(commandId: string, showUI?: boolean, value?: string): boolean;\n queryCommandState(commandId: string): boolean;\n queryCommandValue(commandId: string): string;\n}\n\nfunction asRichTextDoc(doc: Document = document): RichTextDocument {\n return doc as RichTextDocument;\n}\n\nexport function richTextExecCommand(\n commandId: string,\n showUI = false,\n value?: string,\n doc: Document = document,\n): boolean {\n return asRichTextDoc(doc).execCommand(commandId, showUI, value);\n}\n\nexport function richTextQueryCommandState(commandId: string, doc: Document = document): boolean {\n return asRichTextDoc(doc).queryCommandState(commandId);\n}\n\nexport function richTextQueryCommandValue(commandId: string, doc: Document = document): string {\n return asRichTextDoc(doc).queryCommandValue(commandId);\n}\n","/**\n * 邮件编辑器品牌/主题色:写入 .sm-root 的 --sm-primary / --sm-primary-soft。\n */\n\n/** 合法则规范为 #RRGGBB(大写),否则 null */\nexport function normalizeAccentHex(input: string): string | null {\n const t = input.trim();\n if (!t) return null;\n const h = t.replace(/^#/, '');\n if (/^[0-9a-fA-F]{3}$/.test(h)) {\n return `#${(h[0] + h[0] + h[1] + h[1] + h[2] + h[2]).toUpperCase()}`;\n }\n if (/^[0-9a-fA-F]{6}$/.test(h)) {\n return `#${h.toUpperCase()}`;\n }\n return null;\n}\n\n/** 由 getComputedStyle 得到的 rgb(...) / rgba(...) 转 #rrggbb */\nexport function rgbCssToHex(rgb: string): string | null {\n const m = rgb.trim().match(/^rgba?\\((\\d+),\\s*(\\d+),\\s*(\\d+)/);\n if (!m) return null;\n const h = (n: string) => Number(n).toString(16).padStart(2, '0');\n return `#${h(m[1])}${h(m[2])}${h(m[3])}`;\n}\n\n/**\n * 与浅色/深色界面配套的浅底强调色(选区、滑块 accent 等)。\n */\nexport function accentPrimarySoftRgba(primaryHex: string, isDarkChrome: boolean): string {\n const hex = normalizeAccentHex(primaryHex);\n if (!hex) return isDarkChrome ? 'rgba(129, 140, 248, 0.18)' : 'rgba(79, 70, 229, 0.12)';\n const r = parseInt(hex.slice(1, 3), 16);\n const g = parseInt(hex.slice(3, 5), 16);\n const b = parseInt(hex.slice(5, 7), 16);\n const a = isDarkChrome ? 0.22 : 0.14;\n return `rgba(${r},${g},${b},${a})`;\n}\n","import { normalizeAccentHex } from '../utils/accentColor';\nimport { h } from '../utils/dom';\n\n/** 邮件常用预设色 */\nexport const COLOR_PICKER_PALETTE = [\n '#FFFFFF',\n '#F5F6F8',\n '#E6E8EC',\n '#9AA0A6',\n '#6B7280',\n '#433F3F',\n '#1F2328',\n '#000000',\n '#DC2626',\n '#EA580C',\n '#FF5A00',\n '#CA8A04',\n '#16A34A',\n '#059669',\n '#2563EB',\n '#4F46E5',\n '#7C3AED',\n '#DB2777',\n '#FEE2E2',\n '#FFEDD5',\n '#FEF3C7',\n '#D1FAE5',\n '#EEF2FF',\n '#F3E8FF',\n] as const;\n\nexport interface ColorPickerPopoverOptions {\n anchor: HTMLElement;\n layerRoot: HTMLElement;\n value: string;\n placeholder?: string;\n /** 显示「清除」并允许提交空值 */\n allowClear?: boolean;\n /** 每次改色立即 onCommit(富文本/顶栏) */\n liveCommit?: boolean;\n onPreview?: (hex: string) => void;\n onCommit: (hex: string) => void;\n onClear?: () => void;\n /** 打开前调用(富文本:在失焦前保存选区) */\n onBeforeOpen?: () => void;\n /** 为 false 时不自动 focus 十六进制输入,避免抢编辑区选区 */\n autoFocusHex?: boolean;\n onClosed?: () => void;\n}\n\nlet activeTeardown: (() => void) | null = null;\n\nexport function isColorPickerOpen(): boolean {\n return activeTeardown !== null;\n}\n\nexport function closeActiveColorPicker(): void {\n activeTeardown?.();\n activeTeardown = null;\n}\n\nfunction positionLayer(layer: HTMLElement, anchor: HTMLElement, layerRoot: HTMLElement) {\n const rect = anchor.getBoundingClientRect();\n const rootRect = layerRoot.getBoundingClientRect();\n layer.style.top = `${rect.bottom - rootRect.top + 4}px`;\n layer.style.left = `${Math.max(4, rect.left - rootRect.left)}px`;\n\n requestAnimationFrame(() => {\n const popRect = layer.getBoundingClientRect();\n if (popRect.right > rootRect.right - 8) {\n layer.style.left = `${Math.max(4, parseFloat(layer.style.left) - (popRect.right - rootRect.right + 8))}px`;\n }\n if (popRect.bottom > window.innerHeight - 8) {\n layer.style.top = `${rect.top - rootRect.top - popRect.height - 4}px`;\n }\n });\n}\n\n/** 点击色块网格缝隙等无焦点区域时,避免编辑区 blur 导致误提交 */\nfunction guardInlineEditFocus(layer: HTMLElement) {\n layer.addEventListener(\n 'mousedown',\n (e) => {\n const t = e.target as Element;\n if (t.closest('input, button, select, textarea, a, [contenteditable]')) return;\n e.preventDefault();\n },\n true,\n );\n}\n\nfunction syncNativeInput(native: HTMLInputElement, hex: string) {\n const n = normalizeAccentHex(hex);\n if (n) native.value = n;\n}\n\n/** 打开自定义色板(含关闭按钮);点击色卡触发,不再使用系统色板。 */\nexport function openColorPickerPopover(opts: ColorPickerPopoverOptions): void {\n closeActiveColorPicker();\n opts.onBeforeOpen?.();\n\n const initialHex = normalizeAccentHex(opts.value);\n let draft = initialHex ?? '#4F46E5';\n let closed = false;\n\n const layer = h('div', {\n class: 'sm-color-picker-layer',\n 'data-sm-color-picker-layer': '',\n });\n const panel = h('div', {\n class: 'sm-color-picker',\n role: 'dialog',\n 'aria-label': '选择颜色',\n });\n\n const closeBtn = h(\n 'button',\n {\n class: 'sm-color-picker__close',\n type: 'button',\n title: '关闭',\n 'aria-label': '关闭',\n },\n ['×'],\n );\n\n const head = h('div', { class: 'sm-color-picker__head' }, [\n h('span', { class: 'sm-color-picker__title' }, ['选择颜色']),\n closeBtn,\n ]);\n\n const native = h('input', {\n class: 'sm-color-picker__native',\n type: 'color',\n 'aria-label': '自定义颜色',\n }) as HTMLInputElement;\n\n const hexInput = h('input', {\n class: 'sm-input sm-color-picker__hex',\n type: 'text',\n placeholder: opts.placeholder ?? '#RRGGBB',\n }) as HTMLInputElement;\n\n const applyDraft = (hex: string, commit: boolean) => {\n const n = normalizeAccentHex(hex);\n if (!n) return;\n draft = n;\n syncNativeInput(native, n);\n hexInput.value = n;\n opts.onPreview?.(n);\n if (commit || opts.liveCommit) opts.onCommit(n);\n };\n\n syncNativeInput(native, draft);\n hexInput.value = initialHex ?? '';\n\n const teardown = (commit: boolean) => {\n if (closed) return;\n closed = true;\n activeTeardown = null;\n document.removeEventListener('keydown', onKey, true);\n document.removeEventListener('mousedown', onDoc, true);\n layer.remove();\n if (commit && !opts.liveCommit) {\n const n = normalizeAccentHex(draft);\n if (n) opts.onCommit(n);\n }\n opts.onClosed?.();\n };\n\n const swatchGrid = h('div', { class: 'sm-color-picker__swatches' });\n for (const hex of COLOR_PICKER_PALETTE) {\n const btn = h('button', {\n class: 'sm-color-picker__swatch',\n type: 'button',\n title: `${hex}(双击确认)`,\n style: `background:${hex}`,\n 'aria-label': hex,\n });\n btn.addEventListener('click', () => applyDraft(hex, false));\n btn.addEventListener('dblclick', (e) => {\n e.preventDefault();\n applyDraft(hex, true);\n teardown(true);\n });\n swatchGrid.append(btn);\n }\n\n native.addEventListener('input', () => applyDraft(native.value, false));\n\n hexInput.addEventListener('input', () => {\n const n = normalizeAccentHex(hexInput.value);\n if (n) applyDraft(n, false);\n });\n hexInput.addEventListener('keydown', (e) => {\n const ke = e as KeyboardEvent;\n if (ke.key === 'Enter') {\n ke.preventDefault();\n const n = normalizeAccentHex(hexInput.value);\n if (n) {\n applyDraft(n, true);\n teardown(true);\n }\n }\n });\n\n const footKids: HTMLElement[] = [];\n if (opts.allowClear) {\n footKids.push(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost sm-color-picker__clear',\n type: 'button',\n onclick: () => {\n opts.onClear?.();\n teardown(false);\n },\n },\n ['清除'],\n ),\n );\n }\n\n panel.append(head, swatchGrid, native, hexInput);\n if (footKids.length) panel.append(h('div', { class: 'sm-color-picker__foot' }, footKids));\n\n layer.append(panel);\n guardInlineEditFocus(layer);\n opts.layerRoot.append(layer);\n positionLayer(layer, opts.anchor, opts.layerRoot);\n\n closeBtn.addEventListener('click', (e) => {\n e.preventDefault();\n teardown(true);\n });\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n if (initialHex) opts.onPreview?.(initialHex);\n teardown(false);\n }\n };\n\n const onDoc = (ev: MouseEvent) => {\n const t = ev.target as Node;\n if (layer.contains(t) || opts.anchor.contains(t)) return;\n teardown(true);\n };\n\n document.addEventListener('keydown', onKey, true);\n setTimeout(() => document.addEventListener('mousedown', onDoc, true), 0);\n\n activeTeardown = () => teardown(true);\n if (opts.autoFocusHex !== false) hexInput.focus();\n}\n\nexport interface BindColorPickerInputOptions\n extends Omit<ColorPickerPopoverOptions, 'anchor' | 'layerRoot' | 'value'> {\n layerRoot?: HTMLElement;\n getValue?: () => string;\n}\n\n/** 拦截色卡点击,改为打开自定义色板。 */\nexport function bindColorPickerInput(\n pick: HTMLInputElement,\n opts: BindColorPickerInputOptions,\n): void {\n if (!pick.title) pick.title = '点击打开色板;预设色块可双击快速确认';\n\n pick.addEventListener('mousedown', (e) => {\n e.preventDefault();\n opts.onBeforeOpen?.();\n });\n\n pick.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n const layerRoot =\n opts.layerRoot ?? (pick.closest('.sm-root') as HTMLElement | null) ?? document.body;\n const value = opts.getValue?.() ?? pick.value;\n openColorPickerPopover({\n ...opts,\n anchor: pick,\n layerRoot,\n value,\n });\n });\n}\n","/**\n * 把任意 DOM 元素临时变成 contenteditable,并暴露提交/取消/选区事件。\n *\n * 设计要点:\n * - 不直接同步到 store。编辑过程中只在本地累积,提交(blur / Esc / 单行 Enter)时一次性回调,\n * 避免每次按键都触发画布全量重渲染导致光标丢失。\n * - mode=plain 时仅取 textContent,并在 paste/keydown 上拦截换行;\n * mode=rich 时保留 inline HTML,但会在提交时做一次清理(白名单标签 + inline style);\n * mode=html 时提交原始 innerHTML(用于 mj-raw 等),不挂富文本浮动条。\n * - 选区变化通过 `onSelectionChange` 实时回调,便于浮动工具条同步按钮状态/位置。\n */\nimport { normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport {\n richTextExecCommand,\n richTextQueryCommandState,\n richTextQueryCommandValue,\n} from '../utils/richTextCommand';\nimport { isColorPickerOpen } from './ColorPickerPopover';\n\nexport interface InlineEditorOptions {\n el: HTMLElement;\n initialValue: string;\n mode: 'rich' | 'plain' | 'html';\n multiline: boolean;\n placeholder?: string;\n onCommit: (value: string) => void;\n onCancel: () => void;\n onSelectionChange?: (state: SelectionState | null) => void;\n}\n\nexport interface SelectionState {\n hasSelection: boolean;\n rect: DOMRect | null;\n /** queryCommandState 的若干常用值,用于工具条按钮高亮 */\n formats: {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strikethrough: boolean;\n unorderedList: boolean;\n orderedList: boolean;\n align: 'left' | 'center' | 'right' | 'justify' | null;\n link: string | null;\n foreColor: string | null;\n fontSize: string | null;\n fontName: string | null;\n fontWeight: string | null;\n backColor: string | null;\n };\n}\n\nexport class InlineEditor {\n private opts: InlineEditorOptions;\n private el: HTMLElement;\n private listeners: Array<() => void> = [];\n private committed = false;\n private originalContent: string;\n /** 防止 selectionchange 在我们 destroy 之后还回调 */\n private alive = true;\n /**\n * 上一次\"用户在编辑区内\"时的有效选区。\n * 当用户去工具条点 select / input 时焦点会离开 contenteditable,\n * execCommand 在那种状态下会哑火——必须先 focus 回来,再恢复选区,再执行命令。\n */\n private savedRange: Range | null = null;\n /** 富文本工具条控件会抢走焦点,此时 getSelection 已不在编辑区内;保留上一帧状态避免工具条整栏收起。 */\n private lastSelectionState: SelectionState | null = null;\n /** hiliteColor 在输入前不写 DOM;记录「待输入背景色 + 锚点」以便 bar 即时同步,移开光标后清除 */\n private pendingHiliteColor: string | null = null;\n private pendingHiliteAnchor: string | null = null;\n\n constructor(opts: InlineEditorOptions) {\n this.opts = opts;\n this.el = opts.el;\n this.originalContent = this.el.innerHTML;\n this._mount();\n }\n\n /** 立即提交并销毁。 */\n commit() {\n if (this.committed) return;\n this.committed = true;\n const value =\n this.opts.mode === 'plain'\n ? (this.el.textContent ?? '').replace(/\\s+\\n/g, '\\n').trim()\n : this.opts.mode === 'html'\n ? this.el.innerHTML\n : sanitizeRichHtml(this.el.innerHTML);\n this.opts.onCommit(value);\n this.destroy(false);\n }\n\n /** 放弃编辑、还原 DOM 并销毁。 */\n cancel() {\n if (this.committed) return;\n this.committed = true;\n this.el.innerHTML = this.originalContent;\n this.opts.onCancel();\n this.destroy(false);\n }\n\n destroy(restore = true) {\n if (!this.alive) return;\n this.alive = false;\n this.listeners.forEach((off) => off());\n this.listeners = [];\n this.el.removeAttribute('contenteditable');\n this.el.classList.remove('sm-inline-editing');\n if (restore && !this.committed) this.el.innerHTML = this.originalContent;\n }\n\n /**\n * 保存当前在编辑区内的选区。Toolbar 在 mousedown(capture)阶段调用:\n * 在浏览器把焦点切到 select/input 之前抢先存档。\n */\n saveSelection() {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (!this.el.contains(range.startContainer) || !this.el.contains(range.endContainer)) return;\n this.savedRange = range.cloneRange();\n }\n\n /** 直接对当前选区执行命令(供 Toolbar 调用)。 */\n exec(command: string, value?: string) {\n this._ensureFocus();\n this._restoreSelection();\n const sel = window.getSelection();\n let hiliteAnchor: string | null = null;\n if (command === 'hiliteColor' && sel?.rangeCount) {\n hiliteAnchor = selectionAnchorKey(sel.getRangeAt(0));\n }\n // 列表:Chrome 等在 styleWithCSS=true 下 insertOrderedList / insertUnorderedList 常失灵,需退回 HTML 列表标签\n const isListCmd = command === 'insertOrderedList' || command === 'insertUnorderedList';\n richTextExecCommand('styleWithCSS', false, isListCmd ? 'false' : 'true');\n richTextExecCommand(command, false, value);\n if (command === 'hiliteColor') {\n this.pendingHiliteColor = value ?? null;\n this.pendingHiliteAnchor = hiliteAnchor;\n }\n // 命令执行后选区可能已经变化(例如插入链接会扩展),刷新存档\n this.saveSelection();\n this._emitSelection();\n }\n\n /**\n * 设置或移除超链接:已有 &lt;a&gt; 则改 href;否则 createLink。\n * (仅用 createLink 在链接内需改 URL 时浏览器行为不一致。)\n */\n setLink(url: string) {\n this._ensureFocus();\n this._restoreSelection();\n const trimmed = url.trim();\n if (!trimmed) {\n richTextExecCommand('unlink');\n this.saveSelection();\n this._emitSelection();\n return;\n }\n const safe = /^https?:|^mailto:|^tel:|^\\{\\{/i.test(trimmed) ? trimmed : `https://${trimmed}`;\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const anchor = findAncestorAnchor(sel.anchorNode, this.el);\n if (anchor) {\n anchor.setAttribute('href', safe);\n if (!anchor.getAttribute('rel')) anchor.setAttribute('rel', 'noopener');\n } else {\n richTextExecCommand('styleWithCSS', false, 'true');\n richTextExecCommand('createLink', false, safe);\n }\n this.saveSelection();\n this._emitSelection();\n }\n\n /** 在当前光标处插入纯文本(供\"插入变量\"使用)。 */\n insertText(text: string) {\n this._ensureFocus();\n this._restoreSelection();\n richTextExecCommand('insertText', false, text);\n this.saveSelection();\n }\n\n /** Toolbar 关闭某个面板/控件后调用,把选区还给编辑区,方便用户继续输入。 */\n refocus() {\n this._ensureFocus();\n this._restoreSelection();\n }\n\n /** 字号:走原生 fontSize 命令(styleWithCSS 下浏览器会写 span),与 foreColor 同类 */\n applyFontSize(px: string) {\n this.exec('fontSize', pxToLegacyFontSize(px));\n }\n\n /**\n * 字重:浏览器只有 bold 命令,没有 font-weight:500/600 的原生 API,需包 span。\n * 有选区包裹内容;折叠光标插入 typing span,后续输入沿用。\n */\n applyFontWeight(weight: string) {\n this._ensureFocus();\n this._restoreSelection();\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return;\n const range = sel.getRangeAt(0);\n if (!this.el.contains(range.startContainer) || !this.el.contains(range.endContainer)) return;\n\n if (!range.collapsed) {\n const span = document.createElement('span');\n span.setAttribute('style', `font-weight:${weight};`);\n try {\n span.appendChild(range.extractContents());\n range.insertNode(span);\n const newRange = document.createRange();\n newRange.selectNodeContents(span);\n sel.removeAllRanges();\n sel.addRange(newRange);\n } catch {\n return;\n }\n } else {\n const span = document.createElement('span');\n span.setAttribute('style', `font-weight:${weight};`);\n span.appendChild(document.createTextNode('\\u200b'));\n range.insertNode(span);\n const caret = document.createRange();\n caret.setStart(span.firstChild!, 1);\n caret.collapse(true);\n sel.removeAllRanges();\n sel.addRange(caret);\n }\n\n this.saveSelection();\n this._emitSelection();\n }\n\n /** 内联编辑根节点(如 `.sm-text-content`)的盒模型矩形,供富文本条贴在正文区域外沿定位 */\n getAnchorRect(): DOMRect {\n return this.el.getBoundingClientRect();\n }\n\n private _restoreSelection() {\n if (!this.savedRange) return;\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(this.savedRange);\n }\n\n /* -------------------------------- 内部 ---------------------------------- */\n\n private _mount() {\n const { el, mode, multiline, placeholder } = this.opts;\n el.setAttribute('contenteditable', 'true');\n el.classList.add('sm-inline-editing');\n if (placeholder) el.setAttribute('data-placeholder', placeholder);\n\n if (this.opts.initialValue) {\n el.innerHTML =\n mode === 'plain' ? escapeHtml(this.opts.initialValue) : this.opts.initialValue;\n }\n\n // 初始聚焦并把光标移到末尾,便于\"双击 → 直接输入\"\n requestAnimationFrame(() => {\n el.focus();\n placeCaretAtEnd(el);\n });\n\n let imeComposing = false;\n /** 部分浏览器在 compositionend 之后才派发 Enter keydown,需吞掉紧随其后的这一次 */\n let suppressNextEnter = false;\n\n const onCompositionStart = () => {\n imeComposing = true;\n };\n const onCompositionEnd = () => {\n imeComposing = false;\n suppressNextEnter = true;\n };\n\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.cancel();\n return;\n }\n if (e.key === 'Enter') {\n // 拼音等 IME 用 Enter 上屏:不可 preventDefault / insertLineBreak\n if (e.isComposing || imeComposing || e.keyCode === 229) return;\n if (suppressNextEnter) {\n suppressNextEnter = false;\n return;\n }\n if (!multiline) {\n e.preventDefault();\n this.commit();\n return;\n }\n // 多行下,回车默认会插入 <div> / <br>。强制 <br>,避免出现各种奇怪嵌套。\n e.preventDefault();\n richTextExecCommand('insertLineBreak');\n }\n };\n const onBlur = (e: FocusEvent) => {\n // 给点钟摆余地,避免点击工具条按钮时立刻提交\n setTimeout(() => {\n if (!this.alive) return;\n const active = document.activeElement as HTMLElement | null;\n if (active && (active === el || el.contains(active))) return;\n if (isColorPickerOpen()) return;\n if (active?.closest?.('.sm-floating-toolbar, .sm-color-picker, .sm-color-picker-layer')) return;\n // 从左栏拖入 / 画布内 Sortable 排序:mousedown 会先 blur,若在此时提交会触发画布重渲染并拆掉 drop 目标\n if (active?.closest?.('.sm-panel--left')) return;\n if (active?.closest?.('.sm-block__handle, .sm-section__handle')) return;\n const related = e.relatedTarget as HTMLElement | null;\n if (related?.closest?.('.sm-panel--left')) return;\n if (related?.closest?.('.sm-block-card')) return;\n if (related?.closest?.('.sm-block__handle, .sm-section__handle')) return;\n if (related?.closest?.('.sm-color-picker, .sm-color-picker-layer')) return;\n if (document.querySelector('.sm-root .sm-drag, .sm-root .sm-chosen')) return;\n this.commit();\n }, 0);\n };\n const onPaste = (e: ClipboardEvent) => {\n if (mode !== 'plain') return;\n e.preventDefault();\n const text = e.clipboardData?.getData('text/plain') ?? '';\n const safe = multiline ? text : text.replace(/\\r?\\n/g, ' ');\n richTextExecCommand('insertText', false, safe);\n };\n const onSelChange = () => {\n if (!this.alive) return;\n this._syncPendingHiliteAnchor();\n this.saveSelection();\n this._emitSelection();\n };\n\n const linkInsideEditing = (t: EventTarget | null): HTMLAnchorElement | null => {\n if (!(t instanceof Element)) return null;\n const a = t.closest('a');\n if (!a || !el.contains(a)) return null;\n const href = a.getAttribute('href');\n if (href == null || href === '' || href === '#') return null;\n return a;\n };\n\n /** Chrome:contenteditable 里的 <a href> 仍会在 click 时导航;mousedown 不拦截以保留拖选 */\n const stopLinkActivate = (e: MouseEvent) => {\n if (mode !== 'rich' && mode !== 'html') return;\n if (!linkInsideEditing(e.target)) return;\n e.preventDefault();\n };\n\n el.addEventListener('keydown', onKeyDown);\n el.addEventListener('compositionstart', onCompositionStart);\n el.addEventListener('compositionend', onCompositionEnd);\n el.addEventListener('blur', onBlur);\n el.addEventListener('paste', onPaste);\n document.addEventListener('selectionchange', onSelChange);\n el.addEventListener('input', onSelChange);\n el.addEventListener('mouseup', onSelChange);\n if (mode === 'rich' || mode === 'html') {\n el.addEventListener('click', stopLinkActivate, true);\n el.addEventListener('auxclick', stopLinkActivate, true);\n }\n\n this.listeners.push(\n () => el.removeEventListener('keydown', onKeyDown),\n () => el.removeEventListener('compositionstart', onCompositionStart),\n () => el.removeEventListener('compositionend', onCompositionEnd),\n () => el.removeEventListener('blur', onBlur),\n () => el.removeEventListener('paste', onPaste),\n () => document.removeEventListener('selectionchange', onSelChange),\n () => el.removeEventListener('input', onSelChange),\n () => el.removeEventListener('mouseup', onSelChange),\n ...(mode === 'rich' || mode === 'html'\n ? [\n () => el.removeEventListener('click', stopLinkActivate, true),\n () => el.removeEventListener('auxclick', stopLinkActivate, true),\n ]\n : []),\n );\n }\n\n private _ensureFocus() {\n if (document.activeElement !== this.el) {\n this.el.focus();\n }\n }\n\n private _syncPendingHiliteAnchor() {\n if (!this.pendingHiliteColor || !this.pendingHiliteAnchor) return;\n const sel = window.getSelection();\n if (!sel?.rangeCount) {\n this._clearPendingHilite();\n return;\n }\n if (selectionAnchorKey(sel.getRangeAt(0)) !== this.pendingHiliteAnchor) {\n this._clearPendingHilite();\n }\n }\n\n private _clearPendingHilite() {\n this.pendingHiliteColor = null;\n this.pendingHiliteAnchor = null;\n }\n\n private _emitSelection() {\n if (!this.opts.onSelectionChange) return;\n if (this.opts.mode === 'plain' || this.opts.mode === 'html') {\n this.opts.onSelectionChange(null); // plain / 原始 HTML 不挂富文本浮动条\n return;\n }\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) {\n this._emitSelectionOrKeepToolbar(null);\n return;\n }\n if (!this.el.contains(sel.anchorNode)) {\n this._emitSelectionOrKeepToolbar(null);\n return;\n }\n const range = sel.getRangeAt(0);\n const rect = sel.isCollapsed ? this._caretRect(range) : range.getBoundingClientRect();\n\n const align: SelectionState['formats']['align'] = richTextQueryCommandState('justifyCenter')\n ? 'center'\n : richTextQueryCommandState('justifyRight')\n ? 'right'\n : richTextQueryCommandState('justifyFull')\n ? 'justify'\n : 'left';\n\n const link = (() => {\n const a = findAncestorAnchor(sel.anchorNode, this.el);\n return a?.getAttribute('href') ?? null;\n })();\n\n const inline = resolveInlineFormatsAtSelection(this.el, sel);\n\n let foreColor = inline.foreColor ?? safeQueryValue('foreColor');\n let backColor = inline.backColor;\n if (\n !backColor &&\n range.collapsed &&\n this.pendingHiliteColor &&\n this.pendingHiliteAnchor === selectionAnchorKey(range)\n ) {\n backColor = this.pendingHiliteColor;\n }\n if (inline.backColor) this._clearPendingHilite();\n\n const state: SelectionState = {\n hasSelection: true,\n rect,\n formats: {\n bold: richTextQueryCommandState('bold'),\n italic: richTextQueryCommandState('italic'),\n underline: richTextQueryCommandState('underline'),\n strikethrough: richTextQueryCommandState('strikeThrough'),\n unorderedList: richTextQueryCommandState('insertUnorderedList'),\n orderedList: richTextQueryCommandState('insertOrderedList'),\n align,\n link,\n foreColor,\n fontSize: inline.fontSize,\n fontName: safeQueryValue('fontName'),\n fontWeight: inline.fontWeight,\n backColor,\n },\n };\n this.lastSelectionState = state;\n this.opts.onSelectionChange(state);\n }\n\n /** 焦点在浮动工具条上时沿用上一帧选区,避免点开链接框 / 颜色等控件后工具条消失。 */\n private _emitSelectionOrKeepToolbar(fallback: null) {\n if (\n fallback === null &&\n this.lastSelectionState &&\n isColorPickerOpen() ||\n document.activeElement?.closest?.(\n '.sm-floating-toolbar, .sm-color-picker, .sm-color-picker-layer',\n )\n ) {\n this.opts.onSelectionChange?.(this.lastSelectionState);\n return;\n }\n if (fallback === null) this.lastSelectionState = null;\n this.opts.onSelectionChange?.(fallback);\n }\n\n private _caretRect(range: Range): DOMRect | null {\n const rects = range.getClientRects();\n if (rects.length) return rects[0];\n // 折叠选区在空段落上时 rects 为空,造一个零宽 range 拿到位置\n const tmp = range.cloneRange();\n tmp.collapse(true);\n const span = document.createElement('span');\n span.appendChild(document.createTextNode('\\u200b'));\n tmp.insertNode(span);\n const r = span.getBoundingClientRect();\n span.remove();\n return r;\n }\n}\n\n/* ----------------------------- helpers ----------------------------- */\n\nfunction findAncestorAnchor(node: Node | null, root: HTMLElement): HTMLAnchorElement | null {\n while (node && node !== root) {\n if (node.nodeType === 1 && (node as HTMLElement).tagName === 'A') {\n return node as HTMLAnchorElement;\n }\n node = node.parentNode;\n }\n return null;\n}\n\nfunction placeCaretAtEnd(el: HTMLElement) {\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nfunction safeQueryValue(cmd: string): string | null {\n try {\n const v = richTextQueryCommandValue(cmd);\n return v ? v : null;\n } catch {\n return null;\n }\n}\n\n/** 光标/选区处的字号、字重、文字色、背景色(queryCommandValue 对 span style 与链接内颜色不可靠) */\nfunction resolveInlineFormatsAtSelection(\n root: HTMLElement,\n sel: Selection,\n): {\n fontSize: string | null;\n fontWeight: string | null;\n foreColor: string | null;\n backColor: string | null;\n} {\n const host = selectionHostElement(sel, root);\n if (!host) return { fontSize: null, fontWeight: null, foreColor: null, backColor: null };\n\n let fontWeight: string | null = null;\n for (let el: HTMLElement | null = host; el && root.contains(el) && el !== root; el = el.parentElement) {\n if (el.style.fontWeight) fontWeight = el.style.fontWeight;\n }\n\n const foreColor = resolveForeColorAtSelection(root, host);\n const backColor = resolveBackColorAtSelection(root, host);\n // 用 computed px,避免读到 .sm-text-content 块级默认字号盖掉 <font>/span 上的真实字号\n const fontSize = window.getComputedStyle(host).fontSize;\n\n if (!fontWeight) {\n fontWeight = richTextQueryCommandState('bold')\n ? '700'\n : normalizeFontWeightStep(window.getComputedStyle(host).fontWeight);\n } else {\n fontWeight = normalizeFontWeightStep(fontWeight);\n }\n\n return { fontSize, fontWeight, foreColor, backColor };\n}\n\n/** 光标处文字色(foreColor / 链接局部 color;queryCommandValue 在 <a> 内常不准) */\nfunction resolveForeColorAtSelection(root: HTMLElement, host: HTMLElement): string | null {\n for (let el: HTMLElement | null = host; el && root.contains(el) && el !== root; el = el.parentElement) {\n const inline = el.style.color?.trim();\n if (inline) return inline;\n\n const fromAttr = readColorFromStyleAttr(el.getAttribute('style'));\n if (fromAttr) return fromAttr;\n }\n\n const computed = window.getComputedStyle(host).color;\n return computed || null;\n}\n\nfunction readColorFromStyleAttr(styleAttr: string | null): string | null {\n if (!styleAttr) return null;\n const m = styleAttr.match(/(?:^|;)\\s*color\\s*:\\s*([^;]+)/i);\n if (!m) return null;\n const c = m[1].trim();\n return c || null;\n}\n\n/** 光标处文字背景/高亮色(hiliteColor 的 queryCommandValue 在 Chrome 常为空,需读 DOM) */\nfunction resolveBackColorAtSelection(root: HTMLElement, host: HTMLElement): string | null {\n for (let el: HTMLElement | null = host; el && root.contains(el) && el !== root; el = el.parentElement) {\n const inline = el.style.backgroundColor?.trim();\n if (inline && !isTransparentColor(inline)) return inline;\n\n const fromAttr = readBackgroundFromStyleAttr(el.getAttribute('style'));\n if (fromAttr) return fromAttr;\n\n const computed = window.getComputedStyle(el).backgroundColor;\n if (computed && !isTransparentColor(computed)) return computed;\n }\n\n // 不用 queryCommandValue('hiliteColor'):它返回的是「下次输入用的颜色」,光标在无高亮处时仍会带上一次配置\n return null;\n}\n\nfunction readBackgroundFromStyleAttr(styleAttr: string | null): string | null {\n if (!styleAttr) return null;\n const m = styleAttr.match(/background(?:-color)?\\s*:\\s*([^;]+)/i);\n if (!m) return null;\n const c = m[1].trim();\n return c && !isTransparentColor(c) ? c : null;\n}\n\nfunction selectionHostElement(sel: Selection, root: HTMLElement): HTMLElement | null {\n const node = sel.anchorNode;\n if (!node || !root.contains(node)) return null;\n return node.nodeType === Node.TEXT_NODE ? node.parentElement : (node as HTMLElement);\n}\n\nfunction selectionAnchorKey(range: Range): string {\n return `${range.startContainer.nodeType}:${range.startOffset}:${range.endContainer.nodeType}:${range.endOffset}`;\n}\n\n/** execCommand fontSize 只认 1–7,与工具条 px 互转 */\nfunction pxToLegacyFontSize(px: string): string {\n const map: Record<string, string> = {\n '10px': '1',\n '12px': '2',\n '13px': '3',\n '14px': '3',\n '15px': '4',\n '16px': '4',\n '18px': '4',\n '20px': '5',\n '24px': '6',\n '28px': '6',\n '32px': '7',\n };\n const key = px.trim().toLowerCase();\n if (map[key]) return map[key];\n const num = parseFloat(key);\n if (Number.isNaN(num)) return '4';\n const steps: [number, string][] = [\n [10, '1'],\n [12, '2'],\n [14, '3'],\n [16, '4'],\n [20, '5'],\n [24, '6'],\n [32, '7'],\n ];\n let best = '4';\n let bestD = Infinity;\n for (const [size, legacy] of steps) {\n const d = Math.abs(size - num);\n if (d < bestD) {\n bestD = d;\n best = legacy;\n }\n }\n return best;\n}\n\nfunction isTransparentColor(c: string): boolean {\n const s = c.trim().toLowerCase();\n if (s === 'transparent' || s === 'inherit' || s === 'initial' || s === 'unset') return true;\n if (s === 'rgba(0, 0, 0, 0)' || s === 'rgba(0,0,0,0)') return true;\n const rgba = s.match(/^rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)(?:[,\\s/]+([\\d.]+))?\\s*\\)$/);\n if (rgba) {\n const a = rgba[4] !== undefined ? parseFloat(rgba[4]) : 1;\n return a === 0;\n }\n return false;\n}\n\nfunction escapeHtml(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;');\n}\n\n/**\n * 邮件 HTML 必须只用一组保守的标签 + inline style。\n * 这里做一次轻量清理:\n * - 白名单标签:保留 a/b/strong/i/em/u/s/strike/span/br/p/div/ul/ol/li/h1-h6/font\n * - 标准化:<b> -> <strong>,<i> -> <em>,<font color> -> <span style=\"color:..\">\n * - 属性白名单:href / target / rel / style / class(保留邮件常见属性)\n */\nexport function sanitizeRichHtml(html: string): string {\n const tpl = document.createElement('template');\n tpl.innerHTML = html;\n walk(tpl.content);\n return tpl.innerHTML.replace(/\\u200b/g, '');\n\n function walk(root: Node) {\n const toRemove: Element[] = [];\n const all = (root as ParentNode).querySelectorAll('*');\n all.forEach((el) => {\n const tag = el.tagName.toLowerCase();\n // <font color=\"...\" size=\"...\" face=\"...\"> → 转成 span style\n if (tag === 'font') {\n const span = document.createElement('span');\n const color = el.getAttribute('color');\n const size = el.getAttribute('size');\n const face = el.getAttribute('face');\n const styles: string[] = [el.getAttribute('style') ?? ''];\n if (color) styles.push(`color:${color}`);\n if (size) styles.push(`font-size:${fontSizeFromLegacy(size)}`);\n if (face) styles.push(`font-family:${face}`);\n const cleaned = styles.filter(Boolean).join(';');\n if (cleaned) span.setAttribute('style', cleaned);\n while (el.firstChild) span.appendChild(el.firstChild);\n el.parentNode?.replaceChild(span, el);\n return;\n }\n // 标签级白名单\n const allowed = [\n 'a',\n 'b',\n 'strong',\n 'i',\n 'em',\n 'u',\n 's',\n 'strike',\n 'span',\n 'br',\n 'p',\n 'div',\n 'ul',\n 'ol',\n 'li',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n ];\n if (!allowed.includes(tag)) {\n toRemove.push(el);\n return;\n }\n // 属性白名单\n const allowedAttrs = ['href', 'target', 'rel', 'style', 'class'];\n [...el.attributes].forEach((attr) => {\n if (!allowedAttrs.includes(attr.name.toLowerCase())) {\n el.removeAttribute(attr.name);\n }\n });\n // 链接安全\n if (tag === 'a') {\n const href = el.getAttribute('href') ?? '';\n if (/^javascript:/i.test(href)) el.setAttribute('href', '#');\n if (!el.getAttribute('rel')) el.setAttribute('rel', 'noopener');\n }\n });\n toRemove.forEach((el) => {\n while (el.firstChild) el.parentNode?.insertBefore(el.firstChild, el);\n el.remove();\n });\n }\n}\n\nfunction fontSizeFromLegacy(size: string): string {\n // 旧 <font size=\"1..7\"> → px 近似\n const map: Record<string, string> = {\n '1': '10px',\n '2': '12px',\n '3': '14px',\n '4': '16px',\n '5': '20px',\n '6': '24px',\n '7': '32px',\n };\n return map[size] ?? size;\n}\n","import Sortable from 'sortablejs';\nimport type { Registry } from '../registry/registry';\nimport {\n createSection,\n findBlockLocation,\n findSection,\n pruneSectionIfEmpty,\n type Store,\n} from '../store/store';\nimport type { Block, Column, EmailDoc, RenderContext, Section, SectionLayout } from '../types';\nimport { blockButtonWidthCss, docContentWidthCss } from '../utils/contentWidth';\nimport { normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport { clear, escapeHtml, h } from '../utils/dom';\nimport { htmlFragmentForLockedHtmlBlockCanvas } from '../utils/lockedMjml';\nimport { layoutHumanLabel } from '../utils/sectionLayout';\nimport { BlockCodeModal } from './BlockCodeModal';\nimport { InlineEditor, type SelectionState } from './InlineEditor';\nimport type { RichTextToolbar } from './RichTextToolbar';\n\nexport interface CanvasOptions {\n store: Store;\n registry: Registry;\n /** 富文本工具条由 Editor 主类创建,Canvas 只负责调用 attach/detach/update */\n toolbar: RichTextToolbar;\n /** 是否允许 Block 落到 sections 之间空白处时自动裹一列 Section */\n autoWrapSection: boolean;\n /**\n * 为 true 时:点击中栏灰色衬底、白底画布上未落到 Section/块的空白、空文档提示区等会提交内联编辑并清空选中。\n * 默认不绑定(由 MailEditor 的 clearSelectionOnCanvasMargin 控制)。\n */\n clearSelectionOnCanvasMargin?: boolean;\n /**\n * 画布内弹层(如「编辑组件代码」)挂接到此节点,以继承 `.sm-root` 上的主题 CSS 变量。\n * 应传入 MailEditor 根节点;若挂到 `document.body`,`var(--sm-code-bg)` 等会失效,弹框背景会变透明。\n */\n layerRoot: HTMLElement;\n}\n\n/**\n * 画布。负责:\n * 1. 根据 doc 渲染轻量预览 DOM(非真实邮件 HTML)\n * 2. 选中态/悬浮态/工具条\n * 3. SortableJS 两级拖拽(仅 hover 显示的拖拽 handle 触发):\n * - 顶层(sections 组):Section 列表纵向排序,并接收左栏布局拖入\n * - 列内(blocks 组):Block 列表纵向排序,并接收左栏内容/自定义拖入\n * 4. 双击 Block 进入\"内联编辑\"——文本类直接富文本编辑,按钮文字单行编辑\n * 5. 设计画布内所有 <a href> 拦截默认行为,避免误跳转;真实跳转仅在「预览」iframe 中可用。\n *\n * 关键约束:所有数据变更走 store.update(),UI 通过 subscribe 全量重渲染。\n * 内联编辑是例外:编辑期间不再每次输入都 update,避免 contenteditable 因重渲染丢光标。\n */\nexport class Canvas {\n el: HTMLElement;\n private inner: HTMLElement;\n private addBar: HTMLElement;\n private opts: CanvasOptions;\n private sortableRefs: Sortable[] = [];\n /** 正在内联编辑的 block id;进入时画布不会被 store 触发的重渲染干扰它 */\n private editingBlockId: string | null = null;\n private inlineEditor: InlineEditor | null = null;\n /** 当 store 在编辑期间触发了 change(外部调用之类),延迟到编辑结束再重渲染 */\n private pendingRender = false;\n /** 设计模式下禁用画布内超链接导航(预览弹框 iframe 不在此 DOM 内,不受影响) */\n private linkNavSuppression = new AbortController();\n private blockCodeModal: BlockCodeModal;\n\n constructor(opts: CanvasOptions) {\n this.opts = opts;\n this.el = h('div', { class: 'sm-canvas-wrap' });\n this.inner = h('div', { class: 'sm-canvas' });\n this.addBar = this._renderAddBar();\n this.el.append(this.inner, this.addBar);\n this.blockCodeModal = new BlockCodeModal({\n store: opts.store,\n registry: opts.registry,\n mountParent: opts.layerRoot,\n });\n\n this._bindDesignModeLinkSuppression();\n if (opts.clearSelectionOnCanvasMargin) {\n this._bindClearSelectionOnCanvasWhitespace();\n this._bindClearSelectionOnCanvasMargin();\n }\n\n this.inner.addEventListener('dblclick', (e: MouseEvent) => {\n this._onEmptyCanvasDblClick(e);\n });\n\n this._render();\n\n opts.store.subscribe(() => {\n if (this.editingBlockId) {\n this.pendingRender = true;\n return;\n }\n this._render();\n });\n opts.store.subscribeSelection(() => this._syncSelection());\n }\n\n setWidth(width: number) {\n this.inner.style.maxWidth = `${width}px`;\n }\n\n /** 暴露给 Editor,用于\"插入变量\"等外部交互直接写入到当前富文本光标处。 */\n get currentInlineEditor(): InlineEditor | null {\n return this.inlineEditor;\n }\n\n /** 强制提交并退出当前内联编辑(切换源码模式、destroy 前等场景) */\n commitInlineEdit() {\n this.inlineEditor?.commit();\n }\n\n destroy() {\n this.linkNavSuppression.abort();\n this._exitEditing(false);\n this._destroySortables();\n this.blockCodeModal.destroy();\n }\n\n /**\n * 点击画布白底上未落到 Section 内的区域(如 min-height 下方留白、空文档提示)时清空选中,\n * Section/Block 上的点击会在冒泡到此前被 stopPropagation,不会误清。\n */\n private _bindClearSelectionOnCanvasWhitespace() {\n this.inner.addEventListener('click', (e: MouseEvent) => {\n const t = e.target;\n if (!(t instanceof Node)) return;\n const el = t instanceof Element ? t : t.parentElement;\n if (!el) return;\n if (el === this.inner || el.closest('.sm-empty-doc')) {\n this.commitInlineEdit();\n this.opts.store.setSelection(null);\n }\n });\n }\n\n /** 点击中栏灰色衬底(非白底画布、非底部添加 Section 条)时取消选中 */\n private _bindClearSelectionOnCanvasMargin() {\n this.el.addEventListener('click', (e: MouseEvent) => {\n const t = e.target;\n if (!(t instanceof Node)) return;\n if (!this.el.contains(t)) return;\n if (this.inner.contains(t)) return;\n if (this.addBar.contains(t)) return;\n this.commitInlineEdit();\n this.opts.store.setSelection(null);\n });\n }\n\n /** 捕获阶段拦截 <a href>,防止 Chrome 等在画布预览 DOM 上触发跳转(含未进入内联编辑时点到按钮块链接) */\n private _bindDesignModeLinkSuppression() {\n const opts = { capture: true, signal: this.linkNavSuppression.signal } as const;\n const linkFromTarget = (target: EventTarget | null): HTMLAnchorElement | null => {\n if (!(target instanceof Element)) return null;\n const a = target.closest('a');\n if (!a || !this.inner.contains(a)) return null;\n if (!a.hasAttribute('href')) return null;\n return a;\n };\n this.inner.addEventListener(\n 'mousedown',\n (e: MouseEvent) => {\n const a = linkFromTarget(e.target);\n if (!a) return;\n // 内联编辑时保留 mousedown 默认行为,以便在链接文字上拖选\n if (a.closest('.sm-inline-editing')) return;\n e.preventDefault();\n },\n opts,\n );\n const stopNavigate = (e: MouseEvent) => {\n if (!linkFromTarget(e.target)) return;\n e.preventDefault();\n };\n this.inner.addEventListener('click', stopNavigate, opts);\n this.inner.addEventListener('auxclick', stopNavigate, opts);\n }\n\n /* -------------------------------- 渲染 ---------------------------------- */\n\n private _render() {\n this._destroySortables();\n clear(this.inner);\n\n const { doc } = this.opts.store;\n this.inner.style.maxWidth = docContentWidthCss(doc.meta.width);\n this.inner.style.background = doc.styles.contentBackgroundColor;\n this.inner.style.fontFamily = doc.styles.fontFamily;\n this.inner.style.fontSize = doc.styles.fontSize;\n this.inner.style.fontWeight = normalizeFontWeightStep(doc.styles.fontWeight);\n this.inner.style.color = doc.styles.color;\n this.inner.style.lineHeight = doc.styles.lineHeight ?? '1.25';\n this.inner.style.setProperty('--sm-editor-link-color', doc.styles.linkColor);\n\n if (!doc.sections.length) {\n this.inner.append(\n h('div', { class: 'sm-empty-doc' }, [\n '从左侧拖入布局开始,或直接双击开始 ✦',\n ]),\n );\n } else {\n for (let si = 0; si < doc.sections.length; si++) {\n this.inner.append(this._renderSection(doc.sections[si], doc, si));\n }\n }\n\n // 顶层 Sortable:负责 Section 排序。\n // put 规则随 autoWrapSection 切换:\n // - autoWrapSection=true:同时接收 sections 与 blocks(block 落到这里时由 path B/C 自动套壳)\n // - autoWrapSection=false:仅接收 sections(block 落不下来,SortableJS 会显示禁止)\n // pull:false 始终:Section 不允许被拖到 column 里(保持四层模型)\n const topPut: string[] = this.opts.autoWrapSection ? ['sections', 'blocks'] : ['sections'];\n const top = Sortable.create(this.inner, {\n group: { name: 'sections', pull: false, put: topPut },\n animation: 150,\n handle: '.sm-section__handle',\n draggable: '> .sm-section-host',\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n onAdd: (e) => this._handleSectionAdd(e),\n onUpdate: (e) => this._handleSectionMove(e),\n });\n this.sortableRefs.push(top);\n\n this._syncSelection();\n }\n\n private _renderSection(section: Section, doc: EmailDoc, sectionIndex: number) {\n const a = section.attrs;\n const padding = `${a.paddingTop ?? 0}px ${a.paddingRight ?? 0}px ${\n a.paddingBottom ?? 0\n }px ${a.paddingLeft ?? 0}px`;\n\n const layoutShort = layoutHumanLabel(section.layout);\n const sectionChip = `区块 ${sectionIndex + 1} · ${layoutShort}`;\n\n const sw = blockButtonWidthCss(a.width);\n const box =\n sw != null ? `max-width:${sw};width:100%;margin-left:auto;margin-right:auto;box-sizing:border-box;` : '';\n\n const host = h('div', {\n class: 'sm-section-host',\n 'data-id': section.id,\n });\n\n const wrap = h('div', {\n class: 'sm-section',\n title: `${sectionChip}。子组件铺满列内时:按 Esc 或 Alt+点击块可选中本节。`,\n style: `padding:${padding};${a.backgroundColor ? `background:${a.backgroundColor};` : ''}${box}`,\n });\n\n const toolbar = h('div', { class: 'sm-section__toolbar' }, [\n h('span', { class: 'sm-section__toolbar-label', title: sectionChip }, [sectionChip]),\n h('div', { class: 'sm-section__toolbar-actions' }, [\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-section__handle',\n type: 'button',\n title: '拖拽排序',\n },\n [iconDrag()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '复制',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._duplicateSection(section.id);\n },\n },\n [iconCopy()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-tool-btn--danger',\n type: 'button',\n title: '删除',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._removeSection(section.id);\n },\n },\n [iconTrash()],\n ),\n ]),\n ]);\n\n const cols = h('div', {\n class: 'sm-section__columns',\n style: layoutFlexStyle(section.layout, section.attrs.columnGap),\n });\n\n section.columns.forEach((col, i) => {\n cols.append(this._renderColumn(section, col, i, doc));\n });\n\n wrap.append(cols);\n\n host.append(wrap, toolbar);\n\n host.addEventListener('click', (e) => {\n if ((e.target as HTMLElement).closest('.sm-block')) return;\n // 文本拖选时在 Section padding 等区域松开会冒泡 click,不应误切成 Section 选中\n if (!e.altKey && this._shouldSuppressSectionSelectFromTextInteraction()) return;\n e.stopPropagation();\n this.opts.store.setSelection({ kind: 'section', sectionId: section.id });\n });\n\n return host;\n }\n\n private _renderColumn(\n section: Section,\n column: Column,\n columnIndex: number,\n doc: EmailDoc,\n ): HTMLElement {\n const isEmpty = column.blocks.length === 0;\n const colEl = h('div', {\n class: `sm-column ${isEmpty ? 'is-empty' : ''}`,\n 'data-section-id': section.id,\n 'data-column-index': String(columnIndex),\n style: `flex:${layoutFlexValue(section.layout, columnIndex)};${\n column.attrs.backgroundColor ? `background:${column.attrs.backgroundColor};` : ''\n }${column.attrs.verticalAlign ? `align-self:${vaToFlex(column.attrs.verticalAlign)};` : ''}`,\n });\n\n for (const block of column.blocks) {\n colEl.append(this._renderBlock(section, columnIndex, block, doc));\n }\n\n if (isEmpty) {\n colEl.addEventListener('dblclick', (e: MouseEvent) => {\n if ((e.target as HTMLElement).closest('.sm-block')) return;\n e.preventDefault();\n e.stopPropagation();\n this._insertEmptyTextAndEdit(section.id, columnIndex);\n });\n }\n\n // 列内 Sortable:负责块排序,并且:\n // - put: ['blocks'] 接受外来 block(同 group)\n // - pull: true(默认) 允许把内部 block 拖出到其他列 / 或顶层(自动裹一列)\n // - handle 限制为 .sm-block__handle:点选/编辑文本不会误触拖拽\n const sortable = Sortable.create(colEl, {\n group: { name: 'blocks', put: ['blocks'] },\n animation: 150,\n draggable: '.sm-block',\n handle: '.sm-block__handle',\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n onAdd: (e) => this._handleBlockAdd(e, section.id, columnIndex),\n onUpdate: (e) => this._handleBlockMove(e, section.id, columnIndex),\n onRemove: () => {\n /* DOM 调整由 store 重渲染负责;这里不处理。\n 源 column 把 block 拖出后,store 会被 onAdd 同步从源数组里移除该 block。 */\n },\n });\n this.sortableRefs.push(sortable);\n\n return colEl;\n }\n\n private _renderBlock(\n section: Section,\n columnIndex: number,\n block: Block,\n doc: EmailDoc,\n ): HTMLElement {\n const ctx: RenderContext = { doc, engine: 'mjml' };\n const def = this.opts.registry.get(block.type);\n let inner = '';\n if (block.lockedMjml) {\n if (block.type === 'html') {\n const p = block.props as {\n paddingTop?: number;\n paddingRight?: number;\n paddingBottom?: number;\n paddingLeft?: number;\n };\n const frag = htmlFragmentForLockedHtmlBlockCanvas(block.lockedMjml, {\n top: Number(p.paddingTop ?? 8),\n right: Number(p.paddingRight ?? 0),\n bottom: Number(p.paddingBottom ?? 8),\n left: Number(p.paddingLeft ?? 0),\n });\n inner = `<div class=\"sm-html-content\">${frag}</div>`;\n } else {\n inner = `<div style=\"padding:8px;color:#92400e;background:#fffbeb;border:1px dashed #f59e0b;font-family:monospace;font-size:11px;white-space:pre-wrap;\">${escapeHtml(\n block.lockedMjml,\n )}</div>`;\n }\n } else if (def?.renderPreview) {\n inner = def.renderPreview(block.props as any, ctx);\n } else if (def) {\n inner = `<div style=\"padding:16px;color:#6b7280;background:#f9fafb;border:1px dashed #d1d5db;text-align:center;\">${escapeHtml(\n def.name,\n )}</div>`;\n } else {\n inner = `<div style=\"padding:8px;color:#dc2626;\">未知组件: ${escapeHtml(block.type)}</div>`;\n }\n\n const displayName = def?.name ?? block.type;\n\n const el = h('div', {\n class: `sm-block ${block.lockedMjml ? 'is-locked' : ''}`,\n 'data-id': block.id,\n 'data-section-id': section.id,\n 'data-column-index': String(columnIndex),\n });\n\n // 内容容器:renderPreview 输出放这里,便于精确定位 inlineEditable selector\n const content = h('div', { class: 'sm-block__content', html: inner });\n\n // 块工具条:hover 仅名称;选中 / 编辑中显示全部按钮;贴在块顶边之上不压内容\n const blockToolbar = h('div', { class: 'sm-block__toolbar' }, [\n h('span', { class: 'sm-block__toolbar-name', title: displayName }, [displayName]),\n h('div', { class: 'sm-block__toolbar-actions' }, [\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-block__handle',\n type: 'button',\n title: '拖拽排序',\n onclick: (e: Event) => e.stopPropagation(),\n },\n [iconDrag()],\n ),\n def?.inlineEditable && !block.lockedMjml\n ? h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '编辑文本',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._enterEditing(block);\n },\n },\n [iconEdit()],\n )\n : null,\n h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '编辑组件代码',\n onclick: (e: Event) => {\n e.stopPropagation();\n this.blockCodeModal.open(block.id, displayName);\n },\n },\n [iconCode()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn',\n type: 'button',\n title: '复制',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._duplicateBlock(block.id);\n },\n },\n [iconCopy()],\n ),\n h(\n 'button',\n {\n class: 'sm-tool-btn sm-tool-btn--danger',\n type: 'button',\n title: '删除',\n onclick: (e: Event) => {\n e.stopPropagation();\n this._removeBlock(block.id);\n },\n },\n [iconTrash()],\n ),\n ]),\n ]);\n\n el.append(blockToolbar, content);\n\n el.addEventListener('click', (e) => {\n if (this.editingBlockId === block.id) return; // 编辑中不抢焦点\n /** Alt(mac Option):穿透选中父级 Section,解决单列内边距为 0 时块铺满无法点到 Section */\n if (e.altKey) {\n e.stopPropagation();\n this.opts.store.setSelection({ kind: 'section', sectionId: section.id });\n return;\n }\n e.stopPropagation();\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: section.id,\n columnIndex,\n blockId: block.id,\n });\n });\n\n if (def?.inlineEditable && !block.lockedMjml) {\n el.addEventListener('dblclick', (e) => {\n e.stopPropagation();\n this._enterEditing(block);\n });\n }\n\n return el;\n }\n\n private _renderAddBar(): HTMLElement {\n const layouts: { layout: SectionLayout; label: string }[] = [\n { layout: '1', label: '一列' },\n { layout: '1-1', label: '两列' },\n { layout: '1-1-1', label: '三列' },\n ];\n const bar = h('div', { class: 'sm-add-section-bar' }, [h('span', {}, ['+ 添加 Section:'])]);\n for (const l of layouts) {\n bar.append(\n h(\n 'button',\n {\n class: 'sm-add-section-bar__btn',\n type: 'button',\n onclick: () =>\n this.opts.store.update((d) => {\n d.sections.push(createSection(l.layout));\n }),\n },\n [l.label],\n ),\n );\n }\n return bar;\n }\n\n /* ----------------------------- 内联编辑 -------------------------------- */\n\n /** 空文档时:在画布白底区域双击,插入一列 Section + 空文本并进入编辑 */\n private _onEmptyCanvasDblClick(e: MouseEvent) {\n if (this.opts.store.doc.sections.length > 0) return;\n const t = e.target as HTMLElement | null;\n if (!t || !this.inner.contains(t)) return;\n e.preventDefault();\n e.stopPropagation();\n this._bootstrapEmptyDocWithText();\n }\n\n /** 无任何 Section 时:创建单栏布局并放入空正文块,再进入内联编辑 */\n private _bootstrapEmptyDocWithText() {\n const reg = this.opts.registry;\n if (!reg.get('text')?.inlineEditable) return;\n this.opts.store.update((d) => {\n if (d.sections.length > 0) return;\n const newBlock = reg.createBlock('text');\n (newBlock.props as { content: string }).content = '';\n const section = createSection('1');\n section.columns[0].blocks.push(newBlock);\n d.sections.push(section);\n });\n\n const doc = this.opts.store.doc;\n const firstBlock = doc.sections[0]?.columns[0]?.blocks[0];\n if (!firstBlock) return;\n\n requestAnimationFrame(() => {\n const loc = findBlockLocation(this.opts.store.doc, firstBlock.id);\n if (loc) this._enterEditing(loc.block);\n });\n }\n\n /** 空列双击:插入正文组件(content 为空)并直接进入编辑 */\n private _insertEmptyTextAndEdit(sectionId: string, columnIndex: number) {\n const reg = this.opts.registry;\n if (!reg.get('text')?.inlineEditable) return;\n const newBlock = reg.createBlock('text');\n (newBlock.props as { content: string }).content = '';\n\n this.opts.store.update((d) => {\n const sec = findSection(d, sectionId);\n if (!sec) return;\n const col = sec.columns[columnIndex];\n if (!col || col.blocks.length > 0) return;\n col.blocks.push(newBlock);\n });\n\n requestAnimationFrame(() => {\n const loc = findBlockLocation(this.opts.store.doc, newBlock.id);\n if (loc) this._enterEditing(loc.block);\n });\n }\n\n private _enterEditing(block: Block) {\n if (this.editingBlockId === block.id) return;\n this._exitEditing(true);\n\n const def = this.opts.registry.get(block.type);\n if (!def?.inlineEditable) return;\n\n const blockEl = this.inner.querySelector(\n `.sm-block[data-id=\"${cssEscape(block.id)}\"]`,\n ) as HTMLElement | null;\n const contentRoot = blockEl?.querySelector('.sm-block__content') as HTMLElement | null;\n if (!contentRoot) return;\n\n const target = (\n def.inlineEditable.selector\n ? contentRoot.querySelector(def.inlineEditable.selector)\n : contentRoot.firstElementChild\n ) as HTMLElement | null;\n if (!target) return;\n\n this.editingBlockId = block.id;\n blockEl?.classList.add('is-editing');\n\n const initial =\n def.inlineEditable.mode === 'plain'\n ? String((block.props as any)[def.inlineEditable.propKey] ?? '')\n : String((block.props as any)[def.inlineEditable.propKey] ?? '');\n\n this.inlineEditor = new InlineEditor({\n el: target,\n initialValue: initial,\n mode: def.inlineEditable.mode,\n multiline: !!def.inlineEditable.multiline,\n placeholder: def.inlineEditable.placeholder,\n onCommit: (value) => {\n const propKey = def.inlineEditable!.propKey;\n const editingId = block.id;\n this._exitEditing(false);\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, editingId);\n if (loc) (loc.block.props as any)[propKey] = value;\n });\n },\n onCancel: () => this._exitEditing(true),\n onSelectionChange: (state: SelectionState | null) => {\n this.opts.toolbar.update(state);\n },\n });\n\n if (def.inlineEditable.mode === 'rich') {\n this.opts.toolbar.attach(this.inlineEditor);\n }\n\n // 选中该 block,便于属性面板同步\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: blockEl!.getAttribute('data-section-id')!,\n columnIndex: Number(blockEl!.getAttribute('data-column-index')),\n blockId: block.id,\n });\n }\n\n /** restoreUI=true:编辑器自身恢复原 DOM(取消场景);false:保留新内容(提交场景,等待 store 回写后重渲染) */\n private _exitEditing(restoreUI: boolean) {\n if (!this.editingBlockId) return;\n const id = this.editingBlockId;\n this.editingBlockId = null;\n if (this.inlineEditor) {\n this.inlineEditor.destroy(restoreUI);\n this.inlineEditor = null;\n }\n this.opts.toolbar.detach();\n const blockEl = this.inner.querySelector(\n `.sm-block[data-id=\"${cssEscape(id)}\"]`,\n ) as HTMLElement | null;\n blockEl?.classList.remove('is-editing');\n\n if (this.pendingRender) {\n this.pendingRender = false;\n this._render();\n }\n }\n\n /* -------------------------------- 拖拽 ---------------------------------- */\n\n /** 结构变更(拖入/排序)前提交内联编辑,避免编辑态 pendingRender 与 Sortable DOM 不同步 */\n private _commitEditingBeforeStructureChange() {\n if (this.editingBlockId) this.commitInlineEdit();\n }\n\n private _blocksFromPaletteDrop(blockType: string): Block[] {\n const def = this.opts.registry.get(blockType);\n if (def?.expandPaletteDrop) {\n return def.expandPaletteDrop((t) => this.opts.registry.createBlock(t));\n }\n return [this.opts.registry.createBlock(blockType)];\n }\n\n private _handleSectionAdd(e: Sortable.SortableEvent) {\n this._commitEditingBeforeStructureChange();\n const item = e.item;\n const layout = item.getAttribute('data-layout') as SectionLayout | null;\n const blockType = item.getAttribute('data-block-type');\n const fromBlockId = item.getAttribute('data-id');\n const sourceGroup = item.getAttribute('data-source-group');\n const newIndex = e.newIndex ?? 0;\n\n // 路径 A:左栏布局卡片\n if (layout) {\n item.parentElement?.removeChild(item);\n this.opts.store.update((d) => {\n d.sections.splice(newIndex, 0, createSection(layout));\n });\n return;\n }\n\n // 路径 B:左栏内容/自定义卡片拖到 sections 之间 → 自动裹一列 Section\n if (sourceGroup === 'blocks' && blockType) {\n item.parentElement?.removeChild(item);\n const blocks = this._blocksFromPaletteDrop(blockType);\n const newSection = createSection('1');\n newSection.columns[0].blocks.splice(newIndex, 0, ...blocks);\n this.opts.store.update((d) => {\n d.sections.splice(newIndex, 0, newSection);\n });\n const head = blocks[0];\n if (head) {\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: newSection.id,\n columnIndex: 0,\n blockId: head.id,\n });\n }\n return;\n }\n\n // 路径 C:从某个已有 column 把 block 拖到 sections 之间 → 自动裹一列 Section\n if (fromBlockId) {\n item.parentElement?.removeChild(item);\n const newSection = createSection('1');\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, fromBlockId);\n if (!loc) return;\n const fromCol = loc.section.columns[loc.columnIndex];\n const idx = fromCol.blocks.findIndex((b) => b.id === fromBlockId);\n if (idx < 0) return;\n const [moved] = fromCol.blocks.splice(idx, 1);\n newSection.columns[0].blocks.push(moved);\n // 注意:newIndex 是 SortableJS 把 item 放进 DOM 后看到的索引;\n // 由于来源 column 内的 block 不属于 inner 的直接子节点,\n // newIndex 在 inner 的可视位置上是准确的。\n d.sections.splice(newIndex, 0, newSection);\n pruneSectionIfEmpty(d, loc.section.id);\n });\n this.opts.store.setSelection({\n kind: 'block',\n sectionId: newSection.id,\n columnIndex: 0,\n blockId: fromBlockId,\n });\n }\n }\n\n private _handleSectionMove(e: Sortable.SortableEvent) {\n this._commitEditingBeforeStructureChange();\n const oldIndex = e.oldIndex ?? 0;\n const newIndex = e.newIndex ?? 0;\n if (oldIndex === newIndex) return;\n this.opts.store.update((d) => {\n const [moved] = d.sections.splice(oldIndex, 1);\n d.sections.splice(newIndex, 0, moved);\n });\n }\n\n private _handleBlockAdd(e: Sortable.SortableEvent, sectionId: string, columnIndex: number) {\n this._commitEditingBeforeStructureChange();\n const item = e.item;\n const newIndex = e.newIndex ?? 0;\n const sourceGroup = item.getAttribute('data-source-group');\n const blockType = item.getAttribute('data-block-type');\n const fromBlockId = item.getAttribute('data-id');\n\n if (sourceGroup === 'blocks' && blockType) {\n item.parentElement?.removeChild(item);\n const blocks = this._blocksFromPaletteDrop(blockType);\n this.opts.store.update((d) => {\n const sec = d.sections.find((s) => s.id === sectionId);\n if (!sec) return;\n sec.columns[columnIndex]?.blocks.splice(newIndex, 0, ...blocks);\n });\n const head = blocks[0];\n if (head) {\n this.opts.store.setSelection({\n kind: 'block',\n sectionId,\n columnIndex,\n blockId: head.id,\n });\n }\n return;\n }\n\n if (fromBlockId) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, fromBlockId);\n if (!loc) return;\n const fromCol = loc.section.columns[loc.columnIndex];\n const idx = fromCol.blocks.findIndex((b) => b.id === fromBlockId);\n if (idx < 0) return;\n const [moved] = fromCol.blocks.splice(idx, 1);\n const targetSec = d.sections.find((s) => s.id === sectionId);\n targetSec?.columns[columnIndex]?.blocks.splice(newIndex, 0, moved);\n pruneSectionIfEmpty(d, loc.section.id);\n });\n }\n }\n\n private _handleBlockMove(e: Sortable.SortableEvent, sectionId: string, columnIndex: number) {\n this._commitEditingBeforeStructureChange();\n const oldIndex = e.oldIndex ?? 0;\n const newIndex = e.newIndex ?? 0;\n if (oldIndex === newIndex) return;\n this.opts.store.update((d) => {\n const sec = d.sections.find((s) => s.id === sectionId);\n const col = sec?.columns[columnIndex];\n if (!col) return;\n const [moved] = col.blocks.splice(oldIndex, 1);\n col.blocks.splice(newIndex, 0, moved);\n });\n }\n\n /* -------------------------------- 操作 ---------------------------------- */\n\n private _removeSection(id: string) {\n this.opts.store.update((d) => {\n d.sections = d.sections.filter((s) => s.id !== id);\n });\n this.opts.store.setSelection(null);\n }\n\n private _duplicateSection(id: string) {\n this.opts.store.update((d) => {\n const idx = d.sections.findIndex((s) => s.id === id);\n if (idx < 0) return;\n const clone = structuredClone(d.sections[idx]);\n clone.id = `${clone.id}_c${Date.now().toString(36)}`;\n clone.columns = clone.columns.map((c) => ({\n ...c,\n id: `${c.id}_c${Date.now().toString(36)}`,\n blocks: c.blocks.map((b) => ({ ...b, id: `${b.id}_c${Date.now().toString(36)}` })),\n }));\n d.sections.splice(idx + 1, 0, clone);\n });\n }\n\n private _removeBlock(id: string) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, id);\n if (!loc) return;\n const col = loc.section.columns[loc.columnIndex];\n col.blocks = col.blocks.filter((b) => b.id !== id);\n pruneSectionIfEmpty(d, loc.section.id);\n });\n this.opts.store.setSelection(null);\n }\n\n private _duplicateBlock(id: string) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, id);\n if (!loc) return;\n const col = loc.section.columns[loc.columnIndex];\n const idx = col.blocks.findIndex((b) => b.id === id);\n if (idx < 0) return;\n const clone = structuredClone(col.blocks[idx]);\n clone.id = `${clone.id}_c${Date.now().toString(36)}`;\n col.blocks.splice(idx + 1, 0, clone);\n });\n }\n\n /**\n * 内联编辑中拖选文字,若 mouseup 落在 Section padding 等非 Block 区域,\n * 浏览器仍会向 Section 冒泡 click;此时选区仍在编辑区内,不应切换右侧面板到 Section。\n */\n private _shouldSuppressSectionSelectFromTextInteraction(): boolean {\n if (!this.editingBlockId) return false;\n const editingEl = this.inner.querySelector('.sm-inline-editing');\n if (!editingEl) return false;\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0 || sel.isCollapsed) return false;\n const nodeInEditing = (n: Node | null): boolean => {\n if (!n) return false;\n const el = n.nodeType === Node.TEXT_NODE ? n.parentNode : n;\n return !!el && editingEl.contains(el);\n };\n return nodeInEditing(sel.anchorNode) || nodeInEditing(sel.focusNode);\n }\n\n private _syncSelection() {\n const sel = this.opts.store.selection;\n this.inner.querySelectorAll('.is-selected').forEach((el) => el.classList.remove('is-selected'));\n if (!sel) return;\n if (sel.kind === 'section') {\n this.inner\n .querySelector(`.sm-section-host[data-id=\"${cssEscape(sel.sectionId)}\"]`)\n ?.classList.add('is-selected');\n } else {\n this.inner\n .querySelector(`.sm-block[data-id=\"${cssEscape(sel.blockId)}\"]`)\n ?.classList.add('is-selected');\n }\n }\n\n private _destroySortables() {\n for (const s of this.sortableRefs) s.destroy();\n this.sortableRefs = [];\n }\n}\n\n/* ---------------------------------- utils --------------------------------- */\n\nfunction layoutFlexStyle(_layout: SectionLayout, columnGap?: number): string {\n const gap =\n columnGap != null && columnGap > 0 ? `gap:${Math.min(columnGap, 200)}px;` : '';\n return `display:flex;flex-wrap:nowrap;width:100%;${gap}`;\n}\n\nfunction layoutFlexValue(layout: SectionLayout, index: number): string {\n const parts = layout.split('-').map(Number);\n const total = parts.reduce((s, x) => s + x, 0);\n const ratio = parts[index] ?? 1;\n return `${ratio} 1 0;min-width:0;width:${((ratio / total) * 100).toFixed(2)}%`;\n}\n\nfunction vaToFlex(va: 'top' | 'middle' | 'bottom'): string {\n return va === 'top' ? 'flex-start' : va === 'bottom' ? 'flex-end' : 'center';\n}\n\nfunction cssEscape(s: string): string {\n if (typeof CSS !== 'undefined' && CSS.escape) return CSS.escape(s);\n return s.replace(/[^\\w-]/g, '\\\\$&');\n}\n\nfunction svg(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '12');\n el.setAttribute('height', '12');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML = inner;\n return el;\n}\nfunction iconDrag() {\n return svg(\n '<circle cx=\"7\" cy=\"5\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"13\" cy=\"5\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"7\" cy=\"10\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"13\" cy=\"10\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"7\" cy=\"15\" r=\"1.4\" fill=\"currentColor\"/><circle cx=\"13\" cy=\"15\" r=\"1.4\" fill=\"currentColor\"/>',\n );\n}\nfunction iconCopy() {\n return svg(\n '<rect x=\"6\" y=\"6\" width=\"10\" height=\"10\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><path d=\"M4 12V5a1 1 0 011-1h7\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/>',\n );\n}\nfunction iconTrash() {\n return svg(\n '<path d=\"M5 6h10M8 6V4h4v2M6 6l1 10h6l1-10\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\" stroke-linejoin=\"round\"/>',\n );\n}\nfunction iconEdit() {\n return svg(\n '<path d=\"M4 14l8-8 2 2-8 8H4v-2z\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\" stroke-linejoin=\"round\"/>',\n );\n}\nfunction iconCode() {\n return svg(\n '<path d=\"M7 7l-3 3 3 3M13 7l3 3-3 3\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n );\n}\n","import { EditorState } from '@codemirror/state';\nimport { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport type { Registry } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport type { Store } from '../store/store';\nimport { prettyHtml } from '../utils/html';\nimport { h } from '../utils/dom';\nimport { richTextExecCommand } from '../utils/richTextCommand';\nimport { Modal } from './Modal';\n\nexport interface ExportModalOptions {\n store: Store;\n registry: Registry;\n /** 替换 {{var}} 为 sample 值 */\n withSampleVariables?: boolean;\n}\n\n/**\n * 导出 HTML 弹框:\n * - body 用 CodeMirror 只读展示当前文档编译产物\n * - footer:复制、美化、下载 三个动作\n */\nexport class ExportModal {\n private opts: ExportModalOptions;\n private modal: Modal;\n private cm: EditorView | null = null;\n private current: string = '';\n\n constructor(opts: ExportModalOptions) {\n this.opts = opts;\n this.modal = new Modal({\n title: '导出 HTML',\n className: 'sm-modal--export',\n width: 'min(960px, 96vw)',\n height: 'min(720px, 88vh)',\n onClose: () => this._destroyCm(),\n });\n\n const editorHost = h('div', { class: 'sm-export__editor' });\n this.modal.body.append(editorHost);\n\n const copyBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: () => this._copy() },\n ['复制 HTML'],\n );\n const beautifyBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: () => this._beautify() },\n ['美化'],\n );\n const downloadBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onclick: () => this._download(),\n },\n ['下载 .html'],\n );\n this.modal.footer.append(copyBtn, beautifyBtn, downloadBtn);\n\n // 初始化 CodeMirror(在 open 时填充 doc)\n this.cm = new EditorView({\n parent: editorHost,\n state: EditorState.create({\n doc: '',\n extensions: [basicSetup, cmHtml(), EditorState.readOnly.of(true)],\n }),\n });\n }\n\n open(parent?: HTMLElement) {\n this._compile();\n this.modal.open(parent);\n }\n\n private _compile() {\n const result = renderDoc(this.opts.store.doc, this.opts.registry, {\n withSampleVariables: this.opts.withSampleVariables ?? true,\n });\n this.current = result.html;\n this._setText(result.html);\n }\n\n private _setText(text: string) {\n if (!this.cm) return;\n this.cm.dispatch({\n changes: { from: 0, to: this.cm.state.doc.length, insert: text },\n });\n }\n\n private async _copy() {\n try {\n await navigator.clipboard.writeText(this.current);\n this._toast('已复制到剪贴板');\n } catch {\n const ta = document.createElement('textarea');\n ta.value = this.current;\n document.body.appendChild(ta);\n ta.select();\n richTextExecCommand('copy');\n document.body.removeChild(ta);\n this._toast('已复制');\n }\n }\n\n private _beautify() {\n this.current = prettyHtml(this.current);\n this._setText(this.current);\n }\n\n private _download() {\n const blob = new Blob([this.current], { type: 'text/html;charset=utf-8' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `email-${Date.now()}.html`;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n }\n\n private _toast(text: string) {\n const t = h('div', { class: 'sm-toast' }, [text]);\n this.modal.body.append(t);\n requestAnimationFrame(() => t.classList.add('is-visible'));\n setTimeout(() => {\n t.classList.remove('is-visible');\n setTimeout(() => t.remove(), 200);\n }, 1400);\n }\n\n private _destroyCm() {\n this.cm?.destroy();\n this.cm = null;\n }\n}\n","import Sortable from 'sortablejs';\nimport type { Registry } from '../registry/registry';\nimport type { BlockDefinition, SectionLayout } from '../types';\nimport { clear, h } from '../utils/dom';\n\nexport interface LeftPanelOptions {\n registry: Registry;\n}\n\ninterface LayoutCard {\n layout: SectionLayout;\n name: string;\n icon: string;\n}\n\nconst LAYOUT_CARDS: LayoutCard[] = [\n { layout: '1', name: '一列', icon: layoutSvg([1]) },\n /** 默认 1:1;1:2 / 2:1 在选中 Section 后于右栏「列比例」切换 */\n { layout: '1-1', name: '两列', icon: layoutSvg([1, 1]) },\n { layout: '1-1-1', name: '三列', icon: layoutSvg([1, 1, 1]) },\n];\n\n/**\n * 左栏分两类:\n * - 布局(layout):决定 Section 结构,拖入到画布顶层(group: 'sections')\n * - 内容/自定义:作为 Block,拖入到 Column 中(group: 'blocks')\n *\n * 通过 SortableJS 的 group + clone + sort:false 实现。\n * 这两个组分开,画布顶层只接 'sections',列内只接 'blocks',\n * 严格两层拖拽,禁止跨级别——这是解决 GrapesJS 嵌套混乱的核心。\n */\nexport class LeftPanel {\n el: HTMLElement;\n private opts: LeftPanelOptions;\n\n constructor(opts: LeftPanelOptions) {\n this.opts = opts;\n this.el = h('aside', { class: 'sm-panel sm-panel--left' });\n this._render();\n }\n\n refresh() {\n this._render();\n }\n\n private _render() {\n clear(this.el);\n const content = this.opts.registry.byCategory('content');\n const custom = this.opts.registry.byCategory('custom');\n\n const wrap = h('div', { class: 'sm-blocks' });\n\n wrap.append(this._renderLayoutGroup());\n if (content.length) wrap.append(this._renderBlockGroup('内容', content));\n if (custom.length) wrap.append(this._renderBlockGroup('自定义', custom));\n\n this.el.append(wrap);\n }\n\n private _renderLayoutGroup(): HTMLElement {\n const grid = h('div', { class: 'sm-blocks__grid' });\n for (const c of LAYOUT_CARDS) {\n grid.append(\n h(\n 'div',\n {\n class: 'sm-block-card',\n 'data-source-group': 'sections',\n 'data-layout': c.layout,\n title: c.name,\n },\n [\n h('span', { class: 'sm-block-card__icon', html: c.icon }),\n h('span', { class: 'sm-block-card__name' }, [c.name]),\n ],\n ),\n );\n }\n Sortable.create(grid, {\n group: { name: 'sections', pull: 'clone', put: false },\n sort: false,\n animation: 120,\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n });\n return h('section', { class: 'sm-blocks__group' }, [\n h('div', { class: 'sm-panel__title' }, ['布局']),\n grid,\n ]);\n }\n\n private _renderBlockGroup(title: string, defs: BlockDefinition[]): HTMLElement {\n const grid = h('div', { class: 'sm-blocks__grid' });\n for (const def of defs) {\n grid.append(\n h(\n 'div',\n {\n class: 'sm-block-card',\n 'data-source-group': 'blocks',\n 'data-block-type': def.type,\n title: def.name,\n },\n [\n h('span', { class: 'sm-block-card__icon', html: def.icon }),\n h('span', { class: 'sm-block-card__name' }, [def.name]),\n ],\n ),\n );\n }\n Sortable.create(grid, {\n group: { name: 'blocks', pull: 'clone', put: false },\n sort: false,\n animation: 120,\n ghostClass: 'sm-ghost',\n chosenClass: 'sm-chosen',\n dragClass: 'sm-drag',\n });\n return h('section', { class: 'sm-blocks__group' }, [\n h('div', { class: 'sm-panel__title' }, [title]),\n grid,\n ]);\n }\n}\n\nfunction layoutSvg(parts: number[]): string {\n const total = parts.reduce((s, x) => s + x, 0);\n const w = 24;\n const gap = 1;\n const innerW = w - gap * (parts.length - 1);\n let x = 0;\n const rects = parts\n .map((p) => {\n const rw = (p / total) * innerW;\n const rect = `<rect x=\"${x}\" y=\"6\" width=\"${rw.toFixed(\n 2,\n )}\" height=\"12\" fill=\"currentColor\" opacity=\"0.8\" rx=\"1\"/>`;\n x += rw + gap;\n return rect;\n })\n .join('');\n return `<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">${rects}</svg>`;\n}\n","import type { Registry } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport type { Store } from '../store/store';\nimport { h } from '../utils/dom';\nimport { Modal } from './Modal';\n\nexport type PreviewDevice = 'pc' | 'pad' | 'phone';\n\ninterface DeviceSpec {\n width: number;\n label: string;\n}\n\nconst DEVICES: Record<PreviewDevice, DeviceSpec> = {\n pc: { width: 800, label: 'PC' },\n pad: { width: 640, label: 'Pad' },\n phone: { width: 375, label: 'Phone' },\n};\n\nexport interface PreviewModalOptions {\n store: Store;\n registry: Registry;\n}\n\n/**\n * 预览弹框:用 iframe 渲染真实 mjml 编译产物。\n * 通过 srcdoc 写入 HTML,避免跨域;用变量 sample 值替换占位符,所见即所得。\n * 三个设备宽度切换:800 / 640 / 375,按邮件常见宽度档位。\n */\nexport class PreviewModal {\n private opts: PreviewModalOptions;\n private modal: Modal;\n private device: PreviewDevice = 'pc';\n private iframe: HTMLIFrameElement;\n private viewport: HTMLElement;\n private deviceBtns: Record<PreviewDevice, HTMLButtonElement> = {} as any;\n private iframeRo?: ResizeObserver;\n private layoutRaf: number | null = null;\n private onWinResize?: () => void;\n\n constructor(opts: PreviewModalOptions) {\n this.opts = opts;\n this.modal = new Modal({\n title: '预览邮件',\n className: 'sm-modal--preview',\n width: 'min(960px, calc(100vw - 32px))',\n /** 高度随 iframe 内容测量,见 _fitPreviewHeight;不超过屏高由 CSS max-height 约束 */\n onClose: () => this._teardownLayoutHooks(),\n });\n\n this.iframe = h('iframe', {\n class: 'sm-preview__frame',\n sandbox: 'allow-same-origin',\n title: 'preview',\n }) as HTMLIFrameElement;\n this.iframe.addEventListener('load', () => {\n this._bindIframeResizeObserver();\n this._scheduleFitPreviewHeight();\n });\n\n this.viewport = h('div', { class: 'sm-preview__viewport' }, [this.iframe]);\n this.modal.body.classList.add('sm-modal__body--center');\n this.modal.body.append(this.viewport);\n\n // 设备切换工具条放在 header 右侧\n const switcher = h('div', { class: 'sm-segmented' });\n (['pc', 'pad', 'phone'] as PreviewDevice[]).forEach((d) => {\n const btn = h(\n 'button',\n {\n class: `sm-segmented__item ${d === this.device ? 'sm-segmented__item--active' : ''}`,\n type: 'button',\n onclick: () => this.setDevice(d),\n },\n [iconForDevice(d), DEVICES[d].label],\n ) as HTMLButtonElement;\n this.deviceBtns[d] = btn;\n switcher.append(btn);\n });\n this.modal.appendHeaderTool(switcher);\n }\n\n open(parent?: HTMLElement) {\n this._render();\n this.setDevice(this.device);\n this.modal.open(parent);\n this.onWinResize = () => this._scheduleFitPreviewHeight();\n window.addEventListener('resize', this.onWinResize);\n }\n\n setDevice(d: PreviewDevice) {\n this.device = d;\n const spec = DEVICES[d];\n this.viewport.style.setProperty('--sm-preview-w', `${spec.width}px`);\n for (const k of Object.keys(this.deviceBtns) as PreviewDevice[]) {\n this.deviceBtns[k].classList.toggle('sm-segmented__item--active', k === d);\n }\n requestAnimationFrame(() =>\n requestAnimationFrame(() => this._scheduleFitPreviewHeight()),\n );\n }\n\n private _render() {\n const result = renderDoc(this.opts.store.doc, this.opts.registry, {\n withSampleVariables: true,\n });\n // 用 srcdoc 而非 src=blob:,避免 about:srcdoc 偶发的相对资源问题\n this.iframe.srcdoc = result.html;\n }\n\n /** 标题栏 + body 上下 padding + 与视口的小间距 */\n private static readonly VIEWPORT_RESERVED_Y = 112;\n\n private _scheduleFitPreviewHeight() {\n if (this.layoutRaf != null) cancelAnimationFrame(this.layoutRaf);\n this.layoutRaf = requestAnimationFrame(() => {\n this.layoutRaf = null;\n this._fitPreviewHeight();\n });\n }\n\n private _fitPreviewHeight() {\n if (!this.iframe.isConnected) return;\n try {\n const doc = this.iframe.contentDocument;\n const root = doc?.documentElement;\n const body = doc?.body;\n if (!root || !body) return;\n const raw = Math.max(root.scrollHeight, body.scrollHeight);\n const maxPx = Math.max(\n 240,\n window.innerHeight - PreviewModal.VIEWPORT_RESERVED_Y,\n );\n const minPx = 200;\n const next = Math.min(Math.max(Math.ceil(raw), minPx), maxPx);\n this.viewport.style.height = `${next}px`;\n } catch {\n /* srcdoc 同域,极端情况下忽略 */\n }\n }\n\n private _bindIframeResizeObserver() {\n this.iframeRo?.disconnect();\n try {\n const doc = this.iframe.contentDocument;\n const body = doc?.body;\n if (!body || typeof ResizeObserver === 'undefined') return;\n this.iframeRo = new ResizeObserver(() => this._scheduleFitPreviewHeight());\n this.iframeRo.observe(body);\n const html = doc.documentElement;\n if (html) this.iframeRo.observe(html);\n } catch {\n /* ignore */\n }\n }\n\n private _teardownLayoutHooks() {\n if (this.onWinResize) {\n window.removeEventListener('resize', this.onWinResize);\n this.onWinResize = undefined;\n }\n this.iframeRo?.disconnect();\n this.iframeRo = undefined;\n if (this.layoutRaf != null) {\n cancelAnimationFrame(this.layoutRaf);\n this.layoutRaf = null;\n }\n }\n}\n\nfunction iconForDevice(d: PreviewDevice): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '14');\n el.setAttribute('height', '14');\n el.setAttribute('viewBox', '0 0 20 20');\n if (d === 'pc')\n el.innerHTML =\n '<rect x=\"2\" y=\"4\" width=\"16\" height=\"11\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><path d=\"M7 18h6\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/>';\n else if (d === 'pad')\n el.innerHTML =\n '<rect x=\"4\" y=\"2\" width=\"12\" height=\"16\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"10\" cy=\"16\" r=\"0.6\" fill=\"currentColor\"/>';\n else\n el.innerHTML =\n '<rect x=\"6\" y=\"2\" width=\"8\" height=\"16\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.4\" fill=\"none\"/><circle cx=\"10\" cy=\"16\" r=\"0.6\" fill=\"currentColor\"/>';\n return el;\n}\n","import { bindColorPickerInput } from './ColorPickerPopover';\nimport { h } from '../utils/dom';\nimport { FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport type { InlineEditor, SelectionState } from './InlineEditor';\n\n/**\n * 富文本浮动工具条。\n *\n * 关键设计:\n * - 工具条挂在 editor root 上,跨 block 实例复用;切换编辑对象时调用 attach()。\n * - **mousedown 在工具条任意位置时(capture 阶段)先调用 editor.saveSelection()**:\n * 在浏览器把焦点切到 select/input 之前抢先把选区存到 InlineEditor,\n * 后续 exec 时会自动 focus 回 contenteditable + 恢复选区——这是\n * \"切字体/字号/颜色失灵\"问题的根本修复。\n * - 按钮全部 mousedown.preventDefault:不抢焦点;select/color/url 这些\n * 必须 takeFocus 的控件不能 preventDefault,但因为 mousedown 已经存档了选区,\n * onChange/onClick 时调 exec 即可。\n * - 定位:贴在当前内联编辑根节点(正文容器)**上沿外**,不跟随选区以免压住文字;顶栏贴顶时落到下沿外。\n */\nexport interface RichTextToolbarOptions {\n /** 工具条的定位上下文:rect 是相对该容器计算的 */\n positionRoot: HTMLElement;\n}\n\nconst FONT_FAMILIES = [\n { label: '默认', value: '' },\n { label: 'Inter', value: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif' },\n { label: '苹方/PingFang', value: '\"PingFang SC\", \"Helvetica Neue\", Arial, sans-serif' },\n { label: '微软雅黑', value: '\"Microsoft YaHei\", \"Segoe UI\", sans-serif' },\n { label: '宋体', value: 'SimSun, \"Songti SC\", serif' },\n { label: 'Helvetica', value: '\"Helvetica Neue\", Arial, sans-serif' },\n { label: 'Arial', value: 'Arial, sans-serif' },\n { label: 'Georgia', value: 'Georgia, serif' },\n { label: 'Courier', value: '\"Courier New\", monospace' },\n];\n\nconst FONT_SIZES = ['12px', '13px', '14px', '15px', '16px', '18px', '20px', '24px', '28px', '32px'];\n\nexport class RichTextToolbar {\n el: HTMLElement;\n private opts: RichTextToolbarOptions;\n private editor: InlineEditor | null = null;\n private btns: Record<string, HTMLButtonElement> = {};\n private selectFontFamily!: HTMLSelectElement;\n private selectFontSize!: HTMLSelectElement;\n private selectFontWeight!: HTMLSelectElement;\n private inputColor!: HTMLInputElement;\n private inputBgColor!: HTMLInputElement;\n private inputLink!: HTMLInputElement;\n private linkPanel!: HTMLElement;\n /** 最近一次选区推断出的链接,供打开面板时预填 */\n private lastLinkHref: string | null = null;\n\n constructor(opts: RichTextToolbarOptions) {\n this.opts = opts;\n this.el = h('div', { class: 'sm-floating-toolbar', role: 'toolbar' });\n this._build();\n this.hide();\n opts.positionRoot.append(this.el);\n\n // 关键:用 capture 阶段在所有控件之前抢先 save selection\n this.el.addEventListener(\n 'mousedown',\n () => {\n this.editor?.saveSelection();\n },\n true,\n );\n }\n\n attach(editor: InlineEditor) {\n this.editor = editor;\n }\n\n detach() {\n this.editor = null;\n this.hide();\n }\n\n show() {\n this.el.classList.add('is-visible');\n }\n\n hide() {\n this.el.classList.remove('is-visible');\n this.linkPanel.classList.remove('is-visible');\n }\n\n /** 由 InlineEditor 推选区状态进来 */\n update(state: SelectionState | null) {\n if (!state || !this.editor) {\n this.hide();\n return;\n }\n this.show();\n\n const f = state.formats;\n this._setActive('bold', f.bold);\n this._setActive('italic', f.italic);\n this._setActive('underline', f.underline);\n this._setActive('strikethrough', f.strikethrough);\n this._setActive('ul', f.unorderedList);\n this._setActive('ol', f.orderedList);\n this._setActive('alignLeft', f.align === 'left');\n this._setActive('alignCenter', f.align === 'center');\n this._setActive('alignRight', f.align === 'right');\n\n const hasLink = !!f.link;\n this.lastLinkHref = f.link;\n this.btns.unlink.style.display = hasLink ? '' : 'none';\n\n if (f.foreColor) {\n const hex = colorToHexInput(f.foreColor);\n if (hex) this.inputColor.value = hex;\n }\n this.inputBgColor.value = f.backColor\n ? (colorToHexInput(f.backColor) ?? '#ffffff')\n : '#ffffff';\n if (f.fontName) this.selectFontFamily.value = matchFamily(f.fontName);\n this.selectFontSize.value = matchFontSize(f.fontSize);\n this.selectFontWeight.value = matchFontWeight(f.fontWeight);\n\n const ed = this.editor;\n requestAnimationFrame(() => {\n if (!this.editor || ed !== this.editor || !this.el.classList.contains('is-visible')) return;\n this._positionForAnchor(ed.getAnchorRect());\n });\n }\n\n destroy() {\n this.el.remove();\n }\n\n /* -------------------------------- 内部 ---------------------------------- */\n\n private _build() {\n const sep = () => h('div', { class: 'sm-floating-toolbar__sep' });\n\n // 这些按钮 mousedown.preventDefault 阻止抢焦点;点击时直接 exec\n const exec = (cmd: string, val?: string) => () => this.editor?.exec(cmd, val);\n\n this.btns.bold = this._btn('B', '加粗 ⌘B', exec('bold'), { fontWeight: '700' });\n this.btns.italic = this._btn('I', '斜体 ⌘I', exec('italic'), { fontStyle: 'italic' });\n this.btns.underline = this._btn('U', '下划线 ⌘U', exec('underline'), {\n textDecoration: 'underline',\n });\n this.btns.strikethrough = this._btn('S', '删除线', exec('strikeThrough'), {\n textDecoration: 'line-through',\n });\n\n this.btns.alignLeft = this._iconBtn(\n svgIcon(\n '<path d=\"M3 5h14M3 9h10M3 13h14M3 17h10\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '左对齐',\n exec('justifyLeft'),\n );\n this.btns.alignCenter = this._iconBtn(\n svgIcon(\n '<path d=\"M3 5h14M5 9h10M3 13h14M5 17h10\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '居中',\n exec('justifyCenter'),\n );\n this.btns.alignRight = this._iconBtn(\n svgIcon(\n '<path d=\"M3 5h14M7 9h10M3 13h14M7 17h10\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '右对齐',\n exec('justifyRight'),\n );\n\n this.btns.ul = this._iconBtn(\n svgIcon(\n '<circle cx=\"4\" cy=\"6\" r=\"1.2\" fill=\"currentColor\"/><circle cx=\"4\" cy=\"10\" r=\"1.2\" fill=\"currentColor\"/><circle cx=\"4\" cy=\"14\" r=\"1.2\" fill=\"currentColor\"/><path d=\"M8 6h9M8 10h9M8 14h9\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '无序列表',\n exec('insertUnorderedList'),\n );\n this.btns.ol = this._iconBtn(\n svgIcon(\n '<text x=\"2\" y=\"8\" font-size=\"6\" font-weight=\"600\" fill=\"currentColor\">1</text><text x=\"2\" y=\"14\" font-size=\"6\" font-weight=\"600\" fill=\"currentColor\">2</text><path d=\"M8 6h9M8 12h9\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '有序列表',\n exec('insertOrderedList'),\n );\n\n // 字体:select 不能 preventDefault(否则下拉打不开);mousedown(capture) 已存档选区\n this.selectFontFamily = h('select', {\n class: 'sm-floating-toolbar__select',\n title: '字体',\n onchange: (e: Event) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v) this.editor?.exec('fontName', v);\n else this.editor?.exec('removeFormat');\n },\n });\n for (const f of FONT_FAMILIES) {\n const opt = document.createElement('option');\n opt.value = f.value;\n opt.textContent = f.label;\n this.selectFontFamily.append(opt);\n }\n\n // 字号\n this.selectFontSize = h('select', {\n class: 'sm-floating-toolbar__select',\n title: '字号',\n onchange: (e: Event) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v) this.editor?.applyFontSize(v);\n },\n });\n {\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = '字号';\n this.selectFontSize.append(placeholder);\n }\n for (const px of FONT_SIZES) {\n const opt = document.createElement('option');\n opt.value = px;\n opt.textContent = px;\n this.selectFontSize.append(opt);\n }\n\n // 字重\n this.selectFontWeight = h('select', {\n class: 'sm-floating-toolbar__select',\n title: '字重',\n onchange: (e: Event) => {\n const v = (e.target as HTMLSelectElement).value;\n if (v) this.editor?.applyFontWeight(v);\n },\n });\n {\n const placeholder = document.createElement('option');\n placeholder.value = '';\n placeholder.textContent = '字重';\n this.selectFontWeight.append(placeholder);\n }\n for (const w of FONT_WEIGHT_STEP_OPTIONS) {\n const opt = document.createElement('option');\n opt.value = w.value;\n opt.textContent = w.label;\n this.selectFontWeight.append(opt);\n }\n\n // 文字颜色\n this.inputColor = h('input', {\n class: 'sm-floating-toolbar__color',\n type: 'color',\n title: '文字颜色',\n value: '#433f3f',\n }) as HTMLInputElement;\n bindColorPickerInput(this.inputColor, {\n layerRoot: this.opts.positionRoot,\n liveCommit: true,\n autoFocusHex: false,\n onBeforeOpen: () => this.editor?.saveSelection(),\n onCommit: (hex) => this.editor?.exec('foreColor', hex),\n onClosed: () => this.editor?.refocus(),\n });\n\n // 文字背景色\n this.inputBgColor = h('input', {\n class: 'sm-floating-toolbar__color',\n type: 'color',\n title: '文字背景色',\n value: '#fff7e6',\n }) as HTMLInputElement;\n bindColorPickerInput(this.inputBgColor, {\n layerRoot: this.opts.positionRoot,\n liveCommit: true,\n autoFocusHex: false,\n onBeforeOpen: () => this.editor?.saveSelection(),\n onCommit: (hex) => this.editor?.exec('hiliteColor', hex),\n onClosed: () => this.editor?.refocus(),\n });\n\n // 链接:插入链接(无链接时显示)\n this.btns.link = this._iconBtn(\n svgIcon(\n '<path d=\"M9 11.5l1.5 1.5a3.5 3.5 0 005-5l-2-2a3.5 3.5 0 00-5 0M11 8.5L9.5 7a3.5 3.5 0 00-5 5l2 2a3.5 3.5 0 005 0\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>',\n ),\n '插入或编辑链接',\n () => this._toggleLinkPanel(),\n );\n\n // 取消链接(有链接时显示)\n this.btns.unlink = this._iconBtn(\n svgIcon(\n '<path d=\"M9 11.5l1.5 1.5a3.5 3.5 0 005-5l-2-2\" stroke=\"currentColor\" stroke-width=\"1.6\" fill=\"none\" stroke-linecap=\"round\"/><path d=\"M3 3l14 14\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"/>',\n ),\n '取消链接',\n exec('unlink'),\n );\n\n // 清除格式:图标改为 Tx,避免被误认为\"关闭工具条\"\n this.btns.clear = this._iconBtn(\n svgIcon(\n '<text x=\"2\" y=\"14\" font-size=\"11\" font-weight=\"700\" fill=\"currentColor\">T</text><text x=\"11\" y=\"9\" font-size=\"7\" font-weight=\"700\" fill=\"currentColor\">x</text><path d=\"M11 11l5 5M16 11l-5 5\" stroke=\"currentColor\" stroke-width=\"1.4\" stroke-linecap=\"round\"/>',\n ),\n '清除格式',\n exec('removeFormat'),\n );\n\n this.linkPanel = h('div', { class: 'sm-floating-toolbar__link-panel' });\n this.inputLink = h('input', {\n class: 'sm-input',\n type: 'url',\n placeholder: 'https://...',\n onkeydown: ((e: Event) => {\n const ke = e as KeyboardEvent;\n if (ke.key === 'Enter') {\n ke.preventDefault();\n this._applyLink();\n } else if (ke.key === 'Escape') {\n ke.preventDefault();\n this.linkPanel.classList.remove('is-visible');\n this.editor?.refocus();\n }\n }) as EventListener,\n }) as HTMLInputElement;\n const applyLinkBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onmousedown: (e: Event) => e.preventDefault(),\n onclick: () => this._applyLink(),\n },\n ['确定'],\n );\n this.linkPanel.append(this.inputLink, applyLinkBtn);\n\n this.el.append(\n this._group([this.btns.bold, this.btns.italic, this.btns.underline, this.btns.strikethrough]),\n sep(),\n this._group([this.selectFontFamily, this.selectFontSize, this.selectFontWeight]),\n sep(),\n this._group([this.inputColor, this.inputBgColor]),\n sep(),\n this._group([this.btns.alignLeft, this.btns.alignCenter, this.btns.alignRight]),\n sep(),\n this._group([this.btns.ul, this.btns.ol]),\n sep(),\n this._group([this.btns.link, this.btns.unlink, this.btns.clear]),\n this.linkPanel,\n );\n }\n\n private _toggleLinkPanel() {\n const opening = !this.linkPanel.classList.contains('is-visible');\n this.linkPanel.classList.toggle('is-visible');\n if (this.linkPanel.classList.contains('is-visible')) {\n if (opening) {\n this.inputLink.value = this.lastLinkHref ?? '';\n }\n requestAnimationFrame(() => this.inputLink.focus());\n } else {\n this.editor?.refocus();\n }\n }\n\n private _applyLink() {\n if (!this.editor) return;\n const url = this.inputLink.value.trim();\n this.editor.setLink(url);\n this.linkPanel.classList.remove('is-visible');\n this.inputLink.value = '';\n }\n\n /**\n * 相对 `positionRoot` 定位:默认贴在**正文容器**上沿上方,避免压在选区文字上;\n * 若顶端空间不足则贴在容器下沿下方。\n */\n private _positionForAnchor(anchor: DOMRect) {\n const rootRect = this.opts.positionRoot.getBoundingClientRect();\n const gap = 6;\n const bar = this.el.getBoundingClientRect();\n const tw = bar.width || this.el.offsetWidth;\n const th = bar.height || this.el.offsetHeight || 40;\n\n let top = anchor.top - rootRect.top - th - gap;\n if (top < 8) {\n top = anchor.bottom - rootRect.top + gap;\n }\n\n const left = Math.max(\n 8,\n Math.min(\n anchor.left - rootRect.left + anchor.width / 2 - tw / 2,\n rootRect.width - tw - 8,\n ),\n );\n\n this.el.style.top = `${top}px`;\n this.el.style.left = `${left}px`;\n }\n\n private _setActive(key: string, on: boolean) {\n this.btns[key]?.classList.toggle('is-active', on);\n }\n\n private _btn(\n text: string,\n title: string,\n onClick: () => void,\n style: Partial<CSSStyleDeclaration> = {},\n ): HTMLButtonElement {\n const b = h(\n 'button',\n {\n class: 'sm-floating-toolbar__btn',\n type: 'button',\n title,\n onmousedown: (e: Event) => e.preventDefault(),\n onclick: onClick,\n },\n [text],\n ) as HTMLButtonElement;\n Object.assign(b.style, style);\n return b;\n }\n\n private _iconBtn(icon: SVGElement, title: string, onClick: () => void): HTMLButtonElement {\n return h(\n 'button',\n {\n class: 'sm-floating-toolbar__btn',\n type: 'button',\n title,\n onmousedown: (e: Event) => e.preventDefault(),\n onclick: onClick,\n },\n [icon],\n ) as HTMLButtonElement;\n }\n\n private _group(children: HTMLElement[]): HTMLElement {\n return h('div', { class: 'sm-floating-toolbar__group' }, children);\n }\n}\n\nfunction svgIcon(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '14');\n el.setAttribute('height', '14');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML = inner;\n return el;\n}\n\nfunction matchFamily(name: string): string {\n const lower = name.toLowerCase().replace(/['\"]/g, '').split(',')[0].trim();\n for (const f of FONT_FAMILIES) {\n if (!f.value) continue;\n if (f.value.toLowerCase().includes(lower)) return f.value;\n }\n return '';\n}\n\nfunction matchFontSize(raw: string | null): string {\n if (!raw) return '';\n const m = raw.trim().match(/^(\\d+(?:\\.\\d+)?)px$/i);\n if (!m) return '';\n const px = `${Math.round(parseFloat(m[1]))}px`;\n if (FONT_SIZES.includes(px)) return px;\n const num = parseFloat(px);\n let best = FONT_SIZES[0];\n let bestD = Infinity;\n for (const s of FONT_SIZES) {\n const d = Math.abs(parseFloat(s) - num);\n if (d < bestD) {\n bestD = d;\n best = s;\n }\n }\n return best;\n}\n\nfunction matchFontWeight(raw: string | null): string {\n if (!raw) return '';\n const step = normalizeFontWeightStep(raw);\n return FONT_WEIGHT_STEP_OPTIONS.some((w) => w.value === step) ? step : '';\n}\n\nfunction colorToHexInput(color: string): string | null {\n const s = color.trim();\n if (!s) return null;\n if (s.startsWith('#')) {\n if (/^#[0-9a-f]{3}$/i.test(s)) {\n const r = s[1];\n const g = s[2];\n const b = s[3];\n return `#${r}${r}${g}${g}${b}${b}`.toLowerCase();\n }\n if (/^#[0-9a-f]{6}$/i.test(s)) return s.toLowerCase();\n return s;\n }\n const m = s.match(/^rgba?\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)/i);\n if (!m) return null;\n const toHex = (n: string) => Number(n).toString(16).padStart(2, '0');\n return `#${toHex(m[1])}${toHex(m[2])}${toHex(m[3])}`;\n}\n","/** 与 blocks 中社交图标预设背景一致;core 不可依赖 blocks,供属性面板展示默认背景色 */\nexport function defaultSocialIconBackground(network: string): string {\n const m: Record<string, string> = {\n wechat: '#1AAD19',\n weibo: '#E6162D',\n x: '#000000',\n linkedin: '#0A66C2',\n github: '#181717',\n facebook: '#1877F2',\n instagram: '#E4405F',\n ig: '#E4405F',\n youtube: '#FF0000',\n tiktok: '#000000',\n rabbit: '#FF2442',\n website: '#6b7280',\n web: '#6b7280',\n };\n return m[network] ?? '#6b7280';\n}\n","import type { Registry } from '../registry/registry';\nimport type { Store } from '../store/store';\nimport { findBlockLocation, findSection } from '../store/store';\nimport { clear, h } from '../utils/dom';\nimport { layoutHumanLabel } from '../utils/sectionLayout';\n\nexport interface FocusBreadcrumbOptions {\n store: Store;\n registry: Registry;\n /** 文档级根节点文案(如「邮件」/「版式」) */\n docRootLabel: string;\n onFocusDocument: () => void;\n onFocusSection: (sectionId: string) => void;\n}\n\ninterface CrumbItem {\n label: string;\n current: boolean;\n onClick?: () => void;\n}\n\n/**\n * 右栏聚焦路径:邮件 > 一列 > 文本。\n * 点击父级等同 Esc 上浮(块 → Section → 文档级面板)。\n */\nexport class FocusBreadcrumb {\n el: HTMLElement;\n private opts: FocusBreadcrumbOptions;\n\n constructor(opts: FocusBreadcrumbOptions) {\n this.opts = opts;\n this.el = h('nav', {\n class: 'sm-focus-crumb',\n 'aria-label': '当前选中',\n });\n opts.store.subscribeSelection(() => this.sync());\n opts.store.subscribe(() => this.sync());\n this.sync();\n }\n\n setVisible(on: boolean) {\n this.el.hidden = !on;\n }\n\n sync() {\n clear(this.el);\n const items = this._buildItems();\n if (!items.length) {\n this.el.hidden = true;\n return;\n }\n this.el.hidden = false;\n\n items.forEach((item, i) => {\n if (i > 0) {\n this.el.append(h('span', { class: 'sm-focus-crumb__sep', 'aria-hidden': 'true' }, ['›']));\n }\n if (item.current || !item.onClick) {\n this.el.append(\n h(\n 'span',\n {\n class: `sm-focus-crumb__item sm-focus-crumb__item--current`,\n title: item.label,\n },\n [item.label],\n ),\n );\n } else {\n this.el.append(\n h(\n 'button',\n {\n type: 'button',\n class: 'sm-focus-crumb__item',\n title: `选中:${item.label}`,\n onclick: () => item.onClick!(),\n },\n [item.label],\n ),\n );\n }\n });\n }\n\n private _buildItems(): CrumbItem[] {\n const { store, registry, docRootLabel, onFocusDocument, onFocusSection } = this.opts;\n const sel = store.selection;\n const doc = store.doc;\n\n if (!sel) {\n return [{ label: docRootLabel, current: true }];\n }\n\n if (sel.kind === 'section') {\n const sec = findSection(doc, sel.sectionId);\n if (!sec) return [{ label: docRootLabel, current: true }];\n return [\n { label: docRootLabel, current: false, onClick: onFocusDocument },\n { label: layoutHumanLabel(sec.layout), current: true },\n ];\n }\n\n const sec = findSection(doc, sel.sectionId);\n const loc = findBlockLocation(doc, sel.blockId);\n if (!sec || !loc) {\n return [{ label: docRootLabel, current: true }];\n }\n\n const blockName = registry.get(loc.block.type)?.name ?? loc.block.type;\n return [\n {\n label: layoutHumanLabel(sec.layout),\n current: false,\n onClick: () => onFocusSection(sel.sectionId),\n },\n { label: blockName, current: true },\n ];\n }\n}\n","import type { GalleryItem, ImageGalleryAdapter } from './imageAssets';\nimport { Modal } from './Modal';\nimport { clear, h } from '../utils/dom';\n\nexport interface OpenImageGalleryModalOptions {\n adapter: ImageGalleryAdapter;\n onPick: (url: string) => void;\n /** 挂载父节点,默认 `document.body` */\n parent?: HTMLElement;\n onClose?: () => void;\n}\n\n/**\n * 打开内置图库弹层:搜索、分页、选图插入;可选「链接添加」「上传到图库」「删除」由 adapter 决定。\n */\nexport function openImageGalleryModal(opts: OpenImageGalleryModalOptions): void {\n const { adapter, onPick, parent = document.body, onClose } = opts;\n\n const modal = new Modal({\n title: '图库',\n width: 'min(760px, 94vw)',\n height: 'min(580px, 88vh)',\n className: 'sm-modal--gallery',\n onClose,\n });\n\n const wrap = h('div', { class: 'sm-gallery-modal' });\n\n let query = '';\n let page = 0;\n let hasMore = false;\n let loading = false;\n let selected: GalleryItem | null = null;\n\n const errEl = h('div', {\n class: 'sm-gallery-modal__error',\n style: 'display:none',\n role: 'alert',\n });\n\n const searchInp = h('input', {\n class: 'sm-input sm-gallery-modal__search',\n type: 'search',\n placeholder: '搜索…',\n 'aria-label': '搜索图片',\n });\n\n let debounceId: ReturnType<typeof setTimeout> | null = null;\n searchInp.addEventListener('input', () => {\n if (debounceId) clearTimeout(debounceId);\n debounceId = setTimeout(() => {\n query = (searchInp as HTMLInputElement).value;\n void loadFirst();\n }, 320);\n });\n\n const gridEl = h('div', { class: 'sm-gallery-modal__grid' });\n\n const loadMoreBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-gallery-modal__loadmore',\n type: 'button',\n style: 'display:none',\n onclick: () => {\n if (!hasMore || loading) return;\n void loadPage(page + 1, true);\n },\n },\n ['加载更多'],\n ) as HTMLButtonElement;\n\n const confirmBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n disabled: true,\n onclick: () => finishPick(),\n },\n ['插入'],\n ) as HTMLButtonElement;\n\n function setError(msg: string | null) {\n if (msg) {\n errEl.textContent = msg;\n errEl.style.display = '';\n } else {\n errEl.textContent = '';\n errEl.style.display = 'none';\n }\n }\n\n function syncSelectionStyles() {\n const cells = gridEl.querySelectorAll('.sm-gallery-modal__cell');\n cells.forEach((c) => {\n const id = (c as HTMLElement).dataset.id;\n c.classList.toggle('is-selected', !!selected && id === selected.id);\n });\n }\n\n function renderCells(items: GalleryItem[], append: boolean) {\n if (!append) clear(gridEl);\n if (items.length === 0 && !append) {\n gridEl.append(\n h('div', { class: 'sm-gallery-modal__empty' }, [\n '暂无图片,可上传、添加链接或更换搜索条件',\n ]),\n );\n loadMoreBtn.style.display = hasMore ? '' : 'none';\n return;\n }\n for (const it of items) {\n const thumb = it.thumbnailUrl || it.url;\n const cellWrap = h('div', { class: 'sm-gallery-modal__cell-wrap' });\n const cell = h(\n 'button',\n {\n type: 'button',\n class: 'sm-gallery-modal__cell',\n title: it.title || it.url,\n 'data-id': it.id,\n onclick: () => {\n selected = it;\n syncSelectionStyles();\n confirmBtn.disabled = false;\n },\n ondblclick: (e: Event) => {\n e.preventDefault();\n selected = it;\n finishPick();\n },\n },\n [],\n );\n const img = h('img', {\n class: 'sm-gallery-modal__thumb',\n alt: '',\n loading: 'lazy',\n decoding: 'async',\n }) as HTMLImageElement;\n img.src = thumb;\n img.onerror = () => {\n img.style.opacity = '0.72';\n };\n const cap = h('div', { class: 'sm-gallery-modal__caption' }, [\n it.title?.trim() ? it.title : '图片',\n ]);\n cell.append(img, cap);\n cellWrap.append(cell);\n\n if (adapter.deleteItem) {\n const delBtn = h(\n 'button',\n {\n type: 'button',\n class: 'sm-gallery-modal__cell-delete',\n title: '从图库删除',\n onclick: async (e: Event) => {\n e.preventDefault();\n e.stopPropagation();\n if (!window.confirm('确定从图库中删除这张图片?')) return;\n try {\n await adapter.deleteItem!(it.id);\n if (selected?.id === it.id) {\n selected = null;\n confirmBtn.disabled = true;\n }\n await loadFirst();\n } catch (err) {\n setError(err instanceof Error ? err.message : '删除失败');\n }\n },\n },\n ['×'],\n );\n cellWrap.append(delBtn);\n }\n\n gridEl.append(cellWrap);\n }\n loadMoreBtn.style.display = hasMore ? '' : 'none';\n }\n\n async function loadPage(p: number, append: boolean) {\n if (loading) return;\n loading = true;\n loadMoreBtn.disabled = true;\n setError(null);\n try {\n const res = await adapter.listItems({ query, page: p });\n hasMore = res.hasMore;\n page = p;\n renderCells(res.items, append);\n } catch (e) {\n setError(e instanceof Error ? e.message : '加载失败');\n } finally {\n loading = false;\n loadMoreBtn.disabled = false;\n }\n }\n\n async function loadFirst() {\n page = 0;\n selected = null;\n confirmBtn.disabled = true;\n clear(gridEl);\n await loadPage(0, false);\n syncSelectionStyles();\n }\n\n function finishPick() {\n if (!selected?.url?.trim()) return;\n onPick(selected.url.trim());\n modal.close();\n }\n\n /** 搜索、链接、添加、上传同一行(窄屏可换行) */\n const toolbar = h('div', { class: 'sm-gallery-modal__toolbar' });\n const toolRow = h('div', { class: 'sm-gallery-modal__toolbar-row' });\n toolRow.append(searchInp);\n\n if (adapter.addByUrl) {\n const urlInp = h('input', {\n class: 'sm-input sm-gallery-modal__addurl-input',\n type: 'url',\n placeholder: '图片链接 https://…',\n }) as HTMLInputElement;\n const addBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-gallery-modal__toolbar-action',\n type: 'button',\n onclick: async () => {\n const u = urlInp.value.trim();\n if (!u) return;\n try {\n await adapter.addByUrl!(u);\n urlInp.value = '';\n await loadFirst();\n } catch (e) {\n setError(e instanceof Error ? e.message : '添加失败');\n }\n },\n },\n ['添加'],\n );\n toolRow.append(urlInp, addBtn);\n }\n\n if (adapter.uploadFile) {\n const fileInp = h('input', {\n type: 'file',\n accept: 'image/*',\n class: 'sm-gallery-modal__file',\n });\n fileInp.addEventListener('change', async () => {\n const f = (fileInp as HTMLInputElement).files?.[0];\n (fileInp as HTMLInputElement).value = '';\n if (!f) return;\n try {\n await adapter.uploadFile!(f);\n await loadFirst();\n } catch (e) {\n setError(e instanceof Error ? e.message : '上传失败');\n }\n });\n const upBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-gallery-modal__toolbar-action',\n type: 'button',\n onclick: () => fileInp.click(),\n },\n ['上传'],\n );\n toolRow.append(upBtn, fileInp);\n }\n\n toolbar.append(toolRow);\n\n const scrollArea = h('div', { class: 'sm-gallery-modal__scroll' }, [gridEl, loadMoreBtn]);\n\n wrap.append(toolbar, errEl, scrollArea);\n\n modal.body.append(wrap);\n modal.footer.append(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary',\n type: 'button',\n onclick: () => modal.close(),\n },\n ['取消'],\n ),\n confirmBtn,\n );\n\n modal.open(parent);\n void loadFirst();\n}\n","import { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport { EditorState } from '@codemirror/state';\nimport type { Registry } from '../registry/registry';\nimport {\n findBlockLocation,\n findSection,\n isTwoColumnLayout,\n setSectionLayout,\n type Store,\n type DocChangedDetail,\n} from '../store/store';\nimport type {\n Block,\n BlockSchemaField,\n EditorUiOptions,\n EmailDoc,\n Section,\n SectionLayout,\n} from '../types';\nimport { defaultSocialIconBackground } from '../socialDefaults';\nimport { bindColorPickerInput } from './ColorPickerPopover';\nimport { normalizeAccentHex } from '../utils/accentColor';\nimport { clear, h } from '../utils/dom';\nimport { metaWidthInputString, parseMetaWidthFromUserInput, parseSectionWidthFromUserInput, sectionWidthInputString } from '../utils/contentWidth';\nimport { FONT_WEIGHT_STEP_OPTIONS, normalizeFontWeightStep } from '../utils/fontWeightSteps';\nimport type { ImageAssetsHandlers, ImageFieldContext } from './imageAssets';\nimport { FocusBreadcrumb } from './FocusBreadcrumb';\nimport { openImageGalleryModal } from './ImageGalleryModal';\n\n/** 与社交组 block 中每行元素结构一致(core 不依赖 blocks) */\ntype SocialLinkRow = {\n network: string;\n href: string;\n label?: string;\n iconSrc?: string;\n backgroundColor?: string;\n};\n\n/** 宽度滑块:解析右栏当前字符串 */\nfunction classifyLayoutWidth(raw: string): 'auto' | 'px' | '%' | 'custom' {\n const t = (raw ?? '').trim();\n if (!t || t.toLowerCase() === 'auto') return 'auto';\n if (/^\\d+(\\.\\d+)?%$/.test(t)) return '%';\n if (/^\\d+(\\.\\d+)?px$/i.test(t)) return 'px';\n if (/^\\d+(\\.\\d+)?$/.test(t)) return 'px';\n return 'custom';\n}\n\nfunction layoutWidthNumeric(raw: string, mode: 'px' | '%'): number {\n const t = (raw ?? '').trim();\n if (!t) return mode === '%' ? 100 : 280;\n const m = t.match(/^(\\d+(\\.\\d+)?)/);\n const n = m ? parseFloat(m[1]) : mode === '%' ? 100 : 280;\n if (mode === '%') return Math.min(100, Math.max(1, Math.round(n)));\n return Math.min(1200, Math.max(1, Math.round(n)));\n}\n\nexport interface RightPanelOptions {\n store: Store;\n registry: Registry;\n /** 聚焦路径根节点文案(文档级),默认「邮件」 */\n docRootLabel?: string;\n /** 点击路径中的 Section 层级 */\n onFocusSection: (sectionId: string) => void;\n /** 点击路径中的文档级层级(等同 Esc 从 Section 上浮) */\n onFocusDocument: () => void;\n /**\n * 可选。配置后,schema 中 `type: 'image'` 的字段会显示「上传 / 图床」按钮并调用对应回调。\n */\n imageAssets?: ImageAssetsHandlers;\n /** 与 MailEditor.opts.ui 对齐 */\n ui?: EditorUiOptions;\n}\n\ntype RightTab = 'props' | 'code';\n\n/**\n * 右栏:选中 Section/Block 时显示对应配置;未选中显示文档级配置(标题/宽度/全局样式)。\n * Block 选中时多一个\"代码\"Tab,可编辑该 Block 的 MJML 片段(CodeMirror)。\n */\nexport class RightPanel {\n el: HTMLElement;\n private opts: RightPanelOptions;\n private headEl: HTMLElement;\n private contentEl: HTMLElement;\n private focusCrumb: FocusBreadcrumb;\n private currentTab: RightTab = 'props';\n private codeView: EditorView | null = null;\n\n private _preferSliderControls(): boolean {\n return this.opts.ui?.preferSliderControls === true;\n }\n\n private _hideMailMeta(): boolean {\n return this.opts.ui?.hideMailMeta === true;\n }\n\n constructor(opts: RightPanelOptions) {\n this.opts = opts;\n this.el = h('aside', { class: 'sm-panel sm-panel--right' });\n this.focusCrumb = new FocusBreadcrumb({\n store: opts.store,\n registry: opts.registry,\n docRootLabel: opts.docRootLabel ?? '邮件',\n onFocusDocument: () => opts.onFocusDocument(),\n onFocusSection: (id) => opts.onFocusSection(id),\n });\n this.headEl = h('div', { class: 'sm-panel__head' }, [this.focusCrumb.el]);\n this.contentEl = h('div', { class: 'sm-panel__body' });\n this.el.append(this.headEl, this.contentEl);\n this._syncHeadVisibility();\n this._render();\n opts.store.subscribe((detail?: DocChangedDetail) => {\n if (detail?.source === 'history') {\n this._renderPreservingFieldFocus();\n return;\n }\n if (detail?.source === 'replace') {\n this._render();\n return;\n }\n // update() 每打一字符都会 notify;整栏 clear 会拆掉输入框导致失焦\n if (this._shouldSkipRenderBecauseFocused()) return;\n this._render();\n });\n opts.store.subscribeSelection(() => {\n this.currentTab = 'props';\n this._syncHeadVisibility();\n this._render();\n });\n }\n\n /** 文档级(无选中)时不展示面包屑,避免与「邮件设置」标题重复 */\n private _syncHeadVisibility() {\n const show = !!this.opts.store.selection;\n this.headEl.hidden = !show;\n }\n\n /** 焦点在右栏可编辑控件上时不要整栏重渲染(避免输入/CodeMirror 失焦) */\n private _shouldSkipRenderBecauseFocused(): boolean {\n const ae = document.activeElement as HTMLElement | null;\n if (!ae || !this.el.contains(ae)) return false;\n if (ae.closest('.cm-editor')) return true;\n const tag = ae.tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return true;\n return false;\n }\n\n /** undo/redo 后整栏重绘,但尽量回到同一输入框与光标位置 */\n private _renderPreservingFieldFocus() {\n const ae = document.activeElement as HTMLElement | null;\n let token: string | null = null;\n let selStart = 0;\n let selEnd = 0;\n if (ae && this.el.contains(ae)) {\n token = ae.getAttribute('data-sm-focus');\n if (\n token &&\n (ae instanceof HTMLInputElement || ae instanceof HTMLTextAreaElement)\n ) {\n selStart = ae.selectionStart ?? 0;\n selEnd = ae.selectionEnd ?? 0;\n }\n }\n this._render();\n if (!token) return;\n const next = this._findFocusEl(token);\n next?.focus();\n if (next instanceof HTMLInputElement || next instanceof HTMLTextAreaElement) {\n const len = next.value.length;\n next.setSelectionRange(Math.min(selStart, len), Math.min(selEnd, len));\n }\n }\n\n private _findFocusEl(token: string): HTMLElement | null {\n for (const el of this.el.querySelectorAll('[data-sm-focus]')) {\n if ((el as HTMLElement).getAttribute('data-sm-focus') === token) return el as HTMLElement;\n }\n return null;\n }\n\n private _render() {\n this._destroyCodeView();\n clear(this.contentEl);\n\n const sel = this.opts.store.selection;\n const doc = this.opts.store.doc;\n\n if (!sel) {\n this.contentEl.append(this._renderDocForm(doc));\n return;\n }\n\n if (sel.kind === 'section') {\n const section = findSection(doc, sel.sectionId);\n if (!section) return;\n this.contentEl.append(this._renderSectionForm(section));\n return;\n }\n\n // block\n const loc = findBlockLocation(doc, sel.blockId);\n if (!loc) {\n const tabs = h('div', { class: 'sm-tabs' }, [\n this._tabBtn('props', '属性'),\n this._tabBtn('code', '代码'),\n ]);\n this.contentEl.append(tabs);\n this.contentEl.append(\n h('div', { class: 'sm-empty-form' }, ['该组件可能已被删除,请重新选中画布中的块。']),\n );\n return;\n }\n const def = this.opts.registry.get(loc.block.type);\n\n const tabs = h('div', { class: 'sm-tabs' }, [\n this._tabBtn('props', '属性'),\n this._tabBtn('code', '代码'),\n ]);\n this.contentEl.append(tabs);\n\n if (this.currentTab === 'props') {\n if (loc.block.lockedMjml) {\n this.contentEl.append(\n h('div', { class: 'sm-empty-form' }, [\n '该组件已被代码模式锁定。',\n h('div', { style: 'margin-top:8px;' }, [\n h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: () => {\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, loc.block.id);\n if (l) delete l.block.lockedMjml;\n });\n },\n },\n ['恢复为属性模式'],\n ),\n ]),\n ]),\n );\n } else if (def) {\n this.contentEl.append(this._renderBlockForm(loc.block, def.schema));\n } else {\n this.contentEl.append(\n h('div', { class: 'sm-empty-form' }, [`未注册的组件: ${loc.block.type}`]),\n );\n }\n } else {\n this.contentEl.append(this._renderBlockCodeView(loc.block));\n }\n }\n\n private _tabBtn(tab: RightTab, label: string) {\n return h(\n 'button',\n {\n class: `sm-tabs__item ${this.currentTab === tab ? 'sm-tabs__item--active' : ''}`,\n type: 'button',\n onclick: () => {\n this.currentTab = tab;\n this._render();\n },\n },\n [label],\n );\n }\n\n /* ------------------------------ 文档级表单 ------------------------------- */\n\n private _renderDocForm(doc: EmailDoc): HTMLElement {\n const hideMeta = this._hideMailMeta();\n const rows: HTMLElement[] = [];\n if (!hideMeta) {\n rows.push(\n h('div', { class: 'sm-panel__title' }, ['邮件设置']),\n this._textField('主题', doc.meta.subject, (v) =>\n this.opts.store.update((d) => {\n d.meta.subject = v;\n }),\n '',\n 'doc:meta.subject',\n ),\n this._textField('Preheader', doc.meta.preheader ?? '', (v) =>\n this.opts.store.update((d) => {\n d.meta.preheader = v;\n }),\n '',\n 'doc:meta.preheader',\n ),\n );\n } else {\n rows.push(h('div', { class: 'sm-panel__title' }, ['版式']));\n }\n rows.push(\n this._textField(\n '内容宽度',\n metaWidthInputString(doc.meta.width),\n (v) =>\n this.opts.store.update((d) => {\n d.meta.width = parseMetaWidthFromUserInput(v);\n }),\n '如 600、600px、100%',\n 'doc:meta.width',\n ),\n h('div', { class: 'sm-panel__title' }, ['全局样式']),\n this._colorField(\n '页面背景',\n doc.styles.backgroundColor,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.backgroundColor = v;\n }),\n 'doc:styles.backgroundColor',\n ),\n this._colorField(\n '内容背景',\n doc.styles.contentBackgroundColor,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.contentBackgroundColor = v;\n }),\n 'doc:styles.contentBackgroundColor',\n ),\n this._textField(\n '字体',\n doc.styles.fontFamily,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.fontFamily = v;\n }),\n '',\n 'doc:styles.fontFamily',\n ),\n this._docFontSizeField(\n doc.styles.fontSize,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.fontSize = v;\n }),\n 'doc:styles.fontSize',\n ),\n this._docFontWeightField(\n doc.styles.fontWeight ?? '400',\n (v) =>\n this.opts.store.update((d) => {\n d.styles.fontWeight = v;\n }),\n 'doc:styles.fontWeight',\n ),\n this._textField(\n '行高',\n doc.styles.lineHeight ?? '1.25',\n (v) =>\n this.opts.store.update((d) => {\n d.styles.lineHeight = v;\n }),\n '如 1.25 或 24px',\n 'doc:styles.lineHeight',\n ),\n this._colorField(\n '正文颜色',\n doc.styles.color,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.color = v;\n }),\n 'doc:styles.color',\n ),\n this._colorField(\n '链接颜色',\n doc.styles.linkColor,\n (v) =>\n this.opts.store.update((d) => {\n d.styles.linkColor = v;\n }),\n 'doc:styles.linkColor',\n ),\n );\n return h('form', { class: 'sm-form', onsubmit: (e: Event) => e.preventDefault() }, rows);\n }\n\n /* ------------------------------ Section 表单 ----------------------------- */\n\n private _renderSectionForm(section: Section): HTMLElement {\n const a = section.attrs;\n return h('form', { class: 'sm-form', onsubmit: (e: Event) => e.preventDefault() }, [\n h('div', { class: 'sm-panel__title' }, ['Section 设置']),\n ...(isTwoColumnLayout(section.layout)\n ? [\n this._twoColumnRatioField(\n section.layout,\n (layout) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) setSectionLayout(s, layout);\n }),\n `section:${section.id}:layout`,\n ),\n ]\n : []),\n this._colorField(\n '背景色',\n a.backgroundColor ?? '',\n (v) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.backgroundColor = v || undefined;\n }),\n `section:${section.id}:attrs.bg`,\n '留空=透明',\n ),\n this._layoutWidthField(\n '区域宽度',\n sectionWidthInputString(a.width),\n (v) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.width = parseSectionWidthFromUserInput(v);\n }),\n `section:${section.id}:attrs.width`,\n '留空=与邮件同宽;自适应等价于清空宽度',\n ),\n this._spacingField(\n '内边距',\n [a.paddingTop, a.paddingRight, a.paddingBottom, a.paddingLeft],\n (vals) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (!s) return;\n [s.attrs.paddingTop, s.attrs.paddingRight, s.attrs.paddingBottom, s.attrs.paddingLeft] =\n vals;\n }),\n `section:${section.id}:attrs.pad`,\n [0, 0, 0, 0],\n ),\n section.layout !== '1'\n ? this._numberField(\n '列间距 (px)',\n a.columnGap ?? 0,\n 0,\n 64,\n (v) => {\n const g = Math.max(0, Math.min(64, Math.round(v)));\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.columnGap = g > 0 ? g : undefined;\n });\n },\n 1,\n `section:${section.id}:attrs.columnGap`,\n )\n : null,\n section.layout !== '1'\n ? this._switchField(\n '小屏仍并排显示多列(可能字很窄)',\n !!a.preserveColumnsOnMobile,\n (checked) =>\n this.opts.store.update((d) => {\n const s = findSection(d, section.id);\n if (s) s.attrs.preserveColumnsOnMobile = checked || undefined;\n }),\n '开启后 MJML 会生成 mj-group,移动端预览/导出与默认「小屏堆叠列」行为不同。',\n `section:${section.id}:attrs.preserveMobile`,\n )\n : null,\n ]);\n }\n\n /* ------------------------------- Block 表单 ----------------------------- */\n\n private _renderBlockForm(block: Block, schema: BlockSchemaField[]): HTMLElement {\n const form = h('form', { class: 'sm-form', onsubmit: (e: Event) => e.preventDefault() });\n for (const field of schema) {\n form.append(this._field(field, block));\n }\n return form;\n }\n\n private _updateBlock(blockId: string, key: string, value: unknown) {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, blockId);\n if (!loc) return;\n (loc.block.props as any)[key] = value;\n });\n }\n\n private _field(field: BlockSchemaField, block: Block): HTMLElement {\n const blockId = block.id;\n const fp = `block:${blockId}:${field.key}`;\n const def = this.opts.registry.get(block.type);\n const defaults = def?.defaultProps as Record<string, unknown> | undefined;\n const raw = (block.props as Record<string, unknown>)[field.key];\n const value: unknown =\n raw !== undefined && raw !== null ? raw : defaults?.[field.key];\n const onChange = (v: any) => this._updateBlock(blockId, field.key, v);\n\n switch (field.type) {\n case 'textarea':\n return this._textareaField(field.label, String(value ?? ''), onChange, field.help, fp);\n case 'number':\n return this._numberField(\n field.label,\n Number(value ?? 0),\n field.min ?? 0,\n field.max ?? 9999,\n onChange,\n field.step ?? 1,\n fp,\n );\n case 'color': {\n const rawColor = (block.props as Record<string, unknown>)[field.key];\n const stored =\n rawColor !== undefined && rawColor !== null ? String(rawColor).trim() : '';\n return this._colorField(\n field.label,\n stored,\n (v) => onChange(v.trim()),\n fp,\n field.placeholder ?? '',\n );\n }\n case 'select': {\n const isFw = field.key === 'fontWeight' || field.key === 'labelFontWeight';\n const opts = field.options?.length\n ? field.options\n : isFw\n ? FONT_WEIGHT_STEP_OPTIONS\n : [];\n if (isFw && field.inheritGlobal) {\n const stored =\n raw !== undefined && raw !== null ? String(raw).trim() : '';\n return this._fontWeightInheritField(\n field.label,\n stored,\n normalizeFontWeightStep(this.opts.store.doc.styles.fontWeight),\n (v) => onChange(v),\n fp,\n opts,\n field.help,\n );\n }\n const displayVal = isFw\n ? normalizeFontWeightStep(String(value ?? ''))\n : String(value ?? '');\n if (isFw || field.selectVariant === 'segmented') {\n const el = this._segmentedSelectField(field.label, displayVal, opts, onChange, fp);\n if (field.help) el.append(h('div', { class: 'sm-field__help' }, [field.help]));\n return el;\n }\n return this._selectField(field.label, displayVal, opts, onChange, fp);\n }\n case 'switch':\n return this._switchField(field.label, !!value, onChange, field.help, fp);\n case 'image':\n return this._imageField(\n field.label,\n String(value ?? ''),\n onChange,\n field.placeholder ?? 'https://',\n fp,\n { blockId, propKey: field.key },\n );\n case 'url':\n case 'text': {\n if (field.key === 'width' && this._preferSliderControls()) {\n return this._layoutWidthField(\n field.label,\n String(value ?? ''),\n (v) => onChange(v),\n fp,\n field.help,\n );\n }\n if (field.key === 'fontSize' && field.inheritGlobal) {\n const rawFs =\n raw !== undefined && raw !== null ? String(raw).trim() : '';\n return this._fontSizeSliderField(\n field.label,\n rawFs,\n (v) => onChange(v.trim()),\n fp,\n field.help,\n this.opts.store.doc.styles.fontSize,\n );\n }\n const row = this._textField(\n field.label,\n String(value ?? ''),\n onChange,\n field.placeholder ?? '',\n fp,\n );\n if (field.help) row.append(h('div', { class: 'sm-field__help' }, [field.help]));\n return row;\n }\n case 'spacing': {\n /** 与各 block 约定:四边分别存 paddingTop / paddingRight / paddingBottom / paddingLeft */\n const p = block.props as Record<string, unknown>;\n const quad = [\n Number(p.paddingTop ?? 0),\n Number(p.paddingRight ?? 0),\n Number(p.paddingBottom ?? 0),\n Number(p.paddingLeft ?? 0),\n ];\n const def = this.opts.registry.get(block.type);\n const dp = def?.defaultProps as Record<string, unknown> | undefined;\n const resetQuad: [number, number, number, number] = [\n Number(dp?.paddingTop ?? 0),\n Number(dp?.paddingRight ?? 0),\n Number(dp?.paddingBottom ?? 0),\n Number(dp?.paddingLeft ?? 0),\n ];\n return this._spacingField(field.label, quad, (vals) => {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, blockId);\n if (!loc) return;\n const pr = loc.block.props as Record<string, number>;\n [pr.paddingTop, pr.paddingRight, pr.paddingBottom, pr.paddingLeft] = vals;\n });\n }, `${fp}:pad`, resetQuad);\n }\n case 'socialLinkList': {\n const rows = Array.isArray(value)\n ? (value as SocialLinkRow[])\n : Array.isArray(defaults?.[field.key])\n ? (defaults[field.key] as SocialLinkRow[])\n : [];\n return this._socialLinkListField(\n field.label,\n rows,\n field.options ?? [],\n blockId,\n field.key,\n field.help,\n fp,\n );\n }\n default:\n return h('div');\n }\n }\n\n /**\n * 社交组:每行含平台、链接、可选标签/图标 URL/图标背景色。\n * 注意:右栏在输入框聚焦时会跳过整栏 _render(),故更新 elements 必须在 store.update 内\n * 读取当前 props 再合并,禁止依赖闭包里的 items 快照(否则改一行会覆盖其它行已编辑未重绘的数据)。\n */\n private _socialLinkListField(\n label: string,\n items: SocialLinkRow[],\n networkOptions: { label: string; value: string }[],\n blockId: string,\n elementsKey: string,\n help: string | undefined,\n focusPrefix: string,\n ): HTMLElement {\n const firstVal = networkOptions[0]?.value ?? 'weibo';\n const wrap = h('div', { class: 'sm-field' });\n wrap.append(h('label', { class: 'sm-field__label' }, [label]));\n\n const listEl = h('div', { class: 'sm-social-link-list' });\n\n const patchElements = (mutate: (rows: SocialLinkRow[]) => SocialLinkRow[]) => {\n this.opts.store.update((d) => {\n const loc = findBlockLocation(d, blockId);\n if (!loc) return;\n const props = loc.block.props as Record<string, unknown>;\n const raw = props[elementsKey];\n const cur: SocialLinkRow[] = Array.isArray(raw)\n ? (raw as SocialLinkRow[]).map((x) => ({ ...x }))\n : [];\n props[elementsKey] = mutate(cur);\n });\n };\n\n const syncItem = (index: number, patch: Partial<SocialLinkRow>) => {\n patchElements((rows) =>\n rows.map((x, i) => (i === index ? { ...x, ...patch } : x)),\n );\n };\n\n const removeAt = (index: number) => {\n patchElements((rows) => rows.filter((_, i) => i !== index));\n };\n\n for (let i = 0; i < items.length; i++) {\n const rowData = items[i];\n const rowWrap = h('div', { class: 'sm-social-link-list__row' });\n const mainRow = h('div', { class: 'sm-social-link-list__row-main' });\n const sel = h('select', {\n class: 'sm-select sm-social-link-list__network',\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:net` } : {}),\n onchange: (e: Event) =>\n syncItem(i, { network: (e.target as HTMLSelectElement).value }),\n });\n for (const o of networkOptions) {\n const opt = document.createElement('option');\n opt.value = o.value;\n opt.textContent = o.label;\n if (o.value === rowData.network) opt.selected = true;\n sel.append(opt);\n }\n if (!networkOptions.some((o) => o.value === rowData.network) && rowData.network) {\n const opt = document.createElement('option');\n opt.value = rowData.network;\n opt.textContent = rowData.network;\n opt.selected = true;\n sel.insertBefore(opt, sel.firstChild);\n }\n const inp = h('input', {\n class: 'sm-input sm-social-link-list__href',\n type: 'url',\n placeholder: 'https://',\n value: rowData.href,\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:href` } : {}),\n oninput: (e: Event) => syncItem(i, { href: (e.target as HTMLInputElement).value }),\n });\n const rm = h(\n 'button',\n {\n class: 'sm-social-link-list__remove',\n type: 'button',\n title: '删除',\n onclick: () => removeAt(i),\n },\n ['×'],\n );\n mainRow.append(sel, inp, rm);\n rowWrap.append(mainRow);\n\n const extras = h('div', { class: 'sm-social-link-list__row-extras' });\n const bgResolved = defaultSocialIconBackground(rowData.network);\n const bgStored = rowData.backgroundColor?.trim();\n const bgDisplay =\n bgStored && bgStored.startsWith('#') ? bgStored : bgResolved;\n extras.append(\n h('input', {\n class: 'sm-input sm-social-link-list__label',\n type: 'text',\n placeholder: '标签文字(可选)',\n value: rowData.label ?? '',\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:label` } : {}),\n oninput: (e: Event) => syncItem(i, { label: (e.target as HTMLInputElement).value }),\n }),\n h('input', {\n class: 'sm-input sm-social-link-list__iconsrc',\n type: 'url',\n placeholder: '图标 URL(可选)',\n value: rowData.iconSrc ?? '',\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:icon` } : {}),\n oninput: (e: Event) => syncItem(i, { iconSrc: (e.target as HTMLInputElement).value }),\n }),\n );\n const bgPick = h('input', {\n class: 'sm-social-link-list__color sm-social-link-list__color--compact',\n type: 'color',\n value: bgDisplay.length >= 4 ? bgDisplay : bgResolved,\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:row:${i}:bg` } : {}),\n }) as HTMLInputElement;\n bindColorPickerInput(bgPick, {\n liveCommit: true,\n onCommit: (hex) => syncItem(i, { backgroundColor: hex }),\n });\n extras.append(bgPick);\n rowWrap.append(extras);\n\n listEl.append(rowWrap);\n }\n\n const addBtn = h(\n 'button',\n {\n class: 'sm-btn sm-social-link-list__add',\n type: 'button',\n onclick: () =>\n patchElements((rows) => [\n ...rows,\n {\n network: firstVal,\n href: 'https://',\n label: '',\n iconSrc: '',\n },\n ]),\n },\n ['+ 添加社交链接'],\n );\n\n wrap.append(listEl, addBtn);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n /* --------------------------------- 控件 --------------------------------- */\n\n private _textField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n placeholder = '',\n focusToken?: string,\n ) {\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('input', {\n class: 'sm-input',\n type: 'text',\n value,\n placeholder,\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n }),\n ]);\n }\n\n /** `type: 'image'`:URL 输入 + 可选上传、图床(由 `imageAssets` 注入) */\n private _imageField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n placeholder: string,\n focusToken: string | undefined,\n ids: Pick<ImageFieldContext, 'blockId' | 'propKey'>,\n ): HTMLElement {\n const assets = this.opts.imageAssets;\n const showUploadBtn = !!assets?.uploadImage && assets.showUpload !== false;\n const showGalleryBtn =\n assets?.showGallery === true &&\n (!!assets.imageGallery || !!assets.pickImageFromGallery);\n const hasAssetCallbacks = !!(\n assets?.uploadImage ||\n assets?.pickImageFromGallery ||\n assets?.imageGallery\n );\n const hasAnyPickerBtn = showUploadBtn || showGalleryBtn;\n\n const row = h('div', { class: 'sm-image-field__row' });\n const urlInp = h('input', {\n class: 'sm-input sm-image-field__url',\n type: 'url',\n value,\n placeholder,\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n });\n const getCtx = (): ImageFieldContext => ({\n blockId: ids.blockId,\n propKey: ids.propKey,\n currentUrl: urlInp.value,\n });\n row.append(urlInp);\n\n const applyUrl = (url: string) => {\n const t = url.trim();\n if (!t) return;\n onChange(t);\n urlInp.value = t;\n };\n\n const runAsync = (p: Promise<string | null | void>, labelErr: string) => {\n p.catch((e) => {\n console.error(`[simple-mail] ${labelErr}`, e);\n });\n };\n\n if (showUploadBtn) {\n const fileInp = h('input', {\n type: 'file',\n accept: 'image/*',\n class: 'sm-image-field__file',\n onchange: (e: Event) => {\n const el = e.target as HTMLInputElement;\n const f = el.files?.[0];\n el.value = '';\n if (!f) return;\n runAsync(\n assets.uploadImage!(f, getCtx()).then((url) => applyUrl(String(url))),\n 'uploadImage',\n );\n },\n });\n row.append(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-image-field__btn',\n type: 'button',\n title: '上传本地图片',\n onclick: () => fileInp.click(),\n },\n ['上传'],\n ),\n );\n row.append(fileInp);\n }\n\n if (showGalleryBtn) {\n row.append(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--secondary sm-image-field__btn',\n type: 'button',\n title: '从图库选择',\n onclick: () => {\n if (assets.imageGallery) {\n openImageGalleryModal({\n adapter: assets.imageGallery,\n onPick: (url) => applyUrl(url),\n });\n return;\n }\n if (assets.pickImageFromGallery) {\n runAsync(\n assets.pickImageFromGallery(getCtx()).then((url) => {\n if (url != null && String(url).trim()) applyUrl(String(url));\n }),\n 'pickImageFromGallery',\n );\n }\n },\n },\n ['图床'],\n ),\n );\n }\n\n let helpBody: string;\n if (hasAnyPickerBtn) {\n const bits: string[] = ['可手输 URL'];\n if (showUploadBtn) bits.push('或使用「上传」');\n if (showGalleryBtn) bits.push('或使用「图床」');\n helpBody = `${bits.join(';')}。`;\n } else if (hasAssetCallbacks) {\n helpBody =\n '已传入 imageAssets:上传默认显示(提供 uploadImage 且未设 showUpload:false);图库需 showGallery:true,可使用内置 imageGallery 或自管 pickImageFromGallery。仍可手输 URL。';\n } else {\n helpBody =\n '在 MailEditor 的 imageAssets 中配置 uploadImage、内置 imageGallery 或 pickImageFromGallery 等;未配置时仅支持手输 URL。';\n }\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n row,\n h('div', { class: 'sm-field__help' }, [helpBody]),\n ]);\n }\n private _textareaField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n help?: string,\n focusToken?: string,\n ) {\n const ta = h('textarea', {\n class: 'sm-textarea',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n oninput: (e: Event) => onChange((e.target as HTMLTextAreaElement).value),\n });\n ta.value = value;\n return h(\n 'div',\n { class: 'sm-field' },\n [\n h('label', { class: 'sm-field__label' }, [label]),\n ta,\n help ? h('div', { class: 'sm-field__help' }, [help]) : null,\n ],\n );\n }\n private _numberField(\n label: string,\n value: number,\n min: number,\n max: number,\n onChange: (v: number) => void,\n step = 1,\n focusToken?: string,\n ) {\n const snap = (n: number) => {\n const c = Math.min(max, Math.max(min, n));\n if (!step || step <= 0) return c;\n const k = Math.round((c - min) / step);\n return Number((min + k * step).toPrecision(12));\n };\n\n if (!this._preferSliderControls()) {\n const inp = h('input', {\n class: 'sm-input',\n type: 'number',\n value: String(value),\n min,\n max,\n step,\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const commitPlain = () => {\n const t = inp.value.trim();\n const fb = snap(value);\n if (t === '') {\n inp.value = String(fb);\n onChange(fb);\n return;\n }\n const v = Number(t);\n const s = snap(Number.isNaN(v) ? fb : v);\n inp.value = String(s);\n onChange(s);\n };\n\n /** min>0 时中途输入会被 snap 打断(如想输入 16 会先变成 10),仅失焦/Enter 提交 */\n if (min > 0) {\n inp.addEventListener('blur', commitPlain);\n inp.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') inp.blur();\n });\n } else {\n inp.addEventListener('input', () => {\n const t = inp.value.trim();\n if (t === '') return;\n const v = Number(t);\n if (Number.isNaN(v)) return;\n onChange(snap(v));\n });\n inp.addEventListener('blur', commitPlain);\n inp.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') commitPlain();\n });\n }\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n inp,\n ]);\n }\n\n const v0 = snap(value);\n const range = h('input', {\n type: 'range',\n min,\n max,\n step,\n value: String(v0),\n }) as HTMLInputElement;\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min,\n max,\n step,\n value: String(v0),\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const syncFromSlider = (n: number) => {\n const s = snap(n);\n range.value = String(s);\n num.value = String(s);\n onChange(s);\n };\n\n range.addEventListener('input', () => {\n syncFromSlider(Number(range.value));\n });\n\n num.addEventListener('input', () => {\n const t = num.value.trim();\n if (t === '') return;\n const raw = Number(t);\n if (Number.isNaN(raw)) return;\n range.value = String(snap(raw));\n });\n\n num.addEventListener('blur', () => {\n const t = num.value.trim();\n const fb = snap(Number(range.value));\n if (t === '') {\n syncFromSlider(fb);\n return;\n }\n const raw = Number(t);\n if (Number.isNaN(raw)) {\n syncFromSlider(fb);\n return;\n }\n syncFromSlider(raw);\n });\n\n num.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('div', { class: 'sm-field__slider-row' }, [range, num]),\n ]);\n }\n private _colorField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n focusPrefix?: string,\n placeholder = '#ffffff',\n ) {\n const pickToken = focusPrefix ? `${focusPrefix}:pick` : undefined;\n const textToken = focusPrefix ? `${focusPrefix}:text` : undefined;\n const pick = h('input', {\n type: 'color',\n ...(pickToken ? { 'data-sm-focus': pickToken } : {}),\n }) as HTMLInputElement;\n const text = h('input', {\n class: 'sm-input',\n type: 'text',\n placeholder,\n ...(textToken ? { 'data-sm-focus': textToken } : {}),\n }) as HTMLInputElement;\n\n let lastValid = value.trim();\n\n const applyPickInherit = () => {\n pick.value = '#808080';\n pick.classList.add('sm-color-row__pick--inherit');\n pick.title = placeholder || '未设置';\n };\n\n const applyStored = (stored: string) => {\n const trimmed = stored.trim();\n text.value = trimmed;\n const hex = normalizeAccentHex(trimmed);\n if (hex) {\n pick.value = hex;\n pick.classList.remove('sm-color-row__pick--inherit');\n pick.title = '';\n } else {\n applyPickInherit();\n }\n };\n\n applyStored(value);\n\n const previewPick = (hex: string) => {\n text.value = hex;\n pick.value = hex;\n pick.classList.remove('sm-color-row__pick--inherit');\n pick.title = '';\n lastValid = hex;\n };\n\n const commitPick = (hex: string) => {\n previewPick(hex);\n onChange(hex);\n };\n\n bindColorPickerInput(pick, {\n getValue: () => text.value.trim() || pick.value,\n placeholder,\n allowClear: true,\n onPreview: previewPick,\n onCommit: commitPick,\n onClear: () => {\n applyStored('');\n lastValid = '';\n onChange('');\n },\n });\n\n text.addEventListener('input', () => {\n const raw = text.value;\n const hex = normalizeAccentHex(raw);\n if (hex) {\n pick.value = hex;\n pick.classList.remove('sm-color-row__pick--inherit');\n pick.title = '';\n lastValid = hex;\n } else if (!raw.trim()) {\n applyPickInherit();\n lastValid = '';\n }\n onChange(raw);\n });\n\n text.addEventListener('blur', () => {\n const raw = text.value.trim();\n if (!raw) {\n applyStored('');\n lastValid = '';\n onChange('');\n return;\n }\n const hex = normalizeAccentHex(raw);\n if (hex) {\n applyStored(hex);\n lastValid = hex;\n if (hex !== raw) onChange(hex);\n return;\n }\n applyStored(lastValid);\n onChange(lastValid);\n });\n\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n h('div', { class: 'sm-color-row' }, [pick, text]),\n ]);\n }\n private _selectField(\n label: string,\n value: string,\n options: { label: string; value: string }[],\n onChange: (v: string) => void,\n focusToken?: string,\n ) {\n const sel = h('select', {\n class: 'sm-select',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n onchange: (e: Event) => onChange((e.target as HTMLSelectElement).value),\n });\n for (const o of options) {\n const opt = document.createElement('option');\n opt.value = o.value;\n opt.textContent = o.label;\n if (o.value === value) opt.selected = true;\n sel.append(opt);\n }\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n sel,\n ]);\n }\n\n /** select 平铺:与顶栏 sm-segmented 视觉一致,占满右栏宽度 */\n private _segmentedSelectField(\n label: string,\n value: string,\n options: { label: string; value: string }[],\n onChange: (v: string) => void,\n focusToken?: string,\n wrap = false,\n ) {\n const group = h('div', {\n class: `sm-segmented sm-segmented--fill${wrap ? ' sm-segmented--wrap' : ''}`,\n role: 'group',\n 'aria-label': label,\n });\n for (const o of options) {\n const active = o.value === value;\n group.append(\n h(\n 'button',\n {\n type: 'button',\n class: `sm-segmented__item${active ? ' sm-segmented__item--active' : ''}`,\n 'aria-pressed': active ? 'true' : 'false',\n title: o.label,\n ...(focusToken ? { 'data-sm-focus': `${focusToken}:${o.value}` } : {}),\n onclick: () => onChange(o.value),\n },\n [o.label],\n ),\n );\n }\n return h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n group,\n ]);\n }\n private _switchField(\n label: string,\n value: boolean,\n onChange: (v: boolean) => void,\n help?: string,\n focusToken?: string,\n ): HTMLElement {\n const row = h('label', {\n class: 'sm-field',\n style: 'flex-direction:row;align-items:center;gap:8px;',\n }, [\n h('input', {\n type: 'checkbox',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n onchange: (e: Event) => onChange((e.target as HTMLInputElement).checked),\n ...(value ? { checked: true } : {}),\n } as any),\n h('span', { class: 'sm-field__label' }, [label]),\n ]);\n if (!help) return row;\n return h('div', { class: 'sm-field', style: 'flex-direction:column;align-items:flex-start;gap:6px;' }, [\n row,\n h('div', { class: 'sm-field__help' }, [help]),\n ]);\n }\n private _spacingField(\n label: string,\n [t, r, b, l]: (number | undefined)[],\n onChange: (vals: number[]) => void,\n focusPrefix?: string,\n resetQuad?: [number, number, number, number],\n ) {\n const titles = ['上', '右', '下', '左'];\n const clampPad = (n: number) => Math.max(0, Math.min(200, Math.round(n)));\n\n /** 右栏聚焦时会跳过整栏重绘,闭包里的 t/r/b/l 会过时;用同一数组累积四边,避免改一边再改另一边时覆盖。 */\n const current: number[] = [\n clampPad(Number(t ?? 0)),\n clampPad(Number(r ?? 0)),\n clampPad(Number(b ?? 0)),\n clampPad(Number(l ?? 0)),\n ];\n const emit = () => onChange([...current]);\n\n const makePlain = (v: number | undefined, idx: number) => {\n const inp = h('input', {\n class: 'sm-input',\n type: 'number',\n min: 0,\n max: 200,\n value: String(v ?? 0),\n title: titles[idx],\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:${idx}` } : {}),\n }) as HTMLInputElement;\n inp.addEventListener('input', () => {\n const t = inp.value.trim();\n if (t === '') return;\n const raw = Number(t);\n if (Number.isNaN(raw)) return;\n current[idx] = clampPad(raw);\n emit();\n });\n inp.addEventListener('blur', () => {\n const t = inp.value.trim();\n if (t === '') {\n inp.value = String(current[idx]);\n return;\n }\n const raw = Number(t);\n const c = clampPad(Number.isNaN(raw) ? current[idx] : raw);\n inp.value = String(c);\n current[idx] = c;\n emit();\n });\n inp.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') inp.blur();\n });\n return inp;\n };\n\n const makeSliderRow = (v: number | undefined, idx: number) => {\n const cur = clampPad(v ?? 0);\n const range = h('input', {\n type: 'range',\n min: 0,\n max: 200,\n step: 1,\n value: String(cur),\n title: titles[idx],\n }) as HTMLInputElement;\n\n range.addEventListener('input', () => {\n const c = clampPad(Number(range.value));\n current[idx] = c;\n num.value = String(c);\n emit();\n });\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min: 0,\n max: 200,\n value: String(cur),\n title: titles[idx],\n ...(focusPrefix ? { 'data-sm-focus': `${focusPrefix}:${idx}` } : {}),\n }) as HTMLInputElement;\n\n num.addEventListener('input', () => {\n const t = num.value.trim();\n if (t === '') return;\n const rawN = Number(t);\n if (Number.isNaN(rawN)) return;\n const c = clampPad(rawN);\n range.value = String(c);\n current[idx] = c;\n emit();\n });\n\n num.addEventListener('blur', () => {\n const t = num.value.trim();\n if (t === '') {\n num.value = String(current[idx]);\n range.value = String(current[idx]);\n return;\n }\n const rawN = Number(t);\n const c = clampPad(Number.isNaN(rawN) ? current[idx] : rawN);\n num.value = String(c);\n range.value = String(c);\n current[idx] = c;\n emit();\n });\n\n num.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n return h('div', { class: 'sm-spacing-row' }, [\n h('span', { class: 'sm-spacing-row__axis' }, [titles[idx]]),\n range,\n num,\n ]);\n };\n\n return h('div', { class: 'sm-field' }, [\n h('div', { class: 'sm-spacing-field__label-row' }, [\n h('label', { class: 'sm-field__label' }, [`${label}(上/右/下/左)`]),\n resetQuad\n ? h(\n 'button',\n {\n type: 'button',\n class: 'sm-btn sm-btn--ghost sm-spacing-field__reset',\n onclick: () => {\n const next = resetQuad.map((n) => clampPad(Number(n)));\n for (let i = 0; i < 4; i++) current[i] = next[i];\n onChange([...current]);\n },\n },\n ['恢复默认'],\n )\n : null,\n ]),\n this._preferSliderControls()\n ? h(\n 'div',\n { class: 'sm-spacing-rows' },\n [0, 1, 2, 3].map((idx) => makeSliderRow([t, r, b, l][idx], idx)),\n )\n : h(\n 'div',\n { class: 'sm-spacing-grid' },\n [0, 1, 2, 3].map((idx) => makePlain([t, r, b, l][idx], idx)),\n ),\n ]);\n }\n\n /** 「继承全局」开关行:开=跟随邮件全局,关=块级固定值 */\n private _globalInheritSwitch(\n inheritOn: boolean,\n globalDisplay: string,\n onToggle: (inherit: boolean) => void,\n focusToken?: string,\n ): { el: HTMLElement; setInherit: (on: boolean, display?: string) => void } {\n const input = h('input', {\n type: 'checkbox',\n class: 'sm-inherit-switch__input',\n role: 'switch',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n ...(inheritOn ? { checked: true } : {}),\n }) as HTMLInputElement;\n const valueEl = h('span', {\n class: 'sm-inherit-switch__value',\n hidden: !inheritOn,\n }, [globalDisplay]);\n const el = h('div', { class: 'sm-inherit-switch' }, [\n h('label', { class: 'sm-inherit-switch__label' }, [\n input,\n h('span', { class: 'sm-inherit-switch__text' }, ['继承全局']),\n ]),\n valueEl,\n ]);\n input.addEventListener('change', () => onToggle(input.checked));\n const setInherit = (on: boolean, display?: string) => {\n input.checked = on;\n if (display !== undefined) valueEl.textContent = display;\n valueEl.hidden = !on;\n };\n return { el, setInherit };\n }\n\n private _fontWeightInheritField(\n label: string,\n stored: string,\n globalWeight: string,\n onChange: (v: string) => void,\n focusToken: string,\n options: { label: string; value: string }[],\n help?: string,\n ): HTMLElement {\n let inheriting = !stored;\n const group = h('div', {\n class: 'sm-segmented sm-segmented--fill',\n role: 'group',\n 'aria-label': label,\n });\n\n const syncGroup = () => {\n group.classList.toggle('sm-segmented--disabled', inheriting);\n const display = inheriting ? '' : normalizeFontWeightStep(stored || globalWeight);\n clear(group);\n for (const o of options) {\n const active = !inheriting && o.value === display;\n group.append(\n h(\n 'button',\n {\n type: 'button',\n class: `sm-segmented__item${active ? ' sm-segmented__item--active' : ''}`,\n 'aria-pressed': active ? 'true' : 'false',\n title: o.label,\n ...(focusToken ? { 'data-sm-focus': `${focusToken}:${o.value}` } : {}),\n onclick: () => {\n inheriting = false;\n stored = o.value;\n inheritSwitch.setInherit(false);\n syncGroup();\n onChange(o.value);\n },\n },\n [o.label],\n ),\n );\n }\n };\n\n const inheritSwitch = this._globalInheritSwitch(\n inheriting,\n globalWeight,\n (on) => {\n if (on) {\n inheriting = true;\n stored = '';\n inheritSwitch.setInherit(true, globalWeight);\n syncGroup();\n onChange('');\n return;\n }\n inheriting = false;\n stored = globalWeight;\n inheritSwitch.setInherit(false);\n syncGroup();\n onChange(globalWeight);\n },\n `${focusToken}:inherit`,\n );\n\n syncGroup();\n\n const wrap = h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n inheritSwitch.el,\n group,\n ]);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n private _fontSizeInheritTextField(\n label: string,\n stored: string,\n onChange: (v: string) => void,\n focusToken: string,\n globalFontSize: string,\n help?: string,\n ): HTMLElement {\n const globalPx = this._snapFontSizeToPx(globalFontSize);\n let inheriting = !stored.trim();\n const input = h('input', {\n class: 'sm-input',\n type: 'text',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const syncInput = () => {\n input.disabled = inheriting;\n input.value = inheriting ? '' : stored;\n input.placeholder = inheriting ? '' : '如 16px';\n input.classList.toggle('sm-input--inherit-disabled', inheriting);\n };\n\n const inheritSwitch = this._globalInheritSwitch(\n inheriting,\n `${globalPx}px`,\n (on) => {\n if (on) {\n inheriting = true;\n stored = '';\n inheritSwitch.setInherit(true, `${globalPx}px`);\n syncInput();\n onChange('');\n return;\n }\n inheriting = false;\n stored = `${globalPx}px`;\n inheritSwitch.setInherit(false);\n syncInput();\n onChange(stored);\n },\n `${focusToken}:inherit`,\n );\n\n syncInput();\n\n input.addEventListener('input', () => {\n if (inheriting) return;\n stored = input.value;\n onChange(stored);\n });\n\n input.addEventListener('blur', () => {\n if (inheriting) return;\n const t = input.value.trim();\n if (!t) {\n stored = `${globalPx}px`;\n input.value = stored;\n onChange(stored);\n }\n });\n\n const wrap = h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n inheritSwitch.el,\n input,\n ]);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n private _snapFontSizeToPx(value: string): number {\n const t = (value ?? '').trim();\n const m = t.match(/^(\\d+(\\.\\d+)?)/);\n if (m) return Math.min(48, Math.max(10, Math.round(parseFloat(m[1]))));\n return 16;\n }\n\n private _fontSizeSliderField(\n label: string,\n value: string,\n onChange: (v: string) => void,\n focusToken: string,\n help?: string,\n globalFontSize?: string,\n ) {\n const inheritGlobal = globalFontSize !== undefined;\n if (!this._preferSliderControls()) {\n if (inheritGlobal) {\n return this._fontSizeInheritTextField(\n label,\n value,\n onChange,\n focusToken,\n globalFontSize,\n help,\n );\n }\n return this._textField(label, value ?? '', onChange, '', focusToken);\n }\n\n const min = 10;\n const max = 48;\n const step = 1;\n const snap = (n: number) => Math.min(max, Math.max(min, Math.round(n)));\n const globalPx = snap(this._snapFontSizeToPx(globalFontSize ?? value ?? '16px'));\n let stored = value.trim();\n let inheriting = inheritGlobal && !stored;\n\n const sliderRow = h('div', { class: 'sm-field__slider-row' });\n const range = h('input', {\n type: 'range',\n min,\n max,\n step,\n }) as HTMLInputElement;\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min,\n max,\n step,\n 'data-sm-focus': focusToken,\n }) as HTMLInputElement;\n sliderRow.append(range, num);\n\n const syncSlider = () => {\n sliderRow.classList.toggle('sm-field__slider-row--inherit', inheriting);\n num.disabled = inheriting;\n if (inheriting) {\n range.value = String(globalPx);\n num.value = '';\n } else {\n const s = snap(this._snapFontSizeToPx(stored || `${globalPx}px`));\n range.value = String(s);\n num.value = String(s);\n }\n };\n\n let inheritSwitch: ReturnType<RightPanel['_globalInheritSwitch']> | null = null;\n if (inheritGlobal) {\n inheritSwitch = this._globalInheritSwitch(\n inheriting,\n `${globalPx}px`,\n (on) => {\n if (on) {\n inheriting = true;\n stored = '';\n inheritSwitch!.setInherit(true, `${globalPx}px`);\n syncSlider();\n onChange('');\n return;\n }\n inheriting = false;\n stored = `${globalPx}px`;\n inheritSwitch!.setInherit(false);\n syncSlider();\n onChange(stored);\n },\n `${focusToken}:inherit`,\n );\n }\n\n syncSlider();\n\n const leaveInherit = () => {\n if (!inheriting) return;\n inheriting = false;\n inheritSwitch?.setInherit(false);\n syncSlider();\n };\n\n range.addEventListener('input', () => {\n leaveInherit();\n const s = snap(Number(range.value));\n num.value = String(s);\n stored = `${s}px`;\n onChange(stored);\n });\n\n num.addEventListener('input', () => {\n if (inheriting) return;\n const rawN = Number(num.value);\n if (Number.isNaN(rawN)) return;\n range.value = String(snap(rawN));\n });\n\n num.addEventListener('blur', () => {\n if (inheriting) return;\n const t = num.value.trim();\n const fb = snap(Number(range.value));\n const s = snap(t === '' || Number.isNaN(Number(t)) ? fb : Number(t));\n stored = `${s}px`;\n num.value = String(s);\n range.value = String(s);\n onChange(stored);\n });\n\n num.addEventListener('keydown', (e) => {\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n const wrap = h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n ...(inheritSwitch ? [inheritSwitch.el] : []),\n sliderRow,\n ]);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n private _docFontSizeField(value: string, onChange: (v: string) => void, focusToken: string) {\n return this._fontSizeSliderField(\n '字号',\n value,\n onChange,\n focusToken,\n '滑块与数字均以 px 写入(如 16px)',\n );\n }\n\n private _layoutWidthField(\n label: string,\n raw: string,\n onChange: (v: string) => void,\n focusToken: string,\n help?: string,\n ) {\n if (!this._preferSliderControls()) {\n const tf = this._textField(label, raw, onChange, '', focusToken);\n if (help) tf.append(h('div', { class: 'sm-field__help' }, [help]));\n return tf;\n }\n\n const kind = classifyLayoutWidth(raw);\n if (kind === 'custom') {\n const wrap = h('div', { class: 'sm-field' });\n wrap.append(h('label', { class: 'sm-field__label' }, [label]));\n wrap.append(\n h('div', { class: 'sm-field__help' }, [\n '当前值为自定义写法,请直接编辑;清空后可选「自适应」再用滑块。',\n ]),\n );\n wrap.append(\n h('input', {\n class: 'sm-input',\n type: 'text',\n value: raw,\n placeholder: '如 480px、90%',\n 'data-sm-focus': focusToken,\n oninput: (e: Event) => onChange((e.target as HTMLInputElement).value),\n }),\n );\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n const mode: 'auto' | 'px' | '%' = kind;\n const max = mode === '%' ? 100 : 1200;\n const min = 1;\n const displayN = mode === 'auto' ? 280 : layoutWidthNumeric(raw, mode === '%' ? '%' : 'px');\n\n const clampW = (n: number) => Math.max(min, Math.min(max, Math.round(n)));\n\n const range = h('input', {\n type: 'range',\n min,\n max,\n step: 1,\n value: String(displayN),\n disabled: mode === 'auto',\n }) as HTMLInputElement;\n\n const num = h('input', {\n class: 'sm-input',\n type: 'number',\n min,\n max,\n step: 1,\n value: String(displayN),\n disabled: mode === 'auto',\n ...(focusToken ? { 'data-sm-focus': focusToken } : {}),\n }) as HTMLInputElement;\n\n const emitW = (c: number) => {\n const v = clampW(c);\n range.value = String(v);\n num.value = String(v);\n onChange(mode === '%' ? `${v}%` : `${v}px`);\n };\n\n range.addEventListener('input', () => {\n if (mode === 'auto') return;\n emitW(Number(range.value));\n });\n\n num.addEventListener('input', () => {\n if (mode === 'auto') return;\n const t = num.value.trim();\n if (t === '') return;\n const rawN = Number(t);\n if (Number.isNaN(rawN)) return;\n range.value = String(clampW(rawN));\n });\n\n num.addEventListener('blur', () => {\n if (mode === 'auto') return;\n const t = num.value.trim();\n const fb = clampW(Number(range.value));\n if (t === '') {\n emitW(fb);\n return;\n }\n const rawN = Number(t);\n emitW(Number.isNaN(rawN) ? fb : rawN);\n });\n\n num.addEventListener('keydown', (e) => {\n if (mode === 'auto') return;\n if ((e as KeyboardEvent).key === 'Enter') num.blur();\n });\n\n const sliderRow = h(\n 'div',\n { class: `sm-width-field__slider-row ${mode === 'auto' ? 'is-disabled' : ''}` },\n [range, num],\n );\n\n const modesWrap = h('div', { class: 'sm-segmented sm-segmented--wrap sm-width-field__modes' });\n const addModeBtn = (m: 'auto' | 'px' | '%', text: string) => {\n modesWrap.append(\n h(\n 'button',\n {\n type: 'button',\n class: `sm-segmented__item ${mode === m ? 'sm-segmented__item--active' : ''}`,\n onclick: () => {\n if (m === 'auto') onChange('');\n else if (m === 'px') onChange(`${layoutWidthNumeric(raw, 'px')}px`);\n else onChange(`${layoutWidthNumeric(raw, '%')}%`);\n },\n },\n [text],\n ),\n );\n };\n addModeBtn('auto', '自适应');\n addModeBtn('px', 'px');\n addModeBtn('%', '%');\n\n const wrap = h('div', { class: 'sm-field' }, [\n h('label', { class: 'sm-field__label' }, [label]),\n modesWrap,\n sliderRow,\n ]);\n if (help) wrap.append(h('div', { class: 'sm-field__help' }, [help]));\n return wrap;\n }\n\n private _docFontWeightField(value: string, onChange: (v: string) => void, focusToken: string) {\n const cur = normalizeFontWeightStep(value);\n return this._segmentedSelectField('字重', cur, FONT_WEIGHT_STEP_OPTIONS, onChange, focusToken);\n }\n\n private _twoColumnRatioField(\n layout: SectionLayout,\n onChange: (layout: SectionLayout) => void,\n focusToken: string,\n ) {\n return this._segmentedSelectField(\n '列比例',\n layout,\n [\n { label: '1:1', value: '1-1' },\n { label: '1:2', value: '1-2' },\n { label: '2:1', value: '2-1' },\n ],\n (v) => onChange(v as SectionLayout),\n focusToken,\n );\n }\n\n private _renderBlockCodeView(block: Block): HTMLElement {\n const def = this.opts.registry.get(block.type);\n const initial =\n block.lockedMjml ??\n (def ? def.toMjml(block.props as any, { doc: this.opts.store.doc, engine: 'mjml' }) : '');\n\n const wrap = h('div', { class: 'sm-code-pane' });\n\n const header = h('div', { class: 'sm-code-pane__header' }, [\n h('div', { class: 'sm-code-pane__title' }, ['编辑组件 MJML 源码']),\n ]);\n\n const editorHost = h('div', { class: 'sm-code' });\n\n const view = new EditorView({\n parent: editorHost,\n state: EditorState.create({\n doc: initial,\n extensions: [basicSetup, cmHtml()],\n }),\n });\n this.codeView = view;\n\n const actions = h('div', { class: 'sm-code-pane__header' }, [\n h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: () => {\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, block.id);\n if (l) delete l.block.lockedMjml;\n });\n },\n },\n ['恢复默认'],\n ),\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--primary',\n type: 'button',\n onclick: () => {\n const text = view.state.doc.toString();\n this.opts.store.update((d) => {\n const l = findBlockLocation(d, block.id);\n if (l) l.block.lockedMjml = text;\n });\n },\n },\n ['保存为锁定 MJML'],\n ),\n ]);\n\n wrap.append(\n header,\n editorHost,\n h('div', { class: 'sm-field__help' }, [\n '保存后该组件将以这段 MJML 直接输出,属性面板会被禁用,可点\"恢复默认\"取消锁定。',\n ]),\n actions,\n );\n return wrap;\n }\n\n private _destroyCodeView() {\n if (this.codeView) {\n this.codeView.destroy();\n this.codeView = null;\n }\n }\n}\n","import { EditorState } from '@codemirror/state';\nimport { EditorView, basicSetup } from 'codemirror';\nimport { html as cmHtml } from '@codemirror/lang-html';\nimport type { Registry } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport type { Store } from '../store/store';\nimport { clear, h } from '../utils/dom';\nimport { richTextExecCommand } from '../utils/richTextCommand';\n\nexport interface SourceViewOptions {\n store: Store;\n registry: Registry;\n}\n\ntype SourceTab = 'mjml' | 'html';\n\n/**\n * 文档级源码视图:只读地展示当前文档编译出的 MJML 与 HTML。\n *\n * 本期不支持把源码直接回写到数据模型——MJML/HTML 反推 doc 风险大且不必要,\n * 用户若需要直接写源码,可在右栏对单个 Block 走\"组件级代码模式\"。\n */\nexport class SourceView {\n el: HTMLElement;\n private opts: SourceViewOptions;\n private currentTab: SourceTab = 'mjml';\n private body: HTMLElement;\n private cm: EditorView | null = null;\n\n constructor(opts: SourceViewOptions) {\n this.opts = opts;\n this.el = h('div', { class: 'sm-doc-source' });\n this.body = h('div', { class: 'sm-doc-source__body' });\n this._render();\n opts.store.subscribe(() => {\n if (this._isVisible()) this._renderEditor();\n });\n }\n\n /**\n * 设计态运行时 SourceView 不在 DOM,`store.subscribe` 里的 `_renderEditor()` 全部被跳过,\n * CodeMirror 里仍是构造函数那一刻的快照。**切到「源码」模式后必须手动调一次**,\n * 否则会看到空文档 / 旧文档,但「导出」「预览」「MJML→HTML」却一直是当前 doc ——这正是用户报告的错位。\n */\n refreshDoc() {\n this._renderEditor();\n }\n\n private _isVisible(): boolean {\n return this.el.isConnected && (this.el.offsetParent !== null || this.el.getClientRects().length > 0);\n }\n\n private _render() {\n clear(this.el);\n const bar = h('div', { class: 'sm-doc-source__bar' }, [\n this._tabBtn('mjml', 'MJML'),\n this._tabBtn('html', 'HTML(编译产物)'),\n h('div', { class: 'sm-topbar__spacer' }),\n h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: () => this._copy(),\n },\n ['复制'],\n ),\n ]);\n this.el.append(bar, this.body);\n this._renderEditor();\n }\n\n private _tabBtn(tab: SourceTab, label: string) {\n return h(\n 'button',\n {\n class: `sm-segmented__item ${tab === this.currentTab ? 'sm-segmented__item--active' : ''}`,\n type: 'button',\n onclick: () => {\n this.currentTab = tab;\n this._render();\n },\n },\n [label],\n );\n }\n\n private _renderEditor() {\n this._destroyCm();\n clear(this.body);\n const result = renderDoc(this.opts.store.doc, this.opts.registry, {\n withSampleVariables: false,\n });\n const text = this.currentTab === 'mjml' ? result.mjml : result.html;\n this.cm = new EditorView({\n parent: this.body,\n state: EditorState.create({\n doc: text,\n extensions: [basicSetup, cmHtml(), EditorState.readOnly.of(true)],\n }),\n });\n }\n\n private async _copy() {\n if (!this.cm) return;\n const text = this.cm.state.doc.toString();\n try {\n await navigator.clipboard.writeText(text);\n } catch {\n const ta = document.createElement('textarea');\n ta.value = text;\n document.body.appendChild(ta);\n ta.select();\n richTextExecCommand('copy');\n document.body.removeChild(ta);\n }\n }\n\n private _destroyCm() {\n if (this.cm) {\n this.cm.destroy();\n this.cm = null;\n }\n }\n\n destroy() {\n this._destroyCm();\n }\n}\n","import type { Store } from '../store/store';\nimport { bindColorPickerInput } from './ColorPickerPopover';\nimport { normalizeAccentHex, rgbCssToHex } from '../utils/accentColor';\nimport { h, clear } from '../utils/dom';\nimport type { EditorTheme } from './theme';\n\nexport type EditorMode = 'design' | 'source';\n\nexport interface TopbarOptions {\n store: Store;\n mode: EditorMode;\n theme: EditorTheme;\n /** 用于读取解析后的 `--sm-primary`,同步到原生 color 输入 */\n accentPickerRoot?: HTMLElement;\n /** 为 true 时在顶栏显示主题色拾取器(需同时提供 `onAccentChange`) */\n showAccentColorPicker?: boolean;\n onAccentChange?: (hex: string) => void;\n onThemeChange: (t: EditorTheme) => void;\n onModeChange: (m: EditorMode) => void;\n onUndo: () => void;\n onRedo: () => void;\n /** 清空画布选中并回到右栏「邮件设置 / 全局样式」 */\n onMailSettings: () => void;\n onInsertVariable: (anchor: HTMLElement) => void;\n onPreview: () => void;\n onExport: () => void;\n /** 切换编辑器根节点浏览器全屏(由 Editor 实现 Fullscreen API) */\n onFullscreenToggle?: () => void;\n /** 切换画布 Section / Block 布局虚线边框 */\n onLayoutBordersToggle?: () => void;\n /** 为 false 时不展示全屏按钮(也可用 `ui.hideTopbarFullscreen`) */\n showFullscreenButton?: boolean;\n /** 为 false 时不展示「邮件设置」按钮(也可用 `ui.hideTopbarMailSettings`) */\n showMailSettingsButton?: boolean;\n /** 为 false 时不渲染左侧产品标题 */\n showTitle?: boolean;\n /** 为 false 时不展示「清空画布」 */\n showClearCanvasButton?: boolean;\n onClearCanvas?: () => void;\n /** 为 false 时不展示「重置内容」 */\n showResetContentButton?: boolean;\n onResetContent?: () => void;\n}\n\nexport class Topbar {\n el: HTMLElement;\n private opts: TopbarOptions;\n private undoBtn!: HTMLButtonElement;\n private redoBtn!: HTMLButtonElement;\n private themeButtons!: Record<EditorTheme, HTMLButtonElement>;\n private modeButtons: Record<EditorMode, HTMLButtonElement> = {} as any;\n private accentInput?: HTMLInputElement;\n private fullscreenBtn?: HTMLButtonElement;\n private layoutBordersBtn?: HTMLButtonElement;\n\n constructor(opts: TopbarOptions) {\n this.opts = opts;\n this.el = h('header', { class: 'sm-topbar' });\n this._render();\n opts.store.subscribe(() => this._sync());\n this._sync();\n }\n\n setMode(m: EditorMode) {\n this.opts.mode = m;\n for (const k of ['design', 'source'] as EditorMode[]) {\n this.modeButtons[k].classList.toggle('sm-segmented__item--active', k === m);\n }\n }\n\n syncTheme(t: EditorTheme) {\n this.opts.theme = t;\n for (const k of ['light', 'dark', 'system'] as const) {\n const on = k === t;\n this.themeButtons[k].classList.toggle('sm-segmented__item--active', on);\n this.themeButtons[k].setAttribute('aria-pressed', on ? 'true' : 'false');\n }\n }\n\n /** 根据 `.sm-root` 上计算后的 `--sm-primary` 更新拾取器显示(无拾取器或未挂 root 时忽略) */\n syncAccentPicker() {\n if (!this.accentInput || !this.opts.accentPickerRoot) return;\n const raw = getComputedStyle(this.opts.accentPickerRoot).getPropertyValue('--sm-primary').trim();\n const base = normalizeAccentHex(raw) || rgbCssToHex(raw);\n if (!base) return;\n const norm = normalizeAccentHex(base);\n if (!norm) return;\n const forInput = `#${norm.slice(1).toLowerCase()}`;\n if (this.accentInput.value.toLowerCase() !== forInput) this.accentInput.value = forInput;\n }\n\n /** 与 document fullscreen 状态同步图标与 aria(按钮不存在时忽略) */\n setFullscreenActive(active: boolean) {\n const btn = this.fullscreenBtn;\n if (!btn) return;\n btn.replaceChildren(active ? iconFullscreenExit() : iconFullscreenEnter());\n btn.title = active ? '退出全屏' : '全屏';\n btn.setAttribute('aria-label', active ? '退出全屏' : '全屏');\n btn.setAttribute('aria-pressed', active ? 'true' : 'false');\n }\n\n /** 与画布布局边框开关同步按钮高亮(按钮不存在时忽略) */\n setLayoutBordersActive(active: boolean) {\n const btn = this.layoutBordersBtn;\n if (!btn) return;\n btn.setAttribute('aria-pressed', active ? 'true' : 'false');\n btn.title = active ? '隐藏 Section / Block 边框' : '显示 Section / Block 边框';\n btn.setAttribute('aria-label', active ? '隐藏 Section / Block 边框' : '显示 Section / Block 边框');\n }\n\n private _render() {\n clear(this.el);\n\n const segmented = h('div', { class: 'sm-segmented' });\n const designBtn = h(\n 'button',\n {\n class: 'sm-segmented__item sm-segmented__item--active',\n type: 'button',\n onclick: () => this.opts.onModeChange('design'),\n },\n ['设计'],\n );\n const sourceBtn = h(\n 'button',\n {\n class: 'sm-segmented__item',\n type: 'button',\n onclick: () => this.opts.onModeChange('source'),\n },\n ['源码'],\n );\n segmented.append(designBtn, sourceBtn);\n this.modeButtons = { design: designBtn, source: sourceBtn };\n\n const themeSeg = h('div', {\n class: 'sm-segmented sm-topbar__theme-seg',\n role: 'group',\n 'aria-label': '界面主题',\n });\n const themeBtn = (theme: EditorTheme, title: string, icon: SVGElement) =>\n h(\n 'button',\n {\n class: 'sm-segmented__item sm-topbar__theme-btn',\n type: 'button',\n title,\n 'aria-pressed': theme === this.opts.theme ? 'true' : 'false',\n onclick: () => this.opts.onThemeChange(theme),\n },\n [icon],\n ) as HTMLButtonElement;\n this.themeButtons = {\n light: themeBtn('light', '浅色', iconSun()),\n dark: themeBtn('dark', '深色', iconMoon()),\n system: themeBtn('system', '跟随系统', iconThemeAuto()),\n };\n themeSeg.append(this.themeButtons.light, this.themeButtons.dark, this.themeButtons.system);\n\n const themeGroupKids: Node[] = [themeSeg];\n if (this.opts.showAccentColorPicker && this.opts.onAccentChange) {\n const inputEl = h('input', {\n type: 'color',\n class: 'sm-topbar__accent-input',\n 'aria-label': '主题色',\n title: '主题色',\n value: '#4f46e5',\n }) as HTMLInputElement;\n bindColorPickerInput(inputEl, {\n layerRoot: this.opts.accentPickerRoot,\n liveCommit: true,\n onCommit: (hex) => this.opts.onAccentChange!(hex),\n });\n this.accentInput = inputEl;\n themeGroupKids.push(h('div', { class: 'sm-topbar__accent' }, [inputEl]));\n } else {\n this.accentInput = undefined;\n }\n\n this.undoBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '撤销 ⌘Z',\n onclick: this.opts.onUndo,\n },\n [iconUndo(), '撤销'],\n );\n this.redoBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '重做 ⌘⇧Z',\n onclick: this.opts.onRedo,\n },\n [iconRedo(), '重做'],\n );\n\n const contentActionKids: HTMLElement[] = [];\n if (this.opts.showClearCanvasButton !== false && typeof this.opts.onClearCanvas === 'function') {\n contentActionKids.push(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '移除画布上所有 Section 与组件',\n onclick: () => this.opts.onClearCanvas!(),\n },\n ['清空画布'],\n ),\n );\n }\n if (\n this.opts.showResetContentButton !== false &&\n typeof this.opts.onResetContent === 'function'\n ) {\n contentActionKids.push(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '恢复为预置邮件结构',\n onclick: () => this.opts.onResetContent!(),\n },\n ['重置内容'],\n ),\n );\n }\n const contentActionsGroup =\n contentActionKids.length > 0 && h('div', { class: 'sm-topbar__group' }, contentActionKids);\n\n const insertVar = h(\n 'button',\n {\n class: 'sm-btn',\n type: 'button',\n onclick: (e: Event) => this.opts.onInsertVariable(e.currentTarget as HTMLElement),\n },\n ['{{ }} 插入变量'],\n );\n\n const previewBtn = h(\n 'button',\n { class: 'sm-btn', type: 'button', onclick: this.opts.onPreview },\n [iconEye(), '预览'],\n );\n\n const exportBtn = h(\n 'button',\n { class: 'sm-btn sm-btn--primary', type: 'button', onclick: this.opts.onExport },\n ['导出 HTML'],\n );\n\n const showMailSettings = this.opts.showMailSettingsButton !== false;\n const trailingGroup: HTMLElement[] = [];\n if (showMailSettings) {\n trailingGroup.push(\n h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost',\n type: 'button',\n title: '邮件主题、宽度与全局样式',\n onclick: () => this.opts.onMailSettings(),\n },\n ['邮件设置'],\n ),\n );\n }\n trailingGroup.push(insertVar, previewBtn, exportBtn);\n\n const canvasToolKids: HTMLElement[] = [];\n\n if (typeof this.opts.onLayoutBordersToggle === 'function') {\n canvasToolKids.push(\n (this.layoutBordersBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost sm-topbar__icon-btn sm-topbar__toggle-btn',\n type: 'button',\n title: '显示 Section / Block 边框',\n 'aria-label': '显示 Section / Block 边框',\n 'aria-pressed': 'false',\n onclick: () => this.opts.onLayoutBordersToggle!(),\n },\n [iconLayoutBorders()],\n ) as HTMLButtonElement),\n );\n } else {\n this.layoutBordersBtn = undefined;\n }\n\n const showFs =\n this.opts.showFullscreenButton !== false &&\n typeof this.opts.onFullscreenToggle === 'function';\n if (showFs) {\n canvasToolKids.push(\n (this.fullscreenBtn = h(\n 'button',\n {\n class: 'sm-btn sm-btn--ghost sm-topbar__icon-btn',\n type: 'button',\n title: '全屏',\n 'aria-label': '全屏',\n 'aria-pressed': 'false',\n onclick: () => this.opts.onFullscreenToggle!(),\n },\n [iconFullscreenEnter()],\n ) as HTMLButtonElement),\n );\n } else {\n this.fullscreenBtn = undefined;\n }\n\n const canvasToolsGroup =\n canvasToolKids.length > 0 && h('div', { class: 'sm-topbar__group' }, canvasToolKids);\n\n const headKids: HTMLElement[] = [];\n if (this.opts.showTitle !== false) {\n headKids.push(h('div', { class: 'sm-topbar__title' }, ['Simple Mail Editor']));\n }\n\n this.el.append(\n ...headKids,\n h('div', { class: 'sm-topbar__group' }, [segmented]),\n h('div', { class: 'sm-topbar__group sm-topbar__theme-group' }, themeGroupKids),\n h('div', { class: 'sm-topbar__group' }, [this.undoBtn, this.redoBtn]),\n ...(contentActionsGroup ? [contentActionsGroup] : []),\n ...(canvasToolsGroup ? [canvasToolsGroup] : []),\n h('div', { class: 'sm-topbar__spacer' }),\n h('div', { class: 'sm-topbar__group' }, trailingGroup),\n );\n\n this.setMode(this.opts.mode);\n this.syncTheme(this.opts.theme);\n }\n\n private _sync() {\n this.undoBtn.disabled = !this.opts.store.canUndo();\n this.redoBtn.disabled = !this.opts.store.canRedo();\n }\n}\n\nfunction iconUndo(): SVGElement {\n return svg(\n '<path d=\"M9 14l-4-4 4-4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M5 10h7a4 4 0 010 8h-1\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconRedo(): SVGElement {\n return svg(\n '<path d=\"M11 14l4-4-4-4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/><path d=\"M15 10H8a4 4 0 000 8h1\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconEye(): SVGElement {\n return svg(\n '<path d=\"M2 10s3-5 8-5 8 5 8 5-3 5-8 5-8-5-8-5z\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/><circle cx=\"10\" cy=\"10\" r=\"2.4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\"/>',\n );\n}\n/** 布局边框:虚线框 + 勾选(点亮时显示勾) */\nfunction iconLayoutBorders(): SVGElement {\n const el = svg(\n '<rect x=\"4.5\" y=\"4.5\" width=\"11\" height=\"11\" rx=\"1.5\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-dasharray=\"2.5 2\"/><path d=\"M7.2 10.1l1.8 1.8 3.8-3.9\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\" class=\"sm-layout-borders-check\"/>',\n );\n return el;\n}\n/** 进入全屏:四角向外 */\nfunction iconFullscreenEnter(): SVGElement {\n return svg(\n '<path d=\"M6 4H4v2M14 4h2v2M6 16H4v-2M14 16h2v-2M4 6V4h2M16 6V4h-2M4 14v2h2M16 14v2h-2\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\n/** 退出全屏:四角向内 */\nfunction iconFullscreenExit(): SVGElement {\n return svg(\n '<path d=\"M8 4v4H4M12 4v4h4M8 16v-4H4M12 16v-4h4M4 8h4v4H4M16 8h-4v4h4\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconSun(): SVGElement {\n return svgTheme(\n '<circle cx=\"10\" cy=\"10\" r=\"3.2\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M10 3.5V5M10 15v1.5M16.5 10H15M5 10H3.5M14.1 5.9 13 7M7 13 5.9 14.1M14.1 14.1 13 13M7 7 5.9 5.9\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>',\n );\n}\nfunction iconMoon(): SVGElement {\n return svgTheme(\n '<path d=\"M8.5 4.2a5.8 5.8 0 100 11.3 4.8 4.8 0 01-1.3-11.3z\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linejoin=\"round\"/>',\n );\n}\n/** 显示器:表示跟随系统外观 */\nfunction iconThemeAuto(): SVGElement {\n return svgTheme(\n '<path d=\"M5 5.5h10c.8 0 1.5.7 1.5 1.5v6c0 .8-.7 1.5-1.5 1.5H5c-.8 0-1.5-.7-1.5-1.5v-6c0-.8.7-1.5 1.5-1.5z\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"/><path d=\"M8 16h4M10 14.2V16\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>',\n );\n}\nfunction svg(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '14');\n el.setAttribute('height', '14');\n el.setAttribute('viewBox', '0 0 20 20');\n el.innerHTML = inner;\n return el;\n}\nfunction svgTheme(inner: string): SVGElement {\n const el = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n el.setAttribute('width', '15');\n el.setAttribute('height', '15');\n el.setAttribute('viewBox', '0 0 20 20');\n el.setAttribute('aria-hidden', 'true');\n el.innerHTML = inner;\n return el;\n}\n","import { Registry, defineBlock } from '../registry/registry';\nimport { renderDoc } from '../renderer';\nimport { Store, pruneSectionIfEmpty } from '../store/store';\nimport type {\n BlockDefinition,\n EditorUiOptions,\n EmailDoc,\n RenderEngine,\n Selection,\n Variable,\n} from '../types';\nimport { clear, h } from '../utils/dom';\nimport { Canvas } from './Canvas';\nimport { ExportModal } from './ExportModal';\nimport { LeftPanel } from './LeftPanel';\nimport { PreviewModal } from './PreviewModal';\nimport { RichTextToolbar } from './RichTextToolbar';\nimport { RightPanel } from './RightPanel';\nimport { SourceView } from './SourceView';\nimport { Topbar, type EditorMode } from './Topbar';\nimport type { EditorTheme } from './theme';\nimport type { ImageAssetsHandlers } from './imageAssets';\nimport { accentPrimarySoftRgba, normalizeAccentHex } from '../utils/accentColor';\n\nimport './styles.css';\n\nexport interface EditorOptions {\n /** 挂载点 */\n container: HTMLElement;\n /** 初始文档;不传时使用空文档 */\n initialDoc?: Partial<EmailDoc>;\n /** 自定义组件定义(除内置组件之外) */\n blocks?: BlockDefinition<any>[];\n /** 渲染引擎,目前仅 'mjml'。预留 'table' 切换 */\n engine?: RenderEngine;\n /**\n * 把 Block 拖到 sections 之间的空白处时,是否自动包一个一列 Section。\n * - true(默认):宽容,运营即使没瞄准列也能落下,自动加壳\n * - false:严格,只允许拖到现有列内;落到顶层会被 SortableJS 显示为禁止\n */\n autoWrapSection?: boolean;\n /**\n * 为 true 时:点击中栏灰色衬底、画布内空白(未点到 Section/块)等会提交内联编辑并清空选中,\n * 右栏回到文档级面板(邮件设置 / 版式与全局样式;若 `ui.hideMailMeta` 则仅版式与全局样式)。\n * 默认 false;需要「点空白取消选中」的宿主再设为 true。\n */\n clearSelectionOnCanvasMargin?: boolean;\n /** 文档变更回调(防抖发出) */\n onChange?: (doc: EmailDoc) => void;\n /**\n * 品牌/主题色(#RRGGBB),映射为界面上的 --sm-primary / --sm-primary-soft(强调、选区、主按钮等)。\n * 不传则使用 styles 里与 light/dark/system 配套的默认紫/靛。\n */\n accentColor?: string;\n /** 为 true 时在顶栏显示主题色拾取(原生 color 控件);默认 false,仅通过 accentColor / setAccentColor 由宿主控制也可 */\n showAccentColorPicker?: boolean;\n /**\n * 编辑器外框主题。`system` 随 `prefers-color-scheme`;邮件画布仍默认白纸以便预览成品。\n * @default 'light'\n */\n theme?: EditorTheme;\n /**\n * 可选。为 `type: 'image'` 提供上传 / 图床;`showUpload` 默认 true(有 uploadImage 时),`showGallery` 默认 false。\n */\n imageAssets?: ImageAssetsHandlers;\n /** 右栏控件形态等可选 UI 偏好。 */\n ui?: EditorUiOptions;\n /**\n * 顶栏「重置内容」恢复的目标文档(与 `initialDoc` 独立;编辑已保存邮件时仍应指向业务预置模板)。\n * 未传时与构造时的 `initialDoc` 合并结果一致。\n */\n presetDoc?: Partial<EmailDoc>;\n}\n\n/**\n * 编辑器主类。所有外部能力都通过它暴露。\n *\n * 使用示例(vanilla):\n * const editor = new MailEditor({\n * container: document.getElementById('app')!,\n * blocks: [/* 自定义组件 *\\/],\n * // imageAssets: { uploadImage, pickImageFromGallery, showGallery: true } // 可选,见 README\n * });\n * editor.setVariables([{ key: 'user.name', label: '用户名', sample: '张三' }]);\n * editor.export(); // -> { mjml, html }\n */\nexport class MailEditor {\n readonly store: Store;\n readonly registry: Registry;\n private opts: EditorOptions;\n private root: HTMLElement;\n private theme: EditorTheme;\n private mode: EditorMode = 'design';\n private topbar!: Topbar;\n private leftPanel!: LeftPanel;\n private canvas!: Canvas;\n private rightPanel!: RightPanel;\n private sourceView!: SourceView;\n private toolbar!: RichTextToolbar;\n private body: HTMLElement;\n private changeTimer: number | null = null;\n /** 显式品牌色时覆盖 CSS 变量;未设置则由 styles 按 light/dark 使用默认紫/靛 */\n private accentColorOverride: string | undefined;\n /** 顶栏开关:是否在画布上始终显示 Section / Block 轻量虚线边框 */\n private showLayoutBorders = false;\n /** 「重置内容」时恢复的文档快照(与当前画布内容无关) */\n private presetContentDoc: EmailDoc;\n private systemThemeMq: MediaQueryList | null = null;\n private readonly _onSystemThemeMqChange = () => {\n if (this.accentColorOverride) this._applyAccentVars();\n };\n\n private readonly _onFullscreenChange = () => {\n const el = smGetFullscreenElement();\n this.topbar?.setFullscreenActive(el === this.root);\n };\n\n /** design 态 Esc:块 → 父级 Section → 文档级面板(邮件设置或版式/全局样式,取决于 `ui.hideMailMeta`) */\n private _mailEscHandler = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n if (this.mode !== 'design') return;\n if (!this.store.selection) return;\n if (document.querySelector('.sm-modal__mask.is-open')) return;\n const t = e.target as HTMLElement | null;\n if (t?.closest?.('.sm-modal__mask')) return;\n const ae = document.activeElement as HTMLElement | null;\n if (ae && (ae.tagName === 'INPUT' || ae.tagName === 'TEXTAREA' || ae.isContentEditable)) return;\n if (ae && ae !== document.body && !this.root.contains(ae)) return;\n e.preventDefault();\n const sel = this.store.selection;\n if (sel.kind === 'block') {\n this.canvas.commitInlineEdit();\n this.store.setSelection({ kind: 'section', sectionId: sel.sectionId });\n return;\n }\n this._focusMailSettings();\n };\n\n /**\n * 文档级撤销/重做(捕获阶段):焦点在右栏 input/CodeMirror 内时,冒泡到 root 的监听太晚,\n * 浏览器会先处理控件内撤销;仅在 store 仍有历史时拦截并走全局 undo/redo。\n */\n private _mailUndoRedoHandler = (e: KeyboardEvent) => {\n const meta = e.metaKey || e.ctrlKey;\n if (!meta) return;\n const k = e.key.toLowerCase();\n if (k !== 'z') return;\n const t = e.target as Node | null;\n if (!t || !this.root.contains(t)) return;\n const undo = !e.shiftKey;\n const redo = e.shiftKey;\n if (undo && !this.store.canUndo()) return;\n if (redo && !this.store.canRedo()) return;\n e.preventDefault();\n if (undo) this.store.undo();\n else this.store.redo();\n };\n\n constructor(opts: EditorOptions) {\n this.opts = opts;\n this.registry = new Registry();\n\n // 注册外部 blocks\n if (opts.blocks) {\n for (const def of opts.blocks) this.registry.register(def);\n }\n\n const initialDoc = createDefaultDoc(opts.initialDoc);\n this.presetContentDoc = structuredClone(\n createDefaultDoc(opts.presetDoc ?? opts.initialDoc),\n );\n this.store = new Store(initialDoc);\n\n const initialAccent = normalizeAccentHex(this.opts.accentColor ?? '');\n if (\n this.opts.accentColor != null &&\n String(this.opts.accentColor).trim() !== '' &&\n !initialAccent\n ) {\n console.warn('[simple-mail] accentColor 无效,已忽略:', this.opts.accentColor);\n }\n this.accentColorOverride = initialAccent ?? undefined;\n\n this.theme = opts.theme ?? 'light';\n this.root = h('div', { class: 'sm-root' });\n this._applyThemeAttr();\n this.body = h('div', { class: 'sm-body' });\n opts.container.append(this.root);\n\n this._buildUI();\n this._bindKeyboard();\n this._bindFullscreen();\n\n this._applyAccentVars();\n this._refreshAccentMqBinding();\n this._syncTopbarAccentPicker();\n\n this.store.subscribe(() => this._onChange());\n }\n\n /* ------------------------------ Public API ------------------------------ */\n\n setValue(doc: EmailDoc) {\n this._blurRightPanelIfFocused();\n this.store.replace(doc);\n }\n\n getValue(): EmailDoc {\n return this.store.doc;\n }\n\n /**\n * 清空画布:移除所有 Section/Block,保留 meta、styles、variables。\n * 会提交内联编辑并清空选中。\n */\n clearCanvas(): void {\n this.canvas.commitInlineEdit();\n this._blurRightPanelIfFocused();\n this.store.update((d) => {\n d.sections = [];\n });\n this.store.setSelection(null);\n }\n\n /** 将画布恢复为构造时 `presetDoc`(或 `initialDoc`)对应的预置内容。 */\n resetToPreset(): void {\n this._blurRightPanelIfFocused();\n this.store.replace(structuredClone(this.presetContentDoc));\n this.store.setSelection(null);\n }\n\n /** 更新「重置内容」的目标(例如宿主异步加载默认模板后)。 */\n setPresetDoc(partial: Partial<EmailDoc>): void {\n this.presetContentDoc = structuredClone(createDefaultDoc(partial));\n }\n\n setVariables(vars: Variable[]) {\n this.store.update((d) => {\n d.variables = vars;\n });\n }\n\n getVariables(): Variable[] {\n return this.store.doc.variables;\n }\n\n /** 当前界面主题(`system` 不解析为 light/dark)。 */\n getTheme(): EditorTheme {\n return this.theme;\n }\n\n /** 切换界面主题;写入 `data-sm-theme`,顶栏选择器同步。 */\n setTheme(t: EditorTheme) {\n if (this.theme === t) return;\n this.theme = t;\n this._applyThemeAttr();\n this._applyAccentVars();\n this._refreshAccentMqBinding();\n this.topbar?.syncTheme(t);\n this._syncTopbarAccentPicker();\n }\n\n /**\n * 品牌/主题色(#RRGGBB)。传 null、undefined 或空字符串则恢复为 light/dark/system 下的 CSS 默认色。\n */\n setAccentColor(hex: string | null | undefined) {\n if (hex == null || String(hex).trim() === '') {\n this.accentColorOverride = undefined;\n } else {\n const n = normalizeAccentHex(String(hex));\n if (!n) {\n console.warn('[simple-mail] setAccentColor 无效,已忽略:', hex);\n return;\n }\n this.accentColorOverride = n;\n }\n this._applyAccentVars();\n this._refreshAccentMqBinding();\n this._syncTopbarAccentPicker();\n }\n\n /** 当前由选项或 setAccentColor 显式设置的品牌色;未覆盖时为 undefined。 */\n getAccentColor(): string | undefined {\n return this.accentColorOverride;\n }\n\n /** 导出 MJML 与编译后的 HTML。withSampleVariables=true 时把 {{var}} 替换为 sample 值用于预览。 */\n export(opts: { withSampleVariables?: boolean } = {}) {\n return renderDoc(this.store.doc, this.registry, {\n engine: this.opts.engine ?? 'mjml',\n withSampleVariables: opts.withSampleVariables ?? false,\n });\n }\n\n registerBlock<P extends object>(def: BlockDefinition<P>) {\n this.registry.register(def);\n this.leftPanel?.refresh();\n }\n\n setSelection(sel: Selection | null) {\n this.store.setSelection(sel);\n }\n\n destroy() {\n this._unbindFullscreen();\n this._unbindSystemThemeMqForAccent();\n if (this.changeTimer) window.clearTimeout(this.changeTimer);\n if (smGetFullscreenElement() === this.root) void smExitFullscreen();\n document.removeEventListener('keydown', this._mailEscHandler, true);\n document.removeEventListener('keydown', this._mailUndoRedoHandler, true);\n this.canvas?.destroy?.();\n this.sourceView?.destroy?.();\n this.toolbar?.destroy?.();\n this.root.remove();\n }\n\n /* -------------------------------- 私有 ---------------------------------- */\n\n private _applyThemeAttr() {\n this.root.setAttribute('data-sm-theme', this.theme);\n }\n\n private _chromeIsEffectivelyDark(): boolean {\n if (this.theme === 'dark') return true;\n if (this.theme === 'light') return false;\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n }\n\n private _applyAccentVars() {\n if (!this.accentColorOverride) {\n this.root.style.removeProperty('--sm-primary');\n this.root.style.removeProperty('--sm-primary-soft');\n return;\n }\n const dark = this._chromeIsEffectivelyDark();\n this.root.style.setProperty('--sm-primary', this.accentColorOverride);\n this.root.style.setProperty('--sm-primary-soft', accentPrimarySoftRgba(this.accentColorOverride, dark));\n }\n\n private _unbindSystemThemeMqForAccent() {\n if (this.systemThemeMq) {\n this.systemThemeMq.removeEventListener('change', this._onSystemThemeMqChange);\n this.systemThemeMq = null;\n }\n }\n\n /** `system` 主题且存在品牌色覆盖时,随系统深浅刷新 --sm-primary-soft */\n private _refreshAccentMqBinding() {\n this._unbindSystemThemeMqForAccent();\n if (this.theme === 'system' && this.accentColorOverride) {\n const mq = window.matchMedia('(prefers-color-scheme: dark)');\n mq.addEventListener('change', this._onSystemThemeMqChange);\n this.systemThemeMq = mq;\n }\n }\n\n private _syncTopbarAccentPicker() {\n this.topbar?.syncAccentPicker();\n }\n\n private _buildUI() {\n this.topbar = new Topbar({\n store: this.store,\n mode: this.mode,\n theme: this.theme,\n accentPickerRoot: this.root,\n showAccentColorPicker: this.opts.showAccentColorPicker === true,\n onAccentChange: (hx) => this.setAccentColor(hx),\n onThemeChange: (t) => this.setTheme(t),\n onModeChange: (m) => this._setMode(m),\n onUndo: () => {\n this.store.undo();\n },\n onRedo: () => {\n this.store.redo();\n },\n onMailSettings: () => this._focusMailSettings(),\n showMailSettingsButton: this.opts.ui?.hideTopbarMailSettings !== true,\n showTitle: this.opts.ui?.hideTopbarTitle !== true,\n onInsertVariable: (anchor) => this._showVariablePopover(anchor),\n onPreview: () => this._showPreview(),\n onExport: () => this._showExport(),\n showFullscreenButton: this.opts.ui?.hideTopbarFullscreen !== true,\n onFullscreenToggle: () => void this._toggleFullscreen(),\n onLayoutBordersToggle: () => this._toggleLayoutBorders(),\n showClearCanvasButton: this.opts.ui?.hideTopbarClearCanvas !== true,\n onClearCanvas: () => this._confirmClearCanvas(),\n showResetContentButton: this.opts.ui?.hideTopbarResetContent !== true,\n onResetContent: () => this._confirmResetContent(),\n });\n\n this.toolbar = new RichTextToolbar({ positionRoot: this.root });\n this.leftPanel = new LeftPanel({ registry: this.registry });\n const autoWrap = this.opts.autoWrapSection !== false;\n this.root.classList.toggle('sm-allow-auto-wrap', autoWrap);\n this.canvas = new Canvas({\n store: this.store,\n registry: this.registry,\n toolbar: this.toolbar,\n autoWrapSection: autoWrap,\n clearSelectionOnCanvasMargin: this.opts.clearSelectionOnCanvasMargin === true,\n layerRoot: this.root,\n });\n this.rightPanel = new RightPanel({\n store: this.store,\n registry: this.registry,\n docRootLabel: this.opts.ui?.hideMailMeta ? '版式' : '邮件',\n onFocusSection: (sectionId) => {\n this.canvas.commitInlineEdit();\n this.store.setSelection({ kind: 'section', sectionId });\n },\n onFocusDocument: () => this._focusMailSettings(),\n imageAssets: this.opts.imageAssets,\n ui: this.opts.ui,\n });\n this.sourceView = new SourceView({ store: this.store, registry: this.registry });\n\n this.body.append(this.leftPanel.el, this.canvas.el, this.rightPanel.el);\n this.root.append(this.topbar.el, this.body);\n }\n\n /** 撤销/替换文档前先失焦右栏,否则 RightPanel 会因「保留焦点」跳过重绘而仍显示旧值 */\n private _blurRightPanelIfFocused() {\n const ae = document.activeElement as HTMLElement | null;\n if (ae && this.rightPanel.el.contains(ae)) ae.blur();\n }\n\n /** 提交内联编辑并清空选中,右栏回到文档级面板 */\n private _focusMailSettings() {\n this.canvas.commitInlineEdit();\n this.store.setSelection(null);\n }\n\n private _confirmClearCanvas(): void {\n const ok = window.confirm(\n '将移除画布上所有 Section 与组件,邮件全局样式与变量列表会保留。此操作可用撤销(⌘Z)恢复。',\n );\n if (!ok) return;\n this.clearCanvas();\n }\n\n private _confirmResetContent(): void {\n const ok = window.confirm(\n '将把邮件正文恢复为预置内容,当前画布上的所有模块将被替换。确定继续?',\n );\n if (!ok) return;\n this.resetToPreset();\n }\n\n private _setMode(m: EditorMode) {\n if (this.mode === m) return;\n if (m !== 'design') this.canvas.commitInlineEdit();\n this.mode = m;\n this.topbar.setMode(m);\n clear(this.body);\n if (m === 'design') {\n this.body.classList.remove('sm-body--source');\n this.body.style.removeProperty('grid-template-columns');\n this.body.append(this.leftPanel.el, this.canvas.el, this.rightPanel.el);\n } else {\n this.body.classList.add('sm-body--source');\n this.body.style.removeProperty('grid-template-columns');\n this.body.append(this.sourceView.el);\n // 见 SourceView.refreshDoc:设计态源码面板未挂载时不更新,否则会一直显示构造函数时的旧快照\n queueMicrotask(() => this.sourceView.refreshDoc());\n }\n }\n\n private _bindKeyboard() {\n this.root.addEventListener('keydown', (e) => {\n if (e.key === 'Delete' || e.key === 'Backspace') {\n const tag = (e.target as HTMLElement).tagName;\n if (tag === 'INPUT' || tag === 'TEXTAREA' || (e.target as HTMLElement).isContentEditable) {\n return;\n }\n const sel = this.store.selection;\n if (!sel) return;\n e.preventDefault();\n if (sel.kind === 'section') {\n this.store.update((d) => {\n d.sections = d.sections.filter((s) => s.id !== sel.sectionId);\n });\n this.store.setSelection(null);\n } else {\n this.store.update((d) => {\n const sec = d.sections.find((s) => s.id === sel.sectionId);\n if (!sec) return;\n const col = sec.columns[sel.columnIndex];\n if (!col) return;\n col.blocks = col.blocks.filter((b) => b.id !== sel.blockId);\n pruneSectionIfEmpty(d, sel.sectionId);\n });\n this.store.setSelection(null);\n }\n }\n });\n document.addEventListener('keydown', this._mailUndoRedoHandler, true);\n document.addEventListener('keydown', this._mailEscHandler, true);\n this.root.tabIndex = 0;\n }\n\n private _onChange() {\n if (!this.opts.onChange) return;\n if (this.changeTimer) window.clearTimeout(this.changeTimer);\n this.changeTimer = window.setTimeout(() => {\n this.opts.onChange?.(this.store.doc);\n this.changeTimer = null;\n }, 60) as unknown as number;\n }\n\n private _showVariablePopover(anchor: HTMLElement) {\n const vars = this.store.doc.variables;\n if (!vars.length) {\n alert('当前未配置变量。请先调用 editor.setVariables([...])');\n return;\n }\n const existing = this.root.querySelector('.sm-popover');\n if (existing) {\n existing.remove();\n return;\n }\n\n const pop = h('div', { class: 'sm-popover' });\n for (const v of vars) {\n pop.append(\n h(\n 'button',\n {\n class: 'sm-popover__item',\n type: 'button',\n onclick: () => {\n this._insertVariable(v);\n pop.remove();\n },\n },\n [\n h('span', { class: 'sm-popover__key' }, [`{{${v.key}}}`]),\n h('span', { class: 'sm-popover__label' }, [v.label]),\n ],\n ),\n );\n }\n\n const rect = anchor.getBoundingClientRect();\n const rootRect = this.root.getBoundingClientRect();\n pop.style.top = `${rect.bottom - rootRect.top + 4}px`;\n pop.style.left = `${rect.left - rootRect.left}px`;\n this.root.append(pop);\n\n const onDocClick = (ev: MouseEvent) => {\n if (!pop.contains(ev.target as Node) && ev.target !== anchor) {\n pop.remove();\n document.removeEventListener('click', onDocClick, true);\n }\n };\n setTimeout(() => document.addEventListener('click', onDocClick, true), 0);\n }\n\n private _insertVariable(v: Variable) {\n const sel = this.store.selection;\n const placeholder = `{{${v.key}}}`;\n\n // 最高优:正在画布内联编辑的富文本光标处\n const inline = this.canvas.currentInlineEditor;\n if (inline) {\n inline.insertText(placeholder);\n return;\n }\n\n // 次之:当前聚焦的 input/textarea(属性面板)\n const active = document.activeElement as HTMLInputElement | HTMLTextAreaElement | null;\n if (\n active &&\n (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA') &&\n this.root.contains(active)\n ) {\n const start = active.selectionStart ?? active.value.length;\n const end = active.selectionEnd ?? active.value.length;\n active.value = active.value.slice(0, start) + placeholder + active.value.slice(end);\n const ev = new Event('input', { bubbles: true });\n active.dispatchEvent(ev);\n return;\n }\n\n // 最次:选中 Block 时追加到该 block 的 inlineEditable 字段或第一个文本字段\n if (sel?.kind === 'block') {\n this.store.update((d) => {\n for (const s of d.sections) {\n for (const c of s.columns) {\n const b = c.blocks.find((x) => x.id === sel.blockId);\n if (!b) continue;\n const def = this.registry.get(b.type);\n const key =\n def?.inlineEditable?.propKey ??\n def?.schema.find((f) => f.type === 'text' || f.type === 'textarea')?.key;\n if (key) {\n const cur = String((b.props as any)[key] ?? '');\n (b.props as any)[key] = cur + placeholder;\n }\n }\n }\n });\n return;\n }\n\n alert('请先双击进入文本编辑、或聚焦一个输入框后再插入变量');\n }\n\n private _showExport() {\n // 切回设计模式时如果还在内联编辑,先把内容提交进 store\n this.canvas.commitInlineEdit();\n const modal = new ExportModal({\n store: this.store,\n registry: this.registry,\n withSampleVariables: true,\n });\n modal.open(this.root);\n }\n\n private _showPreview() {\n this.canvas.commitInlineEdit();\n const modal = new PreviewModal({\n store: this.store,\n registry: this.registry,\n });\n modal.open(this.root);\n }\n\n private _bindFullscreen() {\n if (this.opts.ui?.hideTopbarFullscreen === true) return;\n document.addEventListener('fullscreenchange', this._onFullscreenChange);\n document.addEventListener('webkitfullscreenchange', this._onFullscreenChange);\n this._onFullscreenChange();\n }\n\n private _unbindFullscreen() {\n document.removeEventListener('fullscreenchange', this._onFullscreenChange);\n document.removeEventListener('webkitfullscreenchange', this._onFullscreenChange);\n }\n\n private async _toggleFullscreen() {\n try {\n if (smGetFullscreenElement() === this.root) await smExitFullscreen();\n else await smRequestFullscreen(this.root);\n } catch (err) {\n console.warn('[simple-mail] 全屏不可用:', err);\n }\n }\n\n private _toggleLayoutBorders() {\n this.showLayoutBorders = !this.showLayoutBorders;\n this.root.classList.toggle('sm-show-layout-borders', this.showLayoutBorders);\n this.topbar.setLayoutBordersActive(this.showLayoutBorders);\n }\n}\n\nfunction smGetFullscreenElement(): Element | null {\n const d = document as Document & { webkitFullscreenElement?: Element | null };\n return document.fullscreenElement ?? d.webkitFullscreenElement ?? null;\n}\n\nasync function smRequestFullscreen(el: HTMLElement): Promise<void> {\n const anyEl = el as HTMLElement & { webkitRequestFullscreen?: () => Promise<void> | void };\n if (typeof anyEl.requestFullscreen === 'function') await anyEl.requestFullscreen();\n else if (typeof anyEl.webkitRequestFullscreen === 'function') await anyEl.webkitRequestFullscreen();\n}\n\nasync function smExitFullscreen(): Promise<void> {\n const d = document as Document & { webkitExitFullscreen?: () => Promise<void> | void };\n if (typeof document.exitFullscreen === 'function') await document.exitFullscreen();\n else if (typeof d.webkitExitFullscreen === 'function') await d.webkitExitFullscreen();\n}\n\n/* ----------------------------- 默认空文档 ------------------------------- */\n\nfunction createDefaultDoc(partial?: Partial<EmailDoc>): EmailDoc {\n const mergedStyles = {\n backgroundColor: '#ffffff',\n contentBackgroundColor: '#ffffff',\n fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, \"PingFang SC\", \"Microsoft YaHei\", sans-serif',\n fontSize: '16px',\n fontWeight: '400',\n color: '#433f3f',\n linkColor: '#ff5a00',\n lineHeight: '1.25',\n ...(partial?.styles ?? {}),\n };\n return {\n version: '1',\n meta: {\n subject: '一封新邮件',\n preheader: '',\n width: 600,\n ...(partial?.meta ?? {}),\n },\n variables: partial?.variables ?? [],\n styles: {\n ...mergedStyles,\n fontWeight: mergedStyles.fontWeight ?? '400',\n lineHeight: mergedStyles.lineHeight ?? '1.25',\n },\n sections: partial?.sections ?? [],\n };\n}\n\nexport { defineBlock };\n"],"names":["Registry","__publicField","def","type","category","d","cryptoRandomId","ts","rand","defineBlock","coerceCssWidth","raw","n","s","docContentWidthCss","parseMetaWidthFromUserInput","input","metaWidthInputString","blockButtonWidthCss","parseSectionWidthFromUserInput","sectionWidthInputString","h","tag","attrs","children","el","k","v","child","clear","escapeHtml","escapeAttr","FONT_WEIGHT_STEP_VALUES","FONT_WEIGHT_STEP_OPTIONS","normalizeFontWeightStep","match","steps","best","bestD","st","mjRawCellTypographyFromStyles","cssForDoubleQuotedAttr","value","buildMjRawTdStyle","paddingCss","typo","fontSize","lineHeight","color","fontFamily","fontWeight","mjRawEmailTableWrap","cellInnerHtml","wrapLockedMjmlForMjColumn","fragment","lead","t","normalizeHtmlBlockLockedMjmlForCompile","mj","inner","divStrip","htmlFragmentForLockedHtmlBlockCanvas","lockedMjml","padding","mjMatch","pad","bare","docToMjml","doc","registry","ctx","sections","sectionToMjml","sectionWidthConstraintCss","sectionMjClassName","sectionId","w","section","a","bg","secCls","widths","layoutWidths","gapPx","columns","col","i","columnToMjml","grouped","indent","column","width","columnIndex","columnCount","columnGapPx","va","gapPad","half","pl","rawTypo","blocks","b","frag","p","layout","parts","total","x","text","l","renderDoc","opts","engine","mjml","compiled","mjmlCompile","html","replaceVariables","e","vars","key","_counter","uid","prefix","Store","initial","fn","sel","mutator","draft","prev","next","source","detail","findSection","findBlockLocation","blockId","blk","pruneSectionIfEmpty","sec","pruneEmptySections","TWO_COLUMN_LAYOUTS","isTwoColumnLayout","setSectionLayout","nextCols","curCols","removed","last","createSection","colCount","LAYOUT_LABELS","layoutHumanLabel","prettyHtml","VOID","PRESERVE","tokens","depth","preserveStack","out","tok","inPreserve","_a","_b","selfClosing","txt","Modal","parent","title","tools","closeBtn","iconClose","BlockCodeModal","beautifyBtn","saveBtn","componentLabel","loc","block","EditorView","EditorState","basicSetup","cmHtml","id","asRichTextDoc","richTextExecCommand","commandId","showUI","richTextQueryCommandState","richTextQueryCommandValue","normalizeAccentHex","rgbCssToHex","rgb","m","accentPrimarySoftRgba","primaryHex","isDarkChrome","hex","r","g","COLOR_PICKER_PALETTE","activeTeardown","isColorPickerOpen","closeActiveColorPicker","positionLayer","layer","anchor","layerRoot","rect","rootRect","popRect","guardInlineEditFocus","syncNativeInput","native","openColorPickerPopover","initialHex","closed","panel","head","hexInput","applyDraft","commit","teardown","onKey","onDoc","swatchGrid","btn","ke","footKids","ev","bindColorPickerInput","pick","InlineEditor","sanitizeRichHtml","restore","off","range","command","hiliteAnchor","selectionAnchorKey","url","trimmed","safe","findAncestorAnchor","px","pxToLegacyFontSize","weight","span","caret","newRange","mode","multiline","placeholder","placeCaretAtEnd","imeComposing","suppressNextEnter","onCompositionStart","onCompositionEnd","onKeyDown","onBlur","active","_c","related","_d","_e","_f","_g","onPaste","onSelChange","linkInsideEditing","href","stopLinkActivate","align","link","inline","resolveInlineFormatsAtSelection","foreColor","safeQueryValue","backColor","state","fallback","rects","tmp","node","root","cmd","host","selectionHostElement","resolveForeColorAtSelection","resolveBackColorAtSelection","fromAttr","readColorFromStyleAttr","styleAttr","isTransparentColor","readBackgroundFromStyleAttr","computed","c","map","num","size","legacy","rgba","tpl","walk","toRemove","face","styles","fontSizeFromLegacy","cleaned","allowedAttrs","attr","Canvas","linkFromTarget","target","stopNavigate","si","topPut","top","Sortable","sectionIndex","layoutShort","sectionChip","sw","box","wrap","toolbar","iconDrag","iconCopy","iconTrash","cols","layoutFlexStyle","isEmpty","colEl","layoutFlexValue","vaToFlex","sortable","displayName","content","blockToolbar","iconEdit","iconCode","layouts","bar","reg","newBlock","firstBlock","blockEl","cssEscape","contentRoot","propKey","editingId","restoreUI","blockType","item","fromBlockId","sourceGroup","newIndex","newSection","fromCol","idx","moved","oldIndex","targetSec","clone","editingEl","nodeInEditing","_layout","columnGap","index","ratio","svg","ExportModal","editorHost","copyBtn","downloadBtn","result","ta","blob","LAYOUT_CARDS","layoutSvg","LeftPanel","custom","grid","defs","gap","innerW","rw","DEVICES","_PreviewModal","switcher","iconForDevice","spec","body","maxPx","PreviewModal","FONT_FAMILIES","FONT_SIZES","RichTextToolbar","editor","f","hasLink","colorToHexInput","matchFamily","matchFontSize","matchFontWeight","ed","sep","exec","val","svgIcon","opt","applyLinkBtn","opening","tw","th","left","on","onClick","style","icon","name","lower","step","toHex","defaultSocialIconBackground","network","FocusBreadcrumb","items","store","docRootLabel","onFocusDocument","onFocusSection","blockName","openImageGalleryModal","adapter","onPick","onClose","modal","query","page","hasMore","loading","selected","errEl","searchInp","debounceId","loadFirst","gridEl","loadMoreBtn","loadPage","confirmBtn","finishPick","setError","msg","syncSelectionStyles","renderCells","append","it","thumb","cellWrap","cell","img","cap","delBtn","err","res","toolRow","urlInp","addBtn","u","fileInp","upBtn","scrollArea","classifyLayoutWidth","layoutWidthNumeric","RightPanel","show","ae","token","selStart","selEnd","len","tabs","tab","label","hideMeta","rows","vals","checked","schema","form","field","fp","defaults","onChange","rawColor","stored","isFw","displayVal","rawFs","row","quad","dp","resetQuad","pr","networkOptions","elementsKey","help","focusPrefix","firstVal","listEl","patchElements","mutate","props","cur","syncItem","patch","removeAt","_","rowData","rowWrap","mainRow","o","inp","rm","extras","bgResolved","bgStored","bgDisplay","bgPick","focusToken","ids","assets","showUploadBtn","showGalleryBtn","hasAssetCallbacks","hasAnyPickerBtn","getCtx","applyUrl","runAsync","labelErr","helpBody","bits","min","max","snap","commitPlain","fb","v0","syncFromSlider","pickToken","textToken","lastValid","applyPickInherit","applyStored","previewPick","options","group","titles","clampPad","current","emit","makePlain","makeSliderRow","rawN","inheritOn","globalDisplay","onToggle","valueEl","display","globalWeight","inheriting","syncGroup","inheritSwitch","globalFontSize","globalPx","syncInput","inheritGlobal","sliderRow","syncSlider","leaveInherit","tf","kind","displayN","clampW","emitW","modesWrap","addModeBtn","header","view","actions","SourceView","Topbar","base","norm","forInput","iconFullscreenExit","iconFullscreenEnter","segmented","designBtn","sourceBtn","themeSeg","themeBtn","theme","iconSun","iconMoon","iconThemeAuto","themeGroupKids","inputEl","iconUndo","iconRedo","contentActionKids","contentActionsGroup","insertVar","previewBtn","iconEye","exportBtn","showMailSettings","trailingGroup","canvasToolKids","iconLayoutBorders","canvasToolsGroup","headKids","svgTheme","MailEditor","smGetFullscreenElement","undo","redo","initialDoc","createDefaultDoc","initialAccent","partial","smExitFullscreen","dark","mq","hx","autoWrap","existing","pop","onDocClick","start","end","smRequestFullscreen","anyEl","mergedStyles"],"mappings":"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"}