@weasel-js/core 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/CHANGELOG.md +199 -0
  2. package/dist/animation/poseTarget.js +46 -15
  3. package/dist/animation/poseTarget.js.map +1 -1
  4. package/dist/animation/poseTransition.js +3 -3
  5. package/dist/animation/poseTransition.js.map +1 -1
  6. package/dist/animation/reflow.js +3 -6
  7. package/dist/animation/reflow.js.map +1 -1
  8. package/dist/animation/rig/bindRig.js +2 -2
  9. package/dist/animation/rig/bindRig.js.map +1 -1
  10. package/dist/animation/rig/skinBinding.js +2 -2
  11. package/dist/animation/rig/skinBinding.js.map +1 -1
  12. package/dist/barrel/canvas.js +5 -3
  13. package/dist/barrel/chrome.js +3 -1
  14. package/dist/barrel/paths.js +3 -2
  15. package/dist/barrel/routing.js +2 -2
  16. package/dist/barrel/scene.js +6 -1
  17. package/dist/barrel/text.js +2 -2
  18. package/dist/canvas/NodeShape.js +1 -0
  19. package/dist/canvas/NodeShape.js.map +1 -1
  20. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +2 -0
  21. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
  22. package/dist/canvas/SceneCanvas/canvasPassThrough.js +1 -1
  23. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
  24. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +2 -2
  25. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  26. package/dist/canvas/SceneCanvas/scenePointQuery.js +20 -2
  27. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
  28. package/dist/canvas/SceneCanvas/useCanvasTools.js +3 -0
  29. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  30. package/dist/canvas/SceneCanvas/useContributionRoles.js +2 -0
  31. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
  32. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +25 -19
  33. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  34. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +7 -0
  35. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  36. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +1 -0
  37. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
  38. package/dist/canvas/SceneCanvas/useScenePicking.js +31 -6
  39. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
  40. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +4 -5
  41. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  42. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -3
  43. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
  44. package/dist/canvas/SceneCanvas.js +19 -2
  45. package/dist/canvas/SceneCanvas.js.map +1 -1
  46. package/dist/canvas/accentColor.js +26 -3
  47. package/dist/canvas/accentColor.js.map +1 -1
  48. package/dist/canvas/buildSceneLayer.js +1 -1
  49. package/dist/canvas/buildSceneLayer.js.map +1 -1
  50. package/dist/canvas/buildSceneTree.js +14 -20
  51. package/dist/canvas/buildSceneTree.js.map +1 -1
  52. package/dist/canvas/canvasRenderer.js +6 -2
  53. package/dist/canvas/canvasRenderer.js.map +1 -1
  54. package/dist/canvas/copiesAbove.js +1 -1
  55. package/dist/canvas/copiesAbove.js.map +1 -1
  56. package/dist/canvas/defaultDrawOne.js +10 -7
  57. package/dist/canvas/defaultDrawOne.js.map +1 -1
  58. package/dist/canvas/deps/areaSelect.js +5 -2
  59. package/dist/canvas/deps/areaSelect.js.map +1 -1
  60. package/dist/canvas/deps/booleans.js +1 -1
  61. package/dist/canvas/deps/booleans.js.map +1 -1
  62. package/dist/canvas/deps/enteredGroup.js +81 -0
  63. package/dist/canvas/deps/enteredGroup.js.map +1 -0
  64. package/dist/canvas/deps/hitTestArea.js +27 -15
  65. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  66. package/dist/canvas/deps/insert.js +4 -36
  67. package/dist/canvas/deps/insert.js.map +1 -1
  68. package/dist/canvas/deps/insertSite.js +39 -0
  69. package/dist/canvas/deps/insertSite.js.map +1 -0
  70. package/dist/canvas/deps/lassoSelect.js +6 -3
  71. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  72. package/dist/canvas/deps/pathLeaf.js +1 -1
  73. package/dist/canvas/deps/pathLeaf.js.map +1 -1
  74. package/dist/canvas/deps/slice.js +2 -1
  75. package/dist/canvas/deps/slice.js.map +1 -1
  76. package/dist/canvas/derivedPath.js +14 -6
  77. package/dist/canvas/derivedPath.js.map +1 -1
  78. package/dist/canvas/doubleClickTarget.js +9 -11
  79. package/dist/canvas/doubleClickTarget.js.map +1 -1
  80. package/dist/canvas/drawnBounds.js +16 -7
  81. package/dist/canvas/drawnBounds.js.map +1 -1
  82. package/dist/canvas/inheritedPaints.js +22 -11
  83. package/dist/canvas/inheritedPaints.js.map +1 -1
  84. package/dist/canvas/nodeShapes/nodePaint.js +1 -7
  85. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  86. package/dist/canvas/nodeShapes/pathPainter.js +2 -3
  87. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  88. package/dist/canvas/nodeShapes/rectFallbackPainter.js +1 -1
  89. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  90. package/dist/canvas/nodeShapes/shapePainter.js +2 -3
  91. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  92. package/dist/canvas/ownClip.js +24 -0
  93. package/dist/canvas/ownClip.js.map +1 -0
  94. package/dist/canvas/paintCull.js.map +1 -1
  95. package/dist/canvas/pickIndex/nodeBroadBox.js +86 -0
  96. package/dist/canvas/pickIndex/nodeBroadBox.js.map +1 -0
  97. package/dist/canvas/pickIndex/scenePickIndex.js +208 -0
  98. package/dist/canvas/pickIndex/scenePickIndex.js.map +1 -0
  99. package/dist/canvas/pickWalk.js +14 -90
  100. package/dist/canvas/pickWalk.js.map +1 -1
  101. package/dist/canvas/poseCascade.js +1 -1
  102. package/dist/canvas/poseCascade.js.map +1 -1
  103. package/dist/canvas/publishPreviews.js +97 -0
  104. package/dist/canvas/publishPreviews.js.map +1 -0
  105. package/dist/canvas/sceneAdapter.js +7 -5
  106. package/dist/canvas/sceneAdapter.js.map +1 -1
  107. package/dist/canvas/sceneClipboard.js +17 -10
  108. package/dist/canvas/sceneClipboard.js.map +1 -1
  109. package/dist/canvas/scenePickReads.js +37 -0
  110. package/dist/canvas/scenePickReads.js.map +1 -0
  111. package/dist/canvas/scenePickSource.js +74 -0
  112. package/dist/canvas/scenePickSource.js.map +1 -0
  113. package/dist/canvas/sceneSlotWiring.js +9 -4
  114. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  115. package/dist/canvas/sceneViewRender.js +13 -8
  116. package/dist/canvas/sceneViewRender.js.map +1 -1
  117. package/dist/canvas/shownNodes.js +15 -0
  118. package/dist/canvas/shownNodes.js.map +1 -0
  119. package/dist/canvas/useCanvasPaint.js +3 -1
  120. package/dist/canvas/useCanvasPaint.js.map +1 -1
  121. package/dist/canvas/useSceneAdapter.js +5 -3
  122. package/dist/canvas/useSceneAdapter.js.map +1 -1
  123. package/dist/clipboard.d.ts +2 -2
  124. package/dist/{clone-C3e0OTuF.d.ts → clone-qb2e1F5p.d.ts} +2 -2
  125. package/dist/clone.d.ts +3 -3
  126. package/dist/core/isPlainObject.js +2 -2
  127. package/dist/core/layers/layerGroup.js.map +1 -1
  128. package/dist/core/layers/render.js.map +1 -1
  129. package/dist/core/scene/NodeRouting.js.map +1 -1
  130. package/dist/core/scene/arrivalWindow.js +1 -1
  131. package/dist/core/scene/arrivalWindow.js.map +1 -1
  132. package/dist/core/scene/clipNothing.js +2 -5
  133. package/dist/core/scene/clipNothing.js.map +1 -1
  134. package/dist/core/scene/declaredFieldSetters.js +44 -0
  135. package/dist/core/scene/declaredFieldSetters.js.map +1 -0
  136. package/dist/core/scene/depMemo.js +3 -0
  137. package/dist/core/scene/depMemo.js.map +1 -1
  138. package/dist/core/scene/dependents.js +3 -1
  139. package/dist/core/scene/dependents.js.map +1 -1
  140. package/dist/core/scene/documentOf.js +43 -0
  141. package/dist/core/scene/documentOf.js.map +1 -0
  142. package/dist/core/scene/effectivePose.js +37 -13
  143. package/dist/core/scene/effectivePose.js.map +1 -1
  144. package/dist/core/scene/fieldEdits.js +17 -14
  145. package/dist/core/scene/fieldEdits.js.map +1 -1
  146. package/dist/core/scene/historyForm.js +4 -4
  147. package/dist/core/scene/historyForm.js.map +1 -1
  148. package/dist/core/scene/inheritedPaint.js +27 -5
  149. package/dist/core/scene/inheritedPaint.js.map +1 -1
  150. package/dist/core/scene/kitOps.js +3 -23
  151. package/dist/core/scene/kitOps.js.map +1 -1
  152. package/dist/core/scene/layoutPass.js +1 -2
  153. package/dist/core/scene/layoutPass.js.map +1 -1
  154. package/dist/core/scene/nodeAsShown.js +72 -0
  155. package/dist/core/scene/nodeAsShown.js.map +1 -0
  156. package/dist/core/scene/nodeFnFields.js +2 -10
  157. package/dist/core/scene/nodeFnFields.js.map +1 -1
  158. package/dist/core/scene/nodeMemo.js +6 -1
  159. package/dist/core/scene/nodeMemo.js.map +1 -1
  160. package/dist/core/scene/nodeStore.js +2 -4
  161. package/dist/core/scene/nodeStore.js.map +1 -1
  162. package/dist/core/scene/pathEffects/derive.js +3 -2
  163. package/dist/core/scene/pathEffects/derive.js.map +1 -1
  164. package/dist/core/scene/pathEffects/foundHidden.js +35 -0
  165. package/dist/core/scene/pathEffects/foundHidden.js.map +1 -0
  166. package/dist/core/scene/plyStacks.js +89 -0
  167. package/dist/core/scene/plyStacks.js.map +1 -0
  168. package/dist/core/scene/poseHold.js +42 -24
  169. package/dist/core/scene/poseHold.js.map +1 -1
  170. package/dist/core/scene/poseOverrides.js +35 -38
  171. package/dist/core/scene/poseOverrides.js.map +1 -1
  172. package/dist/core/scene/posePlies.js +59 -0
  173. package/dist/core/scene/posePlies.js.map +1 -0
  174. package/dist/core/scene/reconcileSpecs.js +6 -15
  175. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  176. package/dist/core/scene/renderOrder.js +10 -4
  177. package/dist/core/scene/renderOrder.js.map +1 -1
  178. package/dist/core/scene/sameValue.js +17 -0
  179. package/dist/core/scene/sameValue.js.map +1 -0
  180. package/dist/core/scene/scene.js +3 -3
  181. package/dist/core/scene/scene.js.map +1 -1
  182. package/dist/core/scene/sceneEdits.js +8 -0
  183. package/dist/core/scene/sceneEdits.js.map +1 -1
  184. package/dist/core/scene/sceneState.js +1 -2
  185. package/dist/core/scene/sceneState.js.map +1 -1
  186. package/dist/core/scene/serialization.js +45 -9
  187. package/dist/core/scene/serialization.js.map +1 -1
  188. package/dist/core/scene/staleReplay.js +5 -2
  189. package/dist/core/scene/staleReplay.js.map +1 -1
  190. package/dist/core/scene/statedFields.js +4 -2
  191. package/dist/core/scene/statedFields.js.map +1 -1
  192. package/dist/core/scene/treeEdits.js +2 -4
  193. package/dist/core/scene/treeEdits.js.map +1 -1
  194. package/dist/core/scene/treeOrder.js +3 -1
  195. package/dist/core/scene/treeOrder.js.map +1 -1
  196. package/dist/core/scene/treeReads.js +1 -2
  197. package/dist/core/scene/treeReads.js.map +1 -1
  198. package/dist/core/scene/treeShape.js +13 -0
  199. package/dist/core/scene/treeShape.js.map +1 -0
  200. package/dist/core/scene/types.js.map +1 -1
  201. package/dist/core/scene/useScene.js +1 -1
  202. package/dist/core/scene/useScene.js.map +1 -1
  203. package/dist/{cornerHandles-p8fDIAKt.d.ts → cornerHandles-CNCb7aTY.d.ts} +1 -1
  204. package/dist/{depSchema-mG19aEdD.d.ts → depSchema-CpIQzKWQ.d.ts} +38 -59
  205. package/dist/devtools/handlers.js +1 -1
  206. package/dist/devtools/handlers.js.map +1 -1
  207. package/dist/devtools/protocol.js.map +1 -1
  208. package/dist/devtools-protocol.d.ts +4 -3
  209. package/dist/devtools.d.ts +3 -2
  210. package/dist/features/measure/measureHit.js +5 -3
  211. package/dist/features/measure/measureHit.js.map +1 -1
  212. package/dist/features/measure/measurement.js +1 -1
  213. package/dist/features/measure/measurement.js.map +1 -1
  214. package/dist/features/modes/modeLayers.js +14 -7
  215. package/dist/features/modes/modeLayers.js.map +1 -1
  216. package/dist/features/modes/modeTriggers.js +3 -3
  217. package/dist/features/modes/modeTriggers.js.map +1 -1
  218. package/dist/features/pathEffects/effectSources.js +25 -16
  219. package/dist/features/pathEffects/effectSources.js.map +1 -1
  220. package/dist/features/pathEffects/readSource.js +1 -1
  221. package/dist/features/pathEffects/readSource.js.map +1 -1
  222. package/dist/features/pathEffects/useEffectSourcesLayer.js +15 -19
  223. package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -1
  224. package/dist/features/paths/editablePath.js +1 -1
  225. package/dist/features/paths/editablePath.js.map +1 -1
  226. package/dist/features/paths/pathSnap/sceneIndex.js +1 -1
  227. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
  228. package/dist/features/selection/enteredGroupFrame.js +65 -0
  229. package/dist/features/selection/enteredGroupFrame.js.map +1 -0
  230. package/dist/features/selection/enteredGroupScope.js +44 -0
  231. package/dist/features/selection/enteredGroupScope.js.map +1 -0
  232. package/dist/features/text/sceneTextDrafts.js +26 -27
  233. package/dist/features/text/sceneTextDrafts.js.map +1 -1
  234. package/dist/features/text/textHitAt.js +4 -2
  235. package/dist/features/text/textHitAt.js.map +1 -1
  236. package/dist/features/text/useSceneTextEdit.js +3 -3
  237. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  238. package/dist/features/viewports/viewportLayer.js +2 -1
  239. package/dist/features/viewports/viewportLayer.js.map +1 -1
  240. package/dist/index.d.ts +230 -77
  241. package/dist/index.js +16 -6
  242. package/dist/interactions/actions/admitsChild.js +11 -0
  243. package/dist/interactions/actions/admitsChild.js.map +1 -0
  244. package/dist/interactions/actions/defaults/contextMenu.js +16 -3
  245. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
  246. package/dist/interactions/actions/defaults/createPaintAction.js +4 -1
  247. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  248. package/dist/interactions/actions/defaults/enterGroup.js +88 -0
  249. package/dist/interactions/actions/defaults/enterGroup.js.map +1 -0
  250. package/dist/interactions/actions/defaults/enterPathEdit.js +1 -1
  251. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  252. package/dist/interactions/actions/defaults/enterTextEdit.js +1 -1
  253. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  254. package/dist/interactions/actions/defaults/group.js +7 -7
  255. package/dist/interactions/actions/defaults/group.js.map +1 -1
  256. package/dist/interactions/actions/defaults/selectAll.js +7 -3
  257. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  258. package/dist/interactions/actions/defaults/selectDeep.js +35 -0
  259. package/dist/interactions/actions/defaults/selectDeep.js.map +1 -0
  260. package/dist/interactions/actions/drawnBoxes.js +2 -1
  261. package/dist/interactions/actions/drawnBoxes.js.map +1 -1
  262. package/dist/interactions/actions/insert/action.js +1 -0
  263. package/dist/interactions/actions/insert/action.js.map +1 -1
  264. package/dist/interactions/actions/insert/parent.js +7 -5
  265. package/dist/interactions/actions/insert/parent.js.map +1 -1
  266. package/dist/interactions/actions/insert/placeAction.js +3 -2
  267. package/dist/interactions/actions/insert/placeAction.js.map +1 -1
  268. package/dist/interactions/actions/insert/session.js +2 -2
  269. package/dist/interactions/actions/insert/session.js.map +1 -1
  270. package/dist/interactions/actions/move/commit/reparent.js +1 -1
  271. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  272. package/dist/interactions/actions/move/gestureAdapter.js +6 -7
  273. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  274. package/dist/interactions/actions/move/layout/exits.js +1 -1
  275. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  276. package/dist/interactions/actions/move/session.js +4 -4
  277. package/dist/interactions/actions/move/session.js.map +1 -1
  278. package/dist/interactions/actions/pathCommands/pathNodes.js +14 -5
  279. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -1
  280. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +14 -2
  281. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  282. package/dist/{math-B56zxVs5.d.ts → math-C_elShP_.d.ts} +2 -5
  283. package/dist/math.d.ts +1 -1
  284. package/dist/move.d.ts +4 -4
  285. package/dist/{options-DBxEryYq.d.ts → options-ClEm3SEl.d.ts} +1 -1
  286. package/dist/resize.d.ts +4 -4
  287. package/dist/test-seams.d.ts +6 -6
  288. package/dist/tools/builtin/pressTarget.js +22 -0
  289. package/dist/tools/builtin/pressTarget.js.map +1 -0
  290. package/dist/tools/builtin/select/adapterPointQuery.js +3 -3
  291. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  292. package/dist/tools/builtin/select/collapseDeferred.js +40 -0
  293. package/dist/tools/builtin/select/collapseDeferred.js.map +1 -0
  294. package/dist/tools/builtin/select/groupEntry.js +82 -0
  295. package/dist/tools/builtin/select/groupEntry.js.map +1 -0
  296. package/dist/tools/builtin/select/pressDecision.js +1 -1
  297. package/dist/tools/builtin/select/pressDecision.js.map +1 -1
  298. package/dist/tools/builtin/select/useSelectTool.js +61 -45
  299. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  300. package/dist/{types-7puAuVD2.d.ts → types-49uYJN3j.d.ts} +1 -1
  301. package/dist/{types-CniVctmk.d.ts → types-BEdRIhNc.d.ts} +272 -109
  302. package/dist/{types-oFeQ5VjV.d.ts → types-p2alu-R1.d.ts} +1 -1
  303. package/dist/version.js +1 -1
  304. package/package.json +25 -25
@@ -1,9 +1,10 @@
1
1
  import * as _weasel_js_history from '@weasel-js/history';
2
2
  import { Op, SerializedHistory, History } from '@weasel-js/history';
3
- import { P as ParallaxOpts, C as ContainerBounds, L as LayoutStrategy } from './types-7puAuVD2.js';
3
+ import { P as ParallaxOpts, C as ContainerBounds, L as LayoutStrategy } from './types-49uYJN3j.js';
4
4
  import { UnitScope } from '@weasel-js/quantity';
5
5
  import { NodeId } from '@weasel-js/routing';
6
6
  import { Path, PoseLinear, Affine } from '@weasel-js/geom';
7
+ import { PaintedFill, PaintedStroke, Inherit } from '@weasel-js/paint';
7
8
 
8
9
  /**
9
10
  * Scene edit passes: functions that hear what a live edit did, once its own
@@ -60,10 +61,10 @@ interface SceneBatchOptions {
60
61
  }
61
62
 
62
63
  /** The form a scene's undo entries are recorded in. A serialized history
63
- * carries it, and one carrying another is not restored. Form 2 holds the
64
- * scene's own ops for every edit; before it, an `applyBatch` entry held the
65
- * ops it was given. */
66
- declare const SCENE_HISTORY_FORM = 2;
64
+ * carries it, and one carrying another is not restored. Form 3 names
65
+ * nodes `mark` and `group`; form 2 held the scene's own ops for every edit,
66
+ * and before it an `applyBatch` entry held the ops it was given. */
67
+ declare const SCENE_HISTORY_FORM = 3;
67
68
  /** What `Scene.serializeHistory` answers with. */
68
69
  interface SerializedSceneHistory extends SerializedHistory {
69
70
  form: typeof SCENE_HISTORY_FORM;
@@ -253,11 +254,11 @@ interface ScenePoseReports<TPose, TNode = unknown> {
253
254
  * about a node without saying it about the document.
254
255
  *
255
256
  * Not document content: never recorded in history, never in `toJSON`, and
256
- * writing one does not bump `Scene.getVersion()`. Hoist one entry per node and
257
+ * writing one does not bump `Scene.getVersion()`. A writer hoists one entry per node and
257
258
  * mutate it in place on a frame loop; `PoseOverrides.commit()` is what makes a
258
259
  * mutation visible.
259
260
  */
260
- interface PoseOverride<TPose> {
261
+ interface PoseOverride<TPose, TData = unknown> {
261
262
  /** Replaces the node's document pose everywhere the render and hit-test
262
263
  * paths read one, including the clip a container derives from its pose, and
263
264
  * winning over a `derivePose`. Resolved by `effectivePose` — reading
@@ -269,9 +270,19 @@ interface PoseOverride<TPose> {
269
270
  /** Replaces the geometry the node paints and is picked by: the path in its data, or the one
270
271
  * it derives. It is in the frame a painter draws in, so give `pose` beside it, as the
271
272
  * path's bounds with no rotation, or the pose's turn is applied to the path again and the
272
- * selection chrome stays on the old box. A skinned rig is the writer. */
273
+ * selection chrome stays on the old box. A pose laid over it by another writer carries the
274
+ * path from that box to its own; a path given with no pose is drawn where it is. A skinned
275
+ * rig is the writer. */
273
276
  path?: Path;
277
+ /** The data the node is shown with, from the data it stores — so a recorded write made while it is
278
+ * installed shows through. Painting, picking, drawn bounds and the effective reading of every
279
+ * derivation read it through `nodeAsShown`; the document never sees it. Replace the function to
280
+ * change what it answers: the shown data is kept per stored data and function. A text edit's
281
+ * drafts and a gesture's `previewData` are the writers. */
282
+ data?(stored: TData): TData;
274
283
  }
284
+ /** What a writer publishing whole frames says about one node: see {@link PoseHold.show}. */
285
+ type ShownOverride<TPose, TData = unknown> = Pick<PoseOverride<TPose, TData>, 'pose' | 'data'>;
275
286
  /**
276
287
  * The scene's ephemeral per-node overrides — see {@link PoseOverride}.
277
288
  *
@@ -280,23 +291,44 @@ interface PoseOverride<TPose> {
280
291
  * the painter memo keys on pose *reference*, so a mutation without a commit
281
292
  * paints the previous frame with no error.
282
293
  *
294
+ * Several writers can override one node: each entry `set` is a ply over the
295
+ * ones set before it. A field shows what the topmost ply giving it says —
296
+ * `alpha` multiplies through every ply instead, and `data` runs each ply's
297
+ * function on what the plies under it show — and releasing a ply shows what
298
+ * lies under it. A ply's `path` is drawn in the box of the `pose` it gives
299
+ * beside it, so a pose from a ply above carries the path along.
300
+ *
301
+ * A full `clear(id)` keeps each ply's place: a writer that sets its entry again
302
+ * goes back where it stood, whatever order the writers come back in. A writer
303
+ * checks `has(id, entry)` each frame and sets its entry again when it is gone.
304
+ * A hand-written table honors `entry` on `has` and `clear` too: a writer
305
+ * releasing its own ply must not clear another's.
306
+ *
283
307
  * To promote a frame to document state (dropping a drag, baking an animation),
284
308
  * write it once through `Scene.setPose` and `clear` the override.
285
309
  */
286
- interface PoseOverrides<TPose> {
287
- /** Store `entry` for `id` **by reference**; the caller keeps mutating it. */
288
- set(id: NodeId, entry: PoseOverride<TPose>): void;
289
- /** The entry `set` stored, by reference — what a writer checks to know
290
- * whether its own entry is still installed. Painting reads `read`. */
291
- get(id: NodeId): PoseOverride<TPose> | undefined;
292
- /** What the node is drawn and picked with: every source of overrides for
293
- * it folded into one, as of the last write or `commit()`. `undefined` for
294
- * a node nothing overrides. The object is reused per node. */
295
- read(id: NodeId): PoseOverride<TPose> | undefined;
296
- has(id: NodeId): boolean;
310
+ interface PoseOverrides<TPose, TData = unknown> {
311
+ /** Store `entry` for `id` **by reference**, as the node's top ply, or where it
312
+ * stood when a full `clear` took it off; the caller keeps mutating it. An
313
+ * entry already installed moves to the top. */
314
+ set(id: NodeId, entry: PoseOverride<TPose, TData>): void;
315
+ /** The node's top ply, by reference. Painting reads `read`. */
316
+ get(id: NodeId): PoseOverride<TPose, TData> | undefined;
317
+ /** What the node is drawn and picked with: every ply for it folded into
318
+ * one, as of the last write or `commit()`. `undefined` for a node nothing
319
+ * overrides. The object is reused per node. */
320
+ read(id: NodeId): PoseOverride<TPose, TData> | undefined;
321
+ /** Whether anything overrides the node; given `entry`, whether that entry is
322
+ * one of its plies — what a writer checks to know whether its own is
323
+ * still installed. */
324
+ has(id: NodeId, entry?: PoseOverride<TPose, TData>): boolean;
297
325
  /** The overridden ids, as a snapshot array. */
298
326
  ids(): readonly NodeId[];
299
- clear(id: NodeId): void;
327
+ /** Drop every ply of the node, each keeping its place for its writer's next
328
+ * `set`; given `entry`, only that one, forgetting its place, and nothing
329
+ * else when it is not installed. */
330
+ clear(id: NodeId, entry?: PoseOverride<TPose, TData>): void;
331
+ /** {@link PoseOverrides.clear} of every node. */
300
332
  clearAll(): void;
301
333
  /** Publish this frame's in-place mutations: invalidate the painter memo for
302
334
  * every overridden node, then notify subscribers. */
@@ -308,7 +340,7 @@ interface PoseOverrides<TPose> {
308
340
  getGeneration(): number;
309
341
  /** A claim on some nodes' poses for a writer that publishes a whole frame
310
342
  * at a time: a gesture's preview, a layout run. Each call is a new claim. */
311
- hold(): PoseHold<TPose>;
343
+ hold(): PoseHold<TPose, TData>;
312
344
  }
313
345
  /**
314
346
  * One writer's claim on some nodes' pose overrides, from
@@ -316,18 +348,24 @@ interface PoseOverrides<TPose> {
316
348
  *
317
349
  * A hold knows which entries are its own, so several writers share the table
318
350
  * without clearing each other: a drag and a layout run each publish their
319
- * frame, and each sees the other's nodes as pinned.
351
+ * frame, and each sees the other's nodes as pinned. Each id it holds is one
352
+ * ply of that node's overrides, installed with the hold's first frame
353
+ * naming it.
320
354
  */
321
- interface PoseHold<TPose> {
322
- /** Publish this frame's poses. It is the whole picture, not a delta: an id
323
- * the frame leaves out is released. Subscribers are notified once. */
355
+ interface PoseHold<TPose, TData = unknown> {
356
+ /** Publish this frame's poses. It is the whole picture of this hold's
357
+ * fields, not a delta: an id the frame leaves out is released, and a field
358
+ * it leaves out shows what the plies under it say. Subscribers are
359
+ * notified once. */
324
360
  set(poses: Iterable<readonly [NodeId, TPose]>): void;
325
- /** The poses other writers are publishing, by id. */
361
+ /** {@link PoseHold.set} for a frame that shows data as well as poses. */
362
+ show(frame: Iterable<readonly [NodeId, ShownOverride<TPose, TData>]>): void;
363
+ /** The poses other writers are publishing, by id: each node's topmost pose
364
+ * that is not this hold's. */
326
365
  others(): ReadonlyMap<NodeId, TPose>;
327
- /** Release every id still held. An id whose entry another writer has since
328
- * replaced is left alone: that writer owns it now. When the frame is being
329
- * committed to the document, call this after the write lands, or the scene
330
- * answers with the old pose in between. */
366
+ /** Release every id still held, revealing whatever other writers lay under
367
+ * it. When the frame is being committed to the document, call this after
368
+ * the write lands, or the scene answers with the old pose in between. */
331
369
  drop(): void;
332
370
  }
333
371
 
@@ -356,7 +394,7 @@ interface SerializedLayer<TLayer extends string> extends SystemLayerSpec<TLayer>
356
394
  * (e.g., `clipFromPose`) appear as string keys (`clipFromPoseKey`) and
357
395
  * are resolved through `SceneRegistry` at load time. */
358
396
  interface SerializedScene<TData, TLayer extends string, TPose> {
359
- version: 1;
397
+ version: 2;
360
398
  /** The whole layer stack, system and user alike — the name predates user
361
399
  * layers and is kept so existing snapshots still parse. */
362
400
  systemLayers: readonly SerializedLayer<TLayer>[];
@@ -368,7 +406,7 @@ interface SerializedScene<TData, TLayer extends string, TPose> {
368
406
  * with function fields replaced by registry keys. */
369
407
  interface SerializedNode<TData, TLayer extends string, TPose> {
370
408
  id: string;
371
- kind: 'leaf' | 'container';
409
+ kind: 'mark' | 'group';
372
410
  layer: TLayer;
373
411
  pose: TPose;
374
412
  data: TData;
@@ -395,8 +433,19 @@ interface SerializedNode<TData, TLayer extends string, TPose> {
395
433
  derivePoseKey?: string;
396
434
  /** Registry key for the container's layout strategy. Omitted when it has none. */
397
435
  layoutKey?: string;
398
- /** Mirrors `ContainerNode.units`. Omitted when the container declares none. */
436
+ /** Mirrors `SceneNode.units`. Omitted when the node declares none. */
399
437
  units?: UnitScope;
438
+ /** Mirrors `SceneNode.clip`. Omitted when the node declares none. */
439
+ clip?: NodeClip;
440
+ }
441
+ /** A node as version 1 saves wrote it: the kinds were `leaf` and `container`. */
442
+ interface SerializedNodeV1<TData, TLayer extends string, TPose> extends Omit<SerializedNode<TData, TLayer, TPose>, 'kind'> {
443
+ kind: 'leaf' | 'container';
444
+ }
445
+ /** A version 1 save, still read and never written. */
446
+ interface SerializedSceneV1<TData, TLayer extends string, TPose> extends Omit<SerializedScene<TData, TLayer, TPose>, 'version' | 'nodes'> {
447
+ version: 1;
448
+ nodes: readonly SerializedNodeV1<TData, TLayer, TPose>[];
400
449
  }
401
450
 
402
451
  /**
@@ -418,6 +467,91 @@ interface SceneDocValues {
418
467
  /** A snapshot's document values. */
419
468
  type SerializedDoc = Readonly<Record<string, unknown>>;
420
469
 
470
+ /**
471
+ * What a node declares for its children — the unit scope they are shown in and
472
+ * the clip they are drawn in: the kit ops that write each, and the scene
473
+ * methods that record them.
474
+ */
475
+
476
+ /** The scene methods that write a node's declared `units` and `clip`, each one undo step. */
477
+ interface SceneDeclaredFieldSetters {
478
+ /** Declare the unit scope of container `id`, or clear it with `null`. */
479
+ setUnits(id: NodeId, units: UnitScope | null): void;
480
+ /** Declare the clip `id` draws its children in (see `SceneNode.clip`), or clear it with `null`. */
481
+ setClip(id: NodeId, clip: NodeClip | null): void;
482
+ }
483
+
484
+ /**
485
+ * Decides what one edit's changes to containers do to their children.
486
+ * `arrivals` maps each container to the ids that joined it — by an `add`
487
+ * under it or a `move` into it, whatever op or call made them — in the order
488
+ * they arrived. `changed` names every container whose child set or order
489
+ * changed, whose pose changed size, or one of whose children was posed,
490
+ * arrivals included. Both are read once the edit's other mutations have landed.
491
+ *
492
+ * Return the poses to write, in each node's stored frame; they become part of
493
+ * the same edit, and so of the same undo step. An empty map writes nothing.
494
+ * Return `null` to refuse: the whole edit is reverted (see
495
+ * `SceneArrivalRefused`).
496
+ *
497
+ * Runs only for live edits. Undo, redo and a restored history replay the
498
+ * arrangement that was decided the first time. With none installed, a scene
499
+ * holding declared layouts (`GroupNode.layout`) runs its own.
500
+ */
501
+ type SceneArrivalHandler<TPose> = (arrivals: ReadonlyMap<NodeId, readonly NodeId[]>, changed: ReadonlySet<NodeId>,
502
+ /** The nodes that left each container in the edit, by the container they
503
+ * left — removed, or moved out. */
504
+ departures: ReadonlyMap<NodeId, readonly NodeId[]>) => ReadonlyMap<NodeId, TPose> | null;
505
+
506
+ /** A custom scene mutation registered with `Scene.registerOp`: how to apply
507
+ * it and how to undo it. The pair is what makes it participate in history. */
508
+ interface RegisteredOp<P> {
509
+ apply: (payload: P) => void;
510
+ revert: (payload: P) => void;
511
+ /** Opts this kind into coalescing under `UseSceneOptions.coalesceWindowMs`:
512
+ * two entries of this kind that return the same key inside the window
513
+ * merge, and undoing the merged entry calls `revert` with the first
514
+ * payload only. Declare it only when `revert` restores an absolute state
515
+ * (a stored "from" value), never for a relative payload such as a delta.
516
+ * Omitted, or returning `undefined`, the op is always its own entry. */
517
+ coalesceKey?: (payload: P) => string | undefined;
518
+ }
519
+
520
+ /**
521
+ * A scene to and from its JSON snapshot: the walk that writes one, and the
522
+ * two readers that turn one back into layer records and node specs.
523
+ */
524
+
525
+ /** Decides what a version 1 `container` becomes; `leaf` is always a mark. */
526
+ type V1Classifier<TData, TLayer extends string, TPose> = (node: SerializedNodeV1<TData, TLayer, TPose>) => 'mark' | 'group';
527
+ /** Options for {@link specsFromSerialized}. */
528
+ interface SpecsFromSerializedOptions<TData, TLayer extends string, TPose> {
529
+ /** What a version 1 `container` loads as; see {@link V1Classifier}. */
530
+ classifyV1?: V1Classifier<TData, TLayer, TPose>;
531
+ /** `'skip'` loads a node whose registry key is unknown without that
532
+ * function, for a save that outlived the code that registered it.
533
+ * Default `'throw'`. */
534
+ unknownKeys?: 'throw' | 'skip';
535
+ /** Hears each key `unknownKeys: 'skip'` leaves out, as it is left out. */
536
+ onSkip?: (skipped: SkippedKey) => void;
537
+ }
538
+ /** A registry key a load left out: the node, the function field it named,
539
+ * and the key. */
540
+ interface SkippedKey {
541
+ id: NodeId;
542
+ field: keyof SceneRegistry<unknown>;
543
+ key: string;
544
+ }
545
+ /** Map a `SerializedScene` to construction specs. Shared by `sceneFromJSON`
546
+ * (new instance) and `Scene.loadState` (in-place). Validates version and
547
+ * resolves every `NODE_FN_FIELDS` key → function via the registry;
548
+ * throws on an unsupported version, and on an unknown registry key unless
549
+ * `opts.unknownKeys` is `'skip'`. */
550
+ declare function specsFromSerialized<TData, TLayer extends string, TPose>(json: SerializedScene<TData, TLayer, TPose> | SerializedSceneV1<TData, TLayer, TPose>, registry: SceneRegistry<TPose, TData, TLayer>, opts?: SpecsFromSerializedOptions<TData, TLayer, TPose>): AddNodeSpec<TData, TLayer, TPose>[];
551
+ /** The kind a saved node loads as: its own on version 2; on version 1 a `leaf` is a
552
+ * mark and a `container` goes to `classify`, or is a group without one. */
553
+ declare function nodeKindOf<TData, TLayer extends string, TPose>(version: 1 | 2, n: SerializedNode<TData, TLayer, TPose> | SerializedNodeV1<TData, TLayer, TPose>, classify?: V1Classifier<TData, TLayer, TPose>): 'mark' | 'group';
554
+
421
555
  /**
422
556
  * Axis-aligned rectangle pose with optional rotation. Rotation is in
423
557
  * radians, pivoted on the unrotated AABB center; absent === 0.
@@ -434,6 +568,61 @@ interface RectPose {
434
568
  transform?: PoseLinear;
435
569
  }
436
570
 
571
+ /**
572
+ * What a node's `'inherit'` fill and stroke resolve to: its nearest enclosing
573
+ * container's, `null` for none. A field the node does not inherit is `null`
574
+ * here whatever its containers hold.
575
+ */
576
+ interface InheritedPaint {
577
+ readonly fill: PaintedFill | null;
578
+ readonly stroke: PaintedStroke | null;
579
+ }
580
+ /** Whether `node`'s fill or stroke is {@link INHERIT}, so painting it needs
581
+ * its containers' paint. */
582
+ declare function inheritsPaint(node: {
583
+ data?: unknown;
584
+ }): boolean;
585
+ /**
586
+ * {@link InheritedPaint} for `node`, given its ancestors innermost first. Any
587
+ * ancestor is a source, mark or group; one whose own field is `'inherit'`
588
+ * passes the question on to the next, and running out of ancestors is none.
589
+ *
590
+ * Hands back the object it returned last time for `node` while both values
591
+ * are the same references, so a memo can key on it.
592
+ */
593
+ declare function inheritedPaintOf(node: {
594
+ data?: unknown;
595
+ }, ancestors: Iterable<{
596
+ kind?: string;
597
+ data?: unknown;
598
+ }>): InheritedPaint;
599
+ /** What `node`'s `'inherit'` fields take from its containers in `scene`, or
600
+ * `undefined` for a node that inherits nothing. */
601
+ declare function inheritedPaintIn<TNode extends {
602
+ data?: unknown;
603
+ parent?: string | null;
604
+ }>(scene: {
605
+ get(id: never): TNode | undefined;
606
+ }, node: TNode): InheritedPaint | undefined;
607
+ /** The fields {@link withInheritedPaint} resolves. */
608
+ type ResolvedPaintFields<T> = Omit<T, 'fill' | 'stroke'> & {
609
+ fill?: Exclude<T extends {
610
+ fill?: infer F;
611
+ } ? F : never, Inherit>;
612
+ stroke?: Exclude<T extends {
613
+ stroke?: infer S;
614
+ } ? S : never, Inherit>;
615
+ };
616
+ /**
617
+ * `data` with an `'inherit'` fill or stroke replaced by what `inherited` says
618
+ * it resolves to, for a reader that wants the paint a node shows rather than
619
+ * the one it declares. Hands `data` back as is when nothing inherits.
620
+ */
621
+ declare function withInheritedPaint<T extends {
622
+ fill?: unknown;
623
+ stroke?: unknown;
624
+ }>(data: T, inherited: InheritedPaint | undefined): ResolvedPaintFields<T>;
625
+
437
626
  /**
438
627
  * One dependency, as a derivation reads it: the node itself and the pose it is
439
628
  * painted at.
@@ -453,6 +642,10 @@ interface DerivedDep<TPose, TData = unknown, TLayer extends string = string> {
453
642
  * it to place something *along* a dependency: a label on a routed edge.
454
643
  * Resolved on first read and memoized on the dependency. */
455
644
  readonly path: Path | null;
645
+ /** What its `'inherit'` fill and stroke take from its containers, or
646
+ * `undefined` when it inherits nothing. A dependency built by hand rather
647
+ * than by the scene may leave it out, and then inherits nothing. */
648
+ readonly inherited?: InheritedPaint;
456
649
  }
457
650
  /** `F` with its parameters checked bivariantly, as a method's are, so that a
458
651
  * `Scene<D, L, MyPose>` is a `Scene<unknown, string, unknown>`. A callback for
@@ -466,18 +659,20 @@ type DerivePathFn<TPose, TData = unknown, TLayer extends string = string> = Biva
466
659
  /** Computes a node's pose from its dependencies: the type of a node's
467
660
  * `derivePose` and of each entry in `SceneRegistry.derivePose`. */
468
661
  type DerivePoseFn<TPose, TData = unknown, TLayer extends string = string> = Bivariant<(node: Node<TData, TLayer, TPose>, deps: readonly (DerivedDep<TPose, TData, TLayer> | undefined)[]) => TPose | null>;
469
- /** A container's clip, from its pose: the type of `ContainerNode.clipFromPose`
662
+ /** A container's clip, from its pose: the type of `clipFromPose`
470
663
  * and of each entry in `SceneRegistry.clipFromPose`. */
471
664
  type ClipFromPoseFn<TPose> = Bivariant<(pose: TPose) => Path | null>;
472
665
  /** The extra times a container draws its children: the type of
473
- * `ContainerNode.copiesFromPose` and of each entry in
666
+ * `copiesFromPose` and of each entry in
474
667
  * `SceneRegistry.copiesFromPose`. Each affine is in world coordinates and
475
668
  * carries the children, as drawn, to one copy. */
476
- type CopiesFromPoseFn<TPose, TData = unknown, TLayer extends string = string> = Bivariant<(pose: TPose, node: ContainerNode<TData, TLayer, TPose>) => readonly Affine[] | null>;
669
+ type CopiesFromPoseFn<TPose, TData = unknown, TLayer extends string = string> = Bivariant<(pose: TPose, node: Node<TData, TLayer, TPose>) => readonly Affine[] | null>;
477
670
 
478
671
  /** Brand a string as a NodeId. */
479
672
  declare const asNodeId: (s: string) => NodeId;
480
673
 
674
+ /** A clip a node declares by name rather than by function: see `SceneNode.clip`. */
675
+ type NodeClip = 'outline';
481
676
  interface NodeBase<TData, TLayer extends string, TPose> {
482
677
  id: NodeId;
483
678
  layer: TLayer;
@@ -533,21 +728,16 @@ interface NodeBase<TData, TLayer extends string, TPose> {
533
728
  * the node falls back to its authored `pose`. `setPose` on a derived node
534
729
  * still writes that authored pose; it is simply not what anything reads. */
535
730
  derivePose?: DerivePoseFn<TPose, TData, TLayer>;
536
- }
537
- /** A node with no children — a shape, a label, an image. */
538
- interface LeafNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
539
- kind: 'leaf';
540
- }
541
- /** A node with an ordered list of children. This is the real group: what
542
- * Cmd+G creates, what SVG `<g>` round-trips to. A container has its own pose,
543
- * which its children's poses are relative to, and may optionally clip them. */
544
- interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
545
- kind: 'container';
546
- children: NodeId[];
731
+ /** Ordered child ids. Absent until the node gets its first child. */
732
+ children?: NodeId[];
547
733
  /** Optional clip-path source. Re-evaluated each render. Returning `null`
548
- * means "no clip for this container right now"; an empty / zero-area path
549
- * means "clip everything out" (children render nowhere). */
734
+ * means "no clip for this node right now"; an empty / zero-area path
735
+ * means "clip everything out" (children render nowhere). Wins over `clip`. */
550
736
  clipFromPose?: ClipFromPoseFn<TPose>;
737
+ /** `'outline'` clips the children to this node's own outline: a mark's
738
+ * painter silhouette, or for a group the silhouette of its `data.path`.
739
+ * Absent, and with no `clipFromPose`, the children are not clipped. */
740
+ clip?: NodeClip;
551
741
  /** Draws the whole subtree again under each affine it returns, on top of
552
742
  * the original, which still draws once as authored. The copies are paint,
553
743
  * not nodes: nothing stores them, so they follow every edit to the
@@ -555,7 +745,7 @@ interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends
555
745
  * A copy is a copy of the clipped content — the clip travels with it.
556
746
  * Re-evaluated each render; `null` or `[]` draws no copies. */
557
747
  copiesFromPose?: CopiesFromPoseFn<TPose, TData, TLayer>;
558
- /** How this container arranges its children. Whenever the container's
748
+ /** How this node arranges its children. Whenever the node's
559
749
  * child set or order changes, its bounds change size, or a child's pose is
560
750
  * written, the scene hands the change to the strategy — `depart` for children that left it,
561
751
  * `arrive` for children that joined it, `childPoses` otherwise — and records the poses it writes in the same
@@ -564,16 +754,26 @@ interface ContainerNode<TData, TLayer extends string, TPose = RectPose> extends
564
754
  layout?: LayoutStrategy<TPose>;
565
755
  /** The units its children are shown, typed and snapped in (their poses stay
566
756
  * in world units), and what one base unit is worth in the enclosing scope's.
567
- * It covers the children, not the container; `sceneUnitScopes` reads the chain. */
757
+ * It covers the children, not the node; `sceneUnitScopes` reads the chain. */
568
758
  units?: UnitScope;
569
759
  }
570
- /** A node in the scene tree: either a leaf or a container. Re-exported
760
+ /** A node that is drawn and picked as one thing — a shape, a label, an image.
761
+ * It may still hold children, which are what it is made of. */
762
+ interface MarkNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
763
+ kind: 'mark';
764
+ }
765
+ /** A node the user gathers things into: what Cmd+G creates, what SVG `<g>`
766
+ * round-trips to. An emptied group is still a group. */
767
+ interface GroupNode<TData, TLayer extends string, TPose = RectPose> extends NodeBase<TData, TLayer, TPose> {
768
+ kind: 'group';
769
+ }
770
+ /** A node in the scene tree: either a mark or a group. Re-exported
571
771
  * publicly as `SceneNode`, to avoid colliding with the DOM's `Node`. */
572
- type Node<TData, TLayer extends string, TPose = RectPose> = LeafNode<TData, TLayer, TPose> | ContainerNode<TData, TLayer, TPose>;
772
+ type Node<TData, TLayer extends string, TPose = RectPose> = MarkNode<TData, TLayer, TPose> | GroupNode<TData, TLayer, TPose>;
573
773
  /** What `Scene.add` needs to mint a node. Everything except the id is
574
774
  * required; the id is generated unless one is supplied. */
575
775
  interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
576
- kind: 'leaf' | 'container';
776
+ kind: 'mark' | 'group';
577
777
  layer: TLayer;
578
778
  pose: TPose;
579
779
  data: TData;
@@ -587,10 +787,11 @@ interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
587
787
  hidden?: boolean;
588
788
  /** Mirrors `SceneNode.locked`. */
589
789
  locked?: boolean;
590
- /** Only meaningful when `kind === 'container'`. Attach a clip-path function
591
- * to the node; ignored for leaves. Mirrors `ContainerNode.clipFromPose`. */
790
+ /** Attach a clip-path function to the node; mirrors `SceneNode.clipFromPose`. */
592
791
  clipFromPose?: ClipFromPoseFn<TPose>;
593
- /** Mirrors `ContainerNode.copiesFromPose`; ignored for leaves. */
792
+ /** Mirrors `SceneNode.clip`. */
793
+ clip?: NodeClip;
794
+ /** Mirrors `SceneNode.copiesFromPose`. */
594
795
  copiesFromPose?: CopiesFromPoseFn<TPose, TData, TLayer>;
595
796
  /** Mirrors `SceneNode.dependsOn`. */
596
797
  dependsOn?: readonly NodeId[] | 'children';
@@ -599,60 +800,26 @@ interface AddNodeSpec<TData, TLayer extends string, TPose = RectPose> {
599
800
  derivePath?: DerivePathFn<TPose, TData, TLayer>;
600
801
  /** Mirrors `SceneNode.derivePose`, on the same terms as `derivePath`. */
601
802
  derivePose?: DerivePoseFn<TPose, TData, TLayer>;
602
- /** Mirrors `ContainerNode.layout`; ignored for leaves. */
803
+ /** Mirrors `SceneNode.layout`. */
603
804
  layout?: LayoutStrategy<TPose>;
604
- /** Mirrors `ContainerNode.units`; ignored for leaves. */
805
+ /** Mirrors `SceneNode.units`. */
605
806
  units?: UnitScope;
606
807
  }
607
- /** A custom scene mutation registered with `Scene.registerOp`: how to apply
608
- * it and how to undo it. The pair is what makes it participate in history. */
609
- interface RegisteredOp<P> {
610
- apply: (payload: P) => void;
611
- revert: (payload: P) => void;
612
- /** Opts this kind into coalescing under `UseSceneOptions.coalesceWindowMs`:
613
- * two entries of this kind that return the same key inside the window
614
- * merge, and undoing the merged entry calls `revert` with the first
615
- * payload only. Declare it only when `revert` restores an absolute state
616
- * (a stored "from" value), never for a relative payload such as a delta.
617
- * Omitted, or returning `undefined`, the op is always its own entry. */
618
- coalesceKey?: (payload: P) => string | undefined;
619
- }
620
808
  /** Per-scene registry mapping string keys to live function references.
621
809
  * Passed to `createScene({ ..., registry })` and `sceneFromJSON(json, { registry })`.
622
810
  * Each function-field type has its own keyed map. */
623
811
  interface SceneRegistry<TPose, TData = unknown, TLayer extends string = string> {
624
- /** Maps registry keys to `clipFromPose` factory functions for container nodes. */
812
+ /** Maps registry keys to `clipFromPose` factory functions for nodes. */
625
813
  clipFromPose?: Readonly<Record<string, ClipFromPoseFn<TPose>>>;
626
- /** Maps registry keys to `copiesFromPose` functions for container nodes. */
814
+ /** Maps registry keys to `copiesFromPose` functions for nodes. */
627
815
  copiesFromPose?: Readonly<Record<string, CopiesFromPoseFn<TPose, TData, TLayer>>>;
628
816
  /** Maps registry keys to `derivePath` functions for nodes with `dependsOn`. */
629
817
  derivePath?: Readonly<Record<string, DerivePathFn<TPose, TData, TLayer>>>;
630
818
  /** Maps registry keys to `derivePose` functions for nodes with `dependsOn`. */
631
819
  derivePose?: Readonly<Record<string, DerivePoseFn<TPose, TData, TLayer>>>;
632
- /** Maps registry keys to container layout strategies. */
820
+ /** Maps registry keys to layout strategies. */
633
821
  layout?: Readonly<Record<string, LayoutStrategy<TPose>>>;
634
822
  }
635
- /**
636
- * Decides what one edit's changes to containers do to their children.
637
- * `arrivals` maps each container to the ids that joined it — by an `add`
638
- * under it or a `move` into it, whatever op or call made them — in the order
639
- * they arrived. `changed` names every container whose child set or order
640
- * changed, whose pose changed size, or one of whose children was posed,
641
- * arrivals included. Both are read once the edit's other mutations have landed.
642
- *
643
- * Return the poses to write, in each node's stored frame; they become part of
644
- * the same edit, and so of the same undo step. An empty map writes nothing.
645
- * Return `null` to refuse: the whole edit is reverted (see
646
- * `SceneArrivalRefused`).
647
- *
648
- * Runs only for live edits. Undo, redo and a restored history replay the
649
- * arrangement that was decided the first time. With none installed, a scene
650
- * holding declared layouts (`ContainerNode.layout`) runs its own.
651
- */
652
- type SceneArrivalHandler<TPose> = (arrivals: ReadonlyMap<NodeId, readonly NodeId[]>, changed: ReadonlySet<NodeId>,
653
- /** The nodes that left each container in the edit, by the container they
654
- * left — removed, or moved out. */
655
- departures: ReadonlyMap<NodeId, readonly NodeId[]>) => ReadonlyMap<NodeId, TPose> | null;
656
823
  /**
657
824
  * The kit-owned scene tree: nodes, layers, and the undo history over both.
658
825
  *
@@ -665,7 +832,7 @@ departures: ReadonlyMap<NodeId, readonly NodeId[]>) => ReadonlyMap<NodeId, TPose
665
832
  * which the kit never inspects; `TPose` is the transform shape, `RectPose` by
666
833
  * default; `TLayer` is the union of layer names.
667
834
  */
668
- interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePoseReports<TPose, Node<TData, TLayer, TPose>>, SceneChanges, SceneDocValues, SceneEditPasses {
835
+ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePoseReports<TPose, Node<TData, TLayer, TPose>>, SceneChanges, SceneDocValues, SceneEditPasses, SceneDeclaredFieldSetters {
669
836
  readonly nodes: ReadonlyMap<NodeId, Node<TData, TLayer, TPose>>;
670
837
  readonly roots: readonly NodeId[];
671
838
  readonly layers: readonly LayerRecord<TLayer>[];
@@ -750,7 +917,7 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePos
750
917
  setDependsOn(id: NodeId, dependsOn: readonly NodeId[] | 'children' | undefined): void;
751
918
  /** Give container `id` a different layout — a strategy, its key in
752
919
  * `SceneRegistry.layout`, or `null` for none — and re-arrange its children
753
- * under it, as one undoable step. Throws for a leaf, or a key the registry
920
+ * under it, as one undoable step. Throws for a mark, or a key the registry
754
921
  * does not hold. A registered layout is recorded by its key, so a
755
922
  * serialized history restores it; an unregistered one lives only as long
756
923
  * as the session.
@@ -763,7 +930,6 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePos
763
930
  * Siblings are reindexed. Recorded as one undoable step.
764
931
  *
765
932
  * Rejected (throws) when:
766
- * - `parent` exists but is a **leaf**, not a container;
767
933
  * - the move would form a **cycle** — `parent` is `id` itself or one of
768
934
  * `id`'s own descendants;
769
935
  * - it would drop `id` **below its new parent's layer** (child may not
@@ -851,11 +1017,11 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePos
851
1017
  * undo step of its own. Removing a node deselects it. */
852
1018
  getSelection(): readonly NodeId[];
853
1019
  setSelection(ids: readonly NodeId[]): void;
854
- /** Per-node pose / alpha overrides the render and hit-test paths read
1020
+ /** Per-node pose / alpha / path / data overrides the render and hit-test paths read
855
1021
  * through. Like {@link Scene.getSelection} this is not document content:
856
1022
  * writes are never recorded, never serialized, and do not bump
857
1023
  * {@link Scene.getVersion}. See {@link PoseOverrides}. */
858
- readonly overrides: PoseOverrides<TPose>;
1024
+ readonly overrides: PoseOverrides<TPose, TData>;
859
1025
  /** The scene's undo/redo engine, in the shape `@weasel-js/history` defines.
860
1026
  * Mutating members route through
861
1027
  * the scene's own wrappers, so an undo driven through this bumps
@@ -868,11 +1034,8 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePos
868
1034
  canUndo(): boolean;
869
1035
  canRedo(): boolean;
870
1036
  batch<T>(label: string, fn: () => T, options?: SceneBatchOptions): T;
871
- /** The layout container `id` declares, or `null` for a leaf or a
872
- * container that declares none. */
1037
+ /** The layout group `id` declares, or `null` for a mark or a group with none. */
873
1038
  layoutOf(id: NodeId): LayoutStrategy<TPose> | null;
874
- /** Declare the unit scope of container `id`, or clear it with `null`. */
875
- setUnits(id: NodeId, units: UnitScope | null): void;
876
1039
  /** Run `fn` with every mutation applied but none recorded — for writes
877
1040
  * that are not edits, such as a simulation stepping poses each frame.
878
1041
  * Undo and redo move between recorded states and never restore an
@@ -927,7 +1090,7 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePos
927
1090
  setHistoryAdapter(fn: (() => unknown) | null): void;
928
1091
  /** Snapshot the current scene state to a JSON-serializable shape.
929
1092
  * History (undo/redo stacks) is NOT captured. Function fields like
930
- * `ContainerNode.clipFromPose` are translated to string keys via the
1093
+ * `GroupNode.clipFromPose` are translated to string keys via the
931
1094
  * scene's registry; throws if any function field has no matching key. */
932
1095
  toJSON(): SerializedScene<TData, TLayer, TPose>;
933
1096
  /** Replace this scene's entire node + layer state in place from a snapshot
@@ -942,8 +1105,8 @@ interface Scene<TData, TLayer extends string, TPose = RectPose> extends ScenePos
942
1105
  * undo — which would revert to a state this replaces. Throws on an unsupported version or unknown registry/layer ids; on a
943
1106
  * malformed snapshot the scene is left empty or partially populated (callers should treat a
944
1107
  * `loadState` throw as fatal and reload). Snapshots from `toJSON()` are
945
- * always well-formed. */
946
- loadState(json: SerializedScene<TData, TLayer, TPose>): void;
1108
+ * always well-formed. `opts` reads the snapshot as `specsFromSerialized` does. */
1109
+ loadState(json: SerializedScene<TData, TLayer, TPose> | SerializedSceneV1<TData, TLayer, TPose>, opts?: SpecsFromSerializedOptions<TData, TLayer, TPose>): void;
947
1110
  }
948
1111
 
949
- export { type AddNodeSpec as A, type Bivariant as B, type ClipFromPoseFn as C, type DerivePoseFn as D, type SceneDocValues as E, type SceneEditPass as F, type SceneEditPassOptions as G, type SceneEditSummary as H, IDENTITY_POSE_COMPOSITION as I, type SerializedDoc as J, type SerializedLayer as K, type LayoutFrame as L, type SerializedNode as M, type Node as N, type SerializedSceneHistory as O, type PoseComposition as P, type SystemLayerRecord as Q, type RectPose as R, type Scene as S, asNodeId as T, type UserLayerRecord as U, composeWorldPose as V, composesFrames as W, rebaseLocalPose as X, type SystemLayerSpec as a, type RegisteredOp as b, type SceneRegistry as c, type PoseAdapter as d, type PoseRemoval as e, type PoseWrite as f, type ScenePoseReports as g, type PoseOverrides as h, type SerializedScene as i, type DerivePathFn as j, type DerivedDep as k, type AddLayerSpec as l, type ContainerNode as m, type CopiesFromPoseFn as n, type LayerRecord as o, type LayoutMove as p, type LeafNode as q, type PoseClosure as r, type PoseHold as s, type PoseOverride as t, type PoseWriteOrigin as u, type RemovedNode as v, SCENE_HISTORY_FORM as w, type SceneArrivalHandler as x, type SceneBatchOptions as y, type SceneDoc as z };
1112
+ export { type V1Classifier as $, type AddNodeSpec as A, type Bivariant as B, type ClipFromPoseFn as C, type DerivePoseFn as D, type SceneBatchOptions as E, type SceneDeclaredFieldSetters as F, type GroupNode as G, type SceneDoc as H, type InheritedPaint as I, type SceneDocValues as J, type SceneEditPass as K, type LayoutFrame as L, type MarkNode as M, type Node as N, type SceneEditPassOptions as O, type PoseComposition as P, type SceneEditSummary as Q, type RectPose as R, type Scene as S, type SerializedDoc as T, type SerializedLayer as U, type SerializedNode as V, type SerializedNodeV1 as W, type SerializedSceneHistory as X, type SkippedKey as Y, type SystemLayerRecord as Z, type UserLayerRecord as _, type SystemLayerSpec as a, asNodeId as a0, composeWorldPose as a1, composesFrames as a2, inheritedPaintIn as a3, inheritedPaintOf as a4, inheritsPaint as a5, nodeKindOf as a6, rebaseLocalPose as a7, specsFromSerialized as a8, withInheritedPaint as a9, type RegisteredOp as b, type SceneRegistry as c, type PoseAdapter as d, type PoseRemoval as e, type PoseWrite as f, type ScenePoseReports as g, type PoseOverrides as h, type SerializedScene as i, type SerializedSceneV1 as j, type SpecsFromSerializedOptions as k, type NodeClip as l, type DerivePathFn as m, type DerivedDep as n, type AddLayerSpec as o, type CopiesFromPoseFn as p, IDENTITY_POSE_COMPOSITION as q, type LayerRecord as r, type LayoutMove as s, type PoseClosure as t, type PoseHold as u, type PoseOverride as v, type PoseWriteOrigin as w, type RemovedNode as x, SCENE_HISTORY_FORM as y, type SceneArrivalHandler as z };
@@ -1,4 +1,4 @@
1
- import { L as LayoutStrategy, P as ParallaxOpts } from './types-7puAuVD2.js';
1
+ import { L as LayoutStrategy, P as ParallaxOpts } from './types-49uYJN3j.js';
2
2
  import { Op } from '@weasel-js/history';
3
3
  import { View } from '@weasel-js/geom';
4
4
  import { P as PoseDescriptor } from './poseDescriptor-DN2yfnq_.js';
package/dist/version.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * throwing, since nothing about version reporting should be able to break a
8
8
  * consumer's build.
9
9
  */
10
- var VERSION = "1.12.0";
10
+ var VERSION = "1.13.0";
11
11
 
12
12
  //#endregion
13
13
  export { VERSION };