@hankchen/canvas-editor 0.2.0 → 0.4.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,20 +408,206 @@ 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
  *
414
594
  * D6 钉定:注入边界一次性转译为内部形状树(不在查询期惰性解析原始 schema,
415
595
  * 行业惯例见 schema-completion-research.md)。方言子集 = JSON Schema draft-07 的
416
596
  * 结构关键词(`properties` / `items` / `type`)+ 注解关键词(`description` /
417
- * `title` / `additionalProperties: true`)+ 引用关键词(`$ref` 内部 JSON Pointer、
418
- * `definitions`/`$defs` 命名池);其余关键词(`required`/`format`/`enum`/`const`/
419
- * `allOf` 族/`patternProperties`/`$schema`/`$id` 及一切未识别键)宽松忽略,节点按
420
- * 已识别字段归一(可能变叶子)。
597
+ * `title` / `additionalProperties: true` / 白名单 `format`,见下)+ 引用关键词
598
+ * (`$ref` 内部 JSON Pointer、`definitions`/`$defs` 命名池);其余关键词
599
+ * (`required`/`enum`/`const`/`allOf` 族/`patternProperties`/`$schema`/`$id` 及
600
+ * 一切未识别键)宽松忽略,节点按已识别字段归一(可能变叶子)。
421
601
  *
422
602
  * 声明契约(D1 钉定):schema 声明即 `compile(canvas, dataset)` 收到的 data
423
603
  * 载荷形状——根上下文候选 = 载荷顶层键;根必须是带 properties 的对象声明。
424
604
  *
605
+ * format 注解(expression-type-methods 工单 11/12,content-completion spec D13):
606
+ * draft-07 `format` 从宽松忽略清单开口——仅精确匹配小写 `date` / `date-time`
607
+ * (draft-07 格式词表子集)且节点 type 归一后为 string 才挂注解;其余值(大小写
608
+ * 变体/其他词表值/自定义值)/非 string 节点/形态不符维持宽松忽略,**无诊断**。
609
+ * 注解只影响建议面(date() 建议分桶),求值器/graph/wire 三端零感知。
610
+ *
425
611
  * 降级分级(D7):
426
612
  * - **整份拒绝**仅保留根级结构性问题(在原始文档上判定,拒绝面与 walker 时代
427
613
  * 全等):根非对象 / 根缺 properties 层级(含根级 `$ref`——根不解引用)/
@@ -466,6 +652,11 @@ interface ExpressionSchemaNode {
466
652
  description?: string;
467
653
  /** 开放映射标记(D10):`additionalProperties: true`;动态字段实际键由宿主合入 properties */
468
654
  open?: boolean;
655
+ /**
656
+ * 日期标记注解(工单 11,D13):`format: "date" | "date-time"` 白名单两值、
657
+ * 仅 type 归一为 string 的节点挂;只影响 date() 建议分桶,永不触发诊断
658
+ */
659
+ format?: 'date' | 'date-time';
469
660
  properties?: ReadonlyMap<string, ExpressionSchemaNode>;
470
661
  items?: ExpressionSchemaNode;
471
662
  }
@@ -688,6 +879,14 @@ interface EditorUi {
688
879
  * (与 viewport 同款的面板偏好——openDocument 换文档不重置,永不进历史)。
689
880
  */
690
881
  anchorExpanded: boolean;
882
+ /**
883
+ * 新层样式槽(text-defaults 工单 01,CONTEXT「新层样式」词条):记忆「下一
884
+ * 个新建文本层用什么文本样式族」的编辑器级偏好——属性面板对 TextLayer 文本
885
+ * 族字段的权威写(updateSpec 捕获)更新槽,建层(endCreate/addRootLayer)
886
+ * 以槽值覆盖工厂缺省。与锚点折叠同款的面板偏好——openDocument 换文档不重
887
+ * 置,永不进历史;随工程数据 prefs 桶跨会话持久(宿主通道,内核零 localStorage)。
888
+ */
889
+ nextTextStyle: NextTextStyle;
691
890
  /**
692
891
  * 数据源 schema 声明(content-completion 工单 03/08,D2 宿主随会话注入):
693
892
  * 编译产物形状树或降级 null(根级结构性拒绝,注入期经
@@ -785,7 +984,7 @@ declare class EditorStore {
785
984
  get canRedo(): boolean;
786
985
  /** 打开/替换文档:ui 选择/编辑/重命名会话与双向历史一并重置(新文档不继承旧路径/旧事务);
787
986
  * 参考线/锁定集合/查找会话/建层武装与画拉会话随当次会话清空(对位轴/文档内容防护/
788
- * 查询词/待命层型不跨文档),标尺显隐作为偏好保留 */
987
+ * 查询词/待命层型不跨文档),标尺显隐/锚点折叠/新层样式作为偏好保留 */
789
988
  openDocument(canvas: Canvas): void;
790
989
  /**
791
990
  * 文档事务唯一入口:produceWithPatches 求新树,无变化即空转(不进历史不通知);
@@ -825,6 +1024,11 @@ declare class EditorStore {
825
1024
  setRenaming(path: LayerPath | null): void;
826
1025
  /** 锚点折叠区开合:布尔值等短路(重复点击同一态不重绘) */
827
1026
  setAnchorExpanded(open: boolean): void;
1027
+ /**
1028
+ * 新层样式槽逐字段合并(text-defaults 工单 01:捕获/预设/prefs 恢复的统一
1029
+ * 写入口):patch 并入现值,五字段值等短路(重复写同值零通知),不进历史。
1030
+ */
1031
+ setNextTextStyle(patch: Partial<NextTextStyle>): void;
828
1032
  /**
829
1033
  * 数据源 schema 声明替换(归一产物或降级 null,校验收口在注入缝不在这里):
830
1034
  * 同引用短路(重复注入同一归一产物不惊动订阅方);仅 ui 通知,不参与重绘
@@ -955,10 +1159,16 @@ interface CanvasEditorState {
955
1159
  /** 锁定根层路径集合(随工程数据持久化,仍零 wire 面) */
956
1160
  lockedPaths: readonly LayerPath[];
957
1161
  }
958
- /** 编辑器级偏好:跨文档、跨会话内核自持(工程数据快照的 prefs 桶,分类学终裁两项) */
1162
+ /** 编辑器级偏好:跨文档、跨会话内核自持(工程数据快照的 prefs 桶,分类学终裁三项) */
959
1163
  interface EditorPrefsState {
960
1164
  rulersVisible: boolean;
961
1165
  anchorExpanded: boolean;
1166
+ /**
1167
+ * 新层样式槽(text-defaults 工单 01,CONTEXT「新层样式」词条):随 prefs 桶
1168
+ * 跨会话持久(per-模板记忆)。schemaVersion 不升——加法演进,旧快照缺字段
1169
+ * 由 applyEditorPrefs 宽容读兜底为现值(会话内即工厂缺省)。
1170
+ */
1171
+ nextTextStyle: NextTextStyle;
962
1172
  }
963
1173
 
964
1174
  /**
@@ -1370,8 +1580,13 @@ declare class EditorSession {
1370
1580
  * 武装建层(面板新增项/层型快捷键的统一入口,CONTEXT「武装」词条):置 ui
1371
1581
  * 分支待命层型,下一次画布按下即开画拉;建层提交或 Esc 即解除——一次性
1372
1582
  * 待命态,无粘性工具(spec 决策 2)。重复武装同型值等短路零通知。
1583
+ *
1584
+ * preset(text-defaults 工单 01,CONTEXT「文本预设」词条):文本预设 = 写
1585
+ * 新层样式槽的快捷方式——命中档位先把档位值并入槽(v1 只 fontSize),再
1586
+ * 武装;仅 TextLayer 生效;未知 id = 跳过写槽、武装照常(评审口径统一:
1587
+ * 「空转」只指写槽,武装层型本身仍合法)。
1373
1588
  */
1374
- armLayerCreate(type: LayerType): void;
1589
+ armLayerCreate(type: LayerType, preset?: TextPresetId): void;
1375
1590
  /** 解除建层武装(取消入口):仅清待命态,零副作用。 */
1376
1591
  cancelArmLayerCreate(): void;
1377
1592
  /**
@@ -1499,6 +1714,8 @@ declare class EditorSession {
1499
1714
  /**
1500
1715
  * 应用偏好(会话建立时一次性,跨会话恢复 prefs 的写入口):整体替换
1501
1716
  * rulersVisible/anchorExpanded,不进历史;值等写入经 store 短路零通知。
1717
+ * 新层样式(text-defaults 工单 01)走宽容读逐字段合并(pickNextTextStylePatch
1718
+ * 共享谓词——与捕获同门,缺字/类型不符保留现值)。
1502
1719
  */
1503
1720
  applyEditorPrefs(prefs: EditorPrefsState): void;
1504
1721
  /**
@@ -1600,6 +1817,15 @@ declare class EditorSession {
1600
1817
  * 内容宽/高重同步、行高取最高格)——往返恒等在任何字段编辑后不破。
1601
1818
  */
1602
1819
  updateSpec(path: LayerPath, key: readonly string[], value: unknown, options?: TransactOptions): void;
1820
+ /**
1821
+ * 新层样式捕获(text-defaults 工单 01,CONTEXT「新层样式」词条):属性面板
1822
+ * 对 TextLayer 文本族五字段的权威写顺带更新偏好槽——「用户改过一次,下一个
1823
+ * 新层沿用」。捕获口唯一(updateSpec 漏斗):内容写(updateData)、样式粘贴
1824
+ * (搬运不是偏好)、撤销重做都不经过此口。字段合法性走 editing 域共享谓词
1825
+ * pickNextTextStylePatch(与 prefs 宽容读同门,评审合流不再双写):目标层非
1826
+ * TextLayer、键不命中或值类型不符即空转,符合字段经值等短路入槽。
1827
+ */
1828
+ private captureNextTextStyle;
1603
1829
  /**
1604
1830
  * 更新图层数据字段(wire data.value 的领域展开,按 type 分派):
1605
1831
  * TextLayer → text、ImageLayer → src、QrCodeLayer → value;
@@ -2029,151 +2255,6 @@ interface WheelInput {
2029
2255
  }
2030
2256
  declare function classifyWheel(input: WheelInput): WheelIntent;
2031
2257
 
2032
- /**
2033
- * 图层面板的内核语义(工单 10)。
2034
- *
2035
- * 顺序映射(spec「Vue 绑定与面板」拍板,防反直觉):
2036
- * - 渲染顺序 = graph.layers 数组序 = priority 降序(数组头先画垫底,越大越垫底);
2037
- * - 面板从上到下 = 数组逆序:面板顶 = 视觉最上层 = 数组尾 = 最小 priority。
2038
- *
2039
- * 两套重排语义分立:
2040
- * - 根层重排走 priority 中点插值(保持「数组按 priority 降序」的契约语义,
2041
- * 保存再打开顺序不变);插到上下邻之间 → priority = ⌊(上邻 + 下邻) / 2⌋,
2042
- * 置顶 = min − 1、置底 = max + 1;priority 恒为整数(wire 解码 intval 同门,
2043
- * 小数会在保存→打开时漂移),无整数间隙/同值冲突时对全表做一次按视觉序的
2044
- * 带间隙阶梯归一化重赋(patch 大,仅兜底)。
2045
- * - 表格行重排直接改 rows 数组序(行/格/内容是嵌套数组序语义,绘制按序遍历,
2046
- * priority 字段在容器内不参与排序)。
2047
- *
2048
- * 全模块纯函数、无 DOM;draft 侧变换经 immer 事务落库,查询侧只读。
2049
- */
2050
-
2051
- /** 图层在容器树里的角色(决定面板缩进与可拖动性);templateRow = 行模板替身节点 */
2052
- type LayerOutlineRole = 'root' | 'row' | 'cell' | 'content' | 'templateRow';
2053
- /** 面板大纲节点:领域子树的纯投影(无文档写语义) */
2054
- interface LayerOutlineNode {
2055
- readonly type: LayerType;
2056
- readonly path: LayerPath;
2057
- readonly role: LayerOutlineRole;
2058
- /**
2059
- * 用户命名(layer-panel-ux 工单 09):原样携带文档 name(根层重命名后由此
2060
- * 上屏),空串 = 未命名,显示层回落派生标签。行/格/内容同字段照带(不消费)。
2061
- */
2062
- readonly name: string;
2063
- /**
2064
- * 可见性(layer-panel-ux 工单 10):原样携带文档 visible,根层面板行的眼睛
2065
- * 钮状态与隐藏行降不透明度据此投影。行/格/内容同字段照带(不消费——显隐
2066
- * 语义只在 LayerBase 面)。
2067
- */
2068
- readonly visible: boolean;
2069
- /**
2070
- * 锁定投影(canvas-web-layer-lock 工单 02):isLockedPath 前缀判定——锁定的
2071
- * 根层及其整棵子树(行/格/内容)都携 true。锁定态住 ui 分支(会话级、零
2072
- * wire 键),经 buildLayerOutline 的 ui 分支入参喂入;面板锁定钮状态、锁定
2073
- * 行样式与删除钮/菜单删除项置灰据此投影(内核空转为权威,UI 呈现一致)。
2074
- */
2075
- readonly locked: boolean;
2076
- /**
2077
- * 表达式前置(layer-panel-expression-prefix 工单 01):带标记内容层(三内容层
2078
- * 且 expression !== null)的全部闭合片段按 expr 重构 `{{…}}` 外壳、单空格连接,
2079
- * 面板零计算直读;空串 = 无前置(未标记 / 非内容层),对齐 name 字段先例;
2080
- * 全部片段无效得常量 `{{…}}`。全角色节点照带。
2081
- */
2082
- readonly expressionPrefix: string;
2083
- /** TableLayer 专属:是否模板态(+行按钮置灰与 title 的判定面,spec §2.5) */
2084
- readonly templated?: boolean;
2085
- readonly children: readonly LayerOutlineNode[];
2086
- }
2087
- /**
2088
- * 面板大纲:根层按视觉层级排列(数组逆序——面板顶部 = 视觉最上层 = 数组尾),
2089
- * 表格内行/格/内容保持数组序(行 0 在视觉顶部、格 0 在左)。
2090
- * lockedPaths 为 ui 分支入参(canvas-web-layer-lock 工单 02):锁定态不写 graph,
2091
- * 投影按 isLockedPath 前缀判定携带到锁定子树全树;缺省 [](无锁投影)。
2092
- */
2093
- declare function buildLayerOutline(doc: Canvas, lockedPaths?: readonly LayerPath[]): readonly LayerOutlineNode[];
2094
- /**
2095
- * 编辑器新建图层的缺省形态:可见尺寸(0×0 无法命中/抓取)、top-left 摆位、
2096
- * 中性配色。与 wire 解码缺省是两回事(那是「手写 JSON 宽进」语义),这里是
2097
- * 编辑器 UX 语义;priority 统一由 addRootLayer 按「置顶 min−1」赋值。
2098
- */
2099
- declare function createDefaultLayer(type: LayerType): Layer;
2100
- /**
2101
- * 模板表工厂(spec §2.1):V1 表缺省形态(400×120)+ 行模板装配——auto 行(声明
2102
- * 高按解码归一为 0、宽 := 表宽关 autoWidth)+ 满宽 60 高缺省格带缺省文本内容
2103
- * (内容宽度同步、零高度耦合,ADR 0006)。rowsPath 由调用方必填(解码
2104
- * rows_path_missing 硬约束,创建表单校验前置);缺省格 60 高保证空态预览行可见
2105
- * 可点(合成高 = 最高格,03 票 E1 机制)。
2106
- */
2107
- declare function createTemplateTable(options: {
2108
- rowsPath: string;
2109
- }): TableLayer;
2110
- /**
2111
- * 「insert-before 原始序号 to」移动的公共守卫与落点折算:from/to 须为安全整数、
2112
- * from ∈ [0, n)、to ∈ [0, n];to ∈ {from, from+1}(原位/相邻落点)为无操作。
2113
- * 返回摘除自身后的插入下标;null = 无操作(n < 2 时任何入参都落入无操作集)。
2114
- * 工单 12 的同行格重排复用同一守卫(与行重排同款语义)。
2115
- */
2116
- declare function moveGuard(n: number, from: number, to: number): number | null;
2117
- /**
2118
- * 根层重排(draft 原位变换):面板坐标(0 = 视觉最上)折算数组坐标做 splice,
2119
- * 再对移动层做 priority 中点插值。from 为被拖面板序号,to 为「insert-before
2120
- * 原始面板序号」落点(∈ [0, N];to = N 即面板底);to ∈ {from, from+1} 或越界
2121
- * 为无操作。数组序全程保持 priority 降序(渲染/解码同源的不变量)。
2122
- * 返回移动的 (from, to) 数组下标(供选择路径重映射);null = 无变化。
2123
- */
2124
- declare function moveRootLayerInDraft(draft: Draft<Canvas>, fromPanel: number, toPanel: number): {
2125
- from: number;
2126
- to: number;
2127
- } | null;
2128
- /**
2129
- * 表格行重排(draft 原位变换):直接改 rows 数组序——容器内是嵌套数组序语义,
2130
- * 行的 priority 不参与排序、不插值(与根层重排语义分立)。from/to 为行序号
2131
- * (行 0 在视觉顶部),to 为「insert-before 原始序号」落点 ∈ [0, rows.length]。
2132
- * 返回 (from, to)(to 为插入后最终下标,供路径重映射);null = 无变化/入参不合法。
2133
- */
2134
- declare function moveTableRowInDraft(draft: Draft<Canvas>, tablePath: LayerPath, fromRow: number, toRow: number): {
2135
- from: number;
2136
- to: number;
2137
- } | null;
2138
- /**
2139
- * 新增根层(draft 原位变换):工厂缺省形态 + priority = min − 1(空画布取 0),
2140
- * push 到数组尾(视觉最上层)。返回新层的数组下标。
2141
- */
2142
- declare function addRootLayerInDraft(draft: Draft<Canvas>, type: LayerType): number;
2143
- /**
2144
- * 根层插入(draft 原位变换,工单 14 剪贴板粘贴共用):priority = min − 1(空画布
2145
- * 取 0)+ push 到数组尾(视觉最上层)。数组序保持 priority 降序的解码不变量
2146
- * (min−1 严格小于现最小值)。调用方负责传入的图层形态(如粘贴子树的深拷贝 +
2147
- * 位置偏移)。返回新层的数组下标。
2148
- */
2149
- declare function insertRootLayerInDraft(draft: Draft<Canvas>, layer: Draft<Layer>): number;
2150
- /**
2151
- * 根层紧邻插入(draft 原位变换,alt-drag-paste 工单 01 原语,⌘V 粘贴工单 02 共用):
2152
- * 新层 splice 到源层后一格 = 源层视觉上方一格,priority 取源与其视觉上一层(数组
2153
- * 序 +1 位)之间的中点插值——数组序全程保持 priority 降序的解码不变量,整数插值
2154
- * 同 moveRootLayerInDraft 门规(midpointPriority:无整数间隙时全表归一化兜底);
2155
- * 源为视觉最顶/数组尾时取 source.priority − 1(置顶 min−1 同门)。
2156
- * source 按根下标或路径寻址:路径取根祖先段(path[1],格内容等子树源紧邻其根层)。
2157
- * 返回新层的数组下标;源下标越界/路径无数字根段返回 null(退化语义归调用方——
2158
- * ⌘V 的「源不可解析退化置顶」在消费面回落 insertRootLayerInDraft)。
2159
- */
2160
- declare function insertRootLayerAdjacentInDraft(draft: Draft<Canvas>, layer: Draft<Layer>, source: number | LayerPath): number | null;
2161
- /** 删除定位:list = 容器列表 splice(roots/rows/cells),content = 格内容置 null */
2162
- type DeletedLayerRef = {
2163
- kind: 'list';
2164
- containerPath: LayerPath;
2165
- key: 'layers' | 'rows' | 'cells';
2166
- index: number;
2167
- } | {
2168
- kind: 'content';
2169
- path: LayerPath;
2170
- };
2171
- /**
2172
- * 删除图层(draft 原位变换):根层连子树整删、行/格走列表 splice、格内容置 null
2173
- * (镜像 impl 研究 §2.8「条目操作」)。路径越界/形态不符/内容已空返回 null(无操作)。
2174
- */
2175
- declare function deleteLayerInDraft(draft: Draft<Canvas>, path: LayerPath): DeletedLayerRef | null;
2176
-
2177
2258
  /**
2178
2259
  * 剪贴板内核语义(工单 14):复制/粘贴/创建副本的纯函数面。
2179
2260
  *
@@ -2474,26 +2555,6 @@ type ExpressionPathParse = {
2474
2555
  /** 解析点路径:head 分类 + 余段;语法不合法(空片段/空段)返回错误信号 */
2475
2556
  declare function parseExpressionPath(expr: string): ExpressionPathParse;
2476
2557
 
2477
- /**
2478
- * 片段扫描纯函数(content-completion 工单 01,spec §4 纯函数 ①)。
2479
- *
2480
- * 语义逐条对齐 php-canvas-next `InterpolationEvaluator::evaluate` 扫描循环(只读
2481
- * 对齐,不改求值器):首个未闭合 `{{` 起剩余全字面、片段内容 trim、`{{}}` 不嵌套
2482
- * (首个 `}}` 收口,内容含 `{{`)、片段外字面直通;空片段/路径空段 =
2483
- * `expression_syntax_error` 信号(与求值器同码,经 parseExpressionPath 判定)。
2484
- *
2485
- * 与求值器的一处表示分叉(编辑器侧补全所需):未闭合 `{{` 在求值期按字面直通,
2486
- * 在扫描结果里另立 **open 片段**(kind: 'open')——这正是「输入 `{{` 自动弹出」的
2487
- * 触发态(spec §3),其 expr 是待输入路径;closed 片段仍按求值语义带错误信号。
2488
- *
2489
- * 位置字段是 JS 码元索引(end 独占)——与 PHP 字节索引不同空间,跨端共享 fixture
2490
- * (expression-scan v1)只钉切分内容不钉位置,位置由本端派生并由单测锁死。
2491
- * trim 字符集对齐 PHP `trim()` 默认六字符(" \t\n\r\0\x0B"),**不是** JS 的
2492
- * `String.trim()`(后者含全角空格等 Unicode 空白,会造成双端漂移)。
2493
- *
2494
- * 全模块纯函数、无 DOM(editor-shared-isolation)。
2495
- */
2496
-
2497
2558
  /** 字面直通段(不含任何 `{{`) */
2498
2559
  interface ExpressionScanLiteral {
2499
2560
  kind: 'literal';
@@ -2530,6 +2591,12 @@ interface ExpressionScan {
2530
2591
  /** PHP trim() 默认字符集(JS String.trim 的 Unicode 空白集与之不同,勿用);
2531
2592
  * 编辑器侧补全的接受手术同用此集(导出防按值复刻漂移,工单 04) */
2532
2593
  declare const PHP_TRIM_CHARS = " \t\n\r\0\v";
2594
+ /**
2595
+ * PHP trim() 语义(六字符集):片段 trim 与 vue 侧补全的 expr 前缀截取同用此集
2596
+ * (光标定位参数位,expression-type-methods 工单 12——单一事实源,勿按值复刻;
2597
+ * JS `String.trim()` 含全角空格等 Unicode 空白,会造成与 PHP 的双端漂移)。
2598
+ */
2599
+ declare function phpTrim(value: string): string;
2533
2600
  /** 扫描模板串的片段切分:闭合/未闭合/多片段/错误信号,语义对齐求值器扫描循环 */
2534
2601
  declare function scanExpressionFragments(template: string): ExpressionScan;
2535
2602
  /**
@@ -2540,48 +2607,107 @@ declare function scanExpressionFragments(template: string): ExpressionScan;
2540
2607
  declare function expressionFragmentAtCursor(scan: ExpressionScan, cursor: number): ExpressionScanFragment | ExpressionScanOpen | null;
2541
2608
 
2542
2609
  /**
2543
- * 候选枚举器(content-completion 工单 02,spec §2 候选枚举规则表)。
2610
+ * 最小调用形解析纯函数(expression-type-methods 工单 12,spec §1.1/§1.2 ⑦⑨)。
2544
2611
  *
2545
- * 规则逐条导出自 php-canvas-next 求值/填充语义(InterpolationEvaluator +
2546
- * CanvasHydrator,只读对齐),非新发明:
2547
- * - 根上下文(根层三字段)头部候选 = 载荷顶层键(D1:schema 声明即 data 载荷
2548
- * 形状)+ `$root`;行上下文(格内容层)追加 `row` + `$index`。`$index` 仅行
2549
- * 上下文给——行外求值为空串非报错,但不给写得出来而无效的表达式;`row.` 行外
2550
- * 报 `expression_row_outside_loop`,同样不给。
2551
- * - 裸键在两种上下文都走根 schema:行上下文求值上下文 = `$rowNamespace + $root`
2552
- * 合并(CanvasHydrator::evaluateNode),行命名空间只有 row/$index 且
2553
- * reserved_root_key 保证根级键不遮蔽——裸键即根键。
2554
- * - `.` 下钻走 properties 树;无 properties 节点终止该分支;数组节点收敛为叶子
2555
- * 无具名子候选(D9 修订 D3:具名段下钻数组在求值器是静默空串——缺字段信号,
2556
- * 不给写得出来而渲染为空白的表达式;下钻层 items 链保留供 rowsPath/`row.*`
2557
- * 机制,类型徽标仍显示 array 本身)。开放映射(open)节点的枚举结果携带 open
2558
- * 信号(结果面扩展,不污染候选条目契约),供工单 10 浮层占位提示(D10)。
2612
+ * JS 预览端最小文法面 = **结构面识别、名单面不校验**(spec §1.2 ⑨):
2613
+ * - 分类(⑦):trim 后首个 token(ASCII 特界符/空白前)其后紧跟可选空白与 `(` 即
2614
+ * 调用,否则路径——`foo(bar)` / `日期(bar)` / `foo (bar)` 均按调用分类(白名单
2615
+ * 校验后置),`{{date}}` 无 `(` 恒为路径,数据集根键叫 date 合法。
2616
+ * - 结构错(括号不平衡、空参数位、尾逗号、字符串未闭合)照 `expression_syntax_error`
2617
+ * 同码标红;首参必须为路径(§1.2 ① 文法层钉死)同面标红。
2618
+ * - **未知函数名不在 JS 标红**(PHP 权威端先发新函数、编辑器后跟期间避免「求值
2619
+ * 正常但编辑器假红」的名单漂移);签名面(参数个数/第二参类型/n 范围)同不校验。
2620
+ * - 算法逐字节镜像 php-canvas-next `InterpolationEvaluator::resolveFragment /
2621
+ * parseCallArgs / parseCallArg`(权威端):路径实参吞至 `,`/`)` 为止(段内空白
2622
+ * 属于键名,缺逗号非结构错)、字符串仅单引号 `''` 翻倍转义、数字无符号无指数。
2559
2623
  *
2560
- * 消费契约(工单 04 浮层):
2561
- * - 入参 expr 是片段表达式(trim 后,来自 expressionScan);**单个尾点 = 补全点
2562
- * 标记**,先剥再解析(对齐工单 01 备注:`row.` 按求值语义是空段错误,剥点后
2563
- * `row` 才是可下钻前缀);剥点后为空且原 expr 非空 = 孤点前缀,无合法续写 →
2564
- * expression_syntax_error 信号。
2565
- * - 结果 `partial` 恒为 expr 的后缀(尾点态 = 空后缀):接受 = 在 expr 末尾把
2566
- * partial 替换为候选 segment;候选给**全量合法子项**、不按 partial 预过滤,
2567
- * 前缀过滤/高亮归浮层(Ctrl+Space 全量展示语义亦归浮层)。
2568
- * - 元信息:path(补全后的完整点路径)+ schema description/title(D8 两字段分离
2569
- * 透传,展示回落 description ?? title 归浮层)+ 类型徽标数据(type 归一)。
2570
- * `$root`/`row`/`$index` 结构头是下钻踏脚石(`{{$root}}`/
2571
- * `{{row}}` 单独求值无意义),元信息仅有行 schema 声明时的 row 携带。
2624
+ * 字符集对 PHP 逐字对齐:跳空白用 PHP skipWs 四字符(" \t\n\r");分类与
2625
+ * parseCallArg 的 trim 用 PHP trim() 默认六字符(PHP_TRIM_CHARS,与 expressionScan
2626
+ * 同源语义)。JS `String.trim()`/正则 `\s` 含全角空白等 Unicode 集,会造成漂移勿用。
2572
2627
  *
2573
- * 降级语义:schema null(声明被拒/形态非法,经 normalizeExpressionSchemaSource
2574
- * 收口)→ 全部无候选;schema 合法而行 schema 未解析(rowsPath 无 items 声明)→
2575
- * 结构头 row 仍在、行子树无候选——辅助声明不作权威,全程不抛错。
2628
+ * 全模块纯函数、零 DOM;层内依赖仅 expressionPath(实参路径空段校验同码)。
2629
+ */
2630
+
2631
+ /** 实参形态(spec §1.1 实参 := 路径 | 字符串 | 数字;value = 归一后文本) */
2632
+ interface ExpressionCallArg {
2633
+ type: 'path' | 'string' | 'number';
2634
+ value: string;
2635
+ }
2636
+ type ExpressionCallParse = {
2637
+ ok: true;
2638
+ name: string;
2639
+ args: readonly ExpressionCallArg[];
2640
+ } | {
2641
+ ok: false;
2642
+ error: ExpressionSyntaxError;
2643
+ };
2644
+ /**
2645
+ * ⑦ 片段分类:首 token 后紧跟可选空白与 `(` 即调用。expr 须已 trim(片段扫描
2646
+ * 职责,与 parseExpressionPath 契约一致)。
2647
+ */
2648
+ declare function isCallFragment(expr: string): boolean;
2649
+ /**
2650
+ * 完整调用形结构解析(scan 错误信号与补全路由共用):只判结构面 + 首参路径
2651
+ * (文法层),名单/签名面不校验。expr 须已 trim;非调用形态由调用方分类后进入。
2652
+ */
2653
+ declare function parseExpressionCall(expr: string): ExpressionCallParse;
2654
+ /** 光标槽位(补全路由消费):光标 = expr 末尾(调用方喂片段的光标前缀) */
2655
+ interface ExpressionCallSlotContext {
2656
+ /** 函数名(⑦ 首 token;名单面不校验) */
2657
+ name: string;
2658
+ /** 实参槽位(0 起) */
2659
+ index: number;
2660
+ /** 槽内光标前文本(字符串槽 = 引号内原文;其余 = trim 后) */
2661
+ text: string;
2662
+ /** 字符串字面量槽(date 格式串建议面) */
2663
+ stringSlot: boolean;
2664
+ }
2665
+ /**
2666
+ * 光标所在实参槽定位:容忍截断前缀(调用未写完/字符串未闭合都是常态输入),
2667
+ * 只定位不判错——结构红标归 parseExpressionCall/扫描面。返回 null = 无建议语义的
2668
+ * 落点(非调用形态 / 调用已闭合)。
2669
+ */
2670
+ declare function expressionCallSlotAtEnd(expr: string): ExpressionCallSlotContext | null;
2671
+
2672
+ /**
2673
+ * 内建函数已知名单与格式建议表(expression-type-methods 工单 12,spec §1.2 ⑨/§2/§3.4)。
2674
+ *
2675
+ * spec §7 JS 行:结构面识别、名单面不校验;**已知名单只喂补全建议**——本表是
2676
+ * v1 白名单(date/number/fixed/percent)的编辑器侧建议数据,不参与任何校验/标红
2677
+ * (PHP 权威端先发新函数、编辑器后跟期间避免「求值正常但编辑器假红」的名单漂移;
2678
+ * PHP 增函数时此处增量跟随,缺位代价只是少建议不误红)。
2679
+ *
2680
+ * 具名预设/中文模板快捷项(spec §3.4):预设是求值面纯糖('date'/'datetime' 整体
2681
+ * 等值命中展开);中文格式不设求值预设——`YYYY年MM月DD日` 写即所得,编辑器快捷项
2682
+ * 与求值面解耦(spec 原文口径)。
2576
2683
  *
2577
- * 全模块纯函数、无 DOM;层内依赖仅 expressionSchema / expressionPath。
2684
+ * 全模块零依赖纯数据、零 DOM(editor-shared-isolation)。
2578
2685
  */
2686
+ /** 一条内建函数建议元数据(segment 由消费方拼装:`名字()` + 光标回落括号内) */
2687
+ interface ExpressionFunctionMeta {
2688
+ name: string;
2689
+ /** 签名展示(候选 tooltip/说明位) */
2690
+ signature: string;
2691
+ /** 一句话语义(候选说明位) */
2692
+ summary: string;
2693
+ }
2694
+ /** v1 内建函数白名单的建议面数据(spec §2;顺序 = 文档序,非优先级) */
2695
+ declare const EXPRESSION_FUNCTIONS: readonly ExpressionFunctionMeta[];
2696
+ /** 数字族桶建议(工单 11 ②:type=number 字段建议三函数,插入裸调用走缺省参) */
2697
+ declare const NUMBER_FUNCTION_SUGGESTIONS: readonly ExpressionFunctionMeta[];
2698
+ /** 一条格式串快捷项(date 第二参字符串槽的建议面) */
2699
+ interface ExpressionFormatSuggestion {
2700
+ segment: string;
2701
+ description: string;
2702
+ }
2703
+ /** date 格式串快捷项:具名预设两枚 + 中文模板(spec §3.4;写即所得不设中文求值预设) */
2704
+ declare const DATE_FORMAT_SUGGESTIONS: readonly ExpressionFormatSuggestion[];
2579
2705
 
2580
2706
  /** 'root' = 根层三字段(独立图层);'row' = 格内容层(模板行内) */
2581
2707
  type ExpressionContextKind = 'root' | 'row';
2582
2708
  /** 一条补全候选:路径 + schema 元信息(description/title/类型徽标,展示回落归浮层) */
2583
2709
  interface ExpressionCandidate {
2584
- /** 补全后的完整点路径(前缀 + 本段;头部候选即头部名),如 row.user.city */
2710
+ /** 补全后的完整点路径(前缀 + 本段;头部候选即头部名;调用候选 = 插入文本) */
2585
2711
  path: string;
2586
2712
  /** 本段名——接受时替换 partial / 追加到前缀后的文本 */
2587
2713
  segment: string;
@@ -2589,8 +2715,23 @@ interface ExpressionCandidate {
2589
2715
  description?: string;
2590
2716
  /** schema title(D8 形状树两字段分离透传,未声明为 undefined)——浮层展示取 description ?? title */
2591
2717
  title?: string;
2592
- /** 类型徽标数据(schema type 归一;未声明为 undefined) */
2718
+ /** 类型徽标数据(schema type 归一;未声明为 undefined;函数/格式候选为建议类别) */
2593
2719
  type?: string;
2720
+ /**
2721
+ * 插入后光标从插入文本末端回退的码元数(工单 12):date() 调用 = 2(落引号内
2722
+ * format 参数占位)、`名字()` 函数名候选 = 1(落括号内);缺省 0(落插入末尾)
2723
+ */
2724
+ cursorBack?: number;
2725
+ /**
2726
+ * 接受时从光标锚位回退替换的长度(工单 12;缺省 = partial 长度):桶候选携带
2727
+ * 整段 expr 长度——调用插入重写「前缀 + 部分段」全量
2728
+ */
2729
+ replaceLen?: number;
2730
+ /**
2731
+ * 前缀过滤键(工单 12;缺省 = segment):桶候选 = 字段键名——与同键路径候选
2732
+ * 一起被浮层按 partial 过滤(segment 是整段调用文本,直接过滤永不匹配)
2733
+ */
2734
+ filterKey?: string;
2594
2735
  }
2595
2736
  interface ExpressionCandidateQuery {
2596
2737
  context: ExpressionContextKind;
@@ -2620,11 +2761,6 @@ type ExpressionCandidateResult = {
2620
2761
  ok: false;
2621
2762
  reason: ExpressionSyntaxError;
2622
2763
  };
2623
- /**
2624
- * 枚举当前片段表达式的合法候选。schema null(声明降级态)直接无候选;
2625
- * 其余按 spec §2 规则表分上下文路由(见模块头注),分支不可达/节点为叶子
2626
- * 一律空候选,不抛错。
2627
- */
2628
2764
  declare function enumerateExpressionCandidates(schema: ExpressionSchemaNode | null, query: ExpressionCandidateQuery): ExpressionCandidateResult;
2629
2765
 
2630
2766
  /**
@@ -2744,4 +2880,4 @@ declare function memoizeTextPolicies(policies?: TextLayoutPolicies, options?: Me
2744
2880
  */
2745
2881
  declare const PACKAGE_NAME: "@hankchen/canvas-editor";
2746
2882
 
2747
- 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 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 };
2883
+ 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, DATE_FORMAT_SUGGESTIONS, DEFAULT_EDITOR_SHORTCUTS, DEFAULT_ZOOM_BOUNDS, type DeletedLayerRef, type DocRecipe, type DragGesture, EDITOR_STATE_SCHEMA_VERSION, EXPRESSION_FUNCTIONS, type EditorChange, type EditorPrefsState, EditorSession, type EditorSessionOptions, type EditorShortcutAction, type EditorShortcutBinding, type EditorShortcutGroup, type EditorShortcutInput, EditorStore, type EditorUi, type ExpressionCallArg, type ExpressionCallParse, type ExpressionCallSlotContext, type ExpressionCandidate, type ExpressionCandidateQuery, type ExpressionCandidateResult, type ExpressionContextKind, type ExpressionFormatSuggestion, type ExpressionFunctionMeta, 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, NUMBER_FUNCTION_SUGGESTIONS, 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, expressionCallSlotAtEnd, expressionFragmentAtCursor, fitRect, fitViewport, growRowToCellInDraft, handleResizesHeight, handleResizesWidth, hitTest, insertRootLayerAdjacentInDraft, insertRootLayerInDraft, isCallFragment, isImageContentUndrawn, isLayerPath, isLockedPath, isRootLayerPath, isRootPasteableType, isTemplateSubtreePath, layerBoxByPath, memoizeTextPolicies, moveGuard, moveRootLayerInDraft, moveTableCellInDraft, moveTableCellToRowInDraft, moveTableRowInDraft, moveTableRowToTableInDraft, nextZoomByWheel, normalizeExpressionSchemaSource, panBy, panToBox, parseExpressionCall, parseExpressionPath, parseExpressionSchema, pastePosition, pathStartsWith, pathsEqual, phpTrim, 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 };