@retikz/core 0.3.0-alpha.3 → 0.3.0-alpha.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/README.md +41 -41
  2. package/dist/es/compile/anchor-cache.d.ts +5 -3
  3. package/dist/es/compile/anchor-cache.d.ts.map +1 -1
  4. package/dist/es/compile/anchor-cache.js +14 -10
  5. package/dist/es/compile/boundary.d.ts +19 -0
  6. package/dist/es/compile/boundary.d.ts.map +1 -0
  7. package/dist/es/compile/boundary.js +64 -0
  8. package/dist/es/compile/compile.d.ts +1 -1
  9. package/dist/es/compile/compile.d.ts.map +1 -1
  10. package/dist/es/compile/compile.js +49 -5
  11. package/dist/es/compile/node.d.ts +26 -8
  12. package/dist/es/compile/node.d.ts.map +1 -1
  13. package/dist/es/compile/node.js +103 -16
  14. package/dist/es/compile/path/anchor.d.ts.map +1 -1
  15. package/dist/es/compile/path/anchor.js +7 -6
  16. package/dist/es/compile/path/index.d.ts.map +1 -1
  17. package/dist/es/compile/path/index.js +7 -3
  18. package/dist/es/compile/path/relative.js +1 -1
  19. package/dist/es/compile/scope.d.ts.map +1 -1
  20. package/dist/es/compile/scope.js +2 -1
  21. package/dist/es/geometry/arc.d.ts +14 -0
  22. package/dist/es/geometry/arc.d.ts.map +1 -1
  23. package/dist/es/geometry/arc.js +65 -9
  24. package/dist/es/geometry/index.d.ts +1 -0
  25. package/dist/es/geometry/index.d.ts.map +1 -1
  26. package/dist/es/geometry/rect.d.ts +2 -2
  27. package/dist/es/geometry/rect.d.ts.map +1 -1
  28. package/dist/es/geometry/rect.js +3 -3
  29. package/dist/es/geometry/roundedContour.d.ts +88 -0
  30. package/dist/es/geometry/roundedContour.d.ts.map +1 -0
  31. package/dist/es/geometry/roundedContour.js +417 -0
  32. package/dist/es/index.d.ts +9 -5
  33. package/dist/es/index.d.ts.map +1 -1
  34. package/dist/es/index.js +11 -6
  35. package/dist/es/ir/animation.d.ts +218 -0
  36. package/dist/es/ir/animation.d.ts.map +1 -0
  37. package/dist/es/ir/animation.js +118 -0
  38. package/dist/es/ir/boundary.d.ts +25 -0
  39. package/dist/es/ir/boundary.d.ts.map +1 -0
  40. package/dist/es/ir/boundary.js +14 -0
  41. package/dist/es/ir/index.d.ts +3 -0
  42. package/dist/es/ir/index.d.ts.map +1 -1
  43. package/dist/es/ir/node.d.ts +219 -27
  44. package/dist/es/ir/node.d.ts.map +1 -1
  45. package/dist/es/ir/node.js +10 -3
  46. package/dist/es/ir/path/arrow.d.ts +36 -36
  47. package/dist/es/ir/path/path.d.ts +702 -203
  48. package/dist/es/ir/path/path.d.ts.map +1 -1
  49. package/dist/es/ir/path/path.js +4 -0
  50. package/dist/es/ir/path/step.d.ts +674 -154
  51. package/dist/es/ir/path/step.d.ts.map +1 -1
  52. package/dist/es/ir/path/step.js +2 -2
  53. package/dist/es/ir/path/target.d.ts +43 -8
  54. package/dist/es/ir/path/target.d.ts.map +1 -1
  55. package/dist/es/ir/path/target.js +4 -5
  56. package/dist/es/ir/scene.d.ts +156 -0
  57. package/dist/es/ir/scene.d.ts.map +1 -1
  58. package/dist/es/ir/scene.js +3 -1
  59. package/dist/es/ir/scope.d.ts +1671 -424
  60. package/dist/es/ir/scope.d.ts.map +1 -1
  61. package/dist/es/ir/scope.js +10 -2
  62. package/dist/es/ir/shape.d.ts +14 -0
  63. package/dist/es/ir/shape.d.ts.map +1 -0
  64. package/dist/es/ir/shape.js +9 -0
  65. package/dist/es/parsers/parseNodeTarget.d.ts.map +1 -1
  66. package/dist/es/parsers/parseNodeTarget.js +4 -2
  67. package/dist/es/presets/animation.d.ts +123 -0
  68. package/dist/es/presets/animation.d.ts.map +1 -0
  69. package/dist/es/presets/animation.js +272 -0
  70. package/dist/es/presets/index.d.ts +3 -0
  71. package/dist/es/presets/index.d.ts.map +1 -0
  72. package/dist/es/primitive/ellipse.d.ts +6 -0
  73. package/dist/es/primitive/ellipse.d.ts.map +1 -1
  74. package/dist/es/primitive/group.d.ts +6 -0
  75. package/dist/es/primitive/group.d.ts.map +1 -1
  76. package/dist/es/primitive/path.d.ts +6 -0
  77. package/dist/es/primitive/path.d.ts.map +1 -1
  78. package/dist/es/primitive/rect.d.ts +6 -0
  79. package/dist/es/primitive/rect.d.ts.map +1 -1
  80. package/dist/es/primitive/scene.d.ts +3 -0
  81. package/dist/es/primitive/scene.d.ts.map +1 -1
  82. package/dist/es/primitive/text.d.ts +6 -0
  83. package/dist/es/primitive/text.d.ts.map +1 -1
  84. package/dist/es/shapes/_contour.d.ts +19 -0
  85. package/dist/es/shapes/_contour.d.ts.map +1 -0
  86. package/dist/es/shapes/_contour.js +60 -0
  87. package/dist/es/shapes/_shared.d.ts +54 -0
  88. package/dist/es/shapes/_shared.d.ts.map +1 -1
  89. package/dist/es/shapes/_shared.js +68 -1
  90. package/dist/es/shapes/arc.d.ts +8 -0
  91. package/dist/es/shapes/arc.d.ts.map +1 -0
  92. package/dist/es/shapes/arc.js +104 -0
  93. package/dist/es/shapes/define.d.ts +13 -0
  94. package/dist/es/shapes/define.d.ts.map +1 -0
  95. package/dist/es/shapes/define.js +13 -0
  96. package/dist/es/shapes/ellipse.d.ts +5 -4
  97. package/dist/es/shapes/ellipse.d.ts.map +1 -1
  98. package/dist/es/shapes/ellipse.js +15 -7
  99. package/dist/es/shapes/index.d.ts +9 -6
  100. package/dist/es/shapes/index.d.ts.map +1 -1
  101. package/dist/es/shapes/index.js +10 -5
  102. package/dist/es/shapes/polygon.d.ts +13 -0
  103. package/dist/es/shapes/polygon.d.ts.map +1 -0
  104. package/dist/es/shapes/polygon.js +104 -0
  105. package/dist/es/shapes/rectangle.d.ts +7 -5
  106. package/dist/es/shapes/rectangle.d.ts.map +1 -1
  107. package/dist/es/shapes/rectangle.js +37 -8
  108. package/dist/es/shapes/sector.d.ts +9 -0
  109. package/dist/es/shapes/sector.d.ts.map +1 -0
  110. package/dist/es/shapes/sector.js +143 -0
  111. package/dist/es/shapes/star.d.ts +15 -0
  112. package/dist/es/shapes/star.d.ts.map +1 -0
  113. package/dist/es/shapes/star.js +113 -0
  114. package/dist/es/shapes/types.d.ts +47 -14
  115. package/dist/es/shapes/types.d.ts.map +1 -1
  116. package/dist/lib/compile/anchor-cache.cjs +14 -10
  117. package/dist/lib/compile/anchor-cache.d.ts +5 -3
  118. package/dist/lib/compile/anchor-cache.d.ts.map +1 -1
  119. package/dist/lib/compile/boundary.cjs +65 -0
  120. package/dist/lib/compile/boundary.d.ts +19 -0
  121. package/dist/lib/compile/boundary.d.ts.map +1 -0
  122. package/dist/lib/compile/compile.cjs +49 -5
  123. package/dist/lib/compile/compile.d.ts +1 -1
  124. package/dist/lib/compile/compile.d.ts.map +1 -1
  125. package/dist/lib/compile/node.cjs +103 -16
  126. package/dist/lib/compile/node.d.ts +26 -8
  127. package/dist/lib/compile/node.d.ts.map +1 -1
  128. package/dist/lib/compile/path/anchor.cjs +7 -6
  129. package/dist/lib/compile/path/anchor.d.ts.map +1 -1
  130. package/dist/lib/compile/path/index.cjs +7 -3
  131. package/dist/lib/compile/path/index.d.ts.map +1 -1
  132. package/dist/lib/compile/path/relative.cjs +1 -1
  133. package/dist/lib/compile/scope.cjs +2 -1
  134. package/dist/lib/compile/scope.d.ts.map +1 -1
  135. package/dist/lib/geometry/arc.cjs +66 -8
  136. package/dist/lib/geometry/arc.d.ts +14 -0
  137. package/dist/lib/geometry/arc.d.ts.map +1 -1
  138. package/dist/lib/geometry/index.d.ts +1 -0
  139. package/dist/lib/geometry/index.d.ts.map +1 -1
  140. package/dist/lib/geometry/rect.cjs +3 -3
  141. package/dist/lib/geometry/rect.d.ts +2 -2
  142. package/dist/lib/geometry/rect.d.ts.map +1 -1
  143. package/dist/lib/geometry/roundedContour.cjs +418 -0
  144. package/dist/lib/geometry/roundedContour.d.ts +88 -0
  145. package/dist/lib/geometry/roundedContour.d.ts.map +1 -0
  146. package/dist/lib/index.cjs +41 -7
  147. package/dist/lib/index.d.ts +9 -5
  148. package/dist/lib/index.d.ts.map +1 -1
  149. package/dist/lib/ir/animation.cjs +127 -0
  150. package/dist/lib/ir/animation.d.ts +218 -0
  151. package/dist/lib/ir/animation.d.ts.map +1 -0
  152. package/dist/lib/ir/boundary.cjs +15 -0
  153. package/dist/lib/ir/boundary.d.ts +25 -0
  154. package/dist/lib/ir/boundary.d.ts.map +1 -0
  155. package/dist/lib/ir/index.d.ts +3 -0
  156. package/dist/lib/ir/index.d.ts.map +1 -1
  157. package/dist/lib/ir/node.cjs +10 -3
  158. package/dist/lib/ir/node.d.ts +219 -27
  159. package/dist/lib/ir/node.d.ts.map +1 -1
  160. package/dist/lib/ir/path/arrow.d.ts +36 -36
  161. package/dist/lib/ir/path/path.cjs +4 -0
  162. package/dist/lib/ir/path/path.d.ts +702 -203
  163. package/dist/lib/ir/path/path.d.ts.map +1 -1
  164. package/dist/lib/ir/path/step.cjs +2 -2
  165. package/dist/lib/ir/path/step.d.ts +674 -154
  166. package/dist/lib/ir/path/step.d.ts.map +1 -1
  167. package/dist/lib/ir/path/target.cjs +4 -5
  168. package/dist/lib/ir/path/target.d.ts +43 -8
  169. package/dist/lib/ir/path/target.d.ts.map +1 -1
  170. package/dist/lib/ir/scene.cjs +3 -1
  171. package/dist/lib/ir/scene.d.ts +156 -0
  172. package/dist/lib/ir/scene.d.ts.map +1 -1
  173. package/dist/lib/ir/scope.cjs +10 -2
  174. package/dist/lib/ir/scope.d.ts +1671 -424
  175. package/dist/lib/ir/scope.d.ts.map +1 -1
  176. package/dist/lib/ir/shape.cjs +9 -0
  177. package/dist/lib/ir/shape.d.ts +14 -0
  178. package/dist/lib/ir/shape.d.ts.map +1 -0
  179. package/dist/lib/parsers/parseNodeTarget.cjs +4 -2
  180. package/dist/lib/parsers/parseNodeTarget.d.ts.map +1 -1
  181. package/dist/lib/presets/animation.cjs +286 -0
  182. package/dist/lib/presets/animation.d.ts +123 -0
  183. package/dist/lib/presets/animation.d.ts.map +1 -0
  184. package/dist/lib/presets/index.d.ts +3 -0
  185. package/dist/lib/presets/index.d.ts.map +1 -0
  186. package/dist/lib/primitive/ellipse.d.ts +6 -0
  187. package/dist/lib/primitive/ellipse.d.ts.map +1 -1
  188. package/dist/lib/primitive/group.d.ts +6 -0
  189. package/dist/lib/primitive/group.d.ts.map +1 -1
  190. package/dist/lib/primitive/path.d.ts +6 -0
  191. package/dist/lib/primitive/path.d.ts.map +1 -1
  192. package/dist/lib/primitive/rect.d.ts +6 -0
  193. package/dist/lib/primitive/rect.d.ts.map +1 -1
  194. package/dist/lib/primitive/scene.d.ts +3 -0
  195. package/dist/lib/primitive/scene.d.ts.map +1 -1
  196. package/dist/lib/primitive/text.d.ts +6 -0
  197. package/dist/lib/primitive/text.d.ts.map +1 -1
  198. package/dist/lib/shapes/_contour.cjs +61 -0
  199. package/dist/lib/shapes/_contour.d.ts +19 -0
  200. package/dist/lib/shapes/_contour.d.ts.map +1 -0
  201. package/dist/lib/shapes/_shared.cjs +70 -0
  202. package/dist/lib/shapes/_shared.d.ts +54 -0
  203. package/dist/lib/shapes/_shared.d.ts.map +1 -1
  204. package/dist/lib/shapes/arc.cjs +104 -0
  205. package/dist/lib/shapes/arc.d.ts +8 -0
  206. package/dist/lib/shapes/arc.d.ts.map +1 -0
  207. package/dist/lib/shapes/define.cjs +13 -0
  208. package/dist/lib/shapes/define.d.ts +13 -0
  209. package/dist/lib/shapes/define.d.ts.map +1 -0
  210. package/dist/lib/shapes/ellipse.cjs +15 -7
  211. package/dist/lib/shapes/ellipse.d.ts +5 -4
  212. package/dist/lib/shapes/ellipse.d.ts.map +1 -1
  213. package/dist/lib/shapes/index.cjs +12 -6
  214. package/dist/lib/shapes/index.d.ts +9 -6
  215. package/dist/lib/shapes/index.d.ts.map +1 -1
  216. package/dist/lib/shapes/polygon.cjs +104 -0
  217. package/dist/lib/shapes/polygon.d.ts +13 -0
  218. package/dist/lib/shapes/polygon.d.ts.map +1 -0
  219. package/dist/lib/shapes/rectangle.cjs +37 -8
  220. package/dist/lib/shapes/rectangle.d.ts +7 -5
  221. package/dist/lib/shapes/rectangle.d.ts.map +1 -1
  222. package/dist/lib/shapes/sector.cjs +143 -0
  223. package/dist/lib/shapes/sector.d.ts +9 -0
  224. package/dist/lib/shapes/sector.d.ts.map +1 -0
  225. package/dist/lib/shapes/star.cjs +113 -0
  226. package/dist/lib/shapes/star.d.ts +15 -0
  227. package/dist/lib/shapes/star.d.ts.map +1 -0
  228. package/dist/lib/shapes/types.d.ts +47 -14
  229. package/dist/lib/shapes/types.d.ts.map +1 -1
  230. package/package.json +2 -2
  231. package/dist/es/shapes/circle.d.ts +0 -8
  232. package/dist/es/shapes/circle.d.ts.map +0 -1
  233. package/dist/es/shapes/circle.js +0 -34
  234. package/dist/es/shapes/diamond.d.ts +0 -8
  235. package/dist/es/shapes/diamond.d.ts.map +0 -1
  236. package/dist/es/shapes/diamond.js +0 -66
  237. package/dist/lib/shapes/circle.cjs +0 -34
  238. package/dist/lib/shapes/circle.d.ts +0 -8
  239. package/dist/lib/shapes/circle.d.ts.map +0 -1
  240. package/dist/lib/shapes/diamond.cjs +0 -66
  241. package/dist/lib/shapes/diamond.d.ts +0 -8
  242. package/dist/lib/shapes/diamond.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,41 +1,41 @@
1
- # @retikz/core
2
-
3
- Framework-agnostic core of [retikz](https://pionpill.github.io/retikz/) — a TikZ-inspired diagramming library. Provides the zod-typed **IR**, the **`compileToScene`** compiler, pure **parsers**, geometry helpers, and the shape / arrow / pattern / path-generator registries.
4
-
5
- 零框架核心:retikz 的中间表示(IR)、`compileToScene` 编译器、纯解析器、几何工具与形状 / 箭头 / 图案 / 路径生成器注册面。**零 React、零 DOM**,运行时依赖只有 `zod`,IR 100% 可 JSON 序列化。
6
-
7
- ## Install
8
-
9
- ```bash
10
- pnpm add @retikz/core
11
- ```
12
-
13
- ## Usage
14
-
15
- `@retikz/core` is renderer-agnostic: it turns an IR into a serializable `Scene`. A backend (`@retikz/render`) or runtime (`@retikz/react` / `@retikz/vanilla`) then renders that Scene.
16
-
17
- ```ts
18
- import { compileToScene } from '@retikz/core';
19
-
20
- const scene = compileToScene(ir);
21
- // optional: compileToScene(ir, { measureText, shapes, arrows, padding, ... })
22
- // hand `scene` to @retikz/render/svg, @retikz/render/canvas, or a runtime
23
- ```
24
-
25
- Most users consume core indirectly through [`@retikz/react`](https://www.npmjs.com/package/@retikz/react) or [`@retikz/vanilla`](https://www.npmjs.com/package/@retikz/vanilla). Use core directly when you build IR programmatically, persist/transport scenes, or write a custom renderer.
26
-
27
- ## Exports
28
-
29
- - `compileToScene` / `computeLayout` / `fallbackMeasurer` — IR → `Scene`
30
- - IR & `Scene` zod schemas + inferred types
31
- - `parseWay` / `parseNodeTarget` / `parseTargetSugar` — pure parsers
32
- - `point` / `rect` / `circle` / `ellipse` / `diamond` / `polar` — geometry
33
- - `BUILTIN_SHAPES` / `BUILTIN_ARROWS` / `BUILTIN_PATTERNS` + `ShapeDefinition` / `ArrowDefinition` / `PatternDefinition` / `definePathGenerator` — registries
34
-
35
- ## Docs
36
-
37
- <https://pionpill.github.io/retikz/>
38
-
39
- ## License
40
-
41
- MIT
1
+ # @retikz/core
2
+
3
+ Framework-agnostic core of [retikz](https://pionpill.github.io/retikz/) — a TikZ-inspired diagramming library. Provides the zod-typed **IR**, the **`compileToScene`** compiler, pure **parsers**, geometry helpers, and the shape / arrow / pattern / path-generator registries.
4
+
5
+ 零框架核心:retikz 的中间表示(IR)、`compileToScene` 编译器、纯解析器、几何工具与形状 / 箭头 / 图案 / 路径生成器注册面。**零 React、零 DOM**,运行时依赖只有 `zod`,IR 100% 可 JSON 序列化。
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @retikz/core
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ `@retikz/core` is renderer-agnostic: it turns an IR into a serializable `Scene`. A backend (`@retikz/render`) or runtime (`@retikz/react` / `@retikz/vanilla`) then renders that Scene.
16
+
17
+ ```ts
18
+ import { compileToScene } from '@retikz/core';
19
+
20
+ const scene = compileToScene(ir);
21
+ // optional: compileToScene(ir, { measureText, shapes, arrows, padding, ... })
22
+ // hand `scene` to @retikz/render/svg, @retikz/render/canvas, or a runtime
23
+ ```
24
+
25
+ Most users consume core indirectly through [`@retikz/react`](https://www.npmjs.com/package/@retikz/react) or [`@retikz/vanilla`](https://www.npmjs.com/package/@retikz/vanilla). Use core directly when you build IR programmatically, persist/transport scenes, or write a custom renderer.
26
+
27
+ ## Exports
28
+
29
+ - `compileToScene` / `computeLayout` / `fallbackMeasurer` — IR → `Scene`
30
+ - IR & `Scene` zod schemas + inferred types
31
+ - `parseWay` / `parseNodeTarget` / `parseTargetSugar` — pure parsers
32
+ - `point` / `rect` / `circle` / `ellipse` / `diamond` / `polar` — geometry
33
+ - `BUILTIN_SHAPES` / `BUILTIN_ARROWS` / `BUILTIN_PATTERNS` + `ShapeDefinition` / `ArrowDefinition` / `PatternDefinition` / `definePathGenerator` — registries
34
+
35
+ ## Docs
36
+
37
+ <https://pionpill.github.io/retikz/>
38
+
39
+ ## License
40
+
41
+ MIT
@@ -1,15 +1,17 @@
1
1
  import { Side } from '../geometry/_edge';
2
- import { IRPosition } from '../ir';
2
+ import { IRBoundary, IRPosition } from '../ir';
3
3
  import { NodeLayout } from './node';
4
4
  /**
5
5
  * 取节点 anchor 的全局坐标,带 per-layout 缓存
6
6
  * @description name 接受 RectAnchor 关键字(如 `'north'` / `'south-west'`)或数字角度字符串(如 `'30'` / `'-45'`);
7
- * 同一 (layout, name) 第二次起返回首调用结果的**同一引用**——上游可用 `===` 判定 cache 命中
7
+ * boundary 指定连接面(默认 `'shape'`,即节点自身视觉轮廓);不同 boundary 产生独立缓存条目,互不串扰;
8
+ * 同一 (layout, name, boundary) 组合第二次起返回首调用结果的**同一引用**——上游可用 `===` 判定 cache 命中
8
9
  * @param layout 已 Pass 1 完成的 NodeLayout(rect 已是全局坐标)
9
10
  * @param anchorName 关键字或数字角度字符串
11
+ * @param boundary 连接面,缺省为 `'shape'`(视觉轮廓)
10
12
  * @returns 全局坐标系下的 IRPosition `[x, y]`
11
13
  */
12
- export declare const resolveAnchor: (layout: NodeLayout, anchorName: string) => IRPosition;
14
+ export declare const resolveAnchor: (layout: NodeLayout, anchorName: string, boundary?: IRBoundary | undefined) => IRPosition;
13
15
  /**
14
16
  * 取节点边上比例点 `{ side, t }` 的全局坐标,带 per-layout 缓存
15
17
  * @description 走 `layout.shapeDef.edgePoint`——shape 未实现(如自定义 shape)抛"does not support side anchors";
@@ -1 +1 @@
1
- {"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../../src/compile/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AA4BzC;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,UAAU,EAClB,YAAY,MAAM,KACjB,UAWF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,UAAU,EAClB,MAAM,IAAI,EACV,GAAG,MAAM,KACR,UAuBF,CAAC"}
1
+ {"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../../src/compile/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAiCzC;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,UAAU,EAClB,YAAY,MAAM,EAClB,WAAU,UAAU,GAAG,SAAmB,KACzC,UAYF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,UAAU,EAClB,MAAM,IAAI,EACV,GAAG,MAAM,KACR,UAuBF,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { boundaryKey } from "./boundary.js";
1
2
  import { anchorOf, angleBoundaryOf } from "./node.js";
2
3
  //#region src/compile/anchor-cache.ts
3
4
  /**
@@ -9,32 +10,35 @@ var cache = /* @__PURE__ */ new WeakMap();
9
10
  var ANGLE_RE = /^-?\d+(\.\d+)?$/;
10
11
  /**
11
12
  * 把 anchorName 解析到对应 shape 的 anchor / boundaryPoint 上
12
- * @description 数字字符串走 angleBoundaryOf;其余按 RectAnchor 走 anchorOf
13
+ * @description 数字字符串走 angleBoundaryOf;其余按 RectAnchor 走 anchorOf;boundary 透传给两者
13
14
  */
14
- var computeAnchor = (layout, anchorName) => {
15
- if (ANGLE_RE.test(anchorName)) return positionToIR(angleBoundaryOf(layout, Number(anchorName)));
16
- return positionToIR(anchorOf(layout, anchorName));
15
+ var computeAnchor = (layout, anchorName, boundary) => {
16
+ if (ANGLE_RE.test(anchorName)) return positionToIR(angleBoundaryOf(layout, Number(anchorName), boundary));
17
+ return positionToIR(anchorOf(layout, anchorName, boundary));
17
18
  };
18
19
  /** geometry Position(含 readonly 形态)转 IRPosition 元组(IRPosition === [number, number]) */
19
20
  var positionToIR = (p) => [p[0], p[1]];
20
21
  /**
21
22
  * 取节点 anchor 的全局坐标,带 per-layout 缓存
22
23
  * @description name 接受 RectAnchor 关键字(如 `'north'` / `'south-west'`)或数字角度字符串(如 `'30'` / `'-45'`);
23
- * 同一 (layout, name) 第二次起返回首调用结果的**同一引用**——上游可用 `===` 判定 cache 命中
24
+ * boundary 指定连接面(默认 `'shape'`,即节点自身视觉轮廓);不同 boundary 产生独立缓存条目,互不串扰;
25
+ * 同一 (layout, name, boundary) 组合第二次起返回首调用结果的**同一引用**——上游可用 `===` 判定 cache 命中
24
26
  * @param layout 已 Pass 1 完成的 NodeLayout(rect 已是全局坐标)
25
27
  * @param anchorName 关键字或数字角度字符串
28
+ * @param boundary 连接面,缺省为 `'shape'`(视觉轮廓)
26
29
  * @returns 全局坐标系下的 IRPosition `[x, y]`
27
30
  */
28
- var resolveAnchor = (layout, anchorName) => {
31
+ var resolveAnchor = (layout, anchorName, boundary = "shape") => {
29
32
  let layoutCache = cache.get(layout);
30
33
  if (!layoutCache) {
31
34
  layoutCache = /* @__PURE__ */ new Map();
32
35
  cache.set(layout, layoutCache);
33
36
  }
34
- const cached = layoutCache.get(anchorName);
37
+ const key = `${boundaryKey(boundary)} ${anchorName}`;
38
+ const cached = layoutCache.get(key);
35
39
  if (cached !== void 0) return cached;
36
- const result = computeAnchor(layout, anchorName);
37
- layoutCache.set(anchorName, result);
40
+ const result = computeAnchor(layout, anchorName, boundary);
41
+ layoutCache.set(key, result);
38
42
  return result;
39
43
  };
40
44
  /**
@@ -57,7 +61,7 @@ var resolveEdgePoint = (layout, side, t) => {
57
61
  const key = `${side}:${t}`;
58
62
  const cached = layoutCache.get(key);
59
63
  if (cached !== void 0) return cached;
60
- const result = positionToIR(edgePoint(layout.rect, side, t));
64
+ const result = positionToIR(edgePoint(layout.rect, side, t, layout.shapeParams ?? {}));
61
65
  layoutCache.set(key, result);
62
66
  return result;
63
67
  };
@@ -0,0 +1,19 @@
1
+ import { Rect } from '../geometry/rect';
2
+ import { IRBoundary } from '../ir';
3
+ import { IRJsonObject } from '../ir/json';
4
+ import { ShapeDefinition } from '../shapes';
5
+ /**
6
+ * 把连接面取值解析为「计算 boundaryPoint / anchor 所需的 def + rect + params」
7
+ * @description layout-neutral:borrowed/builtin 一律喂目标节点的视觉 AABB rect,绝不调其 circumscribe。
8
+ * 保留字 'shape' → 视觉 def 原样;'circle' → ellipse def + squared-to-max rect;
9
+ * 保留字 'rectangle' / 'ellipse' → 对应内置 def + 视觉 AABB;其余 → registry 查表。
10
+ * 保留字优先于 registry 同名 shape。
11
+ */
12
+ export declare const resolveBoundary: (boundary: IRBoundary | undefined, visualDef: ShapeDefinition, visualRect: Rect, visualParams: IRJsonObject, registry: Record<string, ShapeDefinition>) => {
13
+ def: ShapeDefinition;
14
+ rect: Rect;
15
+ params: IRJsonObject;
16
+ };
17
+ /** 连接面的稳定字符串判别(anchor cache key 用) */
18
+ export declare const boundaryKey: (boundary: IRBoundary | undefined) => string;
19
+ //# sourceMappingURL=boundary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"boundary.d.ts","sourceRoot":"","sources":["../../../src/compile/boundary.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAcjD;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,UAAU,GAAG,SAAS,EAChC,WAAW,eAAe,EAC1B,YAAY,IAAI,EAChB,cAAc,YAAY,EAC1B,UAAU,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,KACxC;IAAE,GAAG,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAuB1D,CAAC;AAEF,sCAAsC;AACtC,eAAO,MAAM,WAAW,GAAI,UAAU,UAAU,GAAG,SAAS,KAAG,MAI9D,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { ellipse } from "../shapes/ellipse.js";
2
+ import { rectangle } from "../shapes/rectangle.js";
3
+ //#region src/compile/boundary.ts
4
+ /** 保留字:连接面 = 节点自身视觉形状 */
5
+ var SELF = "shape";
6
+ /** 保留字:真圆(半径 = AABB 较长半轴) */
7
+ var CIRCLE = "circle";
8
+ /** 把 rect 收成边长 = max(width, height) 的正方(中心 / rotate 不变)——circle 连接面用 */
9
+ var squareToMax = (rect) => {
10
+ const side = Math.max(rect.width, rect.height);
11
+ return {
12
+ x: rect.x,
13
+ y: rect.y,
14
+ width: side,
15
+ height: side,
16
+ rotate: rect.rotate
17
+ };
18
+ };
19
+ /**
20
+ * 把连接面取值解析为「计算 boundaryPoint / anchor 所需的 def + rect + params」
21
+ * @description layout-neutral:borrowed/builtin 一律喂目标节点的视觉 AABB rect,绝不调其 circumscribe。
22
+ * 保留字 'shape' → 视觉 def 原样;'circle' → ellipse def + squared-to-max rect;
23
+ * 保留字 'rectangle' / 'ellipse' → 对应内置 def + 视觉 AABB;其余 → registry 查表。
24
+ * 保留字优先于 registry 同名 shape。
25
+ */
26
+ var resolveBoundary = (boundary, visualDef, visualRect, visualParams, registry) => {
27
+ if (boundary === void 0 || boundary === SELF) return {
28
+ def: visualDef,
29
+ rect: visualRect,
30
+ params: visualParams
31
+ };
32
+ if (boundary === CIRCLE) return {
33
+ def: ellipse,
34
+ rect: squareToMax(visualRect),
35
+ params: {}
36
+ };
37
+ if (boundary === "rectangle") return {
38
+ def: rectangle,
39
+ rect: visualRect,
40
+ params: {}
41
+ };
42
+ if (boundary === "ellipse") return {
43
+ def: ellipse,
44
+ rect: visualRect,
45
+ params: {}
46
+ };
47
+ const type = typeof boundary === "string" ? boundary : boundary.type;
48
+ const rawParams = typeof boundary === "string" ? {} : boundary.params ?? {};
49
+ const def = Object.prototype.hasOwnProperty.call(registry, type) ? registry[type] : void 0;
50
+ if (!def) throw new Error(`Unknown connection surface '${type}'; reserved: shape/circle, registered: ${Object.keys(registry).sort().join(", ")}`);
51
+ return {
52
+ def,
53
+ rect: visualRect,
54
+ params: def.paramsSchema.parse(rawParams)
55
+ };
56
+ };
57
+ /** 连接面的稳定字符串判别(anchor cache key 用) */
58
+ var boundaryKey = (boundary) => {
59
+ if (boundary === void 0) return SELF;
60
+ if (typeof boundary === "string") return boundary;
61
+ return `${boundary.type}:${JSON.stringify(boundary.params ?? {})}`;
62
+ };
63
+ //#endregion
64
+ export { boundaryKey, resolveBoundary };
@@ -12,7 +12,7 @@ export type CompileWarning = {
12
12
  * 警告类型代码(机器可读)
13
13
  * @description 用户可按 code 分支处理;未来 alpha 加新 code 不破坏调用方
14
14
  */
15
- code: 'UNRESOLVED_NODE_REFERENCE' | 'PATH_TOO_SHORT' | 'ANCHOR_RESOLUTION_FAILED' | 'OFFSET_BASE_UNRESOLVED' | 'POLAR_ORIGIN_UNRESOLVED' | 'AT_TARGET_UNRESOLVED' | 'RELATIVE_INITIAL_NO_PREV_END' | 'BBOX_EXTREME_INPUT' | 'DUPLICATE_NODE_ID' | 'SHAPE_OVERRIDES_BUILTIN' | 'ARROW_OVERRIDES_BUILTIN' | 'PATTERN_OVERRIDES_BUILTIN' | 'COMPOSITE_NOT_REGISTERED' | (string & {});
15
+ code: 'UNRESOLVED_NODE_REFERENCE' | 'PATH_TOO_SHORT' | 'ANCHOR_RESOLUTION_FAILED' | 'OFFSET_BASE_UNRESOLVED' | 'POLAR_ORIGIN_UNRESOLVED' | 'AT_TARGET_UNRESOLVED' | 'RELATIVE_INITIAL_NO_PREV_END' | 'BBOX_EXTREME_INPUT' | 'DUPLICATE_NODE_ID' | 'SHAPE_OVERRIDES_BUILTIN' | 'ARROW_OVERRIDES_BUILTIN' | 'PATTERN_OVERRIDES_BUILTIN' | 'COMPOSITE_NOT_REGISTERED' | 'ANIMATION_INVALID_PROPERTY' | (string & {});
16
16
  /** 人类可读消息(英文) */
17
17
  message: string;
18
18
  /** IR locator 路径(jq-like,如 `'children[3].path.children[1].to'`) */
@@ -1 +1 @@
1
- {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/compile/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAwC,MAAM,OAAO,CAAC;AACtE,OAAO,KAAK,EAAa,KAAK,EAA6B,MAAM,cAAc,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAwBzD,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA4CrE,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,IAAI,EACA,2BAA2B,GAC3B,gBAAgB,GAChB,0BAA0B,GAC1B,wBAAwB,GACxB,yBAAyB,GACzB,sBAAsB,GACtB,8BAA8B,GAC9B,oBAAoB,GACpB,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,2BAA2B,GAC3B,0BAA0B,GAC1B,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,iBAAiB;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,2BAA2B;AAC3B,MAAM,MAAM,cAAc,GAAG;IAC3B,oCAAoC;IACpC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IACzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACxC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AA+HF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,EAAE,EAAE,UAAS,cAAmB,KAAG,KAmWrE,CAAC"}
1
+ {"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../../../src/compile/compile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAA0D,MAAM,OAAO,CAAC;AACxF,OAAO,KAAK,EAAa,KAAK,EAA6B,MAAM,cAAc,CAAC;AAEhF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAwBzD,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AA6CrE,uEAAuE;AACvE,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,IAAI,EACA,2BAA2B,GAC3B,gBAAgB,GAChB,0BAA0B,GAC1B,wBAAwB,GACxB,yBAAyB,GACzB,sBAAsB,GACtB,8BAA8B,GAC9B,oBAAoB,GACpB,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,2BAA2B,GAC3B,0BAA0B,GAC1B,4BAA4B,GAC5B,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;IAClB,iBAAiB;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,2BAA2B;AAC3B,MAAM,MAAM,cAAc,GAAG;IAC3B,oCAAoC;IACpC,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;IACzD;;;;OAIG;IACH,UAAU,CAAC,EAAE,KAAK,CAAC,mBAAmB,CAAC,CAAC;IACxC;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAsLF;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,IAAI,EAAE,EAAE,UAAS,cAAmB,KAAG,KA6WrE,CAAC"}
@@ -38,7 +38,8 @@ var zeroSizeRectAt = (id, [cx, cy]) => ({
38
38
  textHeight: 0,
39
39
  align: "middle",
40
40
  lineHeight: 0,
41
- fontSize: 0
41
+ fontSize: 0,
42
+ shapes: BUILTIN_SHAPES
42
43
  });
43
44
  /**
44
45
  * 把 coordinate 注册成 0×0 NodeLayout
@@ -77,6 +78,16 @@ var viewBoxToLayout = (vb, round) => {
77
78
  };
78
79
  };
79
80
  /**
81
+ * 自动算 layout 的 finite 守卫:四值非全 finite 即抛清晰错(LLM 可读),不泄漏进 Scene
82
+ * @description computeLayout 由 `center ± halfWidth` 等运算聚合——极端 shape 几何(如 outerRadius:1e308
83
+ * 半轴 finite 但 center+halfWidth 溢出 Infinity)会让运算结果脏。schema 的 `.finite()` 只守单字段输入,
84
+ * 守不住聚合后的溢出;此处复用 viewBoxToLayout 同款 finite 关口,是自动 layout 进 Scene 前的唯一兜底。
85
+ */
86
+ var assertFiniteLayout = (layout) => {
87
+ if (!Number.isFinite(layout.x) || !Number.isFinite(layout.y) || !Number.isFinite(layout.width) || !Number.isFinite(layout.height)) throw new Error(`Node layout produced non-finite bounds (x=${String(layout.x)}, y=${String(layout.y)}, width=${String(layout.width)}, height=${String(layout.height)}); check shape geometry (e.g. extreme radius).`);
88
+ return layout;
89
+ };
90
+ /**
80
91
  * 默认 warn dispatcher:dev 模式 console.warn、生产静默
81
92
  * @description 用户传 onWarn 时使用用户的;不传走此 fallback
82
93
  */
@@ -84,6 +95,26 @@ var defaultWarnDispatcher = (warning) => {
84
95
  if (typeof process !== "undefined" && process.env.NODE_ENV === "production") return;
85
96
  console.warn(`[retikz] ${warning.code} at ${warning.path}: ${warning.message}`);
86
97
  };
98
+ /**
99
+ * 校验 animation tracks 的 viewBox⇔根 约束(schema 上下文无关、分不清元素 vs 根,故在此 compile 层做)
100
+ * @description `viewBox`(镜头)只在 scene 根合法、元素级非法;scene 根只接受 `viewBox`。违例 track → `warn(ANIMATION_INVALID_PROPERTY)` + drop(不丢图、不影响其余 track)。全空返回 undefined(不 stamp 空数组)。
101
+ */
102
+ var filterAnimations = (tracks, context, onWarn, irPath) => {
103
+ if (tracks === void 0) return void 0;
104
+ const kept = tracks.filter((track, index) => {
105
+ const isViewBox = track.property === "viewBox";
106
+ if (!(context === "root" ? isViewBox : !isViewBox)) {
107
+ onWarn({
108
+ code: "ANIMATION_INVALID_PROPERTY",
109
+ message: context === "root" ? `Scene-root animation must use the "viewBox" property (camera); got "${track.property}". Track dropped.` : `Animation property "viewBox" is camera-only (scene root), not valid on an element. Track dropped.`,
110
+ path: `${irPath}.animations[${index}]`
111
+ });
112
+ return false;
113
+ }
114
+ return true;
115
+ });
116
+ return kept.length > 0 ? kept : void 0;
117
+ };
87
118
  var makePathPlaceholder = () => ({ type: "path-placeholder" });
88
119
  /** 把内部 sink 收窄回公开 ScenePrimitive[]:占位已全部回填(compileToScene 末端 placeholderBalance 无条件校验兜底) */
89
120
  var sealSink = (sink) => sink;
@@ -242,7 +273,11 @@ var compileToScene = (ir, options = {}) => {
242
273
  const child = children[i];
243
274
  if ("namespace" in child) throw new Error(`Unexpected composite node '${child.namespace}.${child.type}' reached compile; composites must be lowered via lowerComposites first.`);
244
275
  if (child.type === "node") {
245
- const layout = layoutNode(resolveNodeStyle(child, styleStack), measureText, nameStack, nodeDistance, chain, resolveLabelDefault(styleStack), effectiveShapes, refPointOfTarget);
276
+ const effectiveNode = resolveNodeStyle(child, styleStack);
277
+ const layout = layoutNode({
278
+ ...effectiveNode,
279
+ animations: filterAnimations(effectiveNode.animations, "element", onWarn, `${locatorPrefix}children[${i}].node`)
280
+ }, measureText, nameStack, nodeDistance, chain, resolveLabelDefault(styleStack), effectiveShapes, refPointOfTarget);
246
281
  const globalLayout = chain.length === 0 ? layout : projectLayoutToGlobal(layout, chain);
247
282
  if (child.id) nameStack.register(child.id, globalLayout, `${locatorPrefix}children[${i}].node.id`);
248
283
  for (const prim of emitNodePrimitives(layout, round, paint.resolve)) {
@@ -305,13 +340,20 @@ var compileToScene = (ir, options = {}) => {
305
340
  children: stableSortByZIndex(sealSink(innerSink))
306
341
  };
307
342
  if (child.id !== void 0) group.id = child.id;
343
+ if (child.meta !== void 0) group.meta = child.meta;
344
+ const scopeAnimations = filterAnimations(child.animations, "element", onWarn, `${locatorPrefix}children[${i}].scope`);
345
+ if (scopeAnimations !== void 0) group.animations = scopeAnimations;
308
346
  if (hasOwnTransforms) group.transforms = [...ownTransforms];
309
347
  if (child.clip !== void 0) group.clipRef = clip.resolve(child.clip);
310
348
  sink.push(group);
311
349
  if (child.zIndex !== void 0) zIndexOf.set(group, child.zIndex);
312
350
  } else {
351
+ const effectivePath = resolveEffectivePath(child, styleStack);
313
352
  const pending = {
314
- path: resolveEffectivePath(child, styleStack),
353
+ path: {
354
+ ...effectivePath,
355
+ animations: filterAnimations(effectivePath.animations, "element", onWarn, `${locatorPrefix}children[${i}].path`)
356
+ },
315
357
  irPath: `${locatorPrefix}children[${i}].path`,
316
358
  scopeChain: chain,
317
359
  zIndex: child.zIndex
@@ -337,10 +379,12 @@ var compileToScene = (ir, options = {}) => {
337
379
  throw new Error(`internal: ${placeholderBalance} unresolved path placeholder(s) leaked into Scene output${detail}`);
338
380
  }
339
381
  const resources = [...paint.resources(), ...clip.resources()];
382
+ const rootAnimations = filterAnimations(loweredIr.animations, "root", onWarn, "scene");
340
383
  return {
341
384
  primitives: stableSortByZIndex(sealSink(primitives)),
342
- layout: loweredIr.viewBox !== void 0 ? viewBoxToLayout(loweredIr.viewBox, round) : computeLayout(allPoints, layoutPadding, round),
343
- ...resources.length > 0 ? { resources } : {}
385
+ layout: loweredIr.viewBox !== void 0 ? viewBoxToLayout(loweredIr.viewBox, round) : assertFiniteLayout(computeLayout(allPoints, layoutPadding, round)),
386
+ ...resources.length > 0 ? { resources } : {},
387
+ ...rootAnimations !== void 0 ? { animations: rootAnimations } : {}
344
388
  };
345
389
  };
346
390
  //#endregion
@@ -1,6 +1,6 @@
1
1
  import { Position } from '../geometry/point';
2
2
  import { Rect } from '../geometry/rect';
3
- import { AtDirection, IRLabelDefault, IRNode, IRPaintSpec } from '../ir';
3
+ import { AtDirection, IRAnimationTrack, IRBoundary, IRJsonObject, IRLabelDefault, IRNode, IRPaintSpec } from '../ir';
4
4
  import { PaintResolver } from './paint';
5
5
  import { ScenePrimitive, TextLine, Transform } from '../primitive';
6
6
  import { ShapeDefinition } from '../shapes';
@@ -14,6 +14,12 @@ export type NodeLayout = {
14
14
  shapeName: string;
15
15
  /** 已解析的 shape 定义;circumscribe / boundaryPoint / anchor / emit 多点复用,取代旧 switch */
16
16
  shapeDef: ShapeDefinition;
17
+ /**
18
+ * 已校验的 per-instance shape 参数(经 `paramsSchema.parse` + `JsonObjectSchema.parse` 双护栏)
19
+ * @description 透传给 `shapeDef` 的 circumscribe / boundaryPoint / anchor / edgePoint / emit;
20
+ * 无参形状(内置 4 个)解析为 `{}`。省略时各调用点以空对象兜底(合成 layout 如 coordinate / scope.id)。
21
+ */
22
+ shapeParams?: IRJsonObject;
17
23
  /**
18
24
  * 节点视觉边界框(所有 shape 共享语义)
19
25
  * @description rectangle: rect 本身;circle: width=height=2×radius;ellipse: 2×rx,2×ry;diamond: 2×halfA,2×halfB。x,y 是几何中心,rotate 弧度
@@ -57,7 +63,7 @@ export type NodeLayout = {
57
63
  /** 描边 dash pattern,已把 dashed/dotted 预设解析为具体 pattern */
58
64
  dashPattern?: Array<number>;
59
65
  /** rectangle 圆角半径(非 rect shape 无效) */
60
- roundedCorners?: number;
66
+ cornerRadius?: number;
61
67
  /** 文字颜色,emit 时 'currentColor' 兜底 */
62
68
  textColor?: string;
63
69
  /** 整节点透明度 0~1(同时挂 shape 与 text primitive) */
@@ -67,6 +73,14 @@ export type NodeLayout = {
67
73
  * @description IR 层 `Node.label` 标准化:position 默认 'above'、distance 默认 DEFAULT_LABEL_DISTANCE、font 从 Node 继承
68
74
  */
69
75
  labels?: Array<NodeLabelLayout>;
76
+ /** 节点默认连接面(来自 IR `node.boundary`;undefined = 'shape');path 端点 boundary 可覆盖 */
77
+ boundary?: IRBoundary;
78
+ /** provenance 元数据(来自 IR `node.meta`);emit 时原样 stamp 到 node 的 top-level 图元,renderer 忽略 */
79
+ meta?: IRJsonObject;
80
+ /** 时间轴动画 tracks(来自 IR `node.animations`);emit 时原样 stamp 到 node 的 top-level 图元,renderer 播放 / 降级 */
81
+ animations?: Array<IRAnimationTrack>;
82
+ /** 构建本 layout 的 shape 注册表引用——借用连接面(borrowed boundary)查表用 */
83
+ shapes: Record<string, ShapeDefinition>;
70
84
  };
71
85
  /** 节点附属标签 layout(layoutNode 已合并默认值与样式继承) */
72
86
  export type NodeLabelLayout = {
@@ -96,20 +110,24 @@ export type NodeLabelLayout = {
96
110
  };
97
111
  /**
98
112
  * 取节点 shape 在 toward 方向的附着点(path 端点贴边用)
99
- * @description shapeDef.boundaryPoint;margin > 0 时先膨胀外接 Rect,让 path 在 border 外停 margin
113
+ * @description 走连接面(boundary)对应的 def.boundaryPoint;margin > 0 时先膨胀外接 Rect,让 path 在 border 外停 margin
114
+ * boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
100
115
  */
101
- export declare const boundaryPointOf: (layout: NodeLayout, toward: Position) => Position;
116
+ export declare const boundaryPointOf: (layout: NodeLayout, toward: Position, boundary?: IRBoundary | undefined) => Position;
102
117
  /**
103
118
  * 取节点 shape 命名 anchor(center / north / east / north-east 等)
104
119
  * @description 不应用 margin——TikZ 语义中 explicit anchor 取视觉边界点不涉及 outer sep;用于 `'A.north'` 落点。
105
- * shapeDef.anchor 不认识的名字返回 undefined,此处抛 Unknown anchor(列出 shape 名)
120
+ * compass(9 rect 方位名)走连接面 AABB:'shape' 时归一为 'rectangle'(矩形 AABB),其余按 boundary 解析。
121
+ * 形状专属命名 anchor(tip-N / apex 等非 compass 名)恒走视觉形状自身,boundary 不影响。
122
+ * boundary 缺省 = 'shape',与改前 compass 走 AABB 行为一致(原 shapeDef.anchor 内部也走 rect AABB)。
106
123
  */
107
- export declare const anchorOf: (layout: NodeLayout, name: string) => Position;
124
+ export declare const anchorOf: (layout: NodeLayout, name: string, boundary?: IRBoundary | undefined) => Position;
108
125
  /**
109
126
  * 取节点 shape 在指定角度方向的边界点
110
- * @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'` 落点
127
+ * @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'` 落点。
128
+ * boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
111
129
  */
112
- export declare const angleBoundaryOf: (layout: NodeLayout, angleDeg: number) => Position;
130
+ export declare const angleBoundaryOf: (layout: NodeLayout, angleDeg: number, boundary?: IRBoundary | undefined) => Position;
113
131
  /**
114
132
  * IR Node → 内部 NodeLayout
115
133
  * @description 文本度量 + padding 推内框半轴;按 shape 算外接边界(circle 取半对角线、ellipse ×√2、diamond ×2);解析 position 为几何中心;rotate 度数转弧度。
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../src/compile/node.ts"],"names":[],"mappings":"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"}