@hankchen/canvas-editor 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { LayerBox, Canvas, TextLayoutPolicies, Layer, LayerType, RenderBackend, Padding, HorizontalAlign, VerticalAlign, TableLayer, Anchor, TableRowLayer, TableCellLayer, TableRowTemplateLayer } from '@hankchen/canvas';
1
+ import { LayerBox, Canvas, TextLayoutPolicies, Layer, LayerType, TableLayer, RenderBackend, Padding, HorizontalAlign, VerticalAlign, Anchor, TableRowLayer, TableCellLayer, TableRowTemplateLayer } from '@hankchen/canvas';
2
2
  export { ANCHORS, Anchor, Border, BorderSide, Canvas, HORIZONTAL_ALIGNS, HorizontalAlign, LAYER_TYPES, Layer, LayerBox, LayerType, Padding, TableCellLayer, TableLayer, TableRowLayer, TextLayer, VERTICAL_ALIGNS, VerticalAlign } from '@hankchen/canvas';
3
3
  import { Draft, Patch } from 'immer';
4
4
  export { canvasFontCssFamily } from '@hankchen/canvas-browser-renderer';
@@ -408,6 +408,186 @@ declare function scanTextMatches(doc: Canvas, query: string): FindTextHit[];
408
408
  */
409
409
  declare function replaceHitsInDraft(draft: Draft<Canvas>, hits: readonly FindTextHit[], replacement: string): number;
410
410
 
411
+ /**
412
+ * 图层面板的内核语义(工单 10)。
413
+ *
414
+ * 顺序映射(spec「Vue 绑定与面板」拍板,防反直觉):
415
+ * - 渲染顺序 = graph.layers 数组序 = priority 降序(数组头先画垫底,越大越垫底);
416
+ * - 面板从上到下 = 数组逆序:面板顶 = 视觉最上层 = 数组尾 = 最小 priority。
417
+ *
418
+ * 两套重排语义分立:
419
+ * - 根层重排走 priority 中点插值(保持「数组按 priority 降序」的契约语义,
420
+ * 保存再打开顺序不变);插到上下邻之间 → priority = ⌊(上邻 + 下邻) / 2⌋,
421
+ * 置顶 = min − 1、置底 = max + 1;priority 恒为整数(wire 解码 intval 同门,
422
+ * 小数会在保存→打开时漂移),无整数间隙/同值冲突时对全表做一次按视觉序的
423
+ * 带间隙阶梯归一化重赋(patch 大,仅兜底)。
424
+ * - 表格行重排直接改 rows 数组序(行/格/内容是嵌套数组序语义,绘制按序遍历,
425
+ * priority 字段在容器内不参与排序)。
426
+ *
427
+ * 全模块纯函数、无 DOM;draft 侧变换经 immer 事务落库,查询侧只读。
428
+ */
429
+
430
+ /** 图层在容器树里的角色(决定面板缩进与可拖动性);templateRow = 行模板替身节点 */
431
+ type LayerOutlineRole = 'root' | 'row' | 'cell' | 'content' | 'templateRow';
432
+ /** 面板大纲节点:领域子树的纯投影(无文档写语义) */
433
+ interface LayerOutlineNode {
434
+ readonly type: LayerType;
435
+ readonly path: LayerPath;
436
+ readonly role: LayerOutlineRole;
437
+ /**
438
+ * 用户命名(layer-panel-ux 工单 09):原样携带文档 name(根层重命名后由此
439
+ * 上屏),空串 = 未命名,显示层回落派生标签。行/格/内容同字段照带(不消费)。
440
+ */
441
+ readonly name: string;
442
+ /**
443
+ * 可见性(layer-panel-ux 工单 10):原样携带文档 visible,根层面板行的眼睛
444
+ * 钮状态与隐藏行降不透明度据此投影。行/格/内容同字段照带(不消费——显隐
445
+ * 语义只在 LayerBase 面)。
446
+ */
447
+ readonly visible: boolean;
448
+ /**
449
+ * 锁定投影(canvas-web-layer-lock 工单 02):isLockedPath 前缀判定——锁定的
450
+ * 根层及其整棵子树(行/格/内容)都携 true。锁定态住 ui 分支(会话级、零
451
+ * wire 键),经 buildLayerOutline 的 ui 分支入参喂入;面板锁定钮状态、锁定
452
+ * 行样式与删除钮/菜单删除项置灰据此投影(内核空转为权威,UI 呈现一致)。
453
+ */
454
+ readonly locked: boolean;
455
+ /**
456
+ * 表达式前置(layer-panel-expression-prefix 工单 01):带标记内容层(三内容层
457
+ * 且 expression !== null)的全部闭合片段按 expr 重构 `{{…}}` 外壳、单空格连接,
458
+ * 面板零计算直读;空串 = 无前置(未标记 / 非内容层),对齐 name 字段先例;
459
+ * 全部片段无效得常量 `{{…}}`。全角色节点照带。
460
+ */
461
+ readonly expressionPrefix: string;
462
+ /** TableLayer 专属:是否模板态(+行按钮置灰与 title 的判定面,spec §2.5) */
463
+ readonly templated?: boolean;
464
+ readonly children: readonly LayerOutlineNode[];
465
+ }
466
+ /**
467
+ * 面板大纲:根层按视觉层级排列(数组逆序——面板顶部 = 视觉最上层 = 数组尾),
468
+ * 表格内行/格/内容保持数组序(行 0 在视觉顶部、格 0 在左)。
469
+ * lockedPaths 为 ui 分支入参(canvas-web-layer-lock 工单 02):锁定态不写 graph,
470
+ * 投影按 isLockedPath 前缀判定携带到锁定子树全树;缺省 [](无锁投影)。
471
+ */
472
+ declare function buildLayerOutline(doc: Canvas, lockedPaths?: readonly LayerPath[]): readonly LayerOutlineNode[];
473
+ /**
474
+ * 新层样式(text-defaults 工单 01,CONTEXT「新层样式」词条):记忆「下一个新建
475
+ * 文本层用什么文本样式族」的偏好槽形态——样式粘贴文本族同门的五字段(不含
476
+ * angle,旋转角不是新层偏好)。字段与 TextLayer 顶层字段/shape.lineHeight 对齐。
477
+ */
478
+ interface NextTextStyle {
479
+ font: string;
480
+ fontSize: number;
481
+ fontColor: string;
482
+ autowrap: boolean;
483
+ lineHeight: number;
484
+ }
485
+ /** 文本预设档位(CONTEXT「文本预设」词条):heading 40 / subheading 28 / body 16 */
486
+ type TextPresetId = 'heading' | 'subheading' | 'body';
487
+ /** 文本预设常量(spec 决策 4):v1 只定字号——字体缺口由新层样式槽补 */
488
+ declare const TEXT_PRESETS: readonly {
489
+ id: TextPresetId;
490
+ fontSize: number;
491
+ }[];
492
+ /** 新层样式槽初值:自工厂 TextLayer 形态派生(工厂缺省是单一事实源,槽跟着走) */
493
+ declare function defaultNextTextStyle(): NextTextStyle;
494
+ /**
495
+ * 新层样式字段的宽容读逐字段收口(text-defaults 工单 01;评审合流——捕获与
496
+ * prefs 恢复共用同一谓词,不再双写):合法字段进合并集,缺字/类型不符忽略
497
+ * (调用方保留现值),未知键忽略。autowrap 严格布尔(票 01 口径「不符跳过」,
498
+ * 不做真值强转);lineHeight 须为正有限数。载荷来自属性写入与宿主 JSON 快照,
499
+ * 类型层信任不了,运行时验。
500
+ */
501
+ declare function pickNextTextStylePatch(raw: unknown): Partial<NextTextStyle>;
502
+ /**
503
+ * 编辑器新建图层的缺省形态:可见尺寸(0×0 无法命中/抓取)、top-left 摆位、
504
+ * 中性配色。与 wire 解码缺省是两回事(那是「手写 JSON 宽进」语义),这里是
505
+ * 编辑器 UX 语义;priority 统一由 addRootLayer 按「置顶 min−1」赋值。
506
+ *
507
+ * textDefaults(text-defaults 工单 01):新层样式槽覆盖参,仅 TextLayer 臂逐
508
+ * 字段生效(其余层型忽略)——只有画拉 endCreate 与面板新增 addRootLayer 两个
509
+ * 入口传槽;模板表/表格结构的工厂调用不传,保持确定性缺省(spec 决策 3)。
510
+ */
511
+ declare function createDefaultLayer(type: LayerType, textDefaults?: Partial<NextTextStyle>): Layer;
512
+ /**
513
+ * 模板表工厂(spec §2.1):V1 表缺省形态(400×120)+ 行模板装配——auto 行(声明
514
+ * 高按解码归一为 0、宽 := 表宽关 autoWidth)+ 满宽 60 高缺省格带缺省文本内容
515
+ * (内容宽度同步、零高度耦合,ADR 0006)。rowsPath 由调用方必填(解码
516
+ * rows_path_missing 硬约束,创建表单校验前置);缺省格 60 高保证空态预览行可见
517
+ * 可点(合成高 = 最高格,03 票 E1 机制)。
518
+ */
519
+ declare function createTemplateTable(options: {
520
+ rowsPath: string;
521
+ }): TableLayer;
522
+ /**
523
+ * 「insert-before 原始序号 to」移动的公共守卫与落点折算:from/to 须为安全整数、
524
+ * from ∈ [0, n)、to ∈ [0, n];to ∈ {from, from+1}(原位/相邻落点)为无操作。
525
+ * 返回摘除自身后的插入下标;null = 无操作(n < 2 时任何入参都落入无操作集)。
526
+ * 工单 12 的同行格重排复用同一守卫(与行重排同款语义)。
527
+ */
528
+ declare function moveGuard(n: number, from: number, to: number): number | null;
529
+ /**
530
+ * 根层重排(draft 原位变换):面板坐标(0 = 视觉最上)折算数组坐标做 splice,
531
+ * 再对移动层做 priority 中点插值。from 为被拖面板序号,to 为「insert-before
532
+ * 原始面板序号」落点(∈ [0, N];to = N 即面板底);to ∈ {from, from+1} 或越界
533
+ * 为无操作。数组序全程保持 priority 降序(渲染/解码同源的不变量)。
534
+ * 返回移动的 (from, to) 数组下标(供选择路径重映射);null = 无变化。
535
+ */
536
+ declare function moveRootLayerInDraft(draft: Draft<Canvas>, fromPanel: number, toPanel: number): {
537
+ from: number;
538
+ to: number;
539
+ } | null;
540
+ /**
541
+ * 表格行重排(draft 原位变换):直接改 rows 数组序——容器内是嵌套数组序语义,
542
+ * 行的 priority 不参与排序、不插值(与根层重排语义分立)。from/to 为行序号
543
+ * (行 0 在视觉顶部),to 为「insert-before 原始序号」落点 ∈ [0, rows.length]。
544
+ * 返回 (from, to)(to 为插入后最终下标,供路径重映射);null = 无变化/入参不合法。
545
+ */
546
+ declare function moveTableRowInDraft(draft: Draft<Canvas>, tablePath: LayerPath, fromRow: number, toRow: number): {
547
+ from: number;
548
+ to: number;
549
+ } | null;
550
+ /**
551
+ * 新增根层(draft 原位变换):工厂缺省形态 + priority = min − 1(空画布取 0),
552
+ * push 到数组尾(视觉最上层)。返回新层的数组下标。textDefaults(text-defaults
553
+ * 工单 01)可选透传工厂覆盖——session 侧 addRootLayer 传新层样式槽,其余调用
554
+ * 方不传走纯工厂缺省。
555
+ */
556
+ declare function addRootLayerInDraft(draft: Draft<Canvas>, type: LayerType, textDefaults?: Partial<NextTextStyle>): number;
557
+ /**
558
+ * 根层插入(draft 原位变换,工单 14 剪贴板粘贴共用):priority = min − 1(空画布
559
+ * 取 0)+ push 到数组尾(视觉最上层)。数组序保持 priority 降序的解码不变量
560
+ * (min−1 严格小于现最小值)。调用方负责传入的图层形态(如粘贴子树的深拷贝 +
561
+ * 位置偏移)。返回新层的数组下标。
562
+ */
563
+ declare function insertRootLayerInDraft(draft: Draft<Canvas>, layer: Draft<Layer>): number;
564
+ /**
565
+ * 根层紧邻插入(draft 原位变换,alt-drag-paste 工单 01 原语,⌘V 粘贴工单 02 共用):
566
+ * 新层 splice 到源层后一格 = 源层视觉上方一格,priority 取源与其视觉上一层(数组
567
+ * 序 +1 位)之间的中点插值——数组序全程保持 priority 降序的解码不变量,整数插值
568
+ * 同 moveRootLayerInDraft 门规(midpointPriority:无整数间隙时全表归一化兜底);
569
+ * 源为视觉最顶/数组尾时取 source.priority − 1(置顶 min−1 同门)。
570
+ * source 按根下标或路径寻址:路径取根祖先段(path[1],格内容等子树源紧邻其根层)。
571
+ * 返回新层的数组下标;源下标越界/路径无数字根段返回 null(退化语义归调用方——
572
+ * ⌘V 的「源不可解析退化置顶」在消费面回落 insertRootLayerInDraft)。
573
+ */
574
+ declare function insertRootLayerAdjacentInDraft(draft: Draft<Canvas>, layer: Draft<Layer>, source: number | LayerPath): number | null;
575
+ /** 删除定位:list = 容器列表 splice(roots/rows/cells),content = 格内容置 null */
576
+ type DeletedLayerRef = {
577
+ kind: 'list';
578
+ containerPath: LayerPath;
579
+ key: 'layers' | 'rows' | 'cells';
580
+ index: number;
581
+ } | {
582
+ kind: 'content';
583
+ path: LayerPath;
584
+ };
585
+ /**
586
+ * 删除图层(draft 原位变换):根层连子树整删、行/格走列表 splice、格内容置 null
587
+ * (镜像 impl 研究 §2.8「条目操作」)。路径越界/形态不符/内容已空返回 null(无操作)。
588
+ */
589
+ declare function deleteLayerInDraft(draft: Draft<Canvas>, path: LayerPath): DeletedLayerRef | null;
590
+
411
591
  /**
412
592
  * 数据源 schema 方言编译器(content-completion 工单 02/08,spec §2 + §6 D6–D8)。
413
593
  *
@@ -688,6 +868,14 @@ interface EditorUi {
688
868
  * (与 viewport 同款的面板偏好——openDocument 换文档不重置,永不进历史)。
689
869
  */
690
870
  anchorExpanded: boolean;
871
+ /**
872
+ * 新层样式槽(text-defaults 工单 01,CONTEXT「新层样式」词条):记忆「下一
873
+ * 个新建文本层用什么文本样式族」的编辑器级偏好——属性面板对 TextLayer 文本
874
+ * 族字段的权威写(updateSpec 捕获)更新槽,建层(endCreate/addRootLayer)
875
+ * 以槽值覆盖工厂缺省。与锚点折叠同款的面板偏好——openDocument 换文档不重
876
+ * 置,永不进历史;随工程数据 prefs 桶跨会话持久(宿主通道,内核零 localStorage)。
877
+ */
878
+ nextTextStyle: NextTextStyle;
691
879
  /**
692
880
  * 数据源 schema 声明(content-completion 工单 03/08,D2 宿主随会话注入):
693
881
  * 编译产物形状树或降级 null(根级结构性拒绝,注入期经
@@ -785,7 +973,7 @@ declare class EditorStore {
785
973
  get canRedo(): boolean;
786
974
  /** 打开/替换文档:ui 选择/编辑/重命名会话与双向历史一并重置(新文档不继承旧路径/旧事务);
787
975
  * 参考线/锁定集合/查找会话/建层武装与画拉会话随当次会话清空(对位轴/文档内容防护/
788
- * 查询词/待命层型不跨文档),标尺显隐作为偏好保留 */
976
+ * 查询词/待命层型不跨文档),标尺显隐/锚点折叠/新层样式作为偏好保留 */
789
977
  openDocument(canvas: Canvas): void;
790
978
  /**
791
979
  * 文档事务唯一入口:produceWithPatches 求新树,无变化即空转(不进历史不通知);
@@ -825,6 +1013,11 @@ declare class EditorStore {
825
1013
  setRenaming(path: LayerPath | null): void;
826
1014
  /** 锚点折叠区开合:布尔值等短路(重复点击同一态不重绘) */
827
1015
  setAnchorExpanded(open: boolean): void;
1016
+ /**
1017
+ * 新层样式槽逐字段合并(text-defaults 工单 01:捕获/预设/prefs 恢复的统一
1018
+ * 写入口):patch 并入现值,五字段值等短路(重复写同值零通知),不进历史。
1019
+ */
1020
+ setNextTextStyle(patch: Partial<NextTextStyle>): void;
828
1021
  /**
829
1022
  * 数据源 schema 声明替换(归一产物或降级 null,校验收口在注入缝不在这里):
830
1023
  * 同引用短路(重复注入同一归一产物不惊动订阅方);仅 ui 通知,不参与重绘
@@ -932,6 +1125,41 @@ interface EditorShortcutInput {
932
1125
  */
933
1126
  declare function classifyEditorShortcut(input: EditorShortcutInput, bindings?: readonly EditorShortcutBinding[]): EditorShortcutAction | null;
934
1127
 
1128
+ /**
1129
+ * 编辑器状态切片与偏好(project-data 工单 01,spec §3/§5):内核导出的「单画布
1130
+ * 切片 + 偏好 + schemaVersion 常量」三件,EditorSession 实例方法(editor.ts)消费。
1131
+ *
1132
+ * 分层纪律(内核帧盲):帧名/帧缓冲/文档是宿主领域——frames 容器(帧名 → 切片)
1133
+ * 与完整快照聚合类型(schemaVersion/frames/prefs)归宿主拼装,宿主只透传切片
1134
+ * 内容、不解释 guides/lockedPaths 语义;本模块只出两型 + 版本常量 + restore 的
1135
+ * 轻结构校验。零契约面:切片不进 wire、不进历史栈、不是第二种文档格式——graph
1136
+ * 仍是内核唯一保存物。
1137
+ */
1138
+
1139
+ /** 快照格式版本:随格式演化单调递增;v1 = 1(宽容读贯彻,restore 不分支此值) */
1140
+ declare const EDITOR_STATE_SCHEMA_VERSION = 1;
1141
+ /** 帧作用域切片:当前打开画布的编辑器状态(工程数据快照的 frames[帧名] 值) */
1142
+ interface CanvasEditorState {
1143
+ /**
1144
+ * 参考线(场景坐标):id 是会话内自增值、无持久语义——export 原样带出,
1145
+ * restore 端清空后逐条 addGuide 重取号,快照 id 出方向即失效。
1146
+ */
1147
+ guides: readonly Guide[];
1148
+ /** 锁定根层路径集合(随工程数据持久化,仍零 wire 面) */
1149
+ lockedPaths: readonly LayerPath[];
1150
+ }
1151
+ /** 编辑器级偏好:跨文档、跨会话内核自持(工程数据快照的 prefs 桶,分类学终裁三项) */
1152
+ interface EditorPrefsState {
1153
+ rulersVisible: boolean;
1154
+ anchorExpanded: boolean;
1155
+ /**
1156
+ * 新层样式槽(text-defaults 工单 01,CONTEXT「新层样式」词条):随 prefs 桶
1157
+ * 跨会话持久(per-模板记忆)。schemaVersion 不升——加法演进,旧快照缺字段
1158
+ * 由 applyEditorPrefs 宽容读兜底为现值(会话内即工厂缺省)。
1159
+ */
1160
+ nextTextStyle: NextTextStyle;
1161
+ }
1162
+
935
1163
  /**
936
1164
  * 字体清单(工单 13):编辑会话级的字体可选清单——「清单 ≠ 物化」,core 只持有
937
1165
  * 引用与展示名,字体的加载仍走渲染端物化管线(FontFace 注册),本模块零 I/O。
@@ -1144,8 +1372,13 @@ declare class EditorSession {
1144
1372
  setDevicePixelRatio(dpr: number): void;
1145
1373
  setSurfaceSize(width: number, height: number): void;
1146
1374
  getSurfaceSize(): Readonly<Size>;
1147
- /** 打开/替换文档(转发 store;解码在宿主侧完成,内核只消费领域结构) */
1148
- openDocument(canvas: Canvas): void;
1375
+ /**
1376
+ * 打开/替换文档(转发 store;解码在宿主侧完成,内核只消费领域结构)。
1377
+ * state 传切片即按 restoreEditorState 同一管线原子应用(reset → apply 切片 →
1378
+ * prune)——「开了就恢复」,宿主切帧处不可能忘记重放;切片形状不合法整体拒
1379
+ * (画布照常以默认态打开),现网单参调用零破坏。
1380
+ */
1381
+ openDocument(canvas: Canvas, state?: CanvasEditorState): void;
1149
1382
  /**
1150
1383
  * 预览视图(只读衍生):模板态表格在视图中获得一行预览行(文本格 = 表达式
1151
1384
  * 原文、标记图片/二维码格走占位盒),渲染/命中/导出据此呈现「一行输出效果」;
@@ -1336,8 +1569,13 @@ declare class EditorSession {
1336
1569
  * 武装建层(面板新增项/层型快捷键的统一入口,CONTEXT「武装」词条):置 ui
1337
1570
  * 分支待命层型,下一次画布按下即开画拉;建层提交或 Esc 即解除——一次性
1338
1571
  * 待命态,无粘性工具(spec 决策 2)。重复武装同型值等短路零通知。
1572
+ *
1573
+ * preset(text-defaults 工单 01,CONTEXT「文本预设」词条):文本预设 = 写
1574
+ * 新层样式槽的快捷方式——命中档位先把档位值并入槽(v1 只 fontSize),再
1575
+ * 武装;仅 TextLayer 生效;未知 id = 跳过写槽、武装照常(评审口径统一:
1576
+ * 「空转」只指写槽,武装层型本身仍合法)。
1339
1577
  */
1340
- armLayerCreate(type: LayerType): void;
1578
+ armLayerCreate(type: LayerType, preset?: TextPresetId): void;
1341
1579
  /** 解除建层武装(取消入口):仅清待命态,零副作用。 */
1342
1580
  cancelArmLayerCreate(): void;
1343
1581
  /**
@@ -1439,6 +1677,36 @@ declare class EditorSession {
1439
1677
  listGuides(): readonly Guide[];
1440
1678
  /** 标尺显隐开关(⇧R 分派口):翻转 ui 偏好,不进历史 */
1441
1679
  toggleRulers(): void;
1680
+ /**
1681
+ * 导出当前打开画布的编辑器状态切片:guides 原样带出(id 是会话内自增值,
1682
+ * 宿主不持久化其语义——restore 端重排重取号)、lockedPaths 原样。无文档也可
1683
+ * 导出(ui 分支自成事实,addGuide 无 doc 守卫同门)。内核帧盲:宿主把各帧
1684
+ * 切片按帧名组装成 frames 容器,加上 schemaVersion(EDITOR_STATE_SCHEMA_VERSION)
1685
+ * 与 getEditorPrefs() 才是完整工程数据快照,经宿主层存储——容器不进内核。
1686
+ */
1687
+ exportEditorState(): CanvasEditorState;
1688
+ /**
1689
+ * 恢复当前画布的状态切片(prefs 不在此——内核跨 openDocument 自持):轻结构
1690
+ * 校验(形状不合法整体拒,返 false 宿主记因)→ 整体替换 lockedPaths →
1691
+ * pruneDanglingPaths(悬空锁路径剔除——合法但内容悬空不算拒,prune 兜底)→
1692
+ * guide id 重排(清空后逐条 addGuide 重取号:快照 id 无持久语义,原样入栈必
1693
+ * 与新会话 guideIdSeq 撞号致 removeGuide 误删)。不进历史、不写 graph(红线
1694
+ * 同门)。
1695
+ */
1696
+ restoreEditorState(state: CanvasEditorState): boolean;
1697
+ /**
1698
+ * 只读偏好(保存 prefs 的读取口):与 store.ui 同源,给宿主一个不用下钻
1699
+ * store 的口。读 = getEditorPrefs,写 = applyEditorPrefs,对称成对;帧切片
1700
+ * 走 restoreEditorState,两不相混。
1701
+ */
1702
+ getEditorPrefs(): EditorPrefsState;
1703
+ /**
1704
+ * 应用偏好(会话建立时一次性,跨会话恢复 prefs 的写入口):整体替换
1705
+ * rulersVisible/anchorExpanded,不进历史;值等写入经 store 短路零通知。
1706
+ * 新层样式(text-defaults 工单 01)走宽容读逐字段合并(pickNextTextStylePatch
1707
+ * 共享谓词——与捕获同门,缺字/类型不符保留现值)。
1708
+ */
1709
+ applyEditorPrefs(prefs: EditorPrefsState): void;
1442
1710
  /**
1443
1711
  * 对齐画布 action 族(对齐画布/贴边/贴角,ADR 0011):把 path 处图层盒整体
1444
1712
  * 对齐到画布几何——mode 十种:贴边 left/right/top/bottom(零边距)、居中
@@ -1538,6 +1806,15 @@ declare class EditorSession {
1538
1806
  * 内容宽/高重同步、行高取最高格)——往返恒等在任何字段编辑后不破。
1539
1807
  */
1540
1808
  updateSpec(path: LayerPath, key: readonly string[], value: unknown, options?: TransactOptions): void;
1809
+ /**
1810
+ * 新层样式捕获(text-defaults 工单 01,CONTEXT「新层样式」词条):属性面板
1811
+ * 对 TextLayer 文本族五字段的权威写顺带更新偏好槽——「用户改过一次,下一个
1812
+ * 新层沿用」。捕获口唯一(updateSpec 漏斗):内容写(updateData)、样式粘贴
1813
+ * (搬运不是偏好)、撤销重做都不经过此口。字段合法性走 editing 域共享谓词
1814
+ * pickNextTextStylePatch(与 prefs 宽容读同门,评审合流不再双写):目标层非
1815
+ * TextLayer、键不命中或值类型不符即空转,符合字段经值等短路入槽。
1816
+ */
1817
+ private captureNextTextStyle;
1541
1818
  /**
1542
1819
  * 更新图层数据字段(wire data.value 的领域展开,按 type 分派):
1543
1820
  * TextLayer → text、ImageLayer → src、QrCodeLayer → value;
@@ -1967,151 +2244,6 @@ interface WheelInput {
1967
2244
  }
1968
2245
  declare function classifyWheel(input: WheelInput): WheelIntent;
1969
2246
 
1970
- /**
1971
- * 图层面板的内核语义(工单 10)。
1972
- *
1973
- * 顺序映射(spec「Vue 绑定与面板」拍板,防反直觉):
1974
- * - 渲染顺序 = graph.layers 数组序 = priority 降序(数组头先画垫底,越大越垫底);
1975
- * - 面板从上到下 = 数组逆序:面板顶 = 视觉最上层 = 数组尾 = 最小 priority。
1976
- *
1977
- * 两套重排语义分立:
1978
- * - 根层重排走 priority 中点插值(保持「数组按 priority 降序」的契约语义,
1979
- * 保存再打开顺序不变);插到上下邻之间 → priority = ⌊(上邻 + 下邻) / 2⌋,
1980
- * 置顶 = min − 1、置底 = max + 1;priority 恒为整数(wire 解码 intval 同门,
1981
- * 小数会在保存→打开时漂移),无整数间隙/同值冲突时对全表做一次按视觉序的
1982
- * 带间隙阶梯归一化重赋(patch 大,仅兜底)。
1983
- * - 表格行重排直接改 rows 数组序(行/格/内容是嵌套数组序语义,绘制按序遍历,
1984
- * priority 字段在容器内不参与排序)。
1985
- *
1986
- * 全模块纯函数、无 DOM;draft 侧变换经 immer 事务落库,查询侧只读。
1987
- */
1988
-
1989
- /** 图层在容器树里的角色(决定面板缩进与可拖动性);templateRow = 行模板替身节点 */
1990
- type LayerOutlineRole = 'root' | 'row' | 'cell' | 'content' | 'templateRow';
1991
- /** 面板大纲节点:领域子树的纯投影(无文档写语义) */
1992
- interface LayerOutlineNode {
1993
- readonly type: LayerType;
1994
- readonly path: LayerPath;
1995
- readonly role: LayerOutlineRole;
1996
- /**
1997
- * 用户命名(layer-panel-ux 工单 09):原样携带文档 name(根层重命名后由此
1998
- * 上屏),空串 = 未命名,显示层回落派生标签。行/格/内容同字段照带(不消费)。
1999
- */
2000
- readonly name: string;
2001
- /**
2002
- * 可见性(layer-panel-ux 工单 10):原样携带文档 visible,根层面板行的眼睛
2003
- * 钮状态与隐藏行降不透明度据此投影。行/格/内容同字段照带(不消费——显隐
2004
- * 语义只在 LayerBase 面)。
2005
- */
2006
- readonly visible: boolean;
2007
- /**
2008
- * 锁定投影(canvas-web-layer-lock 工单 02):isLockedPath 前缀判定——锁定的
2009
- * 根层及其整棵子树(行/格/内容)都携 true。锁定态住 ui 分支(会话级、零
2010
- * wire 键),经 buildLayerOutline 的 ui 分支入参喂入;面板锁定钮状态、锁定
2011
- * 行样式与删除钮/菜单删除项置灰据此投影(内核空转为权威,UI 呈现一致)。
2012
- */
2013
- readonly locked: boolean;
2014
- /**
2015
- * 表达式前置(layer-panel-expression-prefix 工单 01):带标记内容层(三内容层
2016
- * 且 expression !== null)的全部闭合片段按 expr 重构 `{{…}}` 外壳、单空格连接,
2017
- * 面板零计算直读;空串 = 无前置(未标记 / 非内容层),对齐 name 字段先例;
2018
- * 全部片段无效得常量 `{{…}}`。全角色节点照带。
2019
- */
2020
- readonly expressionPrefix: string;
2021
- /** TableLayer 专属:是否模板态(+行按钮置灰与 title 的判定面,spec §2.5) */
2022
- readonly templated?: boolean;
2023
- readonly children: readonly LayerOutlineNode[];
2024
- }
2025
- /**
2026
- * 面板大纲:根层按视觉层级排列(数组逆序——面板顶部 = 视觉最上层 = 数组尾),
2027
- * 表格内行/格/内容保持数组序(行 0 在视觉顶部、格 0 在左)。
2028
- * lockedPaths 为 ui 分支入参(canvas-web-layer-lock 工单 02):锁定态不写 graph,
2029
- * 投影按 isLockedPath 前缀判定携带到锁定子树全树;缺省 [](无锁投影)。
2030
- */
2031
- declare function buildLayerOutline(doc: Canvas, lockedPaths?: readonly LayerPath[]): readonly LayerOutlineNode[];
2032
- /**
2033
- * 编辑器新建图层的缺省形态:可见尺寸(0×0 无法命中/抓取)、top-left 摆位、
2034
- * 中性配色。与 wire 解码缺省是两回事(那是「手写 JSON 宽进」语义),这里是
2035
- * 编辑器 UX 语义;priority 统一由 addRootLayer 按「置顶 min−1」赋值。
2036
- */
2037
- declare function createDefaultLayer(type: LayerType): Layer;
2038
- /**
2039
- * 模板表工厂(spec §2.1):V1 表缺省形态(400×120)+ 行模板装配——auto 行(声明
2040
- * 高按解码归一为 0、宽 := 表宽关 autoWidth)+ 满宽 60 高缺省格带缺省文本内容
2041
- * (内容宽度同步、零高度耦合,ADR 0006)。rowsPath 由调用方必填(解码
2042
- * rows_path_missing 硬约束,创建表单校验前置);缺省格 60 高保证空态预览行可见
2043
- * 可点(合成高 = 最高格,03 票 E1 机制)。
2044
- */
2045
- declare function createTemplateTable(options: {
2046
- rowsPath: string;
2047
- }): TableLayer;
2048
- /**
2049
- * 「insert-before 原始序号 to」移动的公共守卫与落点折算:from/to 须为安全整数、
2050
- * from ∈ [0, n)、to ∈ [0, n];to ∈ {from, from+1}(原位/相邻落点)为无操作。
2051
- * 返回摘除自身后的插入下标;null = 无操作(n < 2 时任何入参都落入无操作集)。
2052
- * 工单 12 的同行格重排复用同一守卫(与行重排同款语义)。
2053
- */
2054
- declare function moveGuard(n: number, from: number, to: number): number | null;
2055
- /**
2056
- * 根层重排(draft 原位变换):面板坐标(0 = 视觉最上)折算数组坐标做 splice,
2057
- * 再对移动层做 priority 中点插值。from 为被拖面板序号,to 为「insert-before
2058
- * 原始面板序号」落点(∈ [0, N];to = N 即面板底);to ∈ {from, from+1} 或越界
2059
- * 为无操作。数组序全程保持 priority 降序(渲染/解码同源的不变量)。
2060
- * 返回移动的 (from, to) 数组下标(供选择路径重映射);null = 无变化。
2061
- */
2062
- declare function moveRootLayerInDraft(draft: Draft<Canvas>, fromPanel: number, toPanel: number): {
2063
- from: number;
2064
- to: number;
2065
- } | null;
2066
- /**
2067
- * 表格行重排(draft 原位变换):直接改 rows 数组序——容器内是嵌套数组序语义,
2068
- * 行的 priority 不参与排序、不插值(与根层重排语义分立)。from/to 为行序号
2069
- * (行 0 在视觉顶部),to 为「insert-before 原始序号」落点 ∈ [0, rows.length]。
2070
- * 返回 (from, to)(to 为插入后最终下标,供路径重映射);null = 无变化/入参不合法。
2071
- */
2072
- declare function moveTableRowInDraft(draft: Draft<Canvas>, tablePath: LayerPath, fromRow: number, toRow: number): {
2073
- from: number;
2074
- to: number;
2075
- } | null;
2076
- /**
2077
- * 新增根层(draft 原位变换):工厂缺省形态 + priority = min − 1(空画布取 0),
2078
- * push 到数组尾(视觉最上层)。返回新层的数组下标。
2079
- */
2080
- declare function addRootLayerInDraft(draft: Draft<Canvas>, type: LayerType): number;
2081
- /**
2082
- * 根层插入(draft 原位变换,工单 14 剪贴板粘贴共用):priority = min − 1(空画布
2083
- * 取 0)+ push 到数组尾(视觉最上层)。数组序保持 priority 降序的解码不变量
2084
- * (min−1 严格小于现最小值)。调用方负责传入的图层形态(如粘贴子树的深拷贝 +
2085
- * 位置偏移)。返回新层的数组下标。
2086
- */
2087
- declare function insertRootLayerInDraft(draft: Draft<Canvas>, layer: Draft<Layer>): number;
2088
- /**
2089
- * 根层紧邻插入(draft 原位变换,alt-drag-paste 工单 01 原语,⌘V 粘贴工单 02 共用):
2090
- * 新层 splice 到源层后一格 = 源层视觉上方一格,priority 取源与其视觉上一层(数组
2091
- * 序 +1 位)之间的中点插值——数组序全程保持 priority 降序的解码不变量,整数插值
2092
- * 同 moveRootLayerInDraft 门规(midpointPriority:无整数间隙时全表归一化兜底);
2093
- * 源为视觉最顶/数组尾时取 source.priority − 1(置顶 min−1 同门)。
2094
- * source 按根下标或路径寻址:路径取根祖先段(path[1],格内容等子树源紧邻其根层)。
2095
- * 返回新层的数组下标;源下标越界/路径无数字根段返回 null(退化语义归调用方——
2096
- * ⌘V 的「源不可解析退化置顶」在消费面回落 insertRootLayerInDraft)。
2097
- */
2098
- declare function insertRootLayerAdjacentInDraft(draft: Draft<Canvas>, layer: Draft<Layer>, source: number | LayerPath): number | null;
2099
- /** 删除定位:list = 容器列表 splice(roots/rows/cells),content = 格内容置 null */
2100
- type DeletedLayerRef = {
2101
- kind: 'list';
2102
- containerPath: LayerPath;
2103
- key: 'layers' | 'rows' | 'cells';
2104
- index: number;
2105
- } | {
2106
- kind: 'content';
2107
- path: LayerPath;
2108
- };
2109
- /**
2110
- * 删除图层(draft 原位变换):根层连子树整删、行/格走列表 splice、格内容置 null
2111
- * (镜像 impl 研究 §2.8「条目操作」)。路径越界/形态不符/内容已空返回 null(无操作)。
2112
- */
2113
- declare function deleteLayerInDraft(draft: Draft<Canvas>, path: LayerPath): DeletedLayerRef | null;
2114
-
2115
2247
  /**
2116
2248
  * 剪贴板内核语义(工单 14):复制/粘贴/创建副本的纯函数面。
2117
2249
  *
@@ -2682,4 +2814,4 @@ declare function memoizeTextPolicies(policies?: TextLayoutPolicies, options?: Me
2682
2814
  */
2683
2815
  declare const PACKAGE_NAME: "@hankchen/canvas-editor";
2684
2816
 
2685
- export { ALIGN_CORNER_MARGIN_PX, ALT_DRAG_DEAD_ZONE_SCREEN_PX, ARM_CREATE_LAYER_TYPES, type AlignBoxGeometry, type AlignToCanvasMode, type AlignToCanvasOptions, type ArmCreateShortcutAction, CREATE_DEAD_ZONE_SCREEN_PX, type CreateGesture, type CreateRectResult, DEFAULT_EDITOR_SHORTCUTS, DEFAULT_ZOOM_BOUNDS, type DeletedLayerRef, type DocRecipe, type DragGesture, type EditorChange, EditorSession, type EditorSessionOptions, type EditorShortcutAction, type EditorShortcutBinding, type EditorShortcutGroup, type EditorShortcutInput, EditorStore, type EditorUi, type ExpressionCandidate, type ExpressionCandidateQuery, type ExpressionCandidateResult, type ExpressionContextKind, type ExpressionPathHead, type ExpressionPathParse, type ExpressionScan, type ExpressionScanFragment, type ExpressionScanLiteral, type ExpressionScanOpen, type ExpressionScanPart, type ExpressionSchemaChildEntry, type ExpressionSchemaChildView, type ExpressionSchemaDiagnostic, type ExpressionSchemaDiagnosticCode, type ExpressionSchemaNode, type ExpressionSchemaParse, type ExpressionSchemaRejectReason, type ExpressionSyntaxError, type FindSession, type FindTextHit, FontCatalog, type FontCatalogEntry, type FrameScheduler, type Guide, type GuideOrientation, type HistoryStep, type HitTestOptions, type InvalidateTarget, type LayerOutlineNode, type LayerOutlineRole, type LayerPath, MAX_HISTORY_STEPS, type MemoTextPoliciesOptions, type MovedSubtreeRef, type OverlayPaintArgs, type OverlayPainter, PACKAGE_NAME, PAN_TO_BOX_MARGIN_PX, PASTE_OFFSET_PX, PHP_TRIM_CHARS, type Point, RESIZE_HANDLES, RESIZE_HANDLE_HIT_PX, RESIZE_MIN_SIZE_PX, type Rect, type ResizeAxes, type ResizeBoxGeometry, type ResizeBoxResult, type ResizeHandle, type ResourceStatus, type ResourceStatusMap, type RowsPathCandidate, type RowsPathCandidateResult, SNAP_THRESHOLD_SCREEN_PX, STYLE_FIELD_KEYS_BY_TYPE, type ShortcutCombo, type Size, type SnapAxis, type SnapAxisSource, type SnapBoxGeometry, type SnapPoints, type SnapResolution, type StyleSnapshot, type TextEditLayout, type TextEditingSession, type TransactOptions, type UploadFile, type UploadHandler, UploadHandlerMissingError, type UploadImagePlacement, type Viewport, WHEEL_ZOOM_STEP, type WheelInput, type WheelIntent, type ZoomBounds, addRootLayerInDraft, addTableCellInDraft, addTableRowInDraft, addTemplateCellInDraft, alignToCanvasTarget, applyStyleFieldsInDraft, buildLayerOutline, canCopyLayerAt, canonicalizeTableSyncInDraft, captureStyleSnapshot, clampZoom, classifyEditorShortcut, classifyWheel, cloneLayerSubtree, convertTableToRowsInDraft, convertTableToTemplateInDraft, createDefaultLayer, createRubberBandRect, createTemplateTable, deleteLayerInDraft, enumerateExpressionCandidates, enumerateRowsPathCandidates, expressionFragmentAtCursor, fitRect, fitViewport, growRowToCellInDraft, handleResizesHeight, handleResizesWidth, hitTest, insertRootLayerAdjacentInDraft, insertRootLayerInDraft, isImageContentUndrawn, isLayerPath, isLockedPath, isRootLayerPath, isRootPasteableType, isTemplateSubtreePath, layerBoxByPath, memoizeTextPolicies, moveGuard, moveRootLayerInDraft, moveTableCellInDraft, moveTableCellToRowInDraft, moveTableRowInDraft, moveTableRowToTableInDraft, nextZoomByWheel, normalizeExpressionSchemaSource, panBy, panToBox, parseExpressionPath, parseExpressionSchema, pastePosition, pathStartsWith, pathsEqual, prepareRootPaste, readSpecField, remapPathAfterSplice, replaceHitsInDraft, resizableAxesAt, resizeBox, resizeHandleAt, resizeHandlePoint, resizeHandlesAt, resizeSnapPoints, resolveLayer, resolveRowSchema, resolveRowsPathStartSchema, resolveSnap, resolveSnapPoints, rootLayerOf, scanExpressionFragments, scanTextMatches, sceneToScreen, schemaChildEntries, schemaNodeAtPath, screenToScene, selectionParentPath, setCellAutoHeightInDraft, snapAxesFromBoxes, snapThresholdScene, snapViewportToPhysicalPixels, syncContentIntoCellInDraft, syncRowWidthInDraft, uploadDisplayName, visibleRootBoxes, writeSpecField, zoomAtPoint };
2817
+ export { ALIGN_CORNER_MARGIN_PX, ALT_DRAG_DEAD_ZONE_SCREEN_PX, ARM_CREATE_LAYER_TYPES, type AlignBoxGeometry, type AlignToCanvasMode, type AlignToCanvasOptions, type ArmCreateShortcutAction, CREATE_DEAD_ZONE_SCREEN_PX, type CanvasEditorState, type CreateGesture, type CreateRectResult, DEFAULT_EDITOR_SHORTCUTS, DEFAULT_ZOOM_BOUNDS, type DeletedLayerRef, type DocRecipe, type DragGesture, EDITOR_STATE_SCHEMA_VERSION, type EditorChange, type EditorPrefsState, EditorSession, type EditorSessionOptions, type EditorShortcutAction, type EditorShortcutBinding, type EditorShortcutGroup, type EditorShortcutInput, EditorStore, type EditorUi, type ExpressionCandidate, type ExpressionCandidateQuery, type ExpressionCandidateResult, type ExpressionContextKind, type ExpressionPathHead, type ExpressionPathParse, type ExpressionScan, type ExpressionScanFragment, type ExpressionScanLiteral, type ExpressionScanOpen, type ExpressionScanPart, type ExpressionSchemaChildEntry, type ExpressionSchemaChildView, type ExpressionSchemaDiagnostic, type ExpressionSchemaDiagnosticCode, type ExpressionSchemaNode, type ExpressionSchemaParse, type ExpressionSchemaRejectReason, type ExpressionSyntaxError, type FindSession, type FindTextHit, FontCatalog, type FontCatalogEntry, type FrameScheduler, type Guide, type GuideOrientation, type HistoryStep, type HitTestOptions, type InvalidateTarget, type LayerOutlineNode, type LayerOutlineRole, type LayerPath, MAX_HISTORY_STEPS, type MemoTextPoliciesOptions, type MovedSubtreeRef, type NextTextStyle, type OverlayPaintArgs, type OverlayPainter, PACKAGE_NAME, PAN_TO_BOX_MARGIN_PX, PASTE_OFFSET_PX, PHP_TRIM_CHARS, type Point, RESIZE_HANDLES, RESIZE_HANDLE_HIT_PX, RESIZE_MIN_SIZE_PX, type Rect, type ResizeAxes, type ResizeBoxGeometry, type ResizeBoxResult, type ResizeHandle, type ResourceStatus, type ResourceStatusMap, type RowsPathCandidate, type RowsPathCandidateResult, SNAP_THRESHOLD_SCREEN_PX, STYLE_FIELD_KEYS_BY_TYPE, type ShortcutCombo, type Size, type SnapAxis, type SnapAxisSource, type SnapBoxGeometry, type SnapPoints, type SnapResolution, type StyleSnapshot, TEXT_PRESETS, type TextEditLayout, type TextEditingSession, type TextPresetId, type TransactOptions, type UploadFile, type UploadHandler, UploadHandlerMissingError, type UploadImagePlacement, type Viewport, WHEEL_ZOOM_STEP, type WheelInput, type WheelIntent, type ZoomBounds, addRootLayerInDraft, addTableCellInDraft, addTableRowInDraft, addTemplateCellInDraft, alignToCanvasTarget, applyStyleFieldsInDraft, buildLayerOutline, canCopyLayerAt, canonicalizeTableSyncInDraft, captureStyleSnapshot, clampZoom, classifyEditorShortcut, classifyWheel, cloneLayerSubtree, convertTableToRowsInDraft, convertTableToTemplateInDraft, createDefaultLayer, createRubberBandRect, createTemplateTable, defaultNextTextStyle, deleteLayerInDraft, enumerateExpressionCandidates, enumerateRowsPathCandidates, expressionFragmentAtCursor, fitRect, fitViewport, growRowToCellInDraft, handleResizesHeight, handleResizesWidth, hitTest, insertRootLayerAdjacentInDraft, insertRootLayerInDraft, isImageContentUndrawn, isLayerPath, isLockedPath, isRootLayerPath, isRootPasteableType, isTemplateSubtreePath, layerBoxByPath, memoizeTextPolicies, moveGuard, moveRootLayerInDraft, moveTableCellInDraft, moveTableCellToRowInDraft, moveTableRowInDraft, moveTableRowToTableInDraft, nextZoomByWheel, normalizeExpressionSchemaSource, panBy, panToBox, parseExpressionPath, parseExpressionSchema, pastePosition, pathStartsWith, pathsEqual, pickNextTextStylePatch, prepareRootPaste, readSpecField, remapPathAfterSplice, replaceHitsInDraft, resizableAxesAt, resizeBox, resizeHandleAt, resizeHandlePoint, resizeHandlesAt, resizeSnapPoints, resolveLayer, resolveRowSchema, resolveRowsPathStartSchema, resolveSnap, resolveSnapPoints, rootLayerOf, scanExpressionFragments, scanTextMatches, sceneToScreen, schemaChildEntries, schemaNodeAtPath, screenToScene, selectionParentPath, setCellAutoHeightInDraft, snapAxesFromBoxes, snapThresholdScene, snapViewportToPhysicalPixels, syncContentIntoCellInDraft, syncRowWidthInDraft, uploadDisplayName, visibleRootBoxes, writeSpecField, zoomAtPoint };