@weasel-js/core 1.10.1 → 1.11.1

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 (1501) hide show
  1. package/CHANGELOG.md +1014 -0
  2. package/README.md +16 -15
  3. package/dist/WeaselProvider.js +25 -9
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +217 -140
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +92 -50
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +147 -84
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js +140 -65
  12. package/dist/affordances/pathAnchors.js.map +1 -1
  13. package/dist/affordances/rotateCursor.js +10 -4
  14. package/dist/affordances/rotateCursor.js.map +1 -1
  15. package/dist/affordances/rotationHandle.js +83 -60
  16. package/dist/affordances/rotationHandle.js.map +1 -1
  17. package/dist/animation/behaviors/coast.js +20 -14
  18. package/dist/animation/behaviors/coast.js.map +1 -1
  19. package/dist/animation/behaviors/coastByWrite.js +98 -70
  20. package/dist/animation/behaviors/coastByWrite.js.map +1 -1
  21. package/dist/animation/behaviors/coastOnTargets.js +115 -67
  22. package/dist/animation/behaviors/coastOnTargets.js.map +1 -1
  23. package/dist/animation/behaviors/momentum.js +88 -53
  24. package/dist/animation/behaviors/momentum.js.map +1 -1
  25. package/dist/animation/clipTargets.js +14 -7
  26. package/dist/animation/clipTargets.js.map +1 -1
  27. package/dist/animation/departures.js +116 -0
  28. package/dist/animation/departures.js.map +1 -0
  29. package/dist/animation/index.js +18 -15
  30. package/dist/animation/poseHelpers.js +147 -107
  31. package/dist/animation/poseHelpers.js.map +1 -1
  32. package/dist/animation/poseTarget.js +158 -85
  33. package/dist/animation/poseTarget.js.map +1 -1
  34. package/dist/animation/poseTransition.js +64 -0
  35. package/dist/animation/poseTransition.js.map +1 -0
  36. package/dist/animation/reflow.js +208 -120
  37. package/dist/animation/reflow.js.map +1 -1
  38. package/dist/animation/rewind.js +76 -45
  39. package/dist/animation/rewind.js.map +1 -1
  40. package/dist/animation/rig/bindRig.js +135 -82
  41. package/dist/animation/rig/bindRig.js.map +1 -1
  42. package/dist/animation/rig/rigNode.js +120 -75
  43. package/dist/animation/rig/rigNode.js.map +1 -1
  44. package/dist/animation/rig/rigSeat.js +61 -41
  45. package/dist/animation/rig/rigSeat.js.map +1 -1
  46. package/dist/animation/rig/skinBinding.js +57 -45
  47. package/dist/animation/rig/skinBinding.js.map +1 -1
  48. package/dist/animation/rig/useRig.js +44 -30
  49. package/dist/animation/rig/useRig.js.map +1 -1
  50. package/dist/animation/wrappers/animateLifecycle.js +51 -35
  51. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  52. package/dist/animation/wrappers/animateOnSetPose.js +55 -32
  53. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  54. package/dist/animation/wrappers/instantPose.js +13 -8
  55. package/dist/animation/wrappers/instantPose.js.map +1 -1
  56. package/dist/animation/writtenPoseTarget.js +44 -22
  57. package/dist/animation/writtenPoseTarget.js.map +1 -1
  58. package/dist/{autoPoseDescriptor-DHg5KqaJ.d.ts → autoPoseDescriptor-CZ1eXbzY.d.ts} +1 -1
  59. package/dist/barrel/canvas.js +45 -32
  60. package/dist/barrel/chrome.js +19 -16
  61. package/dist/barrel/icons.js +6 -0
  62. package/dist/barrel/input.js +19 -18
  63. package/dist/barrel/interactions.js +41 -39
  64. package/dist/barrel/paint.js +12 -11
  65. package/dist/barrel/paths.js +39 -13
  66. package/dist/barrel/renderer.js +25 -14
  67. package/dist/barrel/routing.js +64 -58
  68. package/dist/barrel/scene.js +51 -37
  69. package/dist/barrel/text.js +10 -9
  70. package/dist/barrel/viewport.js +48 -45
  71. package/dist/canvas/Canvas.js +191 -306
  72. package/dist/canvas/Canvas.js.map +1 -1
  73. package/dist/canvas/CanvasView.js +273 -199
  74. package/dist/canvas/CanvasView.js.map +1 -1
  75. package/dist/canvas/CursorCoordsHud.js +103 -64
  76. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  77. package/dist/canvas/DrawCanvas.js +68 -41
  78. package/dist/canvas/DrawCanvas.js.map +1 -1
  79. package/dist/canvas/LeanSceneCanvas.js +23 -0
  80. package/dist/canvas/LeanSceneCanvas.js.map +1 -0
  81. package/dist/canvas/ModalityHud.js +58 -43
  82. package/dist/canvas/ModalityHud.js.map +1 -1
  83. package/dist/canvas/NodeShape.js +137 -60
  84. package/dist/canvas/NodeShape.js.map +1 -1
  85. package/dist/canvas/PickHud.js +77 -59
  86. package/dist/canvas/PickHud.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +9 -6
  88. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js.map +1 -1
  89. package/dist/canvas/SceneCanvas/CanvasKitProviders.js +25 -0
  90. package/dist/canvas/SceneCanvas/CanvasKitProviders.js.map +1 -0
  91. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +10 -6
  92. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/DevHuds.js +47 -32
  94. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -1
  95. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +72 -37
  96. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  97. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +124 -0
  98. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -0
  99. package/dist/canvas/SceneCanvas/brushOverlay.js +36 -0
  100. package/dist/canvas/SceneCanvas/brushOverlay.js.map +1 -0
  101. package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
  102. package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
  103. package/dist/canvas/SceneCanvas/canvasPassThrough.js +73 -0
  104. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -0
  105. package/dist/canvas/SceneCanvas/contributionFrameHooks.js +54 -32
  106. package/dist/canvas/SceneCanvas/contributionFrameHooks.js.map +1 -1
  107. package/dist/canvas/SceneCanvas/coordTrace.js +26 -30
  108. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  109. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +323 -159
  110. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  111. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +39 -13
  112. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  113. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js +83 -47
  114. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  115. package/dist/canvas/SceneCanvas/features.js +123 -106
  116. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  117. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +80 -62
  118. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -1
  119. package/dist/canvas/SceneCanvas/mergeLayers.js +43 -0
  120. package/dist/canvas/SceneCanvas/mergeLayers.js.map +1 -0
  121. package/dist/canvas/SceneCanvas/namedPresets.js +56 -0
  122. package/dist/canvas/SceneCanvas/namedPresets.js.map +1 -0
  123. package/dist/canvas/SceneCanvas/poseGeometry.js +66 -31
  124. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  125. package/dist/canvas/SceneCanvas/poseRegistrars.js +18 -8
  126. package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -1
  127. package/dist/canvas/SceneCanvas/presets/arrange.js +27 -0
  128. package/dist/canvas/SceneCanvas/presets/arrange.js.map +1 -0
  129. package/dist/canvas/SceneCanvas/presets/chrome.js +14 -0
  130. package/dist/canvas/SceneCanvas/presets/chrome.js.map +1 -0
  131. package/dist/canvas/SceneCanvas/presets/edit.js +59 -0
  132. package/dist/canvas/SceneCanvas/presets/edit.js.map +1 -0
  133. package/dist/canvas/SceneCanvas/presets/ingest.js +13 -0
  134. package/dist/canvas/SceneCanvas/presets/ingest.js.map +1 -0
  135. package/dist/canvas/SceneCanvas/presets/paths.js +67 -0
  136. package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -0
  137. package/dist/canvas/SceneCanvas/presets/select.js +19 -0
  138. package/dist/canvas/SceneCanvas/presets/select.js.map +1 -0
  139. package/dist/canvas/SceneCanvas/presets/toolDriven.js +20 -0
  140. package/dist/canvas/SceneCanvas/presets/toolDriven.js.map +1 -0
  141. package/dist/canvas/SceneCanvas/presets/transform.js +41 -0
  142. package/dist/canvas/SceneCanvas/presets/transform.js.map +1 -0
  143. package/dist/canvas/SceneCanvas/presets/view.js +14 -0
  144. package/dist/canvas/SceneCanvas/presets/view.js.map +1 -0
  145. package/dist/canvas/SceneCanvas/props.js +9 -35
  146. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  147. package/dist/canvas/SceneCanvas/scenePointQuery.js +43 -35
  148. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
  149. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +22 -15
  150. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -1
  151. package/dist/canvas/SceneCanvas/toolRegistry.js +34 -15
  152. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
  153. package/dist/canvas/SceneCanvas/useActionTunings.js +14 -11
  154. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
  155. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +59 -36
  156. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  157. package/dist/canvas/SceneCanvas/useBakedScene.js +17 -0
  158. package/dist/canvas/SceneCanvas/useBakedScene.js.map +1 -0
  159. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +47 -23
  160. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  161. package/dist/canvas/SceneCanvas/useBuiltinTools.js +22 -14
  162. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
  163. package/dist/canvas/SceneCanvas/useCanvasCamera.js +53 -38
  164. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -1
  165. package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +93 -0
  166. package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
  167. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +24 -14
  168. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -1
  169. package/dist/canvas/SceneCanvas/useCanvasSelection.js +35 -12
  170. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
  171. package/dist/canvas/SceneCanvas/useCanvasTools.js +112 -53
  172. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  173. package/dist/canvas/SceneCanvas/useChromeAffordances.js +31 -0
  174. package/dist/canvas/SceneCanvas/useChromeAffordances.js.map +1 -0
  175. package/dist/canvas/SceneCanvas/useContributionRoles.js +107 -56
  176. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
  177. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js +64 -0
  178. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js.map +1 -0
  179. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +104 -71
  180. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  181. package/dist/canvas/SceneCanvas/useHeldModifiers.js +21 -14
  182. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -1
  183. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +21 -19
  184. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -1
  185. package/dist/canvas/SceneCanvas/useNodeKinds.js +28 -19
  186. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
  187. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +91 -59
  188. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  189. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +62 -35
  190. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
  191. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +121 -50
  192. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  193. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js +30 -0
  194. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js.map +1 -0
  195. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +38 -0
  196. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -0
  197. package/dist/canvas/SceneCanvas/useSceneChrome.js +99 -44
  198. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
  199. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +165 -0
  200. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -0
  201. package/dist/canvas/SceneCanvas/useScenePicking.js +68 -0
  202. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -0
  203. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +28 -17
  204. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -1
  205. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +160 -80
  206. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  207. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +38 -26
  208. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -1
  209. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +107 -0
  210. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -0
  211. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +40 -27
  212. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -1
  213. package/dist/canvas/SceneCanvas/useSurfaceRouting.js +29 -0
  214. package/dist/canvas/SceneCanvas/useSurfaceRouting.js.map +1 -0
  215. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js +44 -0
  216. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js.map +1 -0
  217. package/dist/canvas/SceneCanvas/useToolKeybindings.js +28 -0
  218. package/dist/canvas/SceneCanvas/useToolKeybindings.js.map +1 -0
  219. package/dist/canvas/SceneCanvas/useViewportActions.js +52 -28
  220. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  221. package/dist/canvas/SceneCanvas/worldPointAt.js +10 -4
  222. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
  223. package/dist/canvas/SceneCanvas.js +276 -312
  224. package/dist/canvas/SceneCanvas.js.map +1 -1
  225. package/dist/canvas/SceneViewCanvas.js +68 -42
  226. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  227. package/dist/canvas/SurfaceCanvas.js +38 -33
  228. package/dist/canvas/SurfaceCanvas.js.map +1 -1
  229. package/dist/canvas/accentColor.js +8 -5
  230. package/dist/canvas/accentColor.js.map +1 -1
  231. package/dist/canvas/adapterDerivedPath.js +33 -18
  232. package/dist/canvas/adapterDerivedPath.js.map +1 -1
  233. package/dist/canvas/adapterPickSource.js +49 -23
  234. package/dist/canvas/adapterPickSource.js.map +1 -1
  235. package/dist/canvas/affordanceAt.js +106 -50
  236. package/dist/canvas/affordanceAt.js.map +1 -1
  237. package/dist/canvas/buildSceneLayer.js +111 -80
  238. package/dist/canvas/buildSceneLayer.js.map +1 -1
  239. package/dist/canvas/buildSceneTree.js +101 -59
  240. package/dist/canvas/buildSceneTree.js.map +1 -1
  241. package/dist/canvas/canvasRenderer.js +161 -72
  242. package/dist/canvas/canvasRenderer.js.map +1 -1
  243. package/dist/canvas/colorOverrides.js +18 -10
  244. package/dist/canvas/colorOverrides.js.map +1 -1
  245. package/dist/canvas/contextAttributes.js +14 -0
  246. package/dist/canvas/contextAttributes.js.map +1 -0
  247. package/dist/canvas/copiesAbove.js +24 -14
  248. package/dist/canvas/copiesAbove.js.map +1 -1
  249. package/dist/canvas/defaultDrawOne.js +55 -31
  250. package/dist/canvas/defaultDrawOne.js.map +1 -1
  251. package/dist/canvas/deps/areaSelect.js +30 -12
  252. package/dist/canvas/deps/areaSelect.js.map +1 -1
  253. package/dist/canvas/deps/booleans.js +104 -0
  254. package/dist/canvas/deps/booleans.js.map +1 -0
  255. package/dist/canvas/deps/changes.js +17 -9
  256. package/dist/canvas/deps/changes.js.map +1 -1
  257. package/dist/canvas/deps/debug.js +12 -5
  258. package/dist/canvas/deps/debug.js.map +1 -1
  259. package/dist/canvas/deps/dispatchSources.js +27 -0
  260. package/dist/canvas/deps/dispatchSources.js.map +1 -0
  261. package/dist/canvas/deps/dispatcher.js +18 -7
  262. package/dist/canvas/deps/dispatcher.js.map +1 -1
  263. package/dist/canvas/deps/editAnchors.js +150 -64
  264. package/dist/canvas/deps/editAnchors.js.map +1 -1
  265. package/dist/canvas/deps/geometryProjection.js +13 -7
  266. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  267. package/dist/canvas/deps/hitTestArea.js +78 -53
  268. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  269. package/dist/canvas/deps/ingestion.js +18 -13
  270. package/dist/canvas/deps/ingestion.js.map +1 -1
  271. package/dist/canvas/deps/insert.js +178 -116
  272. package/dist/canvas/deps/insert.js.map +1 -1
  273. package/dist/canvas/deps/kitSettings.js +16 -0
  274. package/dist/canvas/deps/kitSettings.js.map +1 -0
  275. package/dist/canvas/deps/lassoSelect.js +25 -13
  276. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  277. package/dist/canvas/deps/layout.js +32 -20
  278. package/dist/canvas/deps/layout.js.map +1 -1
  279. package/dist/canvas/deps/nodeAtPoint.js +28 -14
  280. package/dist/canvas/deps/nodeAtPoint.js.map +1 -1
  281. package/dist/canvas/deps/pathEditCommits.js +193 -0
  282. package/dist/canvas/deps/pathEditCommits.js.map +1 -0
  283. package/dist/canvas/deps/pathLeaf.js +66 -0
  284. package/dist/canvas/deps/pathLeaf.js.map +1 -0
  285. package/dist/canvas/deps/pathLeafDeps.js +13 -0
  286. package/dist/canvas/deps/pathLeafDeps.js.map +1 -0
  287. package/dist/canvas/deps/poseDescriptor.js +10 -8
  288. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  289. package/dist/canvas/deps/previewPaths.js +44 -0
  290. package/dist/canvas/deps/previewPaths.js.map +1 -0
  291. package/dist/canvas/deps/resizePolicy.js +32 -25
  292. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  293. package/dist/canvas/deps/slice.js +73 -87
  294. package/dist/canvas/deps/slice.js.map +1 -1
  295. package/dist/canvas/deps/snap.js +61 -7
  296. package/dist/canvas/deps/snap.js.map +1 -1
  297. package/dist/canvas/deps/surface.js +30 -0
  298. package/dist/canvas/deps/surface.js.map +1 -0
  299. package/dist/canvas/deps/textEdit.js +21 -13
  300. package/dist/canvas/deps/textEdit.js.map +1 -1
  301. package/dist/canvas/deps/transformFollowers.js +20 -0
  302. package/dist/canvas/deps/transformFollowers.js.map +1 -0
  303. package/dist/canvas/deps/view.js +46 -34
  304. package/dist/canvas/deps/view.js.map +1 -1
  305. package/dist/canvas/derivedPath.js +173 -70
  306. package/dist/canvas/derivedPath.js.map +1 -1
  307. package/dist/canvas/doubleClickTarget.js +20 -0
  308. package/dist/canvas/doubleClickTarget.js.map +1 -0
  309. package/dist/canvas/drawEnvelope.js +26 -17
  310. package/dist/canvas/drawEnvelope.js.map +1 -1
  311. package/dist/canvas/drawnBounds.js +142 -0
  312. package/dist/canvas/drawnBounds.js.map +1 -0
  313. package/dist/canvas/getNodeAtPoint.js +11 -8
  314. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  315. package/dist/canvas/hostAnchor.js +35 -18
  316. package/dist/canvas/hostAnchor.js.map +1 -1
  317. package/dist/canvas/hud.module.js +25 -14
  318. package/dist/canvas/hud.module.js.map +1 -1
  319. package/dist/canvas/insertPreviewExtent.js +82 -61
  320. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  321. package/dist/canvas/kitRequirements.js +154 -115
  322. package/dist/canvas/kitRequirements.js.map +1 -1
  323. package/dist/canvas/layerHover.js +28 -0
  324. package/dist/canvas/layerHover.js.map +1 -0
  325. package/dist/canvas/layerOrder.js +107 -57
  326. package/dist/canvas/layerOrder.js.map +1 -1
  327. package/dist/canvas/layerSlots.js +16 -9
  328. package/dist/canvas/layerSlots.js.map +1 -1
  329. package/dist/canvas/mountedCanvases.js +23 -13
  330. package/dist/canvas/mountedCanvases.js.map +1 -1
  331. package/dist/canvas/nodeShapes/derivedPainter.js +73 -25
  332. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  333. package/dist/canvas/nodeShapes/imagePainter.js +69 -53
  334. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  335. package/dist/canvas/nodeShapes/measurePainter.js +58 -0
  336. package/dist/canvas/nodeShapes/measurePainter.js.map +1 -0
  337. package/dist/canvas/nodeShapes/memo.js +16 -5
  338. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  339. package/dist/canvas/nodeShapes/nodePaint.js +125 -46
  340. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  341. package/dist/canvas/nodeShapes/pathPainter.js +42 -27
  342. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  343. package/dist/canvas/nodeShapes/poseBox.js +20 -13
  344. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  345. package/dist/canvas/nodeShapes/rectFallbackPainter.js +26 -22
  346. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  347. package/dist/canvas/nodeShapes/shapePainter.js +67 -46
  348. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  349. package/dist/canvas/nodeShapes/strokedBounds.js +177 -0
  350. package/dist/canvas/nodeShapes/strokedBounds.js.map +1 -0
  351. package/dist/canvas/nodeShapes/textPainter.js +170 -37
  352. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  353. package/dist/canvas/overChildren.js +29 -18
  354. package/dist/canvas/overChildren.js.map +1 -1
  355. package/dist/canvas/overlayRoleStrokes.js +32 -3
  356. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  357. package/dist/canvas/paintCull.js +24 -12
  358. package/dist/canvas/paintCull.js.map +1 -1
  359. package/dist/canvas/paintedCursorLayer.js +59 -35
  360. package/dist/canvas/paintedCursorLayer.js.map +1 -1
  361. package/dist/canvas/pathOverlay.js +83 -0
  362. package/dist/canvas/pathOverlay.js.map +1 -0
  363. package/dist/canvas/pickReach.js +34 -17
  364. package/dist/canvas/pickReach.js.map +1 -1
  365. package/dist/canvas/pickWalk.js +151 -102
  366. package/dist/canvas/pickWalk.js.map +1 -1
  367. package/dist/canvas/planeClips.js +39 -22
  368. package/dist/canvas/planeClips.js.map +1 -1
  369. package/dist/canvas/poseCascade.js +51 -27
  370. package/dist/canvas/poseCascade.js.map +1 -1
  371. package/dist/canvas/poseRotation.js +24 -14
  372. package/dist/canvas/poseRotation.js.map +1 -1
  373. package/dist/canvas/rasterReadback.js +23 -15
  374. package/dist/canvas/rasterReadback.js.map +1 -1
  375. package/dist/canvas/rasterToPng.js +21 -15
  376. package/dist/canvas/rasterToPng.js.map +1 -1
  377. package/dist/canvas/renderDebugSnapshot.js +37 -19
  378. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  379. package/dist/canvas/renderNeeds.js +33 -18
  380. package/dist/canvas/renderNeeds.js.map +1 -1
  381. package/dist/canvas/renderSceneToPixels.js +203 -87
  382. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  383. package/dist/canvas/sceneAdapter.js +96 -75
  384. package/dist/canvas/sceneAdapter.js.map +1 -1
  385. package/dist/canvas/sceneClipboard.js +141 -92
  386. package/dist/canvas/sceneClipboard.js.map +1 -1
  387. package/dist/canvas/sceneLayerPaint.js +56 -27
  388. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  389. package/dist/canvas/sceneSlotWiring.js +24 -14
  390. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  391. package/dist/canvas/sceneViewRender.js +85 -49
  392. package/dist/canvas/sceneViewRender.js.map +1 -1
  393. package/dist/canvas/slopsDebugLayer.js +58 -49
  394. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  395. package/dist/canvas/surfaceContribution.js +22 -10
  396. package/dist/canvas/surfaceContribution.js.map +1 -1
  397. package/dist/canvas/useCanvasElements.js +31 -0
  398. package/dist/canvas/useCanvasElements.js.map +1 -0
  399. package/dist/canvas/useCanvasHandle.js +69 -0
  400. package/dist/canvas/useCanvasHandle.js.map +1 -0
  401. package/dist/canvas/useCanvasPaint.js +92 -0
  402. package/dist/canvas/useCanvasPaint.js.map +1 -0
  403. package/dist/canvas/useCanvasRenderer.js +45 -23
  404. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  405. package/dist/canvas/useCanvasSurface.js +41 -23
  406. package/dist/canvas/useCanvasSurface.js.map +1 -1
  407. package/dist/canvas/useCanvasView.js +80 -48
  408. package/dist/canvas/useCanvasView.js.map +1 -1
  409. package/dist/canvas/useClientToWorld.js +27 -0
  410. package/dist/canvas/useClientToWorld.js.map +1 -0
  411. package/dist/canvas/useExtraLayers.js +45 -0
  412. package/dist/canvas/useExtraLayers.js.map +1 -0
  413. package/dist/canvas/useFrameLoop.js +109 -49
  414. package/dist/canvas/useFrameLoop.js.map +1 -1
  415. package/dist/canvas/useHitObserver.js +22 -15
  416. package/dist/canvas/useHitObserver.js.map +1 -1
  417. package/dist/canvas/useHostAnchor.js +83 -53
  418. package/dist/canvas/useHostAnchor.js.map +1 -1
  419. package/dist/canvas/useInFlightBounds.js +52 -0
  420. package/dist/canvas/useInFlightBounds.js.map +1 -0
  421. package/dist/canvas/useLateContentRedraw.js +21 -14
  422. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  423. package/dist/canvas/useLayerStack.js +72 -0
  424. package/dist/canvas/useLayerStack.js.map +1 -0
  425. package/dist/canvas/usePaintedCursor.js +28 -0
  426. package/dist/canvas/usePaintedCursor.js.map +1 -0
  427. package/dist/canvas/useRedrawOn.js +24 -14
  428. package/dist/canvas/useRedrawOn.js.map +1 -1
  429. package/dist/canvas/useSceneAdapter.js +21 -16
  430. package/dist/canvas/useSceneAdapter.js.map +1 -1
  431. package/dist/canvas/useSceneLayerList.js +15 -7
  432. package/dist/canvas/useSceneLayerList.js.map +1 -1
  433. package/dist/canvas/useSurfaceInput.js +46 -27
  434. package/dist/canvas/useSurfaceInput.js.map +1 -1
  435. package/dist/canvas/useSurfaceSize.js +43 -0
  436. package/dist/canvas/useSurfaceSize.js.map +1 -0
  437. package/dist/canvas/useToolCursor.js +30 -21
  438. package/dist/canvas/useToolCursor.js.map +1 -1
  439. package/dist/canvas/useViewHelpers.js +110 -61
  440. package/dist/canvas/useViewHelpers.js.map +1 -1
  441. package/dist/canvas/useViewLayerGate.js +29 -0
  442. package/dist/canvas/useViewLayerGate.js.map +1 -0
  443. package/dist/canvas/useViewNesting.js +104 -0
  444. package/dist/canvas/useViewNesting.js.map +1 -0
  445. package/dist/canvas/useViewRegistrySurface.js +44 -0
  446. package/dist/canvas/useViewRegistrySurface.js.map +1 -0
  447. package/dist/canvas/viewInputs.js +14 -11
  448. package/dist/canvas/viewInputs.js.map +1 -1
  449. package/dist/canvas/viewRegistry.js +140 -42
  450. package/dist/canvas/viewRegistry.js.map +1 -1
  451. package/dist/canvas/watchElementMove.js +71 -33
  452. package/dist/canvas/watchElementMove.js.map +1 -1
  453. package/dist/canvas/wrapNodeOutput.js +20 -13
  454. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  455. package/dist/clipboard.d.ts +9 -4
  456. package/dist/clipboard.js +4 -3
  457. package/dist/{clone-C0eADtS0.d.ts → clone-C3e0OTuF.d.ts} +27 -73
  458. package/dist/clone.d.ts +7 -5
  459. package/dist/core/adapters/testing/rootsTree.js +17 -0
  460. package/dist/core/adapters/testing/rootsTree.js.map +1 -0
  461. package/dist/core/applyOps.js +23 -7
  462. package/dist/core/applyOps.js.map +1 -1
  463. package/dist/core/device/index.js +6 -5
  464. package/dist/core/device/targets.js +29 -8
  465. package/dist/core/device/targets.js.map +1 -1
  466. package/dist/core/device/useDeviceProfile.js +86 -52
  467. package/dist/core/device/useDeviceProfile.js.map +1 -1
  468. package/dist/core/device/useTargetBasePx.js +23 -0
  469. package/dist/core/device/useTargetBasePx.js.map +1 -0
  470. package/dist/core/device/watchDevicePixelRatio.js +27 -10
  471. package/dist/core/device/watchDevicePixelRatio.js.map +1 -1
  472. package/dist/core/geometry/autoPoseDescriptor.js +38 -24
  473. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -1
  474. package/dist/core/geometry/inkExtents.js +60 -0
  475. package/dist/core/geometry/inkExtents.js.map +1 -0
  476. package/dist/core/geometry/pathPoseDescriptor.js +101 -76
  477. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -1
  478. package/dist/core/geometry/poseDescriptor.js +199 -136
  479. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  480. package/dist/core/geometry/regionHit.js +127 -79
  481. package/dist/core/geometry/regionHit.js.map +1 -1
  482. package/dist/core/geometry/targetFrame.js +84 -60
  483. package/dist/core/geometry/targetFrame.js.map +1 -1
  484. package/dist/core/geometry/unionBounds.js +103 -48
  485. package/dist/core/geometry/unionBounds.js.map +1 -1
  486. package/dist/core/isPlainObject.js +3 -2
  487. package/dist/core/layers/backgroundFill.js +23 -15
  488. package/dist/core/layers/backgroundFill.js.map +1 -1
  489. package/dist/core/layers/children.js +16 -13
  490. package/dist/core/layers/children.js.map +1 -1
  491. package/dist/core/layers/gateLayer.js +24 -9
  492. package/dist/core/layers/gateLayer.js.map +1 -1
  493. package/dist/core/layers/layerGroup.js +42 -29
  494. package/dist/core/layers/layerGroup.js.map +1 -1
  495. package/dist/core/layers/redrawSource.js +15 -0
  496. package/dist/core/layers/redrawSource.js.map +1 -0
  497. package/dist/core/layers/render.js +183 -93
  498. package/dist/core/layers/render.js.map +1 -1
  499. package/dist/core/layers/retain.js +38 -0
  500. package/dist/core/layers/retain.js.map +1 -0
  501. package/dist/core/ops/arrange.js +30 -19
  502. package/dist/core/ops/arrange.js.map +1 -1
  503. package/dist/core/ops/create.js +32 -23
  504. package/dist/core/ops/create.js.map +1 -1
  505. package/dist/core/ops/createHistory.js +23 -14
  506. package/dist/core/ops/createHistory.js.map +1 -1
  507. package/dist/core/ops/delete.js +80 -53
  508. package/dist/core/ops/delete.js.map +1 -1
  509. package/dist/core/ops/nodeFlags.js +44 -0
  510. package/dist/core/ops/nodeFlags.js.map +1 -0
  511. package/dist/core/ops/registry.js +26 -11
  512. package/dist/core/ops/registry.js.map +1 -1
  513. package/dist/core/ops/reorder/algorithms.js +62 -38
  514. package/dist/core/ops/reorder/algorithms.js.map +1 -1
  515. package/dist/core/ops/reorder/index.js +124 -84
  516. package/dist/core/ops/reorder/index.js.map +1 -1
  517. package/dist/core/ops/reorder/setChildOrder.js +32 -23
  518. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  519. package/dist/core/ops/reparent.js +63 -37
  520. package/dist/core/ops/reparent.js.map +1 -1
  521. package/dist/core/ops/select.js +23 -20
  522. package/dist/core/ops/select.js.map +1 -1
  523. package/dist/core/ops/setData.js +23 -21
  524. package/dist/core/ops/setData.js.map +1 -1
  525. package/dist/core/ops/setDependsOn.js +37 -0
  526. package/dist/core/ops/setDependsOn.js.map +1 -0
  527. package/dist/core/ops/setLayer.js +26 -21
  528. package/dist/core/ops/setLayer.js.map +1 -1
  529. package/dist/core/ops/setLayout.js +27 -18
  530. package/dist/core/ops/setLayout.js.map +1 -1
  531. package/dist/core/ops/setPath.js +60 -41
  532. package/dist/core/ops/setPath.js.map +1 -1
  533. package/dist/core/ops/setText.js +26 -21
  534. package/dist/core/ops/setText.js.map +1 -1
  535. package/dist/core/ops/slot.js +36 -22
  536. package/dist/core/ops/slot.js.map +1 -1
  537. package/dist/core/ops/transform.js +35 -28
  538. package/dist/core/ops/transform.js.map +1 -1
  539. package/dist/core/ops/writtenBy.js +53 -0
  540. package/dist/core/ops/writtenBy.js.map +1 -0
  541. package/dist/core/pages/fitViewToPage.js +24 -11
  542. package/dist/core/pages/fitViewToPage.js.map +1 -1
  543. package/dist/core/pages/pageEdits.js +164 -0
  544. package/dist/core/pages/pageEdits.js.map +1 -0
  545. package/dist/core/pages/pages.js +102 -42
  546. package/dist/core/pages/pages.js.map +1 -1
  547. package/dist/core/pages/pagesLayer.js +19 -13
  548. package/dist/core/pages/pagesLayer.js.map +1 -1
  549. package/dist/core/paint/meshKind.js +16 -11
  550. package/dist/core/paint/meshKind.js.map +1 -1
  551. package/dist/core/paint/meshKindLazy.js +1 -1
  552. package/dist/core/paint/meshKindLazy.js.map +1 -1
  553. package/dist/core/paint/paintKindEntry.js +13 -4
  554. package/dist/core/paint/paintKindEntry.js.map +1 -1
  555. package/dist/core/paint/paintKinds.js +149 -88
  556. package/dist/core/paint/paintKinds.js.map +1 -1
  557. package/dist/core/paint/registerMesh.js +6 -4
  558. package/dist/core/paint/registerMesh.js.map +1 -1
  559. package/dist/core/scene/NodeProperties.js +15 -10
  560. package/dist/core/scene/NodeProperties.js.map +1 -1
  561. package/dist/core/scene/NodeRouting.js +22 -13
  562. package/dist/core/scene/NodeRouting.js.map +1 -1
  563. package/dist/core/scene/annotation.js +28 -0
  564. package/dist/core/scene/annotation.js.map +1 -0
  565. package/dist/core/scene/appliedLog.js +31 -23
  566. package/dist/core/scene/appliedLog.js.map +1 -1
  567. package/dist/core/scene/arrivalWindow.js +120 -75
  568. package/dist/core/scene/arrivalWindow.js.map +1 -1
  569. package/dist/core/scene/arrivals.js +17 -6
  570. package/dist/core/scene/arrivals.js.map +1 -1
  571. package/dist/core/scene/boundOps.js +42 -23
  572. package/dist/core/scene/boundOps.js.map +1 -1
  573. package/dist/core/scene/carryDescendants.js +51 -0
  574. package/dist/core/scene/carryDescendants.js.map +1 -0
  575. package/dist/core/scene/composeFrame.js +51 -21
  576. package/dist/core/scene/composeFrame.js.map +1 -1
  577. package/dist/core/scene/composePose.js +114 -62
  578. package/dist/core/scene/composePose.js.map +1 -1
  579. package/dist/core/scene/depFrame.js +94 -0
  580. package/dist/core/scene/depFrame.js.map +1 -0
  581. package/dist/core/scene/depMemo.js +44 -19
  582. package/dist/core/scene/depMemo.js.map +1 -1
  583. package/dist/core/scene/dependents.js +73 -45
  584. package/dist/core/scene/dependents.js.map +1 -1
  585. package/dist/core/scene/derivedParts.js +58 -0
  586. package/dist/core/scene/derivedParts.js.map +1 -0
  587. package/dist/core/scene/derivedPath.js +52 -22
  588. package/dist/core/scene/derivedPath.js.map +1 -1
  589. package/dist/core/scene/docValues.js +57 -0
  590. package/dist/core/scene/docValues.js.map +1 -0
  591. package/dist/core/scene/editMode.js +11 -11
  592. package/dist/core/scene/editMode.js.map +1 -1
  593. package/dist/core/scene/editPass.js +111 -0
  594. package/dist/core/scene/editPass.js.map +1 -0
  595. package/dist/core/scene/effectivePose.js +173 -51
  596. package/dist/core/scene/effectivePose.js.map +1 -1
  597. package/dist/core/scene/fieldEdits.js +98 -75
  598. package/dist/core/scene/fieldEdits.js.map +1 -1
  599. package/dist/core/scene/historyFacade.js +127 -87
  600. package/dist/core/scene/historyFacade.js.map +1 -1
  601. package/dist/core/scene/historyForm.js +7 -3
  602. package/dist/core/scene/historyForm.js.map +1 -1
  603. package/dist/core/scene/kitOps.js +203 -131
  604. package/dist/core/scene/kitOps.js.map +1 -1
  605. package/dist/core/scene/kitRegistry.js +49 -22
  606. package/dist/core/scene/kitRegistry.js.map +1 -1
  607. package/dist/core/scene/layerStack.js +123 -92
  608. package/dist/core/scene/layerStack.js.map +1 -1
  609. package/dist/core/scene/layoutPass.js +143 -72
  610. package/dist/core/scene/layoutPass.js.map +1 -1
  611. package/dist/core/scene/lockGuard.js +32 -24
  612. package/dist/core/scene/lockGuard.js.map +1 -1
  613. package/dist/core/scene/minSize.js +17 -0
  614. package/dist/core/scene/minSize.js.map +1 -0
  615. package/dist/core/scene/nestedHit.js +45 -31
  616. package/dist/core/scene/nestedHit.js.map +1 -1
  617. package/dist/core/scene/nodeFlags.js +43 -0
  618. package/dist/core/scene/nodeFlags.js.map +1 -0
  619. package/dist/core/scene/nodeFnFields.js +58 -41
  620. package/dist/core/scene/nodeFnFields.js.map +1 -1
  621. package/dist/core/scene/nodeGates.js +58 -0
  622. package/dist/core/scene/nodeGates.js.map +1 -0
  623. package/dist/core/scene/nodeMemo.js +92 -40
  624. package/dist/core/scene/nodeMemo.js.map +1 -1
  625. package/dist/core/scene/nodeStore.js +179 -99
  626. package/dist/core/scene/nodeStore.js.map +1 -1
  627. package/dist/core/scene/notifier.js +30 -19
  628. package/dist/core/scene/notifier.js.map +1 -1
  629. package/dist/core/scene/opTable.js +42 -36
  630. package/dist/core/scene/opTable.js.map +1 -1
  631. package/dist/core/scene/outerOps.js +49 -43
  632. package/dist/core/scene/outerOps.js.map +1 -1
  633. package/dist/core/scene/pathEffects/blend.js +80 -0
  634. package/dist/core/scene/pathEffects/blend.js.map +1 -0
  635. package/dist/core/scene/pathEffects/derive.js +112 -0
  636. package/dist/core/scene/pathEffects/derive.js.map +1 -0
  637. package/dist/core/scene/pathEffects/effects.js +40 -0
  638. package/dist/core/scene/pathEffects/effects.js.map +1 -0
  639. package/dist/core/scene/poseFeed.js +95 -60
  640. package/dist/core/scene/poseFeed.js.map +1 -1
  641. package/dist/core/scene/poseHold.js +33 -24
  642. package/dist/core/scene/poseHold.js.map +1 -1
  643. package/dist/core/scene/poseOverrides.js +86 -49
  644. package/dist/core/scene/poseOverrides.js.map +1 -1
  645. package/dist/core/scene/poseRemovals.js +58 -0
  646. package/dist/core/scene/poseRemovals.js.map +1 -0
  647. package/dist/core/scene/poseSnapshot.js +62 -41
  648. package/dist/core/scene/poseSnapshot.js.map +1 -1
  649. package/dist/core/scene/poseWrites.js +151 -0
  650. package/dist/core/scene/poseWrites.js.map +1 -0
  651. package/dist/core/scene/reconcileSpecs.js +63 -34
  652. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  653. package/dist/core/scene/recorder.js +99 -57
  654. package/dist/core/scene/recorder.js.map +1 -1
  655. package/dist/core/scene/renderOrder.js +105 -59
  656. package/dist/core/scene/renderOrder.js.map +1 -1
  657. package/dist/core/scene/scene.js +139 -80
  658. package/dist/core/scene/scene.js.map +1 -1
  659. package/dist/core/scene/sceneChanges.js +13 -0
  660. package/dist/core/scene/sceneChanges.js.map +1 -0
  661. package/dist/core/scene/sceneEdits.js +69 -49
  662. package/dist/core/scene/sceneEdits.js.map +1 -1
  663. package/dist/core/scene/sceneMutators.js +45 -36
  664. package/dist/core/scene/sceneMutators.js.map +1 -1
  665. package/dist/core/scene/scenePoseAdapter.js +13 -9
  666. package/dist/core/scene/scenePoseAdapter.js.map +1 -1
  667. package/dist/core/scene/sceneRecording.js +106 -73
  668. package/dist/core/scene/sceneRecording.js.map +1 -1
  669. package/dist/core/scene/sceneSelection.js +26 -16
  670. package/dist/core/scene/sceneSelection.js.map +1 -1
  671. package/dist/core/scene/sceneState.js +61 -37
  672. package/dist/core/scene/sceneState.js.map +1 -1
  673. package/dist/core/scene/serialization.js +89 -50
  674. package/dist/core/scene/serialization.js.map +1 -1
  675. package/dist/core/scene/staleReplay.js +35 -26
  676. package/dist/core/scene/staleReplay.js.map +1 -1
  677. package/dist/core/scene/statedFields.js +10 -5
  678. package/dist/core/scene/statedFields.js.map +1 -1
  679. package/dist/core/scene/treeEdits.js +129 -98
  680. package/dist/core/scene/treeEdits.js.map +1 -1
  681. package/dist/core/scene/treeOrder.js +13 -8
  682. package/dist/core/scene/treeOrder.js.map +1 -1
  683. package/dist/core/scene/treeReads.js +25 -16
  684. package/dist/core/scene/treeReads.js.map +1 -1
  685. package/dist/core/scene/types.js +4 -3
  686. package/dist/core/scene/types.js.map +1 -1
  687. package/dist/core/scene/unionOfChildren.js +20 -10
  688. package/dist/core/scene/unionOfChildren.js.map +1 -1
  689. package/dist/core/scene/unitScopes.js +33 -8
  690. package/dist/core/scene/unitScopes.js.map +1 -1
  691. package/dist/core/scene/useScene.js +32 -24
  692. package/dist/core/scene/useScene.js.map +1 -1
  693. package/dist/core/selection/chromeState.js +41 -17
  694. package/dist/core/selection/chromeState.js.map +1 -1
  695. package/dist/core/selection/readOnlySelection.js +39 -24
  696. package/dist/core/selection/readOnlySelection.js.map +1 -1
  697. package/dist/core/selection/selectionTarget.js +14 -3
  698. package/dist/core/selection/selectionTarget.js.map +1 -1
  699. package/dist/core/selection/usePublishSceneSelection.js +20 -19
  700. package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
  701. package/dist/core/selection/useSelection.js +90 -57
  702. package/dist/core/selection/useSelection.js.map +1 -1
  703. package/dist/core/shapeKinds.js +57 -28
  704. package/dist/core/shapeKinds.js.map +1 -1
  705. package/dist/core/stableStringify.js +5 -4
  706. package/dist/core/stableStringify.js.map +1 -1
  707. package/dist/core/stylus/stylus.js +49 -25
  708. package/dist/core/stylus/stylus.js.map +1 -1
  709. package/dist/core/stylus/usePointerStylus.js +61 -34
  710. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  711. package/dist/core/usePaintKinds.js +21 -11
  712. package/dist/core/usePaintKinds.js.map +1 -1
  713. package/dist/core/viewport/clampView.js +31 -15
  714. package/dist/core/viewport/clampView.js.map +1 -1
  715. package/dist/core/viewport/clientToWorld.js +15 -4
  716. package/dist/core/viewport/clientToWorld.js.map +1 -1
  717. package/dist/core/viewport/createVelocityTracker.js +23 -19
  718. package/dist/core/viewport/createVelocityTracker.js.map +1 -1
  719. package/dist/core/viewport/fitToBounds.js +28 -11
  720. package/dist/core/viewport/fitToBounds.js.map +1 -1
  721. package/dist/core/viewport/fitViewToBounds.js +45 -19
  722. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  723. package/dist/core/viewport/interpolateView.js +40 -20
  724. package/dist/core/viewport/interpolateView.js.map +1 -1
  725. package/dist/core/viewport/parallax.js +89 -56
  726. package/dist/core/viewport/parallax.js.map +1 -1
  727. package/dist/core/viewport/sceneNodeClientRect.js +21 -12
  728. package/dist/core/viewport/sceneNodeClientRect.js.map +1 -1
  729. package/dist/core/viewport/screenSlop.js +40 -17
  730. package/dist/core/viewport/screenSlop.js.map +1 -1
  731. package/dist/core/viewport/useAutoCenter.js +36 -22
  732. package/dist/core/viewport/useAutoCenter.js.map +1 -1
  733. package/dist/core/viewport/useCanvasSize.js +43 -22
  734. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  735. package/dist/core/viewport/useDecayLoop.js +120 -48
  736. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  737. package/dist/core/viewport/useNodeOverlayFrame.js +93 -58
  738. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -1
  739. package/dist/core/viewport/useVelocityTracker.js +9 -6
  740. package/dist/core/viewport/useVelocityTracker.js.map +1 -1
  741. package/dist/core/viewport/useViewAnimation.js +143 -84
  742. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  743. package/dist/core/viewport/view.js +48 -24
  744. package/dist/core/viewport/view.js.map +1 -1
  745. package/dist/core/viewport/viewTransform.js +8 -6
  746. package/dist/core/viewport/viewTransform.js.map +1 -1
  747. package/dist/core/viewport/viewportWorldRect.js +15 -7
  748. package/dist/core/viewport/viewportWorldRect.js.map +1 -1
  749. package/dist/core/viewport/wheelHandler.js +31 -20
  750. package/dist/core/viewport/wheelHandler.js.map +1 -1
  751. package/dist/core/viewport/zoomAt.js +47 -19
  752. package/dist/core/viewport/zoomAt.js.map +1 -1
  753. package/dist/core/viewport/zoomBounds.js +33 -17
  754. package/dist/core/viewport/zoomBounds.js.map +1 -1
  755. package/dist/cornerHandles-BHuoMs1o.d.ts +169 -0
  756. package/dist/debug/createDebugOverlayLayer.js +251 -258
  757. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  758. package/dist/debug/createDebugSink.js +69 -47
  759. package/dist/debug/createDebugSink.js.map +1 -1
  760. package/dist/debug/defaultTheme.js +20 -6
  761. package/dist/debug/defaultTheme.js.map +1 -1
  762. package/dist/debug/features.js +17 -0
  763. package/dist/debug/features.js.map +1 -0
  764. package/dist/debug/flag.js +3 -2
  765. package/dist/debug/frameStats.js +11 -9
  766. package/dist/debug/frameStats.js.map +1 -1
  767. package/dist/debug/overlayPanels.js +117 -0
  768. package/dist/debug/overlayPanels.js.map +1 -0
  769. package/dist/debug/parseDebugFlags.js +26 -27
  770. package/dist/debug/parseDebugFlags.js.map +1 -1
  771. package/dist/debug/useDebugSink.js +52 -33
  772. package/dist/debug/useDebugSink.js.map +1 -1
  773. package/dist/depSchema-BpZNOv7q.d.ts +2803 -0
  774. package/dist/devtools/handlers.js +112 -0
  775. package/dist/devtools/handlers.js.map +1 -0
  776. package/dist/devtools/history.js +71 -0
  777. package/dist/devtools/history.js.map +1 -0
  778. package/dist/devtools/hook.js +74 -0
  779. package/dist/devtools/hook.js.map +1 -0
  780. package/dist/devtools/label.js +25 -0
  781. package/dist/devtools/label.js.map +1 -0
  782. package/dist/devtools/notices.js +58 -0
  783. package/dist/devtools/notices.js.map +1 -0
  784. package/dist/devtools/protocol.js +7 -0
  785. package/dist/devtools/protocol.js.map +1 -0
  786. package/dist/devtools/registry.js +90 -0
  787. package/dist/devtools/registry.js.map +1 -0
  788. package/dist/devtools/root.js +80 -0
  789. package/dist/devtools/root.js.map +1 -0
  790. package/dist/devtools/serialize.js +86 -0
  791. package/dist/devtools/serialize.js.map +1 -0
  792. package/dist/devtools/session.js +111 -0
  793. package/dist/devtools/session.js.map +1 -0
  794. package/dist/devtools/transport.js +67 -0
  795. package/dist/devtools/transport.js.map +1 -0
  796. package/dist/devtools/useDevtoolsRoot.js +81 -0
  797. package/dist/devtools/useDevtoolsRoot.js.map +1 -0
  798. package/dist/devtools-protocol.d.ts +435 -0
  799. package/dist/devtools-protocol.js +7 -0
  800. package/dist/devtools.d.ts +8 -0
  801. package/dist/devtools.js +12 -0
  802. package/dist/devtools.js.map +1 -0
  803. package/dist/features/chrome-caps/buildChromeCtx.js +12 -10
  804. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  805. package/dist/features/chrome-caps/conditions.js +103 -25
  806. package/dist/features/chrome-caps/conditions.js.map +1 -1
  807. package/dist/features/chrome-caps/defaults.js +18 -10
  808. package/dist/features/chrome-caps/defaults.js.map +1 -1
  809. package/dist/features/chrome-caps/index.js +8 -7
  810. package/dist/features/chrome-caps/resolve.js +28 -16
  811. package/dist/features/chrome-caps/resolve.js.map +1 -1
  812. package/dist/features/chrome-caps/useChromeCaps.js +52 -44
  813. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -1
  814. package/dist/features/chrome-caps/useHoverTracking.js +58 -26
  815. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  816. package/dist/features/ingestion/contentHandlers.js +105 -36
  817. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  818. package/dist/features/ingestion/imageHandler.js +49 -29
  819. package/dist/features/ingestion/imageHandler.js.map +1 -1
  820. package/dist/features/ingestion/openFilePicker.js +27 -9
  821. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  822. package/dist/features/ingestion/placement.js +20 -11
  823. package/dist/features/ingestion/placement.js.map +1 -1
  824. package/dist/features/ingestion/registerKitHandlers.js +35 -18
  825. package/dist/features/ingestion/registerKitHandlers.js.map +1 -1
  826. package/dist/features/ingestion/svgHandler.js +60 -34
  827. package/dist/features/ingestion/svgHandler.js.map +1 -1
  828. package/dist/features/ingestion/textHandler.js +37 -16
  829. package/dist/features/ingestion/textHandler.js.map +1 -1
  830. package/dist/features/ingestion/useCanvasIngestion.js +57 -39
  831. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -1
  832. package/dist/features/ingestion/weaselJsonHandler.js +38 -28
  833. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  834. package/dist/features/longPress/longPressFeedback.js +110 -81
  835. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  836. package/dist/features/measure/actionIds.js +22 -0
  837. package/dist/features/measure/actionIds.js.map +1 -0
  838. package/dist/features/measure/measureCommands.js +180 -0
  839. package/dist/features/measure/measureCommands.js.map +1 -0
  840. package/dist/features/measure/measureContribution.js +57 -0
  841. package/dist/features/measure/measureContribution.js.map +1 -0
  842. package/dist/features/measure/measureEdits.js +82 -0
  843. package/dist/features/measure/measureEdits.js.map +1 -0
  844. package/dist/features/measure/measureGestures.js +185 -0
  845. package/dist/features/measure/measureGestures.js.map +1 -0
  846. package/dist/features/measure/measureHit.js +80 -0
  847. package/dist/features/measure/measureHit.js.map +1 -0
  848. package/dist/features/measure/measureLayer.js +86 -0
  849. package/dist/features/measure/measureLayer.js.map +1 -0
  850. package/dist/features/measure/measurement.js +79 -0
  851. package/dist/features/measure/measurement.js.map +1 -0
  852. package/dist/features/measure/measurements.js +41 -0
  853. package/dist/features/measure/measurements.js.map +1 -0
  854. package/dist/features/modes/modeLayers.js +81 -55
  855. package/dist/features/modes/modeLayers.js.map +1 -1
  856. package/dist/features/modes/modeTriggers.js +66 -0
  857. package/dist/features/modes/modeTriggers.js.map +1 -0
  858. package/dist/features/pathEffects/index.js +35 -0
  859. package/dist/features/pathEffects/index.js.map +1 -0
  860. package/dist/features/pathEffects/readSource.js +46 -0
  861. package/dist/features/pathEffects/readSource.js.map +1 -0
  862. package/dist/features/paths/anchorData.js +65 -0
  863. package/dist/features/paths/anchorData.js.map +1 -0
  864. package/dist/features/paths/anchorMarkers.js +137 -0
  865. package/dist/features/paths/anchorMarkers.js.map +1 -0
  866. package/dist/features/paths/editablePath.js +149 -46
  867. package/dist/features/paths/editablePath.js.map +1 -1
  868. package/dist/features/paths/index.js +12 -9
  869. package/dist/features/paths/originProjection.js +16 -9
  870. package/dist/features/paths/originProjection.js.map +1 -1
  871. package/dist/features/paths/pathEditExtension.js +26 -0
  872. package/dist/features/paths/pathEditExtension.js.map +1 -0
  873. package/dist/features/paths/pathEditState.js +107 -26
  874. package/dist/features/paths/pathEditState.js.map +1 -1
  875. package/dist/features/paths/pathEditingOverlayLayer.js +58 -110
  876. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  877. package/dist/features/paths/pathLayer.js +79 -29
  878. package/dist/features/paths/pathLayer.js.map +1 -1
  879. package/dist/features/paths/pathRepresentation.js +27 -0
  880. package/dist/features/paths/pathRepresentation.js.map +1 -0
  881. package/dist/features/paths/pathSnap/glyphs.js +39 -0
  882. package/dist/features/paths/pathSnap/glyphs.js.map +1 -0
  883. package/dist/features/paths/pathSnap/pathSnapSource.js +82 -0
  884. package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -0
  885. package/dist/features/paths/pathSnap/sceneIndex.js +85 -0
  886. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -0
  887. package/dist/features/paths/pathSnap/snapGeometry.js +47 -0
  888. package/dist/features/paths/pathSnap/snapGeometry.js.map +1 -0
  889. package/dist/features/paths/penPreviewLayer.js +135 -102
  890. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  891. package/dist/features/paths/shapeGenerator.js +112 -60
  892. package/dist/features/paths/shapeGenerator.js.map +1 -1
  893. package/dist/features/paths/strokeOutline.js +15 -0
  894. package/dist/features/paths/strokeOutline.js.map +1 -0
  895. package/dist/features/paths/useAnchorFields.js +35 -0
  896. package/dist/features/paths/useAnchorFields.js.map +1 -0
  897. package/dist/features/paths/usePathEdit.js +58 -28
  898. package/dist/features/paths/usePathEdit.js.map +1 -1
  899. package/dist/features/poseRun/usePoseRun.js +110 -43
  900. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  901. package/dist/features/selection/handleCommands.js +116 -0
  902. package/dist/features/selection/handleCommands.js.map +1 -0
  903. package/dist/features/selection/overlay.js +288 -328
  904. package/dist/features/selection/overlay.js.map +1 -1
  905. package/dist/features/selection/selectionPose.js +112 -0
  906. package/dist/features/selection/selectionPose.js.map +1 -0
  907. package/dist/features/snap/angle2d.js +158 -0
  908. package/dist/features/snap/angle2d.js.map +1 -0
  909. package/dist/features/snap/debugCandidates.js +27 -0
  910. package/dist/features/snap/debugCandidates.js.map +1 -0
  911. package/dist/features/snap/gather.js +79 -0
  912. package/dist/features/snap/gather.js.map +1 -0
  913. package/dist/features/snap/inputSubspace.js +46 -0
  914. package/dist/features/snap/inputSubspace.js.map +1 -0
  915. package/dist/features/snap/lazySession.js +17 -0
  916. package/dist/features/snap/lazySession.js.map +1 -0
  917. package/dist/features/snap/marks.js +29 -0
  918. package/dist/features/snap/marks.js.map +1 -0
  919. package/dist/features/snap/outcomeStore.js +25 -0
  920. package/dist/features/snap/outcomeStore.js.map +1 -0
  921. package/dist/features/snap/pointSnap.js +48 -0
  922. package/dist/features/snap/pointSnap.js.map +1 -0
  923. package/dist/features/snap/probes2d.js +99 -0
  924. package/dist/features/snap/probes2d.js.map +1 -0
  925. package/dist/features/snap/readoutDraw.js +93 -0
  926. package/dist/features/snap/readoutDraw.js.map +1 -0
  927. package/dist/features/snap/readoutLayer.js +49 -0
  928. package/dist/features/snap/readoutLayer.js.map +1 -0
  929. package/dist/features/snap/registry.js +27 -0
  930. package/dist/features/snap/registry.js.map +1 -0
  931. package/dist/features/snap/resizeBox.js +137 -0
  932. package/dist/features/snap/resizeBox.js.map +1 -0
  933. package/dist/features/snap/roles.js +32 -0
  934. package/dist/features/snap/roles.js.map +1 -0
  935. package/dist/features/snap/rotationSource.js +47 -0
  936. package/dist/features/snap/rotationSource.js.map +1 -0
  937. package/dist/features/snap/sceneReads.js +45 -0
  938. package/dist/features/snap/sceneReads.js.map +1 -0
  939. package/dist/features/snap/sceneSession2d.js +81 -0
  940. package/dist/features/snap/sceneSession2d.js.map +1 -0
  941. package/dist/features/snap/screen.js +23 -0
  942. package/dist/features/snap/screen.js.map +1 -0
  943. package/dist/features/snap/session2d.js +143 -0
  944. package/dist/features/snap/session2d.js.map +1 -0
  945. package/dist/features/snap/spanSnap.js +80 -0
  946. package/dist/features/snap/spanSnap.js.map +1 -0
  947. package/dist/features/snap/stepAngles.js +15 -0
  948. package/dist/features/snap/stepAngles.js.map +1 -0
  949. package/dist/features/text/editingDrawOne.js +32 -0
  950. package/dist/features/text/editingDrawOne.js.map +1 -0
  951. package/dist/features/text/index.js +7 -6
  952. package/dist/features/text/textHitAt.js +51 -0
  953. package/dist/features/text/textHitAt.js.map +1 -0
  954. package/dist/features/text/textLayer.js +21 -27
  955. package/dist/features/text/textLayer.js.map +1 -1
  956. package/dist/features/text/useSceneTextEdit.js +190 -128
  957. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  958. package/dist/features/viewports/viewResolver.js +48 -39
  959. package/dist/features/viewports/viewResolver.js.map +1 -1
  960. package/dist/features/viewports/viewportLayer.js +60 -29
  961. package/dist/features/viewports/viewportLayer.js.map +1 -1
  962. package/dist/iconRegistry/IconRegistryProvider.js +73 -0
  963. package/dist/iconRegistry/IconRegistryProvider.js.map +1 -0
  964. package/dist/iconRegistry/useIconGlyph.js +14 -0
  965. package/dist/iconRegistry/useIconGlyph.js.map +1 -0
  966. package/dist/iconRegistry/useIconVariant.js +29 -0
  967. package/dist/iconRegistry/useIconVariant.js.map +1 -0
  968. package/dist/icons.d.ts +6 -0
  969. package/dist/icons.js +3 -0
  970. package/dist/icons.table.js +13 -0
  971. package/dist/icons.table.js.map +1 -0
  972. package/dist/icons.table.json +546 -0
  973. package/dist/icons2.table.js +9 -0
  974. package/dist/icons2.table.js.map +1 -0
  975. package/dist/index.d.ts +4856 -5666
  976. package/dist/index.js +346 -285
  977. package/dist/input/keyState.js +118 -54
  978. package/dist/input/keyState.js.map +1 -1
  979. package/dist/input/useKeyModifiers.js +13 -7
  980. package/dist/input/useKeyModifiers.js.map +1 -1
  981. package/dist/input/useKeyState.js +23 -16
  982. package/dist/input/useKeyState.js.map +1 -1
  983. package/dist/interactions/actions/align/action.js +78 -45
  984. package/dist/interactions/actions/align/action.js.map +1 -1
  985. package/dist/interactions/actions/align/align.js +86 -48
  986. package/dist/interactions/actions/align/align.js.map +1 -1
  987. package/dist/interactions/actions/booleans/action.js +73 -33
  988. package/dist/interactions/actions/booleans/action.js.map +1 -1
  989. package/dist/interactions/actions/booleans/booleans.js +77 -70
  990. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  991. package/dist/interactions/actions/booleans/commit.js +49 -0
  992. package/dist/interactions/actions/booleans/commit.js.map +1 -0
  993. package/dist/interactions/actions/booleans/custom.js +48 -0
  994. package/dist/interactions/actions/booleans/custom.js.map +1 -0
  995. package/dist/interactions/actions/booleans/operands.js +43 -32
  996. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  997. package/dist/interactions/actions/booleans/pieces.js +29 -23
  998. package/dist/interactions/actions/booleans/pieces.js.map +1 -1
  999. package/dist/interactions/actions/booleans/placement.js +30 -17
  1000. package/dist/interactions/actions/booleans/placement.js.map +1 -1
  1001. package/dist/interactions/actions/booleans/useBooleans.js +30 -17
  1002. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  1003. package/dist/interactions/actions/booleans/useBooleansAdapter.js +8 -5
  1004. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  1005. package/dist/interactions/actions/clipboard/action.js +81 -40
  1006. package/dist/interactions/actions/clipboard/action.js.map +1 -1
  1007. package/dist/interactions/actions/clipboard/clipboardOps.js +100 -72
  1008. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  1009. package/dist/interactions/actions/clipboard/materializePaste.js +38 -19
  1010. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  1011. package/dist/interactions/actions/clipboard/wireFormat.js +66 -28
  1012. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  1013. package/dist/interactions/actions/clone/action.js +102 -70
  1014. package/dist/interactions/actions/clone/action.js.map +1 -1
  1015. package/dist/interactions/actions/clone/behaviors.js +55 -38
  1016. package/dist/interactions/actions/clone/behaviors.js.map +1 -1
  1017. package/dist/interactions/actions/defaultCommitAdapter.js +32 -10
  1018. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  1019. package/dist/interactions/actions/defaults/anchorEditing.js +252 -111
  1020. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  1021. package/dist/interactions/actions/defaults/anchorFields.js +54 -0
  1022. package/dist/interactions/actions/defaults/anchorFields.js.map +1 -0
  1023. package/dist/interactions/actions/defaults/anchorHandles.js +31 -27
  1024. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -1
  1025. package/dist/interactions/actions/defaults/anchorJoin.js +55 -37
  1026. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
  1027. package/dist/interactions/actions/defaults/areaSelect.js +56 -40
  1028. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  1029. package/dist/interactions/actions/defaults/bendSegment.js +67 -31
  1030. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
  1031. package/dist/interactions/actions/defaults/cancelGesture.js +12 -5
  1032. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  1033. package/dist/interactions/actions/defaults/clearSelection.js +22 -7
  1034. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  1035. package/dist/interactions/actions/defaults/contextMenu.js +149 -0
  1036. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -0
  1037. package/dist/interactions/actions/defaults/copySubtree.js +43 -29
  1038. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  1039. package/dist/interactions/actions/defaults/createPaintAction.js +79 -54
  1040. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  1041. package/dist/interactions/actions/defaults/delete.js +92 -55
  1042. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  1043. package/dist/interactions/actions/defaults/duplicate.js +60 -32
  1044. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  1045. package/dist/interactions/actions/defaults/enterPathEdit.js +22 -18
  1046. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  1047. package/dist/interactions/actions/defaults/enterTextEdit.js +20 -8
  1048. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  1049. package/dist/interactions/actions/defaults/escape.js +16 -7
  1050. package/dist/interactions/actions/defaults/escape.js.map +1 -1
  1051. package/dist/interactions/actions/defaults/exitPathEdit.js +6 -6
  1052. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
  1053. package/dist/interactions/actions/defaults/group.js +122 -73
  1054. package/dist/interactions/actions/defaults/group.js.map +1 -1
  1055. package/dist/interactions/actions/defaults/ingest.js +58 -39
  1056. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  1057. package/dist/interactions/actions/defaults/insertPathAnchor.js +43 -22
  1058. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  1059. package/dist/interactions/actions/defaults/nudge.js +57 -55
  1060. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  1061. package/dist/interactions/actions/defaults/nudgeSteps.js +17 -12
  1062. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -1
  1063. package/dist/interactions/actions/defaults/pathEditMarks.js +60 -0
  1064. package/dist/interactions/actions/defaults/pathEditMarks.js.map +1 -0
  1065. package/dist/interactions/actions/defaults/pathEditTools.js +57 -0
  1066. package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -0
  1067. package/dist/interactions/actions/defaults/pinchZoom.js +55 -39
  1068. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  1069. package/dist/interactions/actions/defaults/reorder.js +71 -40
  1070. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  1071. package/dist/interactions/actions/defaults/requiresSelection.js +13 -6
  1072. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  1073. package/dist/interactions/actions/defaults/segmentUnder.js +24 -16
  1074. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -1
  1075. package/dist/interactions/actions/defaults/selectAll.js +21 -7
  1076. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  1077. package/dist/interactions/actions/defaults/setFill.js +37 -21
  1078. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  1079. package/dist/interactions/actions/defaults/setFillOpacity.js +19 -10
  1080. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  1081. package/dist/interactions/actions/defaults/setStroke.js +46 -25
  1082. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  1083. package/dist/interactions/actions/defaults/setStrokeOpacity.js +19 -11
  1084. package/dist/interactions/actions/defaults/setStrokeOpacity.js.map +1 -1
  1085. package/dist/interactions/actions/defaults/slice.js +42 -17
  1086. package/dist/interactions/actions/defaults/slice.js.map +1 -1
  1087. package/dist/interactions/actions/defaults/sliceOps.js +63 -42
  1088. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  1089. package/dist/interactions/actions/defaults/toolActivate.js +34 -16
  1090. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  1091. package/dist/interactions/actions/defaults/toolResetToDefault.js +29 -10
  1092. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  1093. package/dist/interactions/actions/defaults/undoRedo.js +26 -20
  1094. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
  1095. package/dist/interactions/actions/defaults/viewportDragPan.js +91 -58
  1096. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  1097. package/dist/interactions/actions/defaults/viewportWheelPan.js +42 -23
  1098. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  1099. package/dist/interactions/actions/defaults/viewportZoom.js +107 -59
  1100. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  1101. package/dist/interactions/actions/distribute/action.js +64 -39
  1102. package/dist/interactions/actions/distribute/action.js.map +1 -1
  1103. package/dist/interactions/actions/distribute/distribute.js +53 -34
  1104. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  1105. package/dist/interactions/actions/distribute/plan.js +40 -22
  1106. package/dist/interactions/actions/distribute/plan.js.map +1 -1
  1107. package/dist/interactions/actions/drawnBoxes.js +32 -0
  1108. package/dist/interactions/actions/drawnBoxes.js.map +1 -0
  1109. package/dist/interactions/actions/edit-anchors/action.js +245 -72
  1110. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  1111. package/dist/interactions/actions/edit-anchors/extensionDrags.js +50 -0
  1112. package/dist/interactions/actions/edit-anchors/extensionDrags.js.map +1 -0
  1113. package/dist/interactions/actions/edit-anchors/geometry.js +74 -47
  1114. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  1115. package/dist/interactions/actions/edit-anchors/handleDrag.js +101 -0
  1116. package/dist/interactions/actions/edit-anchors/handleDrag.js.map +1 -0
  1117. package/dist/interactions/actions/edit-anchors/handles.js +41 -27
  1118. package/dist/interactions/actions/edit-anchors/handles.js.map +1 -1
  1119. package/dist/interactions/actions/edit-anchors/params.js +12 -0
  1120. package/dist/interactions/actions/edit-anchors/params.js.map +1 -0
  1121. package/dist/interactions/actions/edit-anchors/preview.js +93 -18
  1122. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
  1123. package/dist/interactions/actions/edit-anchors/symmetry.js +12 -7
  1124. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -1
  1125. package/dist/interactions/actions/flip/action.js +121 -61
  1126. package/dist/interactions/actions/flip/action.js.map +1 -1
  1127. package/dist/interactions/actions/flip/helpers.js +69 -36
  1128. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  1129. package/dist/interactions/actions/geometryProjection.js +17 -12
  1130. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  1131. package/dist/interactions/actions/gestureFrames.js +20 -11
  1132. package/dist/interactions/actions/gestureFrames.js.map +1 -1
  1133. package/dist/interactions/actions/gestureLifecycle.js +96 -48
  1134. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  1135. package/dist/interactions/actions/hitSelection.js +6 -4
  1136. package/dist/interactions/actions/hitSelection.js.map +1 -1
  1137. package/dist/interactions/actions/insert/action.js +70 -42
  1138. package/dist/interactions/actions/insert/action.js.map +1 -1
  1139. package/dist/interactions/actions/insert/commit.js +44 -22
  1140. package/dist/interactions/actions/insert/commit.js.map +1 -1
  1141. package/dist/interactions/actions/insert/extras.js +60 -38
  1142. package/dist/interactions/actions/insert/extras.js.map +1 -1
  1143. package/dist/interactions/actions/insert/frame.js +58 -39
  1144. package/dist/interactions/actions/insert/frame.js.map +1 -1
  1145. package/dist/interactions/actions/insert/geometry.js +29 -25
  1146. package/dist/interactions/actions/insert/geometry.js.map +1 -1
  1147. package/dist/interactions/actions/insert/parent.js +11 -0
  1148. package/dist/interactions/actions/insert/parent.js.map +1 -0
  1149. package/dist/interactions/actions/insert/placeAction.js +113 -0
  1150. package/dist/interactions/actions/insert/placeAction.js.map +1 -0
  1151. package/dist/interactions/actions/insert/repositionAction.js +26 -11
  1152. package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
  1153. package/dist/interactions/actions/insert/rotateAction.js +19 -8
  1154. package/dist/interactions/actions/insert/rotateAction.js.map +1 -1
  1155. package/dist/interactions/actions/insert/session.js +61 -41
  1156. package/dist/interactions/actions/insert/session.js.map +1 -1
  1157. package/dist/interactions/actions/insert/shape.js +83 -25
  1158. package/dist/interactions/actions/insert/shape.js.map +1 -1
  1159. package/dist/interactions/actions/lasso-select/action.js +160 -100
  1160. package/dist/interactions/actions/lasso-select/action.js.map +1 -1
  1161. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +44 -25
  1162. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
  1163. package/dist/interactions/actions/move/action.js +91 -52
  1164. package/dist/interactions/actions/move/action.js.map +1 -1
  1165. package/dist/interactions/actions/move/behaviors/layoutDrop.js +55 -36
  1166. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
  1167. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +20 -10
  1168. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -1
  1169. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +40 -24
  1170. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
  1171. package/dist/interactions/actions/move/behaviors/snapToContainer.js +102 -64
  1172. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  1173. package/dist/interactions/actions/move/capture.js +103 -78
  1174. package/dist/interactions/actions/move/capture.js.map +1 -1
  1175. package/dist/interactions/actions/move/commit/index.js +41 -34
  1176. package/dist/interactions/actions/move/commit/index.js.map +1 -1
  1177. package/dist/interactions/actions/move/commit/layoutDrop.js +43 -32
  1178. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -1
  1179. package/dist/interactions/actions/move/commit/layoutRelease.js +97 -77
  1180. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -1
  1181. package/dist/interactions/actions/move/commit/rebase.js +16 -13
  1182. package/dist/interactions/actions/move/commit/rebase.js.map +1 -1
  1183. package/dist/interactions/actions/move/commit/reparent.js +89 -57
  1184. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  1185. package/dist/interactions/actions/move/delta.js +58 -36
  1186. package/dist/interactions/actions/move/delta.js.map +1 -1
  1187. package/dist/interactions/actions/move/frame.js +66 -35
  1188. package/dist/interactions/actions/move/frame.js.map +1 -1
  1189. package/dist/interactions/actions/move/gestureAdapter.js +30 -20
  1190. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  1191. package/dist/interactions/actions/move/landedDescendants.js +43 -25
  1192. package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
  1193. package/dist/interactions/actions/move/layout/container.js +93 -72
  1194. package/dist/interactions/actions/move/layout/container.js.map +1 -1
  1195. package/dist/interactions/actions/move/layout/dragged.js +61 -39
  1196. package/dist/interactions/actions/move/layout/dragged.js.map +1 -1
  1197. package/dist/interactions/actions/move/layout/dropPass.js +153 -94
  1198. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
  1199. package/dist/interactions/actions/move/layout/exits.js +58 -30
  1200. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  1201. package/dist/interactions/actions/move/layout/glide.js +55 -34
  1202. package/dist/interactions/actions/move/layout/glide.js.map +1 -1
  1203. package/dist/interactions/actions/move/session.js +96 -56
  1204. package/dist/interactions/actions/move/session.js.map +1 -1
  1205. package/dist/interactions/actions/move/translate.js +37 -51
  1206. package/dist/interactions/actions/move/translate.js.map +1 -1
  1207. package/dist/interactions/actions/moveNodes.js +87 -0
  1208. package/dist/interactions/actions/moveNodes.js.map +1 -0
  1209. package/dist/interactions/actions/outlines/createOutlines.js +28 -20
  1210. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  1211. package/dist/interactions/actions/outlines/createOutlinesAction.js +43 -31
  1212. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
  1213. package/dist/interactions/actions/outlines/outlineStroke.js +68 -45
  1214. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
  1215. package/dist/interactions/actions/outlines/outlineStrokeAction.js +24 -19
  1216. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -1
  1217. package/dist/interactions/actions/outlines/replaceWithPaths.js +57 -42
  1218. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -1
  1219. package/dist/interactions/actions/outlines/strokeRegion.js +37 -22
  1220. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -1
  1221. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js +8 -5
  1222. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js.map +1 -1
  1223. package/dist/interactions/actions/pathCommands/cutJoin.js +119 -72
  1224. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
  1225. package/dist/interactions/actions/pathCommands/livePathEdit.js +74 -40
  1226. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -1
  1227. package/dist/interactions/actions/pathCommands/pathNodes.js +91 -82
  1228. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -1
  1229. package/dist/interactions/actions/pathCommands/simplifyOffset.js +52 -28
  1230. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -1
  1231. package/dist/interactions/actions/pathGestureTags.js +29 -0
  1232. package/dist/interactions/actions/pathGestureTags.js.map +1 -0
  1233. package/dist/interactions/actions/planeInput.js +198 -123
  1234. package/dist/interactions/actions/planeInput.js.map +1 -1
  1235. package/dist/interactions/actions/pointerState.js +12 -7
  1236. package/dist/interactions/actions/pointerState.js.map +1 -1
  1237. package/dist/interactions/actions/poseDescriptorDep.js +24 -14
  1238. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  1239. package/dist/interactions/actions/poseFrame.js +45 -28
  1240. package/dist/interactions/actions/poseFrame.js.map +1 -1
  1241. package/dist/interactions/actions/resize/action.js +103 -63
  1242. package/dist/interactions/actions/resize/action.js.map +1 -1
  1243. package/dist/interactions/actions/resize/aspect.js +44 -0
  1244. package/dist/interactions/actions/resize/aspect.js.map +1 -0
  1245. package/dist/interactions/actions/resize/behaviors/clampMinSize.js +38 -13
  1246. package/dist/interactions/actions/resize/behaviors/clampMinSize.js.map +1 -1
  1247. package/dist/interactions/actions/resize/boxFrame.js +15 -11
  1248. package/dist/interactions/actions/resize/boxFrame.js.map +1 -1
  1249. package/dist/interactions/actions/resize/capture.js +105 -62
  1250. package/dist/interactions/actions/resize/capture.js.map +1 -1
  1251. package/dist/interactions/actions/resize/commit.js +76 -56
  1252. package/dist/interactions/actions/resize/commit.js.map +1 -1
  1253. package/dist/interactions/actions/resize/cornerHandles.js +154 -17
  1254. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
  1255. package/dist/interactions/actions/resize/frame.js +133 -66
  1256. package/dist/interactions/actions/resize/frame.js.map +1 -1
  1257. package/dist/interactions/actions/resize/minimum.js +35 -0
  1258. package/dist/interactions/actions/resize/minimum.js.map +1 -0
  1259. package/dist/interactions/actions/resize/replay.js +40 -30
  1260. package/dist/interactions/actions/resize/replay.js.map +1 -1
  1261. package/dist/interactions/actions/resize/ruleBounds.js +8 -5
  1262. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -1
  1263. package/dist/interactions/actions/resize/session.js +97 -50
  1264. package/dist/interactions/actions/resize/session.js.map +1 -1
  1265. package/dist/interactions/actions/resolveOverlays.js +48 -33
  1266. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  1267. package/dist/interactions/actions/resolvePreviews.js +63 -46
  1268. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  1269. package/dist/interactions/actions/rotate/action.js +71 -42
  1270. package/dist/interactions/actions/rotate/action.js.map +1 -1
  1271. package/dist/interactions/actions/rotate/commit.js +40 -31
  1272. package/dist/interactions/actions/rotate/commit.js.map +1 -1
  1273. package/dist/interactions/actions/rotate/frame.js +75 -47
  1274. package/dist/interactions/actions/rotate/frame.js.map +1 -1
  1275. package/dist/interactions/actions/rotate/geometry.js +36 -24
  1276. package/dist/interactions/actions/rotate/geometry.js.map +1 -1
  1277. package/dist/interactions/actions/rotate/handle.js +28 -15
  1278. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  1279. package/dist/interactions/actions/rotate/replay.js +22 -18
  1280. package/dist/interactions/actions/rotate/replay.js.map +1 -1
  1281. package/dist/interactions/actions/rotate/session.js +117 -76
  1282. package/dist/interactions/actions/rotate/session.js.map +1 -1
  1283. package/dist/interactions/actions/selectionSubtree.js +135 -53
  1284. package/dist/interactions/actions/selectionSubtree.js.map +1 -1
  1285. package/dist/interactions/actions/spatialReference.js +33 -26
  1286. package/dist/interactions/actions/spatialReference.js.map +1 -1
  1287. package/dist/interactions/actions/testUtils.js +53 -0
  1288. package/dist/interactions/actions/testUtils.js.map +1 -0
  1289. package/dist/interactions/actions/transform-again/action.js +49 -35
  1290. package/dist/interactions/actions/transform-again/action.js.map +1 -1
  1291. package/dist/interactions/actions/transform-again/memory.js +32 -21
  1292. package/dist/interactions/actions/transform-again/memory.js.map +1 -1
  1293. package/dist/interactions/actions/transformFinish.js +106 -0
  1294. package/dist/interactions/actions/transformFinish.js.map +1 -0
  1295. package/dist/interactions/actions/useActionSet.js +83 -0
  1296. package/dist/interactions/actions/useActionSet.js.map +1 -0
  1297. package/dist/interactions/actions/useStandardActions.js +23 -165
  1298. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  1299. package/dist/interactions/gestures/dragGesture/dragGesture.js +109 -68
  1300. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
  1301. package/dist/interactions/gestures/dragGesture/dragPointOf.js +17 -10
  1302. package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -1
  1303. package/dist/interactions/gestures/dragRadial/dragRadial.js +129 -93
  1304. package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -1
  1305. package/dist/interactions/gestures/dragRect/dragRect.js +155 -111
  1306. package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -1
  1307. package/dist/interactions/gestures/handleDrag/handleDrag.js +52 -30
  1308. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
  1309. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +168 -97
  1310. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  1311. package/dist/interactions/gestures/shared/originProjection.js +32 -25
  1312. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  1313. package/dist/interactions/gestures/shared/screenTolerance.js +26 -17
  1314. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  1315. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +39 -21
  1316. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  1317. package/dist/kitSettingsSchema.js +76 -0
  1318. package/dist/kitSettingsSchema.js.map +1 -0
  1319. package/dist/{math-CYUjoyyU.d.ts → math-CrJULaZI.d.ts} +5 -6
  1320. package/dist/math.d.ts +4 -5
  1321. package/dist/math.js +7 -6
  1322. package/dist/mesh.js +3 -2
  1323. package/dist/move.d.ts +9 -7
  1324. package/dist/move.js +4 -3
  1325. package/dist/{originProjection-CoNVpITV.d.ts → options-DBxEryYq.d.ts} +4 -27
  1326. package/dist/originProjection-gY0jb4Wb.d.ts +24 -0
  1327. package/dist/patterns-builtin.js +3 -2
  1328. package/dist/{poseDescriptor-Bqk-11Rl.d.ts → poseDescriptor-DN2yfnq_.d.ts} +7 -7
  1329. package/dist/renderer.d.ts +1 -1
  1330. package/dist/renderer.js +3 -2
  1331. package/dist/resize.d.ts +11 -28
  1332. package/dist/resize.js +6 -7
  1333. package/dist/routing.d.ts +1 -1
  1334. package/dist/routing.js +3 -2
  1335. package/dist/style.css +88 -1
  1336. package/dist/test-hook/createTestHook.js +23 -20
  1337. package/dist/test-hook/createTestHook.js.map +1 -1
  1338. package/dist/test-hook/install.js +32 -13
  1339. package/dist/test-hook/install.js.map +1 -1
  1340. package/dist/test-hook/useTestHook.js +23 -16
  1341. package/dist/test-hook/useTestHook.js.map +1 -1
  1342. package/dist/test-seams.d.ts +168 -1
  1343. package/dist/test-seams.js +8 -3
  1344. package/dist/tools/builtin/ellipse/useEllipseTool.js +22 -17
  1345. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  1346. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +44 -28
  1347. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  1348. package/dist/tools/builtin/hand/dragPanContribution.js +12 -7
  1349. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
  1350. package/dist/tools/builtin/hand/useHandTool.js +21 -13
  1351. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  1352. package/dist/tools/builtin/image/useImageTool.js +28 -19
  1353. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  1354. package/dist/tools/builtin/lasso/useLassoTool.js +48 -36
  1355. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  1356. package/dist/tools/builtin/line/useLineTool.js +24 -17
  1357. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  1358. package/dist/tools/builtin/measure/useMeasureTool.js +84 -0
  1359. package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -0
  1360. package/dist/tools/builtin/pen/penHandle.js +58 -0
  1361. package/dist/tools/builtin/pen/penHandle.js.map +1 -0
  1362. package/dist/tools/builtin/pen/usePenTool.js +461 -303
  1363. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  1364. package/dist/tools/builtin/pencil/usePencilTool.js +20 -15
  1365. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  1366. package/dist/tools/builtin/pickTopMostHit.js +51 -31
  1367. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  1368. package/dist/tools/builtin/polygon/usePolygonTool.js +45 -28
  1369. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  1370. package/dist/tools/builtin/rect/useRectTool.js +24 -16
  1371. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  1372. package/dist/tools/builtin/select/adapterPointQuery.js +47 -30
  1373. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  1374. package/dist/tools/builtin/select/selectionContributions.js +94 -56
  1375. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  1376. package/dist/tools/builtin/select/useSelectTool.js +155 -108
  1377. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  1378. package/dist/tools/builtin/shared/insertToolOptions.js +5 -4
  1379. package/dist/tools/builtin/shared/insertToolOptions.js.map +1 -1
  1380. package/dist/tools/builtin/shared/pointerFollower.js +15 -8
  1381. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  1382. package/dist/tools/builtin/slice/useSliceTool.js +148 -101
  1383. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  1384. package/dist/tools/builtin/star/useStarTool.js +48 -31
  1385. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  1386. package/dist/tools/builtin/sticky/stickyNode.js +49 -0
  1387. package/dist/tools/builtin/sticky/stickyNode.js.map +1 -0
  1388. package/dist/tools/builtin/sticky/useStickyTool.js +86 -0
  1389. package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -0
  1390. package/dist/tools/builtin/text/useTextTool.js +59 -34
  1391. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  1392. package/dist/tools/index.js +26 -0
  1393. package/dist/tools/overlayBinding.js +7 -5
  1394. package/dist/tools/overlayBinding.js.map +1 -1
  1395. package/dist/tools/useKeybindings.js +62 -46
  1396. package/dist/tools/useKeybindings.js.map +1 -1
  1397. package/dist/{types-DBbbCy0i.d.ts → types-7puAuVD2.d.ts} +5 -264
  1398. package/dist/types-BN9hbdMI.d.ts +184 -0
  1399. package/dist/types-CniVctmk.d.ts +949 -0
  1400. package/dist/types-oFeQ5VjV.d.ts +264 -0
  1401. package/dist/util/color.js +39 -18
  1402. package/dist/util/color.js.map +1 -1
  1403. package/dist/util/paint.js +93 -38
  1404. package/dist/util/paint.js.map +1 -1
  1405. package/dist/version.js +11 -3
  1406. package/dist/version.js.map +1 -1
  1407. package/package.json +46 -24
  1408. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +0 -126
  1409. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +0 -1
  1410. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +0 -55
  1411. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +0 -1
  1412. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +0 -16
  1413. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +0 -1
  1414. package/dist/canvas/SceneCanvas/isDev.js +0 -12
  1415. package/dist/canvas/SceneCanvas/isDev.js.map +0 -1
  1416. package/dist/canvas/SceneCanvas/useViewLayerGate.js +0 -20
  1417. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +0 -1
  1418. package/dist/cornerHandles-BSKbyuvQ.d.ts +0 -104
  1419. package/dist/icons/ArrowIcon.js +0 -23
  1420. package/dist/icons/ArrowIcon.js.map +0 -1
  1421. package/dist/icons/EllipseIcon.js +0 -21
  1422. package/dist/icons/EllipseIcon.js.map +0 -1
  1423. package/dist/icons/EyedropperIcon.js +0 -49
  1424. package/dist/icons/EyedropperIcon.js.map +0 -1
  1425. package/dist/icons/HandIcon.js +0 -59
  1426. package/dist/icons/HandIcon.js.map +0 -1
  1427. package/dist/icons/ImageIcon.js +0 -34
  1428. package/dist/icons/ImageIcon.js.map +0 -1
  1429. package/dist/icons/LassoIcon.js +0 -22
  1430. package/dist/icons/LassoIcon.js.map +0 -1
  1431. package/dist/icons/LineIcon.js +0 -22
  1432. package/dist/icons/LineIcon.js.map +0 -1
  1433. package/dist/icons/PenIcon.js +0 -36
  1434. package/dist/icons/PenIcon.js.map +0 -1
  1435. package/dist/icons/PencilIcon.js +0 -25
  1436. package/dist/icons/PencilIcon.js.map +0 -1
  1437. package/dist/icons/PolygonIcon.js +0 -19
  1438. package/dist/icons/PolygonIcon.js.map +0 -1
  1439. package/dist/icons/RectIcon.js +0 -37
  1440. package/dist/icons/RectIcon.js.map +0 -1
  1441. package/dist/icons/SelectIcon.js +0 -20
  1442. package/dist/icons/SelectIcon.js.map +0 -1
  1443. package/dist/icons/SliceIcon.js +0 -24
  1444. package/dist/icons/SliceIcon.js.map +0 -1
  1445. package/dist/icons/StarIcon.js +0 -19
  1446. package/dist/icons/StarIcon.js.map +0 -1
  1447. package/dist/icons/TextIcon.js +0 -19
  1448. package/dist/icons/TextIcon.js.map +0 -1
  1449. package/dist/icons/UnknownIcon.js +0 -33
  1450. package/dist/icons/UnknownIcon.js.map +0 -1
  1451. package/dist/icons/_base.js +0 -12
  1452. package/dist/icons/_base.js.map +0 -1
  1453. package/dist/interactions/actions/actionShortcuts.js +0 -32
  1454. package/dist/interactions/actions/actionShortcuts.js.map +0 -1
  1455. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js +0 -40
  1456. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js.map +0 -1
  1457. package/dist/interactions/actions/defaults/icons/actionGlyphs.js +0 -10
  1458. package/dist/interactions/actions/defaults/icons/actionGlyphs.js.map +0 -1
  1459. package/dist/interactions/actions/defaults/icons/alignIcons.js +0 -173
  1460. package/dist/interactions/actions/defaults/icons/alignIcons.js.map +0 -1
  1461. package/dist/interactions/actions/defaults/icons/anchorIcons.js +0 -75
  1462. package/dist/interactions/actions/defaults/icons/anchorIcons.js.map +0 -1
  1463. package/dist/interactions/actions/defaults/icons/booleanIcons.js +0 -194
  1464. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +0 -1
  1465. package/dist/interactions/actions/defaults/icons/distributeIcons.js +0 -63
  1466. package/dist/interactions/actions/defaults/icons/distributeIcons.js.map +0 -1
  1467. package/dist/interactions/actions/defaults/icons/editIcons.js +0 -307
  1468. package/dist/interactions/actions/defaults/icons/editIcons.js.map +0 -1
  1469. package/dist/interactions/actions/defaults/icons/outlineIcons.js +0 -91
  1470. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +0 -1
  1471. package/dist/interactions/actions/resize/behaviors/index.js +0 -8
  1472. package/dist/interactions/actions/resize/behaviors/index.js.map +0 -1
  1473. package/dist/interactions/actions/resize/behaviors/lockAspect.js +0 -24
  1474. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +0 -1
  1475. package/dist/interactions/actions/resize/pointSnap.js +0 -111
  1476. package/dist/interactions/actions/resize/pointSnap.js.map +0 -1
  1477. package/dist/interactions/actions/rotate/behaviors/index.js +0 -7
  1478. package/dist/interactions/actions/rotate/behaviors/index.js.map +0 -1
  1479. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +0 -12
  1480. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +0 -1
  1481. package/dist/interactions/gestures/shared/snap.js +0 -24
  1482. package/dist/interactions/gestures/shared/snap.js.map +0 -1
  1483. package/dist/test-seams-D0pyV3pR.d.ts +0 -149
  1484. package/dist/tools/builtin/bone/boneActions.js +0 -130
  1485. package/dist/tools/builtin/bone/boneActions.js.map +0 -1
  1486. package/dist/tools/builtin/bone/boneOverlay.js +0 -58
  1487. package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
  1488. package/dist/tools/builtin/bone/placedRig.js +0 -24
  1489. package/dist/tools/builtin/bone/placedRig.js.map +0 -1
  1490. package/dist/tools/builtin/bone/rigEditState.js +0 -21
  1491. package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
  1492. package/dist/tools/builtin/bone/useBoneTool.js +0 -98
  1493. package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
  1494. package/dist/tools/builtin/weight/useWeightTool.js +0 -77
  1495. package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
  1496. package/dist/tools/builtin/weight/weightActions.js +0 -112
  1497. package/dist/tools/builtin/weight/weightActions.js.map +0 -1
  1498. package/dist/tools/builtin/weight/weightOverlay.js +0 -61
  1499. package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
  1500. package/dist/util/constrainTo45.js +0 -17
  1501. package/dist/util/constrainTo45.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,1019 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.11.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 70b12d1: An action can carry a settings form: `Action.settings` holds a prefs schema, a `read` that gives
8
+ the selection's current values (and which fields it disagrees on), and an optional `params` that
9
+ turns one field's change into the params the action is triggered with. Every surface that lists
10
+ actions draws such an action as its form instead of a button that triggers it bare: a bar or a
11
+ panel opens it in a popover under the action's button, a menu shows it as a submenu of its fields,
12
+ and the command palette opens it in a dialog. Each change is one trigger, so one undo step. The
13
+ form is disabled while the action's `enabled` says no. `readActionSettings` and
14
+ `actionSettingsParams` are what the surfaces read it through; `useActionSettings`,
15
+ `ActionSettingsPopover` and `ActionSettingsDialog` are in `@weasel-js/ui/components/ActionSettings`.
16
+ `BarActionButton` takes `expanded` for a button that opens a dialog.
17
+
18
+ Warp Settings (`configureWarp`) and Edit Path Effect (`editPathEffect`) carry one each, so Warp
19
+ Settings on a bar now opens Mode, Rows, Columns, Mapping and Tolerance for the selected warps
20
+ rather than doing nothing, and both are disabled with nothing they apply to selected.
21
+ `editPathEffect` takes an optional `kind`, limiting an edit to effects of that kind, and now reads
22
+ `selection`. The forms are exported as `warpSettingsForm` and `pathEffectSettingsForm`.
23
+ - 3b5750f: Set, swap, or release the spine of a blend that already exists. `setBlendSpineAction`
24
+ (`setBlendSpine`) lays the selected blend along the other selected path, in either selection order,
25
+ replacing any spine it had; `releaseBlendSpineAction` (`releaseBlendSpine`) puts each selected
26
+ blend back on a straight run between its two shapes and selects the spines, ordinary paths where
27
+ they were. Both are in `pathEffectsPreset` and the `pathEffects` group, and each is one undo step.
28
+
29
+ Core adds `createSetDependsOnOp`, an undoable retarget of a derived node's `dependsOn`, and the
30
+ `setDependsOn` write it goes through on `SceneMutators` and the scene-backed adapter.
31
+ - 768be71: Depend on `@msb235/blits` 0.11.0, where stopping an animation no longer costs time in step with how many are running. blits' `loop` now defaults to one pass; no voice weasel cues depends on it, since each is either a motion (a tween or a spring) or a patch with no duration, and blits ignores `loop` for both.
32
+ - 9390be4: `CANVAS_CONTEXT_ATTRIBUTES` is the WebGL2 context attributes a weasel canvas is opened with. A
33
+ context keeps the attributes of whoever opens it first and the renderer refuses one without a
34
+ stencil buffer, so anything that may open the canvas before its first paint, such as a pixel reader
35
+ or a tenant sharing the buffer, passes these.
36
+ - 1dd65f5: `<Canvas>` and `<SceneCanvas>` take an `imageMinification` prop, forwarded to the renderer: `'auto'` builds an image's mipmaps the first time a frame draws it at half size or smaller, so a large bitmap drawn small stops aliasing. The default stays `'linear'`. `WeaselRenderer.setImageMinification` changes the strategy after construction; a change frees every image texture, and each re-uploads when next drawn.
37
+ - 411b629: A `carry` spec takes a `target`, matched against what is under the carry the way a click's is: a binding can now say "dropped onto a selected body" or onto an affordance. An immediate action with a target fires only on a release over it; an ongoing one starts on the first step over its target, as the carry comes over or as it moves on. The route grammar reads `carry(lab/*) => selected-body`. A carry's immediate params carry `affordance`, `bodyTarget`, and `bodyKind`.
38
+
39
+ `Action.enabled`'s `carried` argument is now the exported `Carried` type and sees a carry too: `{ items: [], carry: { type, value } }`, so an action can refuse a payload it would not take.
40
+ - 267d5e4: Connectors can route around shapes. The `avoid` router draws a connector orthogonal, with few bends,
41
+ clear of every shape, and with parallel runs spread apart. Its route is computed when the scene is
42
+ edited and stored on the edge as `diagram.route`, so a saved file draws it without rerouting and
43
+ undo restores it exactly; a stored route that no longer fits its ends draws as `orthogonal`.
44
+ `useAvoidRouting(scene)` (or `installAvoidRouting` outside React) reroutes whatever each edit
45
+ disturbed in that edit's own undo entry, and reroutes the connectors near a dragged shape every
46
+ frame. Containers, pools, and group boxes are in the way only of connectors with neither end inside
47
+ them; lane bodies never are; headers always are. Dragging a segment of an `avoid` connector pins
48
+ only that segment. `DiagramView` takes `router="avoid"`, and `createAvoidRouter` — the search alone,
49
+ over plain boxes and ports — is in `@weasel-js/diagram/layout`. New commands set the selected
50
+ connectors' router (`SET_ROUTER_ACTION_IDS`), and layout no longer writes waypoints to an `avoid`
51
+ connector.
52
+
53
+ Core adds scene edit passes: `scene.addEditPass(pass)` hears each live edit's added, removed,
54
+ posed, re-parented, and data-changed ids once its own mutations and the arrival handler have run,
55
+ and its ops join the same undo entry. Passes never re-trigger on their own writes, and undo, redo,
56
+ and history replay never run them. While any pass is added, a bare scene call runs as an edit of
57
+ its own.
58
+
59
+ weaselchart's connector tool draws connectors that route around shapes, and Format › Connector
60
+ picks Around shapes, Orthogonal, Straight, or Curved for the selected connectors. Charts saved
61
+ before keep the router they have.
62
+ - 922cddf: Diagrams get containers and swimlane pools, and core's layouts and drops carry and filter nested nodes.
63
+
64
+ - core: a layout pass that moves a child container now takes that container's descendants along, under absolute poses, in the same edit; so does a layout drop that shifts siblings, in its preview and its commit. `carriedDescendants(source, root, translate)` and `sceneCarrySource(scene)` are the helper behind both. A new optional `canDropInto(parent, ids)` dep (`CanDropIntoDep`) decides which containers a move may drop into: reparent-on-drop passes over a refused container, the layout drop skips it, and a child leaving its layout container does not land in it.
65
+ - diagram: `CONTAINER_STENCILS` offers Container, Pool (rows), and Pool (columns). A container is a titled box whose members move with it and stay put when it is resized; a pool stacks lanes that reorder by their headers, resize by the boundary after each (`diagram.resizeLane`), and grow by the button past the stack (`diagram.addLane`). `diagram.releaseMembers` removes a container and keeps what it holds. `diagramCanDropInto(scene)` is the drop filter, `diagramContainers` returns the lane layer and the contribution, and `diagramContainerLayout` and `laneStackLayout` register through `withDiagramRegistry`. `useStencilInsert` takes `containers`, and a stencil drawn inside a container or a lane becomes its member. Lanes take no connectors, and `diagramResizable` refuses them.
66
+ - core: a container with a layout is arranged again whenever one of its children's poses is written — a nudge, an align, a panel edit — not only when its children or its size change, in the same undo entry as the write.
67
+ - d5a4102: Breaking at the type level for custom `commit` and `canConnect` callbacks: the ends of a `PendingEdge` and the arguments of `CanConnect` are now a `ConnectEnd`, which is a port or a shape's body, where they were always a port.
68
+
69
+ `@weasel-js/diagram` gains editing surface. Edges connect onto a shape's body (`connectBodies`, the `bodies` option, and a connector tool), and a selected edge's ends reconnect by dragging a handle. A label action (`editEdgeLabelAction`, `edgeLabelSpec`, `labelSize`) creates and edits an edge's label. Stencils (`FLOWCHART_STENCILS`) come with `useStencilInsert` and `useStencilTool`. `DiagramView` takes `onReconnect`, `onDelete`, `onEditLabel`, `connectBodies` and `ambient`, and its ref has `worldAt`. `diagramResizable` keeps resize handles off edges and labels. `DataEdge` and `EffectWire` take an optional `id`, and the `ellipse` outline is new. For effect pipelines there is an edit model, stage types with typed params, and `EffectEditor`, an editable node graph.
70
+
71
+ `@weasel-js/core` exports `createDeleteAction` and `commitDeleteToScene`, so a consumer can swap how a delete commits.
72
+ - 9cd12f7: Edge labels are obstacles, and they dodge. An `avoid` connector now routes around every other
73
+ connector's label, 4 world units clear (`labelClearance`), and never around its own; within one
74
+ commit a label is restationed on its connector's new route before the next connector routes.
75
+ `AvoidEdge.label` carries it, filled from the scene and from `DiagramView`'s specs. An obstacle's
76
+ `kind` may now be `'label'`.
77
+
78
+ After any edit, `useLabelPlacement(scene)` (or `installLabelPlacement` outside React) moves a label
79
+ that sits on a shape, another label, or another connector along its own connector, or across it,
80
+ to the nearest clear station, in that edit's own undo entry, and sizes a label to the text an edit
81
+ gives it. The chosen station is stored on the label trait as `placed`, which `labelDerivePose`
82
+ reads before `at` and `offset`; `dodge: false` opts a label out. Labels hold still during a drag
83
+ and settle on release. `DiagramView` takes `labels="dodge"`, `createSpecLabelPlacer` is that step
84
+ on its own, and `placeLabels` — the placement alone, over plain boxes and routes — is in
85
+ `@weasel-js/diagram/layout` with `labelCenter`.
86
+
87
+ Core adds `documentDepOf(scene, id)`: a dependency at the pose and path the document holds, with
88
+ no override counted, for a reader such as an edit pass.
89
+
90
+ weaselchart places edge labels, so a shape dropped on a label moves the label off it on release.
91
+ - e5ba382: Connectors can jump each other. While a scene's `HOPS_DOC_KEY` document value is set, wherever two
92
+ connectors cross, the one later in render order bows over the other in a half circle of the value's
93
+ `size`. A hop bulges toward −y on a horizontal run and toward −x on a vertical one, whichever way the
94
+ connector travels, and to the left of travel on a diagonal. Crossings near either connector's ends
95
+ or a bend, and collinear overlaps, make no hop, and hops closer than twice their radius merge into
96
+ one longer hop. A connector split across pages neither hops nor is hopped over. Each connector stores its hops as `diagram.hops`, so a saved file draws them with no
97
+ pass running, and a hop no longer on its connector's route does not draw.
98
+
99
+ `useHops(scene)` (or `installHops` outside React) recomputes the hops an edit disturbed in that
100
+ edit's own undo entry, and turning the value on or off recomputes or clears them all in the one
101
+ entry that sets it. While a drag is in progress, the connectors it moves, and those hopping over
102
+ them, draw without hops until release. `diagramWaypoints` carries a Line jumps toggle
103
+ (`SET_HOPS_ACTION_ID`), `DiagramView` takes `hops`, a radius, and `edgeHops`, the crossing finder
104
+ over plain polylines, is in `@weasel-js/diagram/layout`.
105
+
106
+ Core's `TransformFollower.preview` gets a second argument: the data the followers before it
107
+ previewed, by id, so a follower can build on a route an earlier one previewed. A follower that
108
+ calls `preview` itself now passes it. `useAvoidRouting`'s drag preview reads the waypoints a
109
+ `waypointFollower` registered before it carried, rather than carrying them itself, so without one
110
+ the preview leaves waypoints where the commit will.
111
+
112
+ weaselchart adds Format › Connector › Line jumps.
113
+ - 8e317f5: Off-page reference markers. On a scene with pages, a connector whose two shapes sit on different
114
+ pages no longer draws across the gap: each end draws a short stub out of its shape, ending at a tag
115
+ that reads the other page's name and a reference letter, such as "Page 2 · A".
116
+ `useOffPageMarkers` (or `installOffPageMarkers` without React) splits and joins connectors as edits
117
+ move their ends or change the pages, in that edit's own undo entry, and writes
118
+ `DiagramEdge.offPage`. The tags are text nodes with a background (`offPageTagSpec`, registry key
119
+ `diagram:offPageTag`), colored by the theme. `diagramOffPage()` binds a double-click on a tag to
120
+ selecting the shape at the far end and fitting the view to its page. `offPageSplits` is the split
121
+ rule as arithmetic, and `offPageOps` runs the pass over named connectors.
122
+
123
+ A split connector's `ResolvedRoute` carries its two `stubs`, it shows no route handles, and the
124
+ `avoid` router leaves it out until it joins again. An edge label on a path with several subpaths
125
+ sits on the first (`subpathOf`).
126
+
127
+ `pageName` (core) is the name a page shows, its own or "Page" and its place, and `PageTabs` uses it.
128
+ - abf41a7: Scenes hold document values, and a document's pages are one of them.
129
+
130
+ - core: `scene.doc` holds named JSON values beside the tree (`get`, `set`, `keys`). A `set` is undoable, joins an enclosing `batch`, is skipped when the value is deep-equal, and notifies subscribers. `SerializedScene.doc` carries them, `sceneFromJSON` and `loadState` read them back, and `createScene` and `useScene` take `doc` for the starting values. The field is additive: a snapshot without it loads as before. New types: `SceneDoc`, `SceneDocValues`, `SerializedDoc`.
131
+ - core: the page list is the `core:pages` document value (`PAGES_DOC_KEY`, `PagesDoc`, `pagesOf`, `placedPagesOf`). `setPages` replaces it and moves each page's root nodes, with their descendants, by however far their page moved, in one undo entry; `addPage`, `removePage` (which deletes what is on the page and what derives from that), `movePage`, `resizePage`, and `renamePage` are built on it, with `pageMembers` and `nextPageId` beside them. `pageInView` answers the page a view shows most of.
132
+ - ui: `PageTabs` is a strip of tabs over any page list, built on `Tabs`: press to go to a page, press twice to rename, drag or Alt+arrow to reorder, + to add, and a right-click reported for a context menu. `useReorderDragList` takes `axis: 'x'` for a row of items, and `TabList` takes a `ref`.
133
+ - 312eb35: Themes can be edited. `forkTheme`, `setThemeValue` (by a `ThemePath` such as
134
+ `['roles', 'accent', 'fill']` or `['series', 2]`), `addThemeRole`, `renameThemeRole`, and
135
+ `removeThemeRole` return a new theme and leave the one given alone, so a shipped theme is never
136
+ changed; `editableTheme` forks a shipped theme and passes a custom one through. `DiagramTheme` takes
137
+ `roleLabels`, the names of roles beyond the shipped six, and `themeRoles(theme)` lists every role
138
+ with its name. A removed role's shapes are drawn in the default role. `parseDiagramTheme` and
139
+ `themeToJson` read and write `.weasel-theme.json` files, and a bad file comes back as errors naming
140
+ each bad value by its path. `applyDiagramTheme` takes `{ coalesceKey, from }`.
141
+
142
+ Applying a theme whose font size differs from the scene's moves existing text by the step between
143
+ them: shape rows, titles, and connector labels keep their offset from the body size.
144
+ `setDiagramFontSize(scene, ids, size)` sets a shape's or connector's text size by hand and records
145
+ it in the trait's new `ownFont` (`FontField`), which a theme's size change then leaves and choosing
146
+ a role keeps. A body whose text changes size is laid out again in the same undo entry: it grows
147
+ to fit its rows and never shrinks. A body built from text rows alone records how it stacks them
148
+ as `DiagramNode.body`, its rows carrying `bodyRow`; `relayoutBodies` lays such bodies out again,
149
+ and `rendererMeasure` measures text from the registered font as the renderer draws it.
150
+
151
+ Core's `scene.batch(label, fn, { coalesceKey })` folds a batch into the undo entry before it when
152
+ that one was recorded under the same key and nothing came between, so a run of batches, such as a
153
+ color dragged, undoes as one entry back to the state before the first. Unlike an op's own key it
154
+ needs no `coalesceWindowMs`; `scene.history.seal()` ends the run. `@weasel-js/history`'s
155
+ `recordEntry` takes the same `coalesceKey`.
156
+
157
+ weaselchart's Format › Theme › Edit Theme… opens a Theme panel: every role's colors, with roles
158
+ added, renamed, and removed (not the default), the connector, label, container, lane, page, and
159
+ series colors, and the font. The Style panel gains Text size. The chart recolors as a color is dragged, and one undo takes back the
160
+ drag. The first edit to a shipped theme copies it into the chart as "<name> (edited)". Import
161
+ Theme… and Export Theme… move a theme between charts.
162
+ - 7ffc196: Connector routes are editable, and whole-node transforms carry other nodes along through one dep.
163
+
164
+ - core: a `transformFollowers` dep holds every `TransformFollower`, `{ preview(frame), finish(ops, label) }`, and each whole-node transform (move, resize, rotate, flip, align, distribute, nudge, transform again) finishes its batch and previews its frame through all of them in order. `useTransformFollower` adds one. Path edit's constraint links are now one of them, so `EditAnchorsDep.transformOps` and `EditAnchorsDep.transformPreview` are gone; that is breaking for anyone who called them. `writtenBy(scene, ops)` reads the pose and data a batch leaves each node it writes.
165
+ - diagram: a selected edge shows handles along its route. Under `straight` and `bezier`, a dot on each waypoint moves it and a hollow dot in each leg inserts one; under `orthogonal`, a bar slides its segment, jogging where it touches a port. A double-click removes a waypoint or straightens a jog. Drags snap into line with neighboring stops and port axes. `diagramWaypoints` returns the handle layer and a contribution carrying the drag, the double-click, and the `diagram.resetRoute` command; the math is exported on its own (`routeHandles`, `dragSegment`, `simplifyStops`, and the rest). `waypointFollower(scene)` carries waypoints along with a move of both ends. `DiagramView` takes `onEditRoute`, and `EffectEditor` keeps wire routes in `EffectDoc.routes` (`setWireRoute`). `edgeRouter` answers an edge's resolved route, as `edgeDerivePath` draws it.
166
+ - 25a112b: Constraint links follow whole-node drags live, and broken ones are drawn.
167
+
168
+ - core: move, resize and rotate preview the nodes a constraint link ties as they will commit, every frame, through the same finishing the commit runs, and `transformPreviewFields` gives a drag its preview fields with them added.
169
+ - path-tools: `createConstraintLinkMarks(style)` is a screen-space layer, carried by `constraintsPreset`, that draws every broken link: its constraint's mark by the anchor it holds and a dashed line to where it wants that anchor, in the conflict color. `brokenConstraintLink(scene, id)` and `brokenConstraintLinks(scene)` read the links that do not hold, `constraintLinkMarks` draws a list of them, and `DEFAULT_CONSTRAINT_STYLE` is exported.
170
+ - 4d99526: Constraint links now hold through whole-node transforms, preview through every path-edit drag, and have a gesture that makes them.
171
+
172
+ - core: `PathEditExtension.finishTransform(ctx: PathTransformFinishCtx)` answers the other nodes a move, resize, rotate, flip, nudge or transform-again changes along with the ones it transforms — align and distribute too — committed in the same history entry; the `editAnchors` dep runs it as `transformOps(ops, label)`, and those actions now declare `editAnchors`. An extension may refuse a transform by answering null.
173
+ - core: `pathEditPreview` finishes each frame itself through the new `finishPathEditFrame`, so bend segment and the path-tools drags preview the node's constraints and linked nodes as they will commit. Breaking: its `current` thunk now answers a `PathEditFrame` (`{ path, origins? }`) instead of a bare path.
174
+ - geom: `PathsEditItem.yields` lets a path the edit left alone give way freely.
175
+ - path-tools: the constraints extension carries linked nodes through whole-node transforms; `constraintLinkConflictsOf(scene, id)` reports the links tying a node that do not hold; `linkAnchorAction` (in `constraintsPreset`) links an anchor Alt-dragged onto another node's anchor (`coincident`) or segment (`onPath`), with `linkTargetAt` and `linkConstraint` beside it.
176
+ - 853ce69: A dep source is handed `below`, which reads the source it displaced, in its own scope or one above, so a source can handle part of a dep and pass the rest to the default (`DepSource`, accepted by `useDepSource` and `DepRegistry.register`). A source taking no argument works as before. `useStencilInsert` uses it: a kind no stencil names goes to the `insert` dep beneath it, so core's rect, ellipse and text tools work beside stencils.
177
+ - 8c1861a: Add a devtools hook. Each mounted `<SceneCanvas>` registers a root on `window.__weaselDevtools__`,
178
+ which serves a panel over a versioned message protocol: the scene tree a level at a time, a node's
179
+ pose and data, selection, view, tools, probes, the dispatch trace and frame stats, plus select,
180
+ highlight, set-tool and debug-overlay commands. A dev build installs the hook itself; a production
181
+ build installs it only when the app imports the new `@weasel-js/core/devtools` subpath, which also
182
+ exports the protocol types and the in-page and `postMessage` transports. See `docs/devtools.md`.
183
+
184
+ The debug overlay gains a `highlight` feature (`debug={{ highlight: ids }}`), and `<Canvas>` and
185
+ `<SceneCanvas>` take an `aria-label`.
186
+
187
+ Breaking: the dispatch trace is per canvas now. `window.__weaselDispatchLog__`,
188
+ `window.__weaselDispatchLive__` and `window.__weaselCoordLog__` are gone, and so are routing's
189
+ `recordModeSwitch` and `publishLiveDispatch`. A dispatcher records into `DispatcherContext.trace`
190
+ (`createDispatchTrace`), which `useGestureDispatcher` creates or takes as its `trace` option and
191
+ publishes as the `dispatchTrace` dep; record a mode switch with
192
+ `deps.get('dispatchTrace')?.recordModeSwitch(…)`.
193
+ - 6440997: Add `<DevtoolsLabel value>`, which names the canvases beneath it in a devtools panel ahead of any
194
+ labeled element nearer to them. A labkit trial wraps its content in one with its title, so a plain
195
+ `<SceneCanvas>` in a trial, a forge story's included, is listed by the trial's title rather than as
196
+ "Content", the pane it sits in.
197
+ - 44cf2c5: The devtools panel fits a narrow container: below 480 px wide its tabs wrap and the Scene and
198
+ Registry tabs stack their list above the detail. Its header keeps the canvas picker at the left and
199
+ the version at the right, a selected tree row is marked in the accent color, and the node detail's
200
+ values line up.
201
+
202
+ A `<SceneCanvas>` with no `aria-label` or id of its own is listed in devtools by the `aria-label` of
203
+ its nearest labeled ancestor. labkit's `TrialSceneCanvas` labels its canvas with the trial's title.
204
+ `Tree` reads the new `--wzl-tree-selected` hook for a selected row's background.
205
+ - 8ff750f: The devtools panel gains a Registry tab, listing a canvas's tools, actions and deps under a name
206
+ filter, each opening to its details and its bindings drawn in the route grammar, and a History tab,
207
+ following the scene's history steps with each entry's ops, where the history stands with whether it
208
+ can undo or redo, and the checkpoint stack on request. `followHistory` reads `get-history` through
209
+ its cursor without React.
210
+
211
+ A scene gains `getContentVersion()`, which moves on every change but one that only changed the
212
+ selection. The devtools hook uses it, so a selection change is no longer also announced as a
213
+ `scene` change.
214
+ - 161c9c4: Add `@weasel-js/devtools`, a panel that reads and steers every `<SceneCanvas>` on a page over the
215
+ devtools hook. `DevtoolsPanel({ transport })` shows a picker for the page's canvases and four tabs:
216
+ Scene (the node tree, loaded a level at a time, and a picked node's parent, pose and data; hovering a
217
+ row outlines the node on the canvas), State (selection, view, active tool, debug overlay flags and
218
+ probes, with the tool and the flags settable), Dispatch (the dispatch trace, newest first, under what
219
+ a press at the pointer would do, filterable by handled and unhandled, each decision opening to its
220
+ path and its fallthrough diagram; coord records behind a toggle), and Frame (the last paint's cost
221
+ while the `fps` overlay is on). `createInPagePanelTransport()` connects it to the page's own hook.
222
+ `connectDevtools` and `followTrace` are the protocol client underneath, without React. Import
223
+ `@weasel-js/devtools/style.css` beside it.
224
+
225
+ Core exports `DEBUG_FEATURES`, every debug overlay feature a `DebugConfig` flag turns on;
226
+ `DebugFeature` is now derived from it.
227
+ - 33fa471: Add `@weasel-js/core/devtools-protocol`: everything `@weasel-js/core/devtools` exports — the
228
+ protocol types, `DEVTOOLS_PROTOCOL`, the envelope tag, the transports, and the hook's constructors —
229
+ without installing a hook on import. `@weasel-js/core/devtools` re-exports it and still installs one.
230
+ `@weasel-js/devtools` now imports from the new entry, so mounting the panel no longer puts a hook in
231
+ the panel's own window; `createInPagePanelTransport()` still installs one when called.
232
+ - 2eb0370: The devtools hook serves two more requests, still under protocol 1. `get-registry` describes what a
233
+ canvas has registered: its tools and preset contributions with their bindings, its actions, the dep
234
+ names its registry answers, and its node routing kinds. `get-history` hands back the scene's history
235
+ steps since a cursor — each push, merge, undo, redo or jump, with the ops it carried and where the
236
+ history stood — from a rolling buffer of 200 that records in dev builds and in production while a
237
+ panel is connected. `changed` reports both as the new `registry` and `history` areas. See
238
+ `docs/devtools.md`.
239
+
240
+ `History` gains `observe(listener)`, which hears what each change to the stacks was, and
241
+ `touchedIdsFromOps` is exported from `@weasel-js/history`. A hand-written `History` implementation
242
+ must add `observe`. `DepRegistry` gains an optional `list()` naming every dep it answers.
243
+ - c726003: A `<SceneCanvas>`'s devtools root no longer announces a `registry` change on every selection
244
+ change. The dep registry also notifies when a source's value changes, which the selection does on
245
+ every change, so the root now announces only when the deps it lists come or go.
246
+ - e30f4df: `DiagramView` can hold DOM against its nodes, groups and edges, report what the pointer is over, and let a group's members be dragged into a new order. All three are additive.
247
+
248
+ - `overlays` places each `DiagramOverlay` against its target after every paint: centered on it, or beside it through geom's `placeRect`, flipping inside the view. An edge's place is the midpoint along its route. The view now renders a box around its canvas to hold them, and `className` goes on that box rather than on the canvas.
249
+ - `onHover` reports the node, group or edge under the pointer; `pickEdges` lets a click or a hover land on an edge whatever editing callbacks are set. `rectOf(id)` and `subscribeFrame` on the ref give a target's client rect and when to read it again.
250
+ - A `DataGroup` with `reorder: 'x' | 'y'` lets `onReorder` drag any member along that axis, carrying everything inside a member that is a group, or step the picked one with Alt and an arrow key. It reports `{ group, order }` and moves nothing. `layered` keeps such a group's members in the order given across every rank instead of sorting them by crossings. `createReorderAction`, `createStepReorderAction`, `reorderBindings` and `reorderContribution` are exported for use outside `DiagramView`.
251
+
252
+ `SceneCanvas` takes `onHover`, called when the topmost pickable node under the pointer changes. `@weasel-js/react` exports `adoptCss`, `adoptCssOnce` and `styleRootOf`, the stylesheet adoption core's canvas and `KitSettingsFromPrefs` now share.
253
+ - 8c2a9a9: `DiagramView` takes `onResize`. With it set, a selected node shows resize handles; the box resizes
254
+ live under the drag, and on release the view reports `{ id, x, y, width, height }` for each resized
255
+ node and changes nothing until the specs follow. Store the box as the data node's `width`, `height`,
256
+ and `at`; the size is a minimum, so a box dragged smaller than its rows grows back to them.
257
+ `diagramResizable` now refuses a group's box, whose size comes from its members.
258
+
259
+ Core adds `createResizeAction({ commit })`, the resize action with its commit swapped: `commit` is
260
+ handed each resized node's pose at release, and the scene is left as it was.
261
+ - 1156d63: A node that shows a derived path is boxed around that path, stroke included, wherever the kit measures a drawn box: selection chrome, its hit regions, and the actions that read `drawnBoxes`. Its zero-size placeholder pose no longer drags the box back to the origin. `DrawnBoundsScene` takes an optional `derivedPathOf`, and `drawnBoundsScene(scene)` supplies it for a `Scene`; pass a scene through it to `useAlign`'s `scene` for the same box there.
262
+ - adadf5e: Scene edit passes now compose. `scene.addEditPass(pass, { order })` runs passes by ascending
263
+ `order` (default 0), ties in the order they were added, and each pass hears the edit's own changes
264
+ plus every write the passes before it made; it still runs once per edit, and undo, redo, and
265
+ history replay still run none. This changes what a second pass hears: it used to miss the first
266
+ pass's writes. `SceneEditSummary.docChanged` lists the document-value keys an edit set.
267
+
268
+ Diagram exports `DIAGRAM_PASS_ORDER`, where each of its passes runs, and avoid routing installs its
269
+ pass at `DIAGRAM_PASS_ORDER.avoid`. The routers (`straight`, `orthogonal`, `bezier`, `avoid`,
270
+ `ROUTERS`) moved to their own module; the package exports them as before.
271
+ - b3aa7cb: `documentFromScene` exports a shape sitting in the gap between pages on the nearest page rather
272
+ than the first, and marks a connector cross-page exactly when the scene's off-page split does. A
273
+ connector from a gap shape to another page stays whole, keeping its waypoints in world
274
+ coordinates. core gains `pageHolding`, the page a box is on, else the nearest one.
275
+ diagram gains `documentBoundsOf`, the box a node has in document space, which off-page splitting and
276
+ export now both read.
277
+ - ee2f0fc: `GroupTransform` is now only `{ kind: 'translate', dx, dy }`. Its `scale` and `rotate` arms are gone: no gesture produced them, and the move and clone actions ignored a behavior that answered one. A move behavior that switched on `kind` to handle them no longer needs those branches; resize and rotate behaviors answer through `ResizeMoveResult` and `RotateMoveResult` as before. Breaking for code that names the removed arms.
278
+ - ee4cf85: A drop or paste now keeps string flavors of any exact MIME a registered content handler names in its `match` or `types`, for as long as it stays registered, so a handler can claim a drag from the app's own UI by a type of its own instead of tagged `text/plain`. Globs and `application/octet-stream` admit nothing. `admitIngestMime(mime)` (routing, re-exported from core's ingestion module) does the same for code outside the handler registry and returns a release. The kit weasel-JSON handler's `application/x-weasel-clipboard+json` flavor now reaches it on paste as well.
279
+ - d892435: A content handler's `IngestCtx` now carries the canvas's `snap` dep as `ctx.snap`, so a handler can place what it inserts where a gesture would: begin a `'point'` session at the would-be position, take `at()`, and `end()` it. The `ingest` and `clipboard.pasteEvent` actions declare `snap` among their `requires`.
280
+ - 1a1bb83: Drawing or click-placing a node into a container with a unit scope now snaps on that scope's grid
281
+ pitch, not the root's.
282
+
283
+ - `SnapBegin` and `SnapCollect` take `parent`: the container a subject not yet in the scene lands
284
+ in. `insertAction` and `placeAction` pass the container the `insertInto` dep names, the same one
285
+ the `insert` dep puts the node in; an id naming no container passes nothing.
286
+ - `gridSnapSource({ scopes })` reads the scope from `ids` when the gesture has a subject, else from
287
+ `parent`, else the root.
288
+ - kernel3d's `createSnap` passes `parent` on to its sources, as it does `ids`.
289
+ - `placeAction` now requires the `insertInto` and `scene` deps, both optional.
290
+ - 0e24110: A key binding can now carry `opts: { over: true }`: it is live while the pointer is over its canvas, whichever canvas holds the keys, and only then. The loupe's peek key uses it, so with two loupes on a page the key peeks the one under the pointer rather than the one last pressed in, or none before anything was pressed. A `<LoupeGestures>` outside a camera now mounts its own input scope, so two of them under one provider no longer stack their actions on one id.
291
+ - 4bf5dec: `moveNodes(deps, ids, { dx, dy }, label?)` moves nodes the way a drag of them commits: derived nodes through what they derive from, every descendant not carried by a moving frame, each translated in the frame it is stored in, finished by the `transformFollowers` and committed as one undo entry (inside an open `scene.batch`, as part of it). `moveNodesOps` builds the same ops without committing them, and `MOVE_NODES_REQUIRES` names the deps an action calling `moveNodes` declares. The move action, nudge, Transform Again and the measure tool's Move By all build their translate ops through it.
292
+
293
+ The ingest action now also requires `poseDescriptor`, `geometryProjection` and `transformFollowers`, so a content handler can move what it inserts with `moveNodes(ctx.deps, …)`.
294
+ - fe2a8c5: A node's kind has one answer: its routing kind. `<SceneCanvas>` now publishes each selected node's
295
+ routing kind with the selection, so the command palette says "3 rects selected" or "2 groups
296
+ selected"; a node its routing table calls `'unknown'` publishes no kind, and the palette says
297
+ "objects". Before, the default label read `'group'` for a container, `'path'` for a pose carrying a
298
+ `kind`, and nothing for anything else. `describeKind` still replaces the label outright.
299
+
300
+ `SelectionPanel`'s `classifyKind` classifies through the new `routeKind` export, the function behind
301
+ `NodeRouting.classify`, and hands each routing entry the node beside its data. It no longer calls a
302
+ container `'group'` on its own: pass a table carrying `groupNodeRouting`, as `inferredNodeRouting`
303
+ does, for that. This changes behavior for a panel given a table without it, such as
304
+ `defaultNodeRouting` alone.
305
+ - b7e6edc: A Pathfinder action's preview now draws each piece in the paint it would wear — its source's paint, or the paint a counted stroke leaves it — with the overlay's outline over it, rather than as a plain outline. `TransientPath` takes an optional `paint` (a `PathPaint`) to do this for any path an overlay shows.
306
+ - 87cded1: `<SceneCanvas tools>` no longer warns when a patch tool replaces one a preset brings — a custom `hand` under the `view` preset, say. That replacement is the documented way to restyle a preset's tool, and the patched tool still takes the preset tool's place in the palette. The dev warning now fires only when the id is also listed in `defaultTools`, where asking for the built-in and replacing it in the same breath is likely a mistake. Since 1.11.0 the warning reached npm consumers in development (earlier builds shipped it disabled), and it logged on every render.
307
+ - 24267d3: `renderSceneToPixels`, `createRasterSession().render` and `planPixelRender` now leave a scene's annotation layers (measurements, notes) out of the raster, as the SVG export does. Pass `annotations: true` to draw them. `renderDebugSnapshot` draws them by default, since it reproduces the canvas; pass `annotations: false` to leave them out.
308
+ - 683dea0: New package, `@weasel-js/rig`: the bone and weight tools, with the actions they bind, moved out of
309
+ core. `useRigTools({ scene })` builds both for `<SceneCanvas tools>`, keyed by the ids `RIG_TOOLS`
310
+ names; they act on the rig the scene's selection names unless given `selection` or `rig`, and take
311
+ `state`, `reach` and `radius` as `toolOptions.rig` and `toolOptions.weight` used to. `useBoneTool`,
312
+ `useWeightTool`, `createRigEditState`, `placedRig`, `rigOfSelection`, the two overlays and
313
+ `weighedPaths` come from it too, and its glyphs are `rig:bone` and `rig:weight`.
314
+
315
+ **Breaking for core:** `<SceneCanvas>` no longer mounts the rig tools. `'bone'` and `'weight'` are
316
+ gone from `BuiltinToolId`, `BUILTIN_TOOLS` and `BUILTIN_TOOL_IDS`, `RIG_TOOLS` and every name above
317
+ are gone from core's barrel, and so are `toolOptions.rig`, `toolOptions.weight` and the
318
+ `core:bone` and `core:weight` glyphs. The kit settings `targets.boneJointRadiusPx` and
319
+ `targets.weightPointRadiusPx` keep their paths, but are declared by `@weasel-js/rig` and listed in
320
+ its `rigKitSettingsSchema` rather than `coreKitSettingsSchema`. Core keeps the rig itself:
321
+ `useRigNode`, `bindRig`, `placeSkeleton` and the rest bind a skeleton from scene data as before.
322
+ - 61e7b0c: `<SceneCanvas selectTool={{ rotate: false }}>` now turns off only the select tool's rotation: the
323
+ selection's rotation handle is hidden and bound to nothing. The `rotate` action stays registered, so a
324
+ tool of your own that binds `rotate` turns the selection, and a partial `actions.rotate` merges onto
325
+ the kit's action as it does on any other canvas. A `chromeVisibility` rule that shows the handle again
326
+ shows a handle a drag does nothing on, with no dispatcher warning. Before, the action was muted on the
327
+ whole canvas, which also stopped a consumer's tool from rotating.
328
+ - 5053f5b: `SnapBegin` takes `sources` and `omit`, so one gesture can ask snap sources the canvas does not list, or skip ones it does (a listed, registered or default source, by id), without changing the canvas. Gesture sources are ranked with the canvas's own, and one sharing an id with a source still asked throws. Gesture sources are 2D: kernel3d's `createSnap` honors `omit` but does not ask a gesture's `sources`, and warns once in dev when it is given some.
329
+ - 2b267d5: Snap pipeline follow-ups.
330
+
331
+ - kernel3d's `createSnap` takes `kitSettings` and reads its reach from `targets.snapPx` there, as a canvas does (`reachPx` still overrides it).
332
+ - Two snap sources sharing an id now throw, on a canvas when a gesture begins and in kernel3d's `createSnap`, where before the later one silently replaced the earlier: a `<SceneCanvas snap>` source and a preset's alignment source were the likely pair, and the page box went with it. A source still replaces one of the canvas's defaults (`'rotation'`, `'path-snap'`) by taking its id. Core exports the check as `assertSnapSourceIds`.
333
+ - The symmetry axis knob and a repeat's step handle turn through a `rotate` session on the `snap` dep: they now snap to quarter turns and other nodes' angles without Shift, Shift keeps the 15° steps, Ctrl suspends snapping, and the angle readout draws. Breaking: `handleChange` takes a `SymmetryHandleSnap` (`{ point, angle }`, new export) in place of its `stepped` flag and point function. Without a `snap` dep the handles do not snap, Shift included.
334
+ - `resolveSnap` keeps every required candidate past `poolSize`, so Shift's steps can no longer be crowded out by 24 nearer targets, and drops a candidate with a non-finite locus direction instead of treating its line as a point.
335
+ - A move begins its snap session once the drag passes its threshold, so a click on a selected body reads nothing for snapping, and its `geometry` probe is placed within the canvas's reach rather than a fixed 8px.
336
+ - ac892f8: `EffectEditor` takes `look`: `'nodeGraph'` (default), `'rack'`, or `'lanes'`, with that look's options. Under rack and lanes, connecting, reconnecting, and deleting work as under node graph, and a stage on the main line drags along it to another place, which rewires the pipeline (`'Reorder'`). Under lanes a lane drags by its label (`'Reorder lanes'`). `editorScene(doc, look, options)` replaces the node-graph-only signature, which is breaking for a caller that passed options second.
337
+
338
+ The effect model gains `chainLinks`, `moveInChain`, and `canMoveInChain`; `EffectDoc.laneOrder` with `setLaneOrder`; `laneTypeOf`; and `order` and `laneOrder` on `EffectLookResult`, which `rack` and `lanes` fill. `@weasel-js/diagram` adds `createSlotReorderAction`, `slotReorderContribution`, and `sequenceSlots`, which drag one item of any drawn sequence along its axis and draw an insertion bar. Core's overlay strokes and routing's `OverlayRole` add the `insert` and `refused` roles that bar draws in.
339
+ - 71d4416: Synthetic-bold text reaches the outline tier. Past the outline threshold, a glyph faked bold from a
340
+ lighter face used to stay on the distance field; it is now drawn as geometry, its outline grown by
341
+ the distance the field's threshold shift moves the edge, so it is as heavy on either side of the
342
+ threshold. A stroked synthetic-bold run, which stayed on the atlas unstroked, is now stroked. A
343
+ grown glyph's `LaidOutOutlineGlyph.d` holds the grown outline, and its `key` names the growth.
344
+
345
+ `@weasel-js/geom` gains `pathToD`, the inverse of `pathFromD`, also exported from `@weasel-js/core`.
346
+ `@weasel-js/svg`'s `serializePathD` is now that function.
347
+ - 1bb4752: Tool sets: a `ToolSet` names a group of tool ids and other sets as one unit (`toolSet`, `toolIdsOf`, `withoutTools`, `toolSetHas`). `<SceneCanvas defaultTools>`, a preset's `tools`, and `ToolPalette`'s `include` each take sets. Core exports one per family, `SELECT_TOOLS`, `VIEW_TOOLS`, `SHAPE_TOOLS`, `DRAW_TOOLS`, `TYPE_TOOLS`, `PAGE_TOOLS` and `RIG_TOOLS`, with `BUILTIN_TOOLS` over them all; `BUILTIN_TOOL_IDS` is derived from it, and a shape kind's new `family` field says which set names it. `@weasel-js/path-tools` exports `WARP_TOOLS`, `RESHAPE_TOOLS`, `PATH_TOOLS_TOOLS`, and `usePathToolsTools()`, which builds every one of its tools keyed by id.
348
+ - e9404d0: A move, resize or rotate keeps its in-flight poses in one place: the scene's pose overrides.
349
+ Their handles no longer answer `previewPose`; `previewIds` still names the nodes in flight, and
350
+ `previewData` still carries what a transform follower previews. The preview ghost
351
+ (`resolvePreviews`) and the selection chrome resolve a previewed id with no `previewPose` through
352
+ `effectivePose`, so they read the same pose picking and derived geometry already did. Code that
353
+ read `previewPose` off one of these handles reads `effectivePose(scene, node)` instead. A
354
+ transform follower that previews a node at a pose other than its own now publishes that pose to
355
+ the overrides too; one answering the node's own pose pins nothing, so a derived node keeps
356
+ deriving.
357
+ - 433540d: A container's unit scope (`ContainerNode.units`) now reaches grid snapping and node property
358
+ fields. A scope converts what is shown, typed and snapped to; every pose is still stored in world
359
+ units, and pose composition does not scale by it.
360
+
361
+ - `gridSnapSource({ scopes: { root, spacing? } })` snaps the subject on the pitch of the unit
362
+ scope its nodes share, so a node inside a millimeter sub-assembly snaps on millimeter spacing.
363
+ `spacing` is read in that scope's units unless `scopes.spacing` gives a pitch per scope.
364
+ `scopedGridPitch` answers the pitch for a chain of scopes.
365
+ - A snap source is told the gesture's subject: `SnapCollect.ids`.
366
+ - `sceneSharedUnitScopes(scene, ids, root)` is the run of unit scopes every node of `ids` sits in.
367
+ - A number leaf takes `measure: 'length'` for a length stored in world units.
368
+ `prefLeafInScopes(leaf, scopes)` gives such a leaf the unit of the scopes it is shown in, built by
369
+ `scopedPrefUnit(scopes)`: shown in the innermost scope's base unit, with every unit of its system
370
+ accepted as typed text. The kit's node schemas mark X, Y, W, H and text padding as lengths.
371
+ - `SelectionPanel` takes `units`, the scene's outermost scope; given it, a length field shows the
372
+ selected nodes' shared scope.
373
+ - Updated dependencies [70b12d1]
374
+ - Updated dependencies [768be71]
375
+ - Updated dependencies [1dd65f5]
376
+ - Updated dependencies [411b629]
377
+ - Updated dependencies [312eb35]
378
+ - Updated dependencies [4d99526]
379
+ - Updated dependencies [853ce69]
380
+ - Updated dependencies [5cdc3d0]
381
+ - Updated dependencies [8c1861a]
382
+ - Updated dependencies [2eb0370]
383
+ - Updated dependencies [e30f4df]
384
+ - Updated dependencies [13fc67f]
385
+ - Updated dependencies [50da815]
386
+ - Updated dependencies [995eac7]
387
+ - Updated dependencies [716561f]
388
+ - Updated dependencies [ee4cf85]
389
+ - Updated dependencies [c497405]
390
+ - Updated dependencies [0e24110]
391
+ - Updated dependencies [c2dfd4e]
392
+ - Updated dependencies [0f455dc]
393
+ - Updated dependencies [15efc86]
394
+ - Updated dependencies [8cd81e7]
395
+ - Updated dependencies [c29ac84]
396
+ - Updated dependencies [07b686c]
397
+ - Updated dependencies [041bc38]
398
+ - Updated dependencies [f819e61]
399
+ - Updated dependencies [2b267d5]
400
+ - Updated dependencies [8f2c044]
401
+ - Updated dependencies [ac892f8]
402
+ - Updated dependencies [71d4416]
403
+ - Updated dependencies [cee04b9]
404
+ - Updated dependencies [e1eeb08]
405
+ - Updated dependencies [f148f50]
406
+ - Updated dependencies [1bb4752]
407
+ - Updated dependencies [e9404d0]
408
+ - Updated dependencies [433540d]
409
+ - @weasel-js/routing@1.11.1
410
+ - @weasel-js/animator@1.11.1
411
+ - @weasel-js/renderer@1.11.1
412
+ - @weasel-js/gestures@1.11.1
413
+ - @weasel-js/history@1.11.1
414
+ - @weasel-js/geom@1.11.1
415
+ - @weasel-js/react@1.11.1
416
+ - @weasel-js/prefs@1.11.1
417
+ - @weasel-js/stroke@1.11.1
418
+ - @weasel-js/font@1.11.1
419
+ - @weasel-js/text@1.11.1
420
+ - @weasel-js/icons@1.11.1
421
+ - @weasel-js/quantity@1.11.1
422
+ - @weasel-js/simulation@1.11.1
423
+ - @weasel-js/text-dom@1.11.1
424
+ - @weasel-js/cursor@1.11.1
425
+ - @weasel-js/modes@1.11.1
426
+ - @weasel-js/paint@1.11.1
427
+ - @weasel-js/registry@1.11.1
428
+ - @weasel-js/select@1.11.1
429
+
430
+ ## 1.11.0
431
+
432
+ ### Minor Changes
433
+
434
+ - d2749ce: A selection now has a resize handle at the middle of each edge as well as each corner. Dragging one resizes along that axis only, with the opposite edge pinned; on a rotated node it moves along the node's own axis, and shift keeps the aspect, growing the other axis about its center. The handles report `handle:top`, `handle:right`, `handle:bottom`, and `handle:left`, carry a resize cursor along their axis turned with the node, are drawn by the selection overlay alongside the corners, and are hit ahead of any node body, so a press just outside a selected node's edge resizes it rather than moving the node behind. A side under six handle radii on screen (48 px at the default size) gets no edge handles, so a small node keeps its corners and a body to grab.
435
+
436
+ On by default. `<SceneCanvas selectTool={{ resize: { edgeHandles: false } }}>` turns them off; `createCornerResizeAffordance({ edges })` and the selection overlay's `resizeHandles: { edges }` do the same where those are used directly. Whether a node gets edge handles is decided by `resizeHandlesFor` from the handles' hit radius alone, never the painted size: `<SceneCanvas>` resolves one `ResizeHandleLayout` (`selectTool.handleHitRadius`, else the device-scaled default) and its overlay, its own hit-test and every added view's read it, so no setting of `handleHitRadius` or `handles.size` draws a handle that can't be grabbed or takes a press where none is drawn. A `<SceneCanvas>` view added with `views` now also honors `selectTool.handleHitRadius`, which it used to ignore. The handle layout is one table, `RESIZE_HANDLE_ANCHORS` (corners first, then edges), placed by `handlePoint`; `CORNER_ANCHORS` is its corner half and `cornerPoint` is deprecated in favor of `handlePoint`. Behavior change: `fixedCornerOf` now pins the center on a `'free'` anchor axis instead of the bounds origin, which only differs when a constraint resizes that axis.
437
+
438
+ <!-- bump-approved: minor: maintainer — 1.11.0 release requested 2026-10-18 -->
439
+
440
+ ### Patch Changes
441
+
442
+ - 304f53a: Actions and prefs carry `tags`: words they are also found by and gathered under. `Action.tags` and `ActionVariant.tags` (a variant carries its action's and its own, as `ActionItem.tags`); `tags` on every pref leaf, `PrefGroup`, and `PrefSection` (a leaf carries every group's above it). One matcher, `matchQuery` in `@weasel-js/registry`, now serves the command palette's search and `filterPrefSubtree`, so a query matches a tag as it matches a label, and `hasTag` is the exact test. Gathering by tag: `actionsTagged`, `taggedActionItems`, and `matchActionItem` (routing, re-exported by core), and `prefLeavesTagged` / `prefLeafTags` (prefs). `<ActionBar tag="…">` draws a bar from a tag in place of a `group`. A `CommandPalette` row found by a tag and not its label names that tag beside the label. The schema editor edits `tags` on leaves, groups, and sections; its structure, settings, unplaced, and action trees find rows by tag through the same matcher; and an `EditorAction` carries its registered action's tags, shown among what the registry says of the action a pref fires. `flip` is tagged `mirror`. Additive.
443
+ - 3ffe020: An action can say what it would do before it runs. `Action.preview(deps, params)` shows it and returns what takes it down; `ActionsRegistry.preview(id, params)` asks for it under the same `enabled` check and tuned params `trigger` uses, and returns that function. A bar's action button shows its action's preview while it is hovered or focused, and takes it down on leaving or pressing. `<SceneCanvas>` sources a `previewPaths` dep, `show(paths)` over the canvas (`createPreviewPaths`, `usePreviewPathsDepSource`), and every Pathfinder action previews the outlines of the pieces it would make on it. Additive, except for anything implementing `ActionsRegistry` by hand, which now needs `preview`.
444
+ - b882b2e: `<AnchorFields>` shows the anchors selected in path edit as numbers: their X and Y in document units, and for a lone anchor each handle's X and Y, or its angle and length, switched by the panel's Handles toggle (`handleCoords` and `onHandleCoordsChange` hold that choice outside, `defaultHandleCoords` seeds it inside). A field the anchors disagree on reads Mixed. Typing a number moves every selected anchor to it, and `accepts` reads units, so `1in` is 72 points given `{ pt: 1, in: 72 }`. It reads and writes through core's `useAnchorFields()`; pass `fields` to drive it from elsewhere. WeaselDraw shows it at the top of the Properties panel while anchors are selected.
445
+
446
+ `UnitField` and a typed `PropertyField` number take an offset: `+=` or `-=` and an amount, units read. Given `onOffset`, the amount goes there — what a mixed field needs, for each value it stands for to move by its own amount; without it, the offset is added to `value` and commits through `onChange`.
447
+
448
+ `<ActionBar only>` keeps just the named entries of those its `group` or `tag` picks, each an action id or an `id:variant` key.
449
+
450
+ `<SceneCanvas defaultPathEdit={{ id, anchors }}>` opens the canvas with that path in anchor edit and those anchors selected, as though it had been double-clicked; it is read once, at mount, and `id` must be selected. Its type is `PathEditOpening`.
451
+ - 60d8e39: `@weasel-js/path-tools` adds three presets, each also in `pathTools`:
452
+
453
+ - `anchorSelectionPreset` selects anchors along the path in path edit. `growAnchorSelection` (`]`) adds each selected anchor's neighbors in its subpath and `shrinkAnchorSelection` (`[`) drops the anchors at the ends of each selected run, wrapping round a closed subpath. `selectEveryNthAnchor` (Alt+N) selects every `params.n`th anchor counting from the first selected one; `selectCornerAnchors` (Alt+C), `selectSmoothAnchors` (Alt+M), and `invertAnchorSelection` (Alt+I) select by anchor kind and by complement. They are in the `ANCHOR_SELECTION_GROUP` group, change only the selection, and push no undo step.
454
+ - `resamplePreset` brings `resamplePath`, an ongoing path command: it spreads each selected path's anchors evenly along it by arc length, to `params.count` anchors or at `params.spacing`, holds corner anchors fixed unless `params.keepCorners` is false, and refits the curves through the new anchors within `params.tolerance`, halving any piece that cannot follow the original that closely. It previews on `begin` and every update, and commits one undo step.
455
+ - `addExtremesPreset` brings `addExtremeAnchors` (Alt+X), which splits curved segments at their x and y extremes without moving the shape: the segments whose two ends are selected, or the whole path while no anchor is. It is in the `anchors` group.
456
+
457
+ `ActionParamSchema` types the params of `selectEveryNthAnchor` and `resamplePath`.
458
+
459
+ Core exports `livePathEdit`, the builder behind `simplifyPath` and `offsetPath`, for a path command driven live by its params. A live path command now recomputes when any param changes, not only its main number, and reads params a tuning supplies as a thunk.
460
+
461
+ `@weasel-js/geom` adds `resamplePath`, `addExtremaAnchors`, `segmentExtremaTs`, `cubicAxisExtremaTs`, and the selection walks `growAnchorSelection`, `shrinkAnchorSelection`, `everyNthAnchor`, `anchorsWhere`, `cornerAnchors`, `smoothAnchors`, and `invertAnchorSelection`.
462
+ - ed0e096: Path edit can show balance lines: one per curved segment, from the tip of its first handle to the tip of its second, with a grip at the middle. Dragging a grip (`balanceHandles`) scales both handles together, each along its own direction, so the segment fills out or flattens without either end turning; double-clicking it (`equalizeHandles`) gives the two handles the same proportion of the way to the corner their lines meet at. Under a `pathSymmetry` dep the grip drag carries every image of both handles with it, as an anchor or handle drag does. The grip drag keeps every handle's angle, and a length lock in force for handle drags, from `handleLock.length` or Mod, holds it still. The lines and grips show, and the grips hit-test as `balance:N` affordances, while chrome-caps shows the new `path-edit.balance` id (`PATH_BALANCE_CHROME_ID`), which is off by default. Their look comes from the `<SceneCanvas>` layer slot `layers.pathEditingOverlay`'s new `balance` option. Both actions are in the standard actions and the `paths` feature preset. Additive.
463
+
464
+ `@weasel-js/routing` adds `isBalanceGrip`, and `isPathEditPart` now matches a balance grip too, so `move` turns a press on one down. `@weasel-js/geom` adds the geometry: `handleBalances`, `scaleSegmentHandles`, `balanceFactorToward`, and `equalizeSegmentHandles`.
465
+ - 6f839dd: A blend can lay its steps along a spine and space them by distance. A blend node whose `dependsOn` names a third path, `[from, to, spine]`, places each step on the spine as far along it as the step is between its sources, and paints nothing while that spine is gone; `orient` also turns each step by how far the spine's heading differs from the straight run between the sources. `spaceBy: 'distance'` puts a step every `distance` from the first source, along the spine where there is one, as many as fit short of the second; `spaceBy: 'count'`, the default, keeps `steps` evenly spread. Blend made with three shapes selected takes the third as its spine, and `blend` and `editPathEffect` take `spaceBy`, `distance`, and `orient` as params.
466
+ - 327fb63: `bridgePaths` and `bridgeAnchors` gain an icon, `core:bridge`: two open ends joined by a curve that leaves each along its heading.
467
+ - 5338358: Bridge: `bridgePaths` ("Bridge", Mod+Shift+J) joins the nearest open ends of two selected paths with a curve that leaves each end along the direction its path was heading, each new handle `params.tension` times the gap long (default `DEFAULT_BRIDGE_TENSION`, 0.4; `0` is the straight segment Join makes). The two paths become one, the first selected keeping its style, as one undo step; with one path selected, Bridge closes it. In path edit, `bridgeAnchors` ("Bridge anchors", Mod+Shift+J) does the same for the two selected end anchors. Both are in the standard actions and the `paths` feature preset, and their `tension` param types through `ActionParamSchema`, so `<SceneCanvas tune>` reaches it. Underneath, `joinSubpathEnds` and `joinAnchorsAt` in `@weasel-js/geom` take an optional `JoinOptions` with that `tension`. Additive.
468
+ - 7116c36: Create Outlines moves from Mod+Shift+O to Mod+Enter, Affinity's Convert to Curves, and Average Anchors from Mod+Alt+J to Mod+Alt+Shift+J. Chrome takes the old chords first (its bookmark manager and console), so neither fired there. A consumer that relied on the old chords rebinds them.
469
+ - 1c76897: `slice`, `bone`, and `weight` are built-in tool ids, so `<SceneCanvas defaultTools={['bone', 'weight']}>` or `tools={{ slice: true }}` mounts them, and `BUILTIN_TOOL_IDS` lists them after the shape tools. The canvas hands the rig tools its own scene and one `RigEditState` they share, and by default they edit the rig the selection names: with one node selected, the nearest of it and its ancestors holding `data.skeleton`, else that node itself. `toolOptions` gains `slice.closeHitRadius`, `rig` (`rig` to fix the node, `state` to share with `useRigNode`, `reach`), and `weight.radius`. This is additive; a canvas passing `defaultTools={BUILTIN_TOOL_IDS}` now mounts these three tools too.
470
+ - 4447e67: A canvas host given no `width`/`height` fills its parent and follows it as it resizes: `Canvas`,
471
+ `SceneCanvas`, `LeanSceneCanvas`, `DrawCanvas`, `SceneViewCanvas` and `MinimapCanvas`, each with a new
472
+ `onResize` reporting every size. Nothing paints until the first measure. On a resize the view keeps
473
+ its transform, so more or less of the world shows; `DiagramView` and `EffectChart` refit until the
474
+ user pans or zooms, and `MinimapCanvas` refits its overview. `DrawCanvas`'s `draw(size)` gets the
475
+ measured size. Core exports `SurfaceSizeProps` and `viewportWorldRect`; labkit's
476
+ `TrialSceneCanvas` fills through `SceneCanvas` instead of measuring its own trial.
477
+
478
+ `createGridLayer`'s `bounds` is now optional and receives the paint's view and canvas size. Omitted,
479
+ the grid covers whatever the canvas shows, its lines held on world multiples of `spacing` as the view
480
+ pans, and any set of lines that would sit closer than 4px on screen is left out.
481
+ - 84dd318: `<Canvas>`'s body is split into hooks, one per thing it owns: its elements, registered layers, painted cursor, layer stack, view-registry surface, paint, and imperative handle. No behavior or API change.
482
+ - e0608bf: `<Canvas>`, and so `<SceneCanvas>`, repaints after every committed render
483
+ instead of only when a prop on a fixed list changed. A prop that reaches the
484
+ paint through a ref or a memo — `chromeVisibility` is one, since the
485
+ chrome-caps resolver reads its rules live — used to change on screen only when
486
+ something else happened to draw a frame. Renders that land before a frame
487
+ still paint once in it; a hover that changes nothing and a drag paint exactly
488
+ as many frames as before. `<CanvasView>` asks its surface for a frame on every
489
+ committed render for the same reason, so a change to its `bounds`, `layers`,
490
+ or layer gate alone now shows.
491
+ - b0f392c: `<Canvas retain>` sets how a canvas retains its layers: `minCommands` is the
492
+ threshold a layer must reach, `budget` the GPU memory retained layers share,
493
+ and `false` retains no layer on the canvas. `<SceneCanvas>` passes it through.
494
+ `WeaselRenderer.setRetainBudget` changes the budget after construction. New
495
+ API; nothing existing changes.
496
+ - cf7b009: A press that begins on one element and is released over a canvas is a gesture of its own, `carry` (`CarrySpec`), the in-app sibling of an OS drop. `startCarry(origin, pointerdown, { type, value }, callbacks)` opens one from any element; every dispatcher's element is a surface for it unless `channels={{ carry: false }}`, and the surface under the pointer dispatches it through its bindings. An ongoing action bound to `{ kind: 'carry', types }` starts as the carry comes over the surface and reads the payload from `ctx.carry`: moves update it, the release commits it, and leaving the surface or a canceled press cancels it. An immediate action fires on the release, with the payload in `params.carry`. `onEnd` tells the source whether a binding took the drop.
497
+
498
+ labkit's palette drag-drop is a carry now, and a drop routes through the trial canvas's dispatcher beside its pan, zoom, and tap, as the `labkit.paletteDrop` action. This is breaking for a direct `useDragDrop` caller: it no longer takes `canvasContainerRef`, `view`, or `worldSpec`, and its result carries a `target` to render inside the `<CanvasStack>` the palette drops onto. A drop now lands only where nothing else on the page covers the canvas.
499
+ - 53ba41a: Path constraints can tie nodes together. A constraint link is a scene node: its `dependsOn` names the nodes it ties, and its `data.constraintLink` holds one path constraint whose anchors are numbered over theirs one after another. Being a node, it is saved and undone with the scene, and deleting a node it ties deletes it. Additive, except where noted below.
500
+
501
+ `@weasel-js/geom` gains `constrainPathsEdit(items, links)`: an edit of several paths finished in one solve, each path's own constraints and each link renumbered through the edit, and the paths the edit left alone held unless nothing else can give way. `constrainPathEdit` is now its one-path case. A solve takes a frame per constraint (`axisAngles`), so paths drawn in different frames solve together. A dragged anchor held on a segment now starts from the nearest point on it and stays there while the rest give way, where before it slid by moving more freely than everything else, which let it drift off the pointer to satisfy unrelated constraints.
502
+
503
+ In `@weasel-js/core`, a path-edit extension's `finishEdit` gets a fourth argument, a `PathEditFinishCtx` that reads other nodes, their paths and their dependents, and may answer `others`: nodes it changes along with the edited one, each with a new path, data, or `remove`. They are committed in the same history entry, and the anchor drag previews them. The `editAnchors` dep's `finishEdit` now answers `{ path, others }` where it answered the path. This changes its return type.
504
+
505
+ In `@weasel-js/path-tools`, `constraintLinkNode` makes a link node and `constraintLinkOf` reads one. The constraints extension solves every node links reach from the edited one: an anchor held on another node's segment slides along it when dragged, and follows the segment when that node is edited. Link nodes draw nothing and take no clicks.
506
+ - 1322a03: `<ContextMenuHost>` draws the open context menu in the DOM: rows with menu roles, shortcut chips, submenus that open beside their row, keyboard navigation and typeahead, and placement that keeps every panel on screen. It closes on a choice, Escape, a press or wheel outside, and window blur, and gives focus back to where it was. Core now re-exports `useMenuHost`, `useMenus` and the menu types (`MenuDef`, `MenuHost`, `OpenMenu`, `MenuOpenRequest`, `MenuHit`).
507
+
508
+ The gesture dispatcher leaves a key pressed inside an element with `role="menu"` to that menu, so menu keys never fire canvas bindings, even from a `keyboard: 'first'` dispatcher.
509
+
510
+ `<LayerList>` takes `onRowContextMenu(id, event)`, called on a right-click on a row, so an app can open a context menu for a layer.
511
+
512
+ `PropertyGroup` and `MotifFrame` take an `onContextMenu` prop.
513
+
514
+ `@weasel-js/ui` exports `actionIcon`, which turns an action's icon name into the node to draw.
515
+ - 7162a7a: Corner shape: any corner anchor of a path takes a CSS `corner-shape`, and its radius can be changed later. Additive: `PolygonPath` gains `corners`, an optional `CornerSpec` (`{ shape, radius }`) per flat anchor index, where `shape` is one of the six `corner-shape` keywords (`square`, `squircle`, `round`, `bevel`, `scoop`, `notch`) or a finite `superellipse()` parameter, and `radius` is how far along each edge the cut starts. Following CSS Borders 4, every keyword is a point on one parameter, k: `square` is ∞, `squircle` 2, `round` 1, `bevel` 0, `scoop` -1, `notch` -∞. `cornerShapePieces(k, frame)` draws a corner for any k as the quarter superellipse `|u|^n + |v|^n = 1`, `n = 2^|k|`, spanned from the corner's center for k > 0 and from the outer corner for k < 0, fitted with cubics within `CORNER_FIT_TOLERANCE` of the setback and exact at k = 0, ±1, and ±∞. The command stream keeps the bare anchors, and `resolveCorners` expands the specs into plain geometry, each cut clamped so that the two cuts on a segment never overlap; `resolveCornersWithSources` also answers which source anchor each expanded anchor came from, and `remapPerAnchor` carries a per-anchor array across, so the renderer draws `vertexColors` on a cornered path with every point of a cut in its corner's color. Every reader of a path's geometry calls it first: tessellation, `extractPolylines`, the hit tests, `boundsOfPath`, `pathDistanceToPoint`, the booleans, `offsetPath`, the renderer's path draw, and `serializePathD`, which `@weasel-js/svg` now exports. A spec rides on its anchor through `pathToAnchors` / `anchorsToPath` (`PenAnchor.corner`), so anchor inserts and deletes keep it in place, and `transformPath` scales radii with the geometry. Also new: `cornerFrames` and `cornerFrameAt` (where each corner anchor can be cut, and how far), `withCorner`, `cornerAt`, `cornerSpecAt`, `cornerShapeK`, `cornerKeywordOf`, `isCornerShape`, `nextCornerShape`, and `CORNER_KEYWORDS`.
516
+
517
+ `@weasel-js/path-tools` adds `cornerShapePreset` (and `createCornerShapePreset(style)`), which edits corners in path edit. Each corner anchor shows a widget just inside it, a small tile cut in the corner's shape, drawn and pressed as `corner:N` (matched by routing's new `isCornerWidget`) while chrome-caps shows `path-edit.corners`, which is on by default. A drag on one (`editCornerAction`) sets the corner's radius live and commits one undo step; pressing the widget of a selected anchor sets every selected corner. `cycleCornerShapeAction`, in the `anchors` group, steps the selected corners through the keywords, and `setCornersAction` sets their shape or radius from its `shape` and `radius` params, typed for `<SceneCanvas tune>`. `CORNER_CONTROLS`, `cornerControlsState`, `cornerControlsParams`, and the `useCornerControls` hook are a prefs-form panel over the selected corners: the keywords, a curvature slider from -4 to 4, and the radius, mixed where the corners differ.
518
+
519
+ A path-edit extension's part (`PathEditPart`) can carry its own `hitRadiusPx` and a `standoff`, a screen-pixel push along a world-space normal, so it keeps its distance from the path at any zoom.
520
+
521
+ A `PathEditHost` can own the anchor selection too, through optional `selectedAnchors` and `setSelectedAnchors`, so an app seeds which anchors start selected and shows what is selected. Giving a sharp corner a shape, through `setCorners` or `cycleCornerShape`, also gives it a radius: the call's own, or a quarter of the room the corner has.
522
+ - 765cd31: Path edit can show a curvature comb: teeth standing out of each curved segment along its normal, each as long as the curvature where it stands, with a line through their tips. It draws from the same in-flight path as the anchors, so it follows anchor and handle drags. It shows while chrome-caps shows the new `path-edit.comb` id, which is off by default; `editingAnchors`, now exported, is the usual rule to turn it on with. Its scale, teeth per segment, and color come from the `<SceneCanvas>` layer slot `layers.pathEditingOverlay`, which also takes the overlay's `style`. A `null` or a layer of your own in that slot now replaces the overlay, as it does for `selectionOverlay`.
523
+
524
+ `@weasel-js/geom` adds the geometry underneath: `cubicCurvatureAt`, `cubicDerivativeAt`, and `curvatureComb` over an anchor set. `combTeeth` stands a comb on any `CurvatureSource`, a curve read as point, tangent, and curvature over t; `cubicCurvatureSource` makes one from a cubic, and `curvatureSourceOf` in `@weasel-js/geom/curves` makes one from any curve representation. The cubic and Spiro representations' `curvatureAt` now read `cubicCurvatureAt`.
525
+ - 89271a6: A derivation reading a dependency in another frame now gets that dependency's derived `path` carried into its own frame, as its pose already was. Under a composing strategy, an effect whose source is another effect in a different container — copies along a blend's steps, say — now follows that effect where it paints rather than where its own container would put the path's local coordinates. A derived dependency's path is also drawn from its own dependencies as read in its frame.
526
+ - 72a0ea2: `layered` reads a port where `portsOf` puts it on the node's outline rather than at its anchor, and reads a port with several places at the one nearest where the wire's other end falls among the node's wires on that side, while ordering, rather than at their mean. `GraphNode` carries the node's `outline`.
527
+
528
+ The compass ports `diagramScene` names under `layered` are marked as layout's: an `EdgeEnd` records the port layout named as `laidOut` (`layoutOwnsPort`), and `LayoutPlan.ports`, which `layeredPlan` now fills, carries them to `routesOf` and `routeWrites`. A later layout names an end again while it names no port or still names that one, so an edit that turns which way an edge runs no longer leaves it leaving by the old face. A live `layered` run or the layout action now names ports on a hand-built scene's edges that name none, as `diagramScene` does.
529
+
530
+ Breaking: `DiagramLabel`'s `at: { waypoint: k }` is replaced by `at: { near: { x, y } }`, which stations a label where its route passes nearest that point, so a bend added or removed before it leaves it on its stretch. `LayoutPlan.labels`, `LayeredPlan.labels` and `LayeredRoute.labelAt` carry that point instead of a waypoint index.
531
+
532
+ A group box `diagramScene` makes depends on the labels of the wires with both ends inside it, so a long label no longer spills out of it.
533
+
534
+ A live eased run eases each route it will write along with its nodes, published as the edge's path on the override channel, rather than drawing long edges through their old bends until it arrives.
535
+
536
+ Core: `moveSources` and `shapeSources` no longer hand back a node that derives only its path when they reach it through a derived node, so moving or turning a group box that depends on a wire's label does not write the wire's placeholder pose.
537
+ - 14b7551: Chrome now stays off a layer the view hides with `layerVisibility` or leaves out of `layerOrder`, not only off a layer the scene itself hides. In a `<CanvasView>` panel that hides a layer, a node on it that is selected on the surface shows no outline, resize or rotate handles, path anchors, or warp handles there, and none of them can be grabbed there. A diagram's ports are not drawn on such a layer, a press there does not grab one, and a connect drag started in that view does not land on one.
538
+
539
+ To make that possible, `ChromeState` carries `layerIsPainted(layerId)` for the view it was built for, the same answer `ViewApi.layerIsPainted` gives, and its `selection` leaves out ids on a layer that view does not paint (`multiActive` and `unionBounds` follow). `buildChromeState` takes `layerIsPainted` and `layerOf` for this, and a view reads each id's layer through its adapter's `getNode`. `paintsLayer(gate, layer)` is the one test every piece of chrome uses: `gate` is a `ChromeState` or a `ViewApi`. In the diagram package, `sceneParticipants` reports each participant's `layer`, and `offersPorts` takes the view as a second argument. Additive.
540
+ - eec8a5b: An `EffectRun` can carry a picture per output: `previews: { [port]: ImageBitmap }` on a stage's entry. A look's `showPreviews` option (on `nodeGraph`, `rack` and `lanes`) keeps a slot per output, `previewSize` big (default `PREVIEW_SIZE`, a 48-unit square, or `{ width, height }`), laid out from the first draw so a run filling it never lays the chart out again. Until a run fills a slot it draws as an empty frame, and it fades with its stage. `paintRun` fills it by a data edit, so a run that hands back the same bitmap writes nothing to the scene and uploads nothing; `EffectChart` frees the texture of a bitmap the next run no longer shows, and of every one it shows when it unmounts. `RunRowOptions` is the shared type of `showValues`, `showPreviews` and `previewSize`, and `previewRowId(port)` names a slot.
541
+
542
+ `bitmapSrc(bitmap)` (renderer, re-exported by core) names an `ImageBitmap` made at runtime as an image `src`, so an image node draws it with no load. The same bitmap always gets the same name; the cache holds it weakly and never drops it to fit its budget, and `releaseImage` frees its textures and retires the name.
543
+
544
+ A body's `slot` row takes a `width`: the body is at least that wide and the slot's box is that wide, centered. In `diagramScene`, a slot with an `id` becomes a scene node of that name, an empty frame, ready to be filled by a data edit. `DiagramSceneData` gains `image`.
545
+
546
+ `lanes` widens a source or sink stretched taller than it measured, so its round ends no longer eat into its rows.
547
+ - 1774dc4: `useGestureDispatcher` takes a `clientToLocal` option: the host's mapping from a client point to CSS pixels from the canvas's corner. The painted cursor, a wheel or pinch zoom's anchor, and a pending long-press's position use it; without it the element's rect is subtracted as before. `<SceneCanvas>` supplies its own, so on a canvas with a `clientToWorld` override — one drawn under a CSS transform, say — the painted cursor sits under the pointer and a zoom holds the point under it still.
548
+ - 8ff3b4b: A double-click on a grouped member names its outermost group, so `modeTriggers` enters isolation on it, and repeated double-clicks drill one group further in each time. `<SceneCanvas isolatedGroup>` says which group isolation is working inside; a double-click names the outermost group below it, or the node hit where no group stands between them. `doubleClickTarget` is the one rule, applied by the canvas's body classification: `BodyClassification.doubleClick` carries the named node, a press carries it as `doubleClickBody` to the double click it completes, whose `kind:` targets match it, and the `hitAt` dep reports it as `doubleClick`. `enterPathEdit` stands aside when a double-click names a group. Single clicks are unchanged. Behavior change: a double-click on a grouped path used to open the path in path-edit.
549
+ - 02cbe1d: More of the kit boxes a stroked node by its stroke as drawn, through `drawnBoundsOf`:
550
+
551
+ - The selection overlay takes a `scene`. With it, a pose from `getPose` is outlined on the node's stroke, and a container's union takes its members as drawn. `<SceneCanvas>` passes its scene when a `selectionOverlay` slot supplies its own `poseById`, unless `geometry.boundsIncludeStroke` is `false`.
552
+ - `composeSelectionPose` takes a `scene` and a `viewScale`, so a selected container's pose reaches its members' strokes.
553
+ - `useAlign` takes a `scene` and a `viewScale`, and lines up drawn edges when given them.
554
+ - `<Canvas>` takes `nodes`, and its default bounds then box each node as drawn.
555
+ - `kit:text` reports a `drawnBounds`: a stroked line that reaches its layout box's edge grows the box by the stroke's reach.
556
+
557
+ A `{ px }` stroke is now measured as the renderer draws it. `drawnBoundsOf`'s `scale` accepts a per-axis view scale, and with one it hands painters `NodeInkCtx.screen`, the map from the node's frame to screen pixels. Rects, ellipses, and text outset each side by the stroke as it lands on screen, and paths, polygons, and stars build the ribbon in the same space the renderer does, so the box is exact under a stretched view and under a skewing or stretching `transform` rather than right only at the mean scale. Chrome, resize, rotate, flip, align, and distribute pass the view's per-axis scale.
558
+
559
+ `@weasel-js/renderer` exports `resolveStrokeLengths`, which resolves a stroke's `{ px }` lengths against a transform and names the spaces each part is built in.
560
+ - Export three types that public signatures already named: `PreviewPathsDep` (the `previewPaths` action dep), `EditingDrawOne` (`useSceneTextEdit`'s `drawOne`), and `BoxPose` (what `carryPose` takes).
561
+ - 5b20cca: `<SceneCanvas features>` takes `FeaturePreset` objects beside core's names. A preset carries the standard actions it registers, the tools it mounts (built-in ids or tools of its own), its ambient bindings, the selection chrome it owns, contributions installed beside `ambient`, the presets it `includes`, and the presets it `refines`, whose actions its own register ahead of. Core's names each stand for an exported preset (`viewPreset`, `selectPreset`, `outlinePreset`, `movePreset`, `resizePreset`, `rotatePreset`, `editPreset`, `arrangePreset`, `pathsPreset`, `ingestPreset`), so a package ships behavior the same way core does and an app opts in by import. `<LeanSceneCanvas>` takes preset objects only and resolves no names, so an app's bundle holds only the presets it imports: a canvas with `selectPreset` alone no longer carries the pathfinder, outline, path-command, and ingest actions. `useStandardActions` takes an `actions` list, defaulting to every kit-standard action. Additive.
562
+
563
+ Changes behavior: standard actions register preset by preset (a preset after the ones it refines) rather than in one fixed list, so `ActionsRegistry.list()` orders them differently; anchor nudging and deleting still go ahead of their node-level twins, since `paths` refines `edit`. `KIT_STANDARD_ACTION_IDS` lists them in the new order.
564
+ - 516914b: Curves on the live canvas now flatten against the zoom. `flattenTolerance` on
565
+ `WeaselRenderer`, `<Canvas>`, and `<SceneCanvas>` accepts `{ px }` in device
566
+ pixels as well as a world length, and defaults to `{ px: 0.5 }`: each path is
567
+ flattened to stay within half a device pixel under the transform it draws
568
+ with, so a curve at 8x no longer shows 4 px facets, and a scene whose world
569
+ unit is not a pixel no longer needs a tolerance of its own. The tolerance is
570
+ snapped down to a power of two and fill meshes are cached per tolerance, so a
571
+ continuous zoom rebuilds a path's mesh once per octave rather than every frame;
572
+ a fixed world tolerance is now cached too instead of tessellated every frame.
573
+ `renderSceneToPixels` resolves its `flattenTolerancePx` the same way.
574
+ - 6525caa: An ongoing gesture can take the wheel while it is in flight. `OngoingHandle.onWheel(ctx)` is called with each wheel event before any wheel binding sees it, newest gesture first; returning `true` claims the event, so the viewport neither zooms nor pans, and anything else lets it through to the bindings as before.
575
+
576
+ `OngoingHandle.overlay()` may now answer a list of overlays as well as one, for a gesture showing several runs at once. This is breaking for code that reads `overlay()` directly and expects a single overlay: read it through the new `overlaysOf(handle)`, exported from routing and core, which always answers a list. Core's overlay painter, gesture bounds and parallax-plane mapping, and kernel3d's `collectOverlayBoxes`, all read it that way.
577
+
578
+ `OverlayRole` names one more kit role, with a stroke in core's overlay painter: `falloff`, the reach of a soft-selection drag.
579
+ - f4dd2ff: A gesture's `GestureContext` carries the canvas's kit settings as `kitSettings`, so a behavior can read a setting at the moment it uses one; move, resize, rotate, insert, and clone now ask for the `kitSettings` dep to fill it.
580
+ - 5adbb76: The `harmonizeAnchors` action makes smooth anchors curvature-continuous by changing only their handle lengths, along the directions the handles already have, keeping the product of each anchor's two lengths: the selected anchors, or every smooth anchor of the path while none is selected. Corners, open ends, and anchors the curve inflects through are left alone. It is labeled "Harmonize curvature", has no key of its own, and is in the standard actions, the `paths` preset, and the `anchors` group beside `retractHandles` and `makeHandlesSymmetric`, with the icon `core:harmonize`.
581
+
582
+ `@weasel-js/geom` adds the edit underneath: `harmonizeAnchors(set, flatIndexes?)`.
583
+ - 0382007: `<SceneCanvas isPointerInteractive>` gates every point hit on the canvas, as its doc said: a node it rejects is left out of the select tool's pick, the dispatcher's `kind:` classification, the `hitAt` and `nodeAtPoint` deps, and the `onClick`/`onDoubleClick` observers, and whatever is beneath it answers instead. Before, only the observers honored it, and they reported a miss rather than the node beneath. Routing entries are now handed the node beside its data (`NodeRoutingEntry.matches(data, node)`, `NodeRouting.classify(data, node)`), and `inferredNodeRouting`, the default when `routing` is unset, leads with the new `groupNodeRouting`, which routes a container as `'group'` where it was `'unknown'`. `defaultNodeRouting` is unchanged; spread `groupNodeRouting` ahead of it for the same.
584
+ - d0daf94: `IconRegistryProvider` replaces its tables when `icons` changes. The tables it mounted with used to stay registered for its whole life, so a new `icons` value registered beside them rather than in their place. The first tables still register during the first render, so nothing draws without its glyph, and unmounting the provider releases whatever it holds.
585
+ - 63b310c: Icons are named, not drawn, by the code that uses them. This is breaking.
586
+
587
+ `@weasel-js/icons` is new. An icon is a qualified name, `namespace:name` (`core:undo`, `ui:close`, `path-tools:reversePath`), held as an `IconRef`. Each package's `icon()` makes one and qualifies its own bare names: in core, `icon('undo')` is `core:undo`. A registry supplies the glyphs: mount `<IconRegistryProvider icons variants>` from `@weasel-js/core` at the app root, or give `<WeaselProvider>` its new `icons` and `iconVariants` props. Core, ui and path-tools each publish their table at `./icons` (`import { icons } from '@weasel-js/ui/icons'`). A name no registered table holds draws a placeholder and warns in development, and draws nothing in production.
588
+
589
+ `@weasel-js/icons-plugin` is new too. Its build plugin, `weaselIcons`, ships only the glyphs a build names. In an app's vite, rollup or rolldown build, `weaselIcons.vite({ mode: 'app' })` serves `virtual:weasel-icons`, holding the glyphs named by the app and by the weasel packages it imports, and fails the build on a name no table holds. `virtual:weasel-icons/all`, `/<namespace>` and custom variants each load as their own chunk, asked for with `useIconVariant(name)`. Types for the virtual modules are at `@weasel-js/icons-plugin/virtual`. The plugin is its own package so that installing `@weasel-js/icons` does not install a native parser. Core's and ui's `dist` is no longer minified, so the `@icon` annotations the plugin reads survive; a consumer's bundler minifies.
590
+
591
+ What breaks:
592
+
593
+ - routing: `Action.icon`, `ActionVariant.icon`, `ActionItem.icon` and `ToolPresentation.icon` take an `IconRef` from `icon()`, not a React node. So does `useCommand`'s `icon` option, which no longer takes a function read each time the command shows.
594
+ - prefs: `PrefBase.icon` and an enum option's `icon` take an `IconRef`, not a free string. A schema saved with bare names, such as `"icon": "close"`, now draws nothing for them and warns in development; write `"ui:close"`.
595
+ - core, ui and path-tools: the `…Icon` components are removed; draw `<Icon name={icon('core:rect')} />` instead. `NudgeAnchorsIcon` and its `dir` prop become four glyphs, `core:nudgeAnchors` (pointing right), `core:nudgeAnchorsUp`, `core:nudgeAnchorsDown` and `core:nudgeAnchorsLeft`. Core's `PaintKindEntry.icon` and `PaintKindFamily.icon` take an `IconRef`. Core's `ACTION_GLYPHS`, `IconProps` and `ActionGlyphProps` are gone, and so are ui's `ICON_PATHS`, `ICON_FILLS`, `ICON_GROUPS`, `MARK_ICONS`, `IconName`, `MarkIconName`, `FillableIconName` and `ActionIconSource`.
596
+ - ui: `<Icon name>` and `mark`, `actionIcon` and `ActionBar`'s `icons` take `IconRef`s, and `isFillable` takes a glyph. `resolveIcon` draws a ref, or a qualified string read from data. `iconFromData(value)` reads a name from data as a ref, warning once in development about a bare one.
597
+ - labkit: `CommandItem`, `ToolItem`, `ViewportControl` and `TrialTool` take an `IconRef` as `icon`, and so does `ConfigOption.icon`. `IconComponent`, the nine ui icon components labkit re-exported, and its `ICON_PATHS` and `IconName` are gone.
598
+ - forge: `GlobalDeclaration.icon` takes an `IconRef`. `FrameSetup.icons` registers an app's own tables in every frame. A story's `control.icons` argTypes option takes qualified names (`'ui:statusSuccess'`); a bare `'statusSuccess'` now draws nothing.
599
+
600
+ `@weasel-js/registry` exports `isDev()`, which `@weasel-js/react` re-exports. It reads `process.env.NODE_ENV`, which a production bundle folds to `false`, and the development diagnostics in core, routing, ui, labkit, renderer and animator all read it.
601
+ - c6a0a52: Kit settings for gestures, targets, the camera, orbit and the loupe. Under a `<KitSettingsProvider>` a consumer can now set `gestures.doubleClickMs`, `doubleClickPx`, `longPressMs`, `tapPx` and `dragPx` (read by the dispatcher, the move action and `useDragHandle`; an explicit `longPress` prop or `dragThresholdPx` param still wins); core's `targets` leaves `handlePx`, `anchorHitPx` and `rotationDistancePx` (the base that device scaling multiplies, under an explicit `handleHitRadius`), `segmentHitPx`, `anchorClickPx`, `pickTolerancePx` (under `geometry.pickTolerancePx`), and the pen, bone, weight and slice overlay dot radii; `view.animationMs` (under a move's own `ms`); `orbit3d.orbitRate` and `dollyRate` in kernel3d; and `loupe.wheelRate` in labkit. `coreKitSettingsSchema`, `kernel3dKitSettingsSchema` and `labkitKitSettingsSchema` describe these as prefs groups whose paths are the settings' paths, each default being the existing constant. Underneath: `createPointerRecognizer` takes `doubleClickMs`, `doubleClickPx`, `tapPx` and `dragPx` thunks; `<SceneCanvas>` publishes the provider's store as the `kitSettings` dep; `targetSizesPx` and `mergeLayersWithDefaults` take optional base sizes; `createPenPreviewLayer`, `createBoneOverlay` and `createWeightOverlay` take optional size readers; `@weasel-js/react` declares `KitTargetSettings`, the shared `targets` area. Additive.
602
+ - 6812344: `layered` routes long edges and leaves labels room on a live scene too.
603
+
604
+ - **Under `order: 'seeded'`.** An edge spanning ranks now stands in each rank it crosses and a
605
+ labeled edge gets a rank of its own, as under `'barycenter'`. An edge keeps its place in a rank
606
+ the way a node does, from where its route crosses that rank now (`GraphEdge.waypoints`, which
607
+ `buildGraph` fills in), so a second run still moves nothing. This changes where a seeded layout
608
+ puts nodes in any graph with a long or labeled edge.
609
+ - **Written to the scene.** The layout action and a live `layered` run write each long edge's
610
+ waypoints, and station its label in the room left for it, in the same undo entry as the moves.
611
+ `buildGraph` reads a scene label's size as its edge's label room.
612
+ - **Whose route it is.** `DiagramEdge.laidOut` records the waypoints layout wrote, and layout
613
+ rewrites a route only while the edge's waypoints still match them (`layoutOwnsRoute`). An edge
614
+ someone has bent, and the label on it, are left alone, and get no room in the ranks the edge
615
+ crosses (`GraphEdge.authored`); so is a label put at `'start'`, `'end'` or a fraction.
616
+ `diagramScene` marks the routes it lays out the same way. A layout that routes nothing
617
+ (`tree`, `force`, `chain`) takes layered's routes back off.
618
+ - **`diagramScene`.** A label whose edge sets `labelPlacement` at `'mid'` now gets room beside
619
+ its wire like an unplaced one, at that placement's offset. Routes come from any layout with a
620
+ `plan`, not only `layered`.
621
+ - **Locked layers.** `applyLayout` skips a node, edge or label on a locked layer instead of
622
+ throwing.
623
+ - **New surface.** `LayoutFn` may carry a `plan` returning `LayoutPlan` (`moves`, `waypoints`,
624
+ `labels`); `layered.plan` is `layeredPlan`, and `planOf` reads any layout's. `routesOf` and
625
+ `routeWrites` turn a plan into scene edits, and `applyLayout` takes them as `routes`.
626
+ `usePoseRun` takes `commitWith`, writes of the caller's own made inside the commit's batch.
627
+ - `expand`'s `placeholders` and `labels` options are gone; it always adds both.
628
+ - fb75358: Lengthen: in path edit, turn on the Lengthen path-edit tool and drag an open path's end anchor outward to grow the path from that end, or inward to shorten it along itself. It grows straight along the end tangent, or along a circular arc with the curvature the end has, meeting the path smoothly. The `lengthenPath` action's `mode` param (`'tangent'` or `'curvature'`, typed for `<SceneCanvas tune>`) sets which a plain drag does, and Shift, read on every move, picks the other. A straight end segment grows in place; a curved one is continued with a new segment, one per quarter turn of arc. Each drag is one undo step, "Lengthen path" or "Shorten path". `lengthenPreset` in `@weasel-js/path-tools` registers the action and its toggle, `pathEditTool.lengthen` (`lengthenToolAction`, drawn with `path-tools:lengthen`); `pathTools` includes it.
629
+
630
+ `lengthenPathEnd(set, end, distance, mode)` (`@weasel-js/geom`) is the edit underneath, with a negative `distance` shortening. `openEndAt` names the open end an anchor is, `pathEndFrame` gives an end's point, outward tangent, and signed curvature, `lengthToward` turns a pointer position into a distance, and `pathEndAnchorIndex` finds the end anchor again after an edit. `lengthenOpenEnd`, which Extend to next path uses, is now `lengthenPathEnd` in tangent mode, so both tools grow a curved end by the same rule.
631
+
632
+ While a path-edit tool is on, path edit's anchors and handles no longer show their own hover cursor, so the tool's action shows its own.
633
+ - ef6b6ae: Annotation layers, and measurements kept on them. A layer declared with `annotation: true` (in `systemLayers` or `addLayer`) holds aids rather than content: its nodes draw on the canvas, save with the scene (`toJSON` keeps the flag), and undo with it, while content picking — clicks, marquee, lasso, Select All — passes through them. `isAnnotationLayer`, `isAnnotationNode`, and `annotationLayerIds` are the one question export, picking, and layer lists ask; export code should leave out what they say yes to.
634
+
635
+ A measurement is a leaf on an annotation layer whose `data.measure` holds its two ends in world units (`measureNode(id, layer, start, end)`), drawn by the built-in `kit:measure` painter as a line with a tick across each end. `measurementOf(node)` reads one as a `Measurement` — `start`, `end`, `dx`, `dy`, `distance`, and `angle`, in radians, read like a protractor: counterclockwise-positive on screen, so a line rising up and to the right at 30° reads +30°.
636
+
637
+ `createMeasurements({ layer })` names the layer and holds what is not the document's: which measurement is picked, and the one a measure drag is drawing. Give the same object to:
638
+
639
+ - `useMeasureTool({ measurements, angleStep? })` (key M, icon `core:measure`): a drag adds a measurement, both ends through the `snap` dep and Shift holding the angle to `angleStep` (default 15°), and picks it; a click picks the measurement under it; Escape drops the pick and Delete removes it.
640
+ - `measurementsContribution(scene, measurements)`, installed with `<SceneCanvas ambient>`: under every tool, a click on a measurement picks it without touching the content selection, a drag on the picked one's end moves that end, and a drag anywhere else on one carries it. Its commands, in the `measure` group: `measure.moveBy` moves the content selection by the current measurement's offset and `measure.rotateBy` turns it about its center the way the line goes, each one undo step Transform Again repeats; `measure.delete` and `measure.clear` remove one or all. The current measurement is the picked one, else the newest.
641
+ - `<MeasureReadout scene measurements>` in `@weasel-js/ui`: the current measurement's distance, offset, and angle, with Move by, Rotate by, Delete, and Clear all.
642
+
643
+ `@weasel-js/ui`: `useSceneLayerList` leaves annotation layers out unless given `annotations`, when each gets a row holding its nodes, marked not printed: the layer can be hidden from its row, and its nodes picked and removed. `LayerListItem` gains `nonPrinting`, `hideable`, and `removable`. `BarActionButton` takes a `disabledReason`, which keeps a disabled button focusable with its reason in the tooltip and in `aria-description`; `useActionStates` reports the reason an action gives.
644
+ - e4642bb: A right-click, an unclaimed long-press, Shift+F10 or the ContextMenu key now runs the `menu.context` standard action. It selects the shape under the pointer if it was not selected, then asks the menu host for the menu declared for that hit. It is disabled where no menu is declared for the hit, so nothing is selected and a long-press still falls through to the click and drag bound there; the browser menu stays suppressed as before. `MenuHost` gains `has(req)`, which answers whether `open(req)` would show anything.
645
+ - e901a2b: `actionShortcuts` now lives in `@weasel-js/routing` (core still exports it). `evaluateEnabled` takes an optional point and passes it to `Action.enabled`, so a menu can ask whether an action applies where it was opened. `ActionsRegistry.trigger` asks `enabled` at `{ x: params.worldX, y: params.worldY }` when both are numbers, so a menu row runs under the same question it was shown enabled for. `ActionShortcut` is now an alias of `@weasel-js/menu`'s `MenuShortcut`.
646
+ - 57725cc: Menus hang under a rect and register commands from callbacks. `placeMenuUnder` in `@weasel-js/menu` is new public API: it places a menu under a rect, flips it above, and right-aligns it at the right edge. `MenuOpenRequest.under` is an additive field, honored by the DOM and WebGL menu renderers, and `BarMenu` passes its button's rect. `BarMenu` takes an additive `defaultOpen` prop: it opens the menu once on mount, without taking focus, retrying as commands register until the menu has rows. `useCommand(id, label, run, options?)` is new public API in `@weasel-js/routing/react` and `@weasel-js/core`; its `icon` option takes an `IconRef`. The asset editor files menu roots under a "Menus" heading and previews them open.
647
+ - 3f89d6b: A mode's double-click entry is now read. `ModeDefinition.entry.targets` names the routing kinds a `'double-click-target'` trigger takes — `PATH_EDIT` takes `'path'`, `ISOLATION` takes `'group'`, and `TEXT_EDIT` none, since its edit enters it — and `modeTriggers(registry, { enter, canEnter })` in `@weasel-js/core` turns them into an ambient contribution: a double-click on a node of one of those kinds enters the mode on it, unless `canEnter` refuses and the double-click falls through. Additive.
648
+ - 86725ed: An ongoing action can name the modifiers it reads mid-gesture as roles: `Action.modifierRoles` declares each role's default keys, a tuning's `roles` or a binding's `opts.roles` moves one to other keys, and the dispatcher resolves them into `InvocationCtx.roles` on the press, every move, and the release. `roleReader` reads them, falling back to the default keys where nothing resolved them.
649
+
650
+ Path edit's modifiers are roles now. `editAnchors` declares `selection.add` (Shift), `mirror.break` (Alt), `handle.holdAngle` (Shift), and `handle.holdLength` (Cmd or Ctrl); `marqueeAnchors` declares `selection.add`; the pen's handle drag declares `mirror.break`, `snap.constrain` (Shift) and `snap.suspend` (Ctrl); and `balanceHandles` declares the two handle locks. So `<SceneCanvas tune={{ editAnchors: { roles: { 'handle.holdLength': ['alt'] } } }}>` moves the length lock to Alt.
651
+
652
+ Breaking: `locksInForce` takes the invocation context in place of its `ModifierState`, so it can read the roles.
653
+ - f34b290: A `<CanvasView>` can nest in another through `parent`: its `bounds` are measured from that view's
654
+ rect, a thunked `bounds` or `view` receives that view's camera and size, it paints cut to that view
655
+ and only the layers that view paints, and input inside it lands in its world before that view's.
656
+ `SceneCanvasApi.viewAt` names the innermost view under a canvas point. An interactive or
657
+ view-backed loupe now magnifies the camera of the view under its aim, so over a panel it shows and
658
+ edits the panel's world. `createViewportLayer` and `ResolvableView` take an optional `clip`.
659
+ - 679138c: A scene node can be hidden or locked on its own, not only through its layer. `SceneNode.hidden` keeps a node and its whole subtree from being drawn; `SceneNode.locked` keeps a node and its subtree drawn but out of reach, the way a locked layer's nodes are. Both are set through `scene.setHidden(id, hidden)` and `scene.setLocked(id, locked)`, each one undo step that neither lock blocks, or through the new `createSetHiddenOp` / `createSetLockedOp` against an adapter's `setHidden` / `setLocked`. Both go on `AddNodeSpec`, ride a snapshot, and come back with an undone removal. Additive.
660
+
661
+ `scene.isHidden(id)` is new, and `scene.isLocked(id)` now folds in the node flags. Both answer from `nodeGates`, now exported with `isNodeHidden`, `isNodeLocked` and `hidesSubtree`, which every reader asks: painting, point picking, the marquee and lasso, select-all, path snapping, measurement picking and snapping, sibling spacing guides, the slice and Girth tools, and text editing all pass over a hidden node, and the pickers over a locked one. The selection now drops a hidden node as it drops a locked one, so hiding a layer or a node deselects what it hides.
662
+
663
+ `@weasel-js/svg`: `svgNodesFromKit` writes a node carrying `hidden` with `display="none"`, which `parseSvg(…, { keepHidden: true })` reads back as hidden, and `unpackSvgFiles` now keeps a dropped file's hidden content, inserting it hidden rather than leaving it out.
664
+ - a2dcbfb: The Nudge Anchors actions draw a glyph of their own: a hatched block pushed by a two-ring pulse behind it, turned the way each one moves. `core:nudgeAnchors` points right and stands for nudging with no direction given; `core:nudgeAnchorsUp`, `core:nudgeAnchorsDown` and `core:nudgeAnchorsLeft` are the other three. Before, those actions had no icon, and a surface showed their arrow keys in its place.
665
+ - 8775065: A derivation reading a dependency shown by a pose override's `path` now reads that path where it is painted. The override path is given in the painter's unturned box, and derivations were handed it as is: a path effect over a source whose override pose is turned read it unturned, and, under a composing strategy, the render and pick walks read a source inside a turned container where the container's local coordinates would put it.
666
+ - d4d28ad: The command palette titles a variant with its action's label and its own ("New: A4"), and a search matches that title. A variant whose label already opens with the action's keeps it ("Zoom In"). `actionItemTitle` gives the title; menus and bars still show the variant's own label. `@weasel-js/core` also exports `ActionDisabledReasonValue`.
667
+ - ad8f48a: `clipboard.paste` takes an optional world point: `useClipboardOps().paste(at?)`, the `clipboard` dep's `paste(at?)`, and the action's `worldX`/`worldY` params. Given one, the paste lands there instead of at the pointer, so Paste chosen from a context menu pastes where it was opened.
668
+ - 5274f79: The path commands gain icons: `core:join` on `joinPaths` and `joinAnchors`, `core:cutAtCrossings` on `snipAtCrossings`, `core:simplify` on `simplifyPath`, `core:offsetPath` on `offsetPath`, and `core:averageAnchors` on `averageAnchors`. `livePathEdit`'s spec takes an optional `icon`.
669
+ - c4840ed: Geometric constraints on a path's anchors that hold while it is edited. Additive throughout.
670
+
671
+ `@weasel-js/geom` gains `PathConstraint` — fixed, horizontal, vertical, parallel, perpendicular, equal length, length, and coincident, each naming anchors by flat index — and a damped Gauss-Newton solver for them. `solveConstraints` moves points the least that makes a list hold, with held points giving way last and fixed ones put back where they were; `solvePathConstraints` does the same over a path's anchors, carrying each anchor's handles with it. `constrainPathEdit` finishes an edit of a constrained path: it renumbers the constraints through the edit's point origins, holds the anchors the edit moved, and leaves out of the solve, and reports, any constraint that already failed before the edit. `unsatisfiedConstraints` says which of a list do not hold.
672
+
673
+ In `@weasel-js/core`, a node's `data.constraints` holds through every path edit: the `editAnchors` dep's `editOps` solves and renumbers them before storing the path, an edit they cannot survive commits nothing, and the anchor drag calls the dep's new `constrainEdit` each frame so the preview is what the commit stores. `setConstraints` on the dep replaces a node's list in one history entry, moving the path to satisfy it and answering which constraints conflict; a conflicting one is kept, left out of later solves, and drawn as a conflict. The path-edit overlay marks each constraint beside the geometry (`getConstraints` and two colors in `PathEditingOverlayStyle`). The `paths` feature registers `constrainAnchors` (params `{ kind, length? }`, read from the selected anchors in selection order) and `unconstrainAnchors` (params `{ kind? }`), with no default bindings. Clicking a constraint's mark selects it (`selectedConstraint` on the dep, kept by the path-edit state beside the anchor selection, which it excludes), and `deleteConstraint`, on Delete and Backspace, removes it. A solve that holds only by collapsing a named segment to a point is a conflict, not a solution. Resize, rotate and flip carry the list unchanged; `constraintConflictsOf(node)` names what a transform broke, such as a set length under a scale. The whole-path commands — Simplify, Offset, Trim segment, Extend to next path, Join, Bridge, and Snip — drop `data.constraints`, as they drop a skin, since they rebuild the anchors with nothing to renumber the list through.
674
+ - 616a4b2: Path edit's handle drags gain a length lock beside the angle lock. Mod (Cmd or Ctrl) held while dragging a control handle keeps its length and changes only its angle, as Shift keeps its angle and changes only its length; both together freeze it. The lock in force draws what it holds the handle to — the line, or the circle round the anchor — as a `polyline` overlay of the new `lock` role.
675
+
676
+ Two toggle actions, `handleLock.angle` and `handleLock.length` (group `anchors`, no default binding, in the `paths` preset), hold a lock for every handle drag without a modifier. They set `handleLocks` on the `editAnchors` dep, which `EditAnchorsDep` gains with `setHandleLocks`, so a bar, the command palette, and `<SceneCanvas tune>` reach one value: `editAnchors`'s new `handleLock: 'angle' | 'length'` param (`EditAnchorsParams`) is where the locks start until a toggle is pressed.
677
+
678
+ `@weasel-js/geom` adds `handleAtItsLength`, the length-holding counterpart of `handleAlongItsAngle`.
679
+ - 0677769: Path edit gains soft selection and handle snapping, each a preset in `@weasel-js/path-tools` that nothing turns on by default, `pathTools` included.
680
+
681
+ - **Soft selection** (`createSoftSelectionPreset(() => ({ radiusPx, falloff, onRadius }))`, its options read as each anchor drag starts; null leaves the drag hard). Dragging anchors also moves the anchors near them, each by a weight falling from 1 to 0 over the radius, which is measured along the path in screen pixels. The falloff is `'smooth'`, `'linear'` or `'sharp'`. The reach is drawn as a band while the drag lasts, and the wheel scrubs the radius mid-drag, reporting each new value to `onRadius`. Under a `pathSymmetry` dep a soft drag moves no symmetric images.
682
+ - **Handle snapping** (`handleSnapPreset`, or `createHandleSnapPreset({ stepDeg, reachDeg, opposite })`, or a thunk of them read on every move). A dragged control handle's angle snaps to multiples of the step (45° by default) and to the line through the anchor's other handle, within the reach (6° by default), keeping its length. The line it snapped to is drawn. A held angle lock wins over the snap; a held length lock keeps the length while the angle snaps.
683
+
684
+ Both reach the drag through a new member of core's `PathEditExtension`: `drag(start)`, asked as an anchor or handle drag starts, returns the extension's share of it (`PathEditDrag`) — anchors that follow an anchor drag and the share of its delta each moves by (`weights`), where a dragged handle goes after the locks (`handle`), a claim on the wheel mid-drag (`wheel`), and overlays drawn while the drag lasts (`overlays`). `PathEditDragStart` and `PathEditHandleMove` describe what it reads.
685
+
686
+ `@weasel-js/geom` adds the geometry: `measureAnchorPath`, `softSelectionWeights`, `softSelectionBand` and `softFalloff` for soft selection.
687
+ - 974682d: Three live path effects: a blend between two shapes, a shape bent along a path, and copies of a shape along a path. Each is one scene node whose `dependsOn` names its sources and whose path and pose both derive from them, so editing a source — moving it, or dragging its anchors — updates the effect, and it saves and loads under the registry key `kit:pathEffect`. A scene holds path effects when it registers them — `createScene({ registry: withPathEffectsRegistry() })` — since reading a source's outline needs the painters; without that the actions are disabled. `pathEffectNode(effect, sources, layer, PATH_EFFECT_DERIVATIONS)` makes one; `data.pathEffect` holds its settings. Dragging an effect drags its sources; resizing or turning it resizes or turns them, as `shapeSources` now reaches through any node whose pose derives from named dependencies, not only a container's children.
688
+
689
+ The actions are in the standard set and the `paths` preset, in the `pathEffects` group (`PATH_EFFECTS_GROUP`): `blend` (Alt+Shift+B) over the first two selected shapes, `bendAlong` (Alt+Shift+W) and `repeatAlong` (Alt+Shift+R) laying the first selected shape along the second, `editPathEffect` changing an effect's settings as one coalescing undo step, and `expandPathEffect` (Alt+Shift+E, "Expand to Paths") replacing an effect with the ordinary paths it shows. `ActionParamSchema` types their params for `<SceneCanvas tune>`.
690
+
691
+ A blend matches anchors contour to contour, splitting the shape with fewer at its longest segments until the counts agree, and picks the second shape's start point and direction to keep matched anchors closest; `startOffset` and `reverse` override that. Fill and stroke mix through OKLab, and a turned source turns its neighbors rather than squashing them.
692
+
693
+ A `derivePath` can now paint in several parts, each in its own fill and stroke: return `pathFromParts(parts)`, and the `kit:derived` painter draws each part as itself while picking and bounds see one path.
694
+
695
+ `@weasel-js/routing` adds `BROWSER_RESERVED_CHORDS` and `browserReservedChord(spec)`: the key chords a major browser or desktop takes before the page does. The new bindings stay clear of them.
696
+
697
+ `@weasel-js/geom` adds the geometry: `prepareBlend` and `blendPaths`, `bendAlongPath` (refit to a tolerance, corners kept), `stationsAlongPath` and `repeatAlongPath`, `measurePath` (arc length measured once, with an optional smoothed heading, which `pointAlongPath` now uses), and `pathToCubicContours` / `cubicContoursToPath`. `@weasel-js/paint` adds `lerpPaint`, `lerpFill` and `lerpStroke`.
698
+ - 66e3696: A derived node inside a container that composes frames paints where its dependencies are painted. Its path is drawn from their world poses, and the walk used to turn it again by the container's rotation; it now turns by the node's own rotation only. A derivation is handed each dependency's pose in the frame of the node deriving, so a path effect, or any `derivePose`, over shapes in another container boxes itself where it paints. `derivedDepOf(source, id, reader)` reads a dependency the way `reader`'s derivation does, and Expand to Paths uses it, so an effect across containers expands where it is drawn.
699
+ - 5973184: Every path operation carries `tags` naming the gesture that drives it, so the operations sharing a gesture can be gathered with `actionsTagged` / `taggedActionItems`. Each carries `path` and one of `path-drag`, `path-click`, `path-brush`, `path-box`, or `path-command`, defined once as `PATH_GESTURE_TAGS` and applied with `pathOperationTags(family)` (both new in core). `docs/path-operations.md` lists the operations under each tag. Actions built with `makeHandleCommand` and `joinPathsCommand` now carry `path-command` too. Additive.
700
+ - 7afe8cd: Geometric snapping onto paths. `pathSnapSource()` offers the geometry of every node on a visible, non-annotation layer as snap targets: its drawn outline (`nodeOutline`) and, for a painter marked `snapsToBox` (text and images), its pose box and the box's center. The targets are anchors and corners, box centers, where two strokes cross, the tangent and perpendicular points from where the line being drawn starts, segment midpoints, curve extremes and quadrant points, and the nearest point on a stroke. `kinds` turns each kind on or off and `only` names the ones offered. An anchor drag also snaps to its own path's other anchors and segments, leaving out the segments it moves. The snapped point is drawn with a glyph and its kind's name (`pathSnapGlyph`, `PATH_SNAP_LABELS`).
701
+
702
+ `@weasel-js/geom` adds `createPathSnapIndex`, `findPathSnap`, `findPathSnaps`, `PATH_SNAP_KINDS`, and `pathAwayFromAnchors`.
703
+ - 3378ade: Two path-tools presets for a path's structure, both in `pathTools`:
704
+
705
+ - `pathStructurePreset` brings `setPathStart` (group `anchors`), which makes the one selected anchor its subpath's start — a closed subpath turns to start there, and an open one reverses when given its last anchor — and `reversePath` (group `path`), which runs paths the other way without changing their shape. In path edit it reverses the subpaths holding the selected anchors, or every subpath, and the anchor selection follows its anchors; outside path edit it reverses every selected path in one undo step. It also draws an arrow at the middle of every segment of the open path, pointing the way it runs, and a ring round each subpath's start anchor, under the chrome id `path-edit.direction` (`PATH_DIRECTION_CHROME_ID`), off until chrome-caps shows it. `createPathStructurePreset(style)` takes their `color`, `arrowPx`, and `ringPx`.
706
+ - `segmentTypePreset` brings `convertSegments` (group `anchors`, Shift+C), which turns the selected segments — those whose two ends are selected anchors — between straight and curved: a line becomes a curve with handles at its thirds, drawing the same line, and a curve drops the two handles that shape it. `params.to` picks `'line'` or `'curve'`; with none it flips the lot. `convertSegmentAt` flips the segment under a Shift+double-click.
707
+
708
+ Core's `paths` preset gains `setAnchorField`, which writes a typed number into the selected anchors: `{ field, to }` sets every one, `{ field, by }` offsets each. `useAnchorFields()` reads the fields for chrome beside the canvas — the selected anchors' X and Y, `null` where they differ, and a lone anchor's handle X, Y, angle and length — and writes through that action. `segmentUnder` is exported for actions that act on the segment under the pointer in path edit.
709
+
710
+ An anchor edit now carries a node's vertex colors, `data.vertexColors` and `data.stroke.vertexColors`, and its stroke widths, `data.stroke.vertexWidths`, along with its `data.skin`: an anchor the edit keeps keeps its color and width, one it makes blends its neighbors' (each side of a two-sided width on its own), a deleted one's entry goes, and reordering anchors reorders them. Where an edit reverses a subpath, a two-sided width trades its `left` and `right`, so each edge stays on the side it was drawn on.
711
+ - c0d59c6: The path tools gain icons. Smudge brush, Distort, Envelope and Puppet Warp show theirs on the tool and its action; Blend, Bend Along Path, Repeat Along Path, Balance handles and Equalize handles get one each; Expand to Paths and Expand Warp share `path-tools:expand`. All are in the `path-tools` icon namespace. Warp Settings and Edit Path Effect take `core:tune`, and Delete constraint takes `core:delete`.
712
+ - f426089: New package, `@weasel-js/path-tools`: the path-editing tricks moved out of core, each family a `FeaturePreset` an app turns on beside core's (`features={['draw', pathTools]}`, or one preset at a time). It holds the Simplify brush, the handle-lock toggles, Bridge and Bridge anchors, Trim segment, Extend to next path, Smudge brush, Harmonize curvature, the curvature comb, Balance handles and Equalize, path constraints, Blend / Bend along / Repeat along, and the warp actions and tools (distort, envelope, puppet, expand, configure). Their action and tool names are unchanged; they are imported from `@weasel-js/path-tools` now, and core's `paths` preset no longer registers them.
713
+
714
+ Core keeps basic path editing and gains the extension point these are built on: `PathEditExtension`, carried by a preset's `pathEdit`, draws marks on the open path, adds grabbable parts (an `AffordanceRegion` may name a `chromeId` of its own), selects and deletes its marks, and finishes every edit (`finishEdit`). A preset's `chromeRules` sets default visibility for chrome of its own. Breaking for code reading the `editAnchors` dep: `constrainEdit` is `finishEdit`, `selectedConstraint` / `setSelectedConstraint` are `selectedMark` / `setSelectedMark`, and `setConstraints` is gone (`setConstraints(dep, …)` in the package); the dep adds `store` and `extensions`. The overlay slot's `comb` and `balance` options, `PATH_COMB_CHROME_ID`, `PATH_BALANCE_CHROME_ID`, and the constraint colors in `PathEditingOverlayStyle` move to the package's presets. Core now exports what a path command or path-edit feature built outside it needs — `selectedPathNodes`, `withPath`, `reshapeOps`, `commitOps`, `joinPathsCommand`, `makeHandleCommand`, `commitAnchorEdit`, `GEOMETRY_BOUND_DATA`, and the rest — plus `flipAction` and the anchor actions (`selectAnchorAction`, `deleteAnchorsAction`, `nudgeAnchors*Action`), and `makeEditAnchorsDepForTests` and `useEditAnchorsDepSourceForTests` in `@weasel-js/core/test-seams`. The path-effect scene nodes and their derivations stay in core, so a saved document renders without the package.
715
+ - dcca70c: Three warp tools bend the selected paths and keep the warp editable until it is expanded. `useDistortTool` drags the four corners of the selection's box on their own, mapped bilinearly (`mode: 'free'`) or projectively (`'perspective'`, which keeps straight lines straight). `useEnvelopeTool` drags the points of a mesh over the box (`rows`, `cols`), interpolated as a bicubic surface or as one Coons patch per cell (`mapping`). `usePuppetTool` pins a path where it is clicked and bends it when a pin is dragged, moving everything else as rigidly as the pins allow; Alt-click takes a pin out. Pass them through `<SceneCanvas tools>`; their keys are F, M, and B, and `keybinding` overrides or (with `null`) omits one. Their drag and pin actions read the same settings as params, so `<SceneCanvas tune>` can set them too, and the controls drawn over a path holding no warp yet are drawn from those tuned settings. `ActionsRegistry.paramsOf(id, given)` answers the params an invocation would start with, tunings included, and `<SceneCanvas>` publishes it as the `actionParams` dep.
716
+
717
+ A warp is held on each path as `data.warp`, beside the geometry it made, and survives moving, resizing and rotating the node. Two new actions in the `paths` preset work on whatever warp the selection holds: `expandWarp` drops it, leaving plain geometry, and `configureWarp` remakes it with new settings. Editing the path's anchors, or any path command, also drops it. `withPathWarp` builds a node that opens already warped; `heldPathWarpOf` and `resolvePathWarp` read one back.
718
+
719
+ `@weasel-js/geom` adds the maps underneath — `bilinearQuad`, `projectiveQuad`, `bicubicMesh`, `coonsMesh`, and `rigidPuppetMap` — and `warpPath(path, map, { tolerance })`, which carries any path through any point map and refits each segment as cubics within the tolerance, keeping every anchor. `PathWarp` describes a warp as data, with `applyPathWarp`, `warpControls` and `moveWarpControl` over it.
720
+ - 420e4b2: The pen's and the knife's close reach are kit settings: `targets.penCloseHitPx` and `targets.sliceCloseHitPx`, each 8 screen px where nothing sets it, and each in `coreKitSettingsSchema`. A tool's own `closeHitRadius` option still wins over a provider.
721
+ - bfb566c: A leaf drawn as its rect pose alone, with no `data.path`, now has an editable
722
+ path: `classifyPathStorage` and `resolveEditablePathOf` read it as a rect
723
+ `data.path` the size of its pose, and its first edit writes one, as a drawn
724
+ rectangle's does. Trim segment, Extend to next path, path edit, and the other
725
+ path commands reach it. `EditableShape` takes the node's `kind`, since only a
726
+ leaf drawn by the kit's rect fallback qualifies.
727
+ - d019f44: A removal on a canvas can animate out. `scene.onPoseWrite` listeners get a second argument, the nodes each change removed (an undone add among them), each a `PoseRemoval` carrying the node as it stood, the pose it was shown at, its parent and its descendants. `<SceneCanvas poseTransition={{ transition, exit }}>` sees each one off as a ghost: drawn through the scene slot's `drawOne` on a layer above the scene, gliding to `exit(pose)` while it fades out, and never a scene node, so picking, selection and history do not see it. `exits` picks which removals leave this way (default: all but untracked ones), and a node an undo brings back mid-exit returns from where its ghost was. The ghost needs an `AnimatedReflow` (`useAnimatedReflow`, `createReflowTransition`), which gains `over(scene, geometry)` to run the same timing over another scene. `usePoseTransition` returns the ghosts it shows (`Departures`). Additive, except for anything implementing `ScenePoseReports` or `AnimatedReflow` by hand.
728
+ - 79b65f5: `<SceneCanvas poseTransition>` glides the poses a scene writes on screen instead of snapping them:
729
+ a button's `scene.setPose`, an undo, a redo, and with `enter` a node the scene adds. It takes the
730
+ same kind of transition as `reflowTransition` (`useAnimatedReflow`), and `glides` picks which
731
+ writes move — by default direct scene calls and history steps, not an action's commit. The
732
+ document takes each write at once; only what is shown travels.
733
+
734
+ `scene.onPoseWrite(listener)` is new: once per change, it reports each node whose pose the change
735
+ wrote or that it added, with the pose it left, where the write came from (`'call'`, `'ops'`,
736
+ `'undo'`, `'redo'`, `'layout'` or `'untracked'`), and the edit's label. Also new:
737
+ `bindPoseTransition`, `usePoseTransition`, `glidesByDefault`, and the `PoseWrite`,
738
+ `PoseWriteOrigin`, `ScenePoseReports`, `PoseTransitionSeat` and `PoseTransitionScene` types.
739
+ - cc54285: `ActionVariant` and `ActionDisabledReason` are now public API, no longer tagged `@experimental`. `useCommand`'s `variants` option takes `ActionVariant`s, so a command's variants can carry `tags`; the unreleased `CommandVariant` type is gone.
740
+ - e021579: `contextMenuAction` (`menu.context`) and `openContextMenu` are public from `@weasel-js/core`. They
741
+ need only `menuHost`, `view` and `worldToClient` to open a menu at a right-click or, from Shift+F10
742
+ and the ContextMenu key, at the middle of the view; a scene's selection and hit testing refine the
743
+ hit where they are supplied. labkit's trial cameras now register this action instead of their own
744
+ copy.
745
+ - 36eca7a: Breaking: `useAnimator` moved to `@weasel-js/animator/react`; the root entry has no React. `@weasel-js/core/math` no longer reaches routing or animator in its types. geom exports `FramedBox`. New `@weasel-js/font/metrics` entry carries `parseBmFont`, the face-metric readers and `cssFamilyName` with no DOM in its types, and `@weasel-js/diagram/layout` measures through it, so neither it nor `@weasel-js/diagram-elk` needs a browser. `faceMetricsOf` takes any value with `entry` and `outlineFace`, a `ResolveResult` included.
746
+ - cc11671: More tools and actions gain icons. In core, the Bone and Weight tools (`core:bone`, `core:weight`) and Bend segment (`core:bendSegment`). In `@weasel-js/path-tools`, Trim segment and Extend to next path get their own (`path-tools:trim`, `path-tools:extend`) in place of the Slice knife, on both tool and action; Reverse path, Set path start, Set corners and the corner radius drag, Next corner shape, Convert segments with a straight and a curved variant, and Add extreme anchors get one each; and `path-tools:girth` is drawn for the Girth tool.
747
+ - c1680fd: A rectangle stored as a rect `data.path` can be edited in path edit: it shows its four corners as anchors, and the first edit stores it as the equivalent polygon, in the same undo step as that edit. Entering and leaving path edit without editing leaves it a rect. The path commands that act on the selected paths, such as offset, now take a rectangle too. Additive: `asPolygonPath` (geom, re-exported by core) returns any `Path` as a command stream, a rect as its corners clockwise from its origin, the order `countPathAnchors` numbers them in, so per-anchor colors keep their corners; core's `hasEditablePath(node)` says whether path edit can show anchors for a node.
748
+ - 0430dcc: Every type a public signature names is now exported, so the API reference links it. Signatures that named a file-local point alias (`Pt`, `XY`, `Vec`) take geom's `Point`, and ones that named a local `AnyScene` or `AnyNode` say `Scene<unknown, string, unknown>` or the node type outright. Newly exported: core's `AnnotationFlag`, `AnchorEdit`, `JoinPlan`, `PathEditPreview`, `PathStorageKind`, and `ViewPoseAdapter`; diagram's `RoutedScene`; prefs' `UsePrefsStoreOptions`; symmetry's `SymmetryKindDef`; path-tools' `WarpToolOptions`; and ui's `SceneLayerListProps`.
749
+ - 39f86d1: An unchanged layer of a few hundred commands or more is now drawn once into a texture of its own and composited as one quad on later frames, instead of being submitted again every frame.
750
+
751
+ `GroupDrawCommand.retain` names the surface. The renderer keeps the group's pixels while its `children` array and everything it was drawn under hold: the enclosing transform, alpha and color matrix, the view matrix, the drawing size and dpr, and the fonts, textures, paint kinds and programs it serves. Anything else draws it again. A surface is drawn in a multisampled buffer matching the canvas's own, so its edges come out as they would have on the canvas, and it is freed at the end of the first frame that does not draw its id. `WeaselRendererOptions.retainBudget` caps the memory retained surfaces hold together (default `DEFAULT_RETAIN_BUDGET`, 256 MiB, scratch buffer included); a group past it draws straight through. `RenderStats.retained` reports how many groups were composited, redrawn, or declined, and the bytes held.
752
+
753
+ `drawLayers` marks a layer for retaining once its `deps` have held for a frame and, for a world-space layer, the view has too, if it holds at least `DEFAULT_LAYER_RETAIN.minCommands` (250) drawing commands. `RenderLayer.retain: false` opts a layer out and `true` retains it whatever its size. A layer with `effects` is not retained. The new trailing `drawLayers` argument takes another `LayerRetainPolicy`, or `false` to retain nothing.
754
+ - f3398d4: The `@experimental` designation is retired. Everything that carried it is now ordinary public API: the actions registry and its built-in action descriptors and icons, the ambient pointer and selection contexts, `CanvasView`, the canvas extension API, the view resolver and viewport layer, the affordance helpers, path-tools' commands and icons, and `registerEffect`. No signatures changed.
755
+ - 86a5ec7: The shape builder lives in `@weasel-js/path-tools`, in a directory of its own, rather than in core: import `useShapeBuilderTool`, `planShapeBuilder`, `facesAlong` and their types from there, and mount the tool with `<SceneCanvas tools>`. It carries its own actions, so it needs no preset. Its behavior is unchanged, and core has no code of its own for it.
756
+
757
+ Core opens its Boolean pipeline to an operation of the caller's own, which is what the shape builder now runs on: `resolveBooleanOperands(adapter, opts)` answers the selection's operands back to front, resolved as the built-in operations resolve them (text outlines, a counted stroke's region and the paint it leaves), and `commitBooleanPieces(adapter, operands, pieces, label)` replaces them with the caller's pieces as one undo step, each minted from the source it names and stacked in that source's slot. `PATHFINDER_STROKES`, what a stroked operand gives the Pathfinder actions, is exported, and `@weasel-js/core/test-seams` adds `rootsTreeForTests`, the flat tree of a fake adapter.
758
+ - c2048de: `@weasel-js/path-tools` adds `useShapeBuilderTool` (Shift+M), which builds shapes from the faces two or more selected paths cut each other into. The face under the pointer is shown; a drag unites every face it passes through into one path standing in for the first face's source, so it wears that source's paint, and an Alt-drag deletes them instead, Alt being read live through the drag. A click takes a single face. Every face not taken becomes a path of its own, and each gesture is one undo step. With fewer than two paths selected, a drag marquee-selects. `mode: 'delete'` swaps the two, so a plain gesture deletes and Alt unites. It reads the `booleansAdapter` dep the Pathfinder actions use, and counts an unfilled stroke as the region it covers, as they do.
759
+
760
+ Core's `<SceneCanvas>` now publishes a `booleansAdapter` of its own over its path leaves (`data.path` drawn through the pose's box), so the Pathfinder actions and the shape builder work on a canvas whose consumer publishes none. A result is minted from the source it stands in for, keeping its layer, parent, frame, and data. A consumer's `useBooleansAdapter` under the canvas still replaces it — for text operands, which this one does not read. `useBooleansAdapterSource` is the hook behind it.
761
+
762
+ `planShapeBuilder(adapter, opts)` is the engine under it: the faces, `faceAt(x, y)`, and a `commit(picked, 'merge' | 'delete')` that writes the batch. `facesAlong(plan, run, step)` answers the faces a run of points passes through, in the order it enters them.
763
+
764
+ Core's `createPathOverlay({ id })` holds paths that are not nodes and gives a world-space `RenderLayer` drawing them over the scene, for a tool's `overlay` or a canvas's `layers`. Each path names a role, styled by `PATH_OVERLAY_ROLES` (`'chrome'`, `'picked'`, `'remove'`) or the caller's own.
765
+
766
+ `@weasel-js/geom` adds `pathFacePieces(...paths)`: `pathDividePieces` with a region that falls apart split into one piece per connected part.
767
+ - 9073669: Path edit has tools: a set of named tools, one active at a time, that each change what a plain drag in path edit does. With none on, a drag edits anchors as before. The `editAnchors` dep carries the active one as `tool` and switches it with `setTool(id | null)`; a `<SceneCanvas pathEdit>` host may own it by also giving `tool()` and `setTool(id)`, as it already owns the open path. A tool belongs to the open path, so leaving path edit puts it down. `pathEditToolAction(tool, label, icon)` makes a bar toggle for one (id `pathEditTool.<tool>`, group `anchors`, pressed while on), and `pathEditTool.exit` puts the tool down on Escape, so a second Escape leaves path edit. While any tool is on, `editAnchors`, `bendSegment`, `marqueeAnchors`, and `selectAnchor` stand aside; Alt-click still inserts an anchor.
768
+
769
+ The first tool is the Simplify brush, a local version of the Simplify command. Its toggle, `pathEditTool.simplifyBrush`, sits in the `anchors` bar with the icon `core:simplifyBrush`. While it is on, a plain drag gathers every anchor a round brush passes over, and each unbroken stretch of them along a subpath is refitted as one span by Simplify's own fitter, at a tolerance in world units (default 1, as for Simplify). Only the anchors the shape does not need within that tolerance go, corners stay, and anchors outside the brush are left exactly as they were. The path previews the result during the stroke, release commits one undo step, and Escape mid-stroke cancels it. The action is `simplifyBrush`, in the standard actions and the `paths` feature preset; `ActionParamSchema` types its `radiusPx` (screen pixels, default 12) and `tolerance` for `<SceneCanvas tune>`. The cursor over the canvas is the brush ring, as wide as the brush a drag there would start, a tuned radius included.
770
+
771
+ An action's hover `cursor` may now be a function of the params the winning binding would start it with, tunings included; `actionCursor(action, params)` reads either form, and `resolveOnly` reports the winning binding's `params`.
772
+
773
+ Path edit draws the open path's outline as a thin accent line over its own paint, so a path stays visible under its markers, and an unselected anchor that sits closer to a neighbor on screen than a marker is wide is drawn as a small dot, so a dense freehand run reads as a line of dots rather than a solid band. `PathEditingOverlayStyle` takes `outlineStroke`, `outlineWidthPx`, and `denseDotRadiusPx`.
774
+
775
+ `@weasel-js/routing` adds a `brush` overlay variant: `{ kind: 'brush', points, radiusPx }`, the world path a round brush has taken and its radius on screen. `<SceneCanvas>`'s dispatcher overlay paints it as the swept band and a rim at the brush's position, gated by the `action.brush` chrome-caps id.
776
+
777
+ `@weasel-js/geom` factors Simplify's fitter onto a span: `simplifySpan(sub, closed, from, to, tolerance)` refits one stretch of a subpath and `simplifySubpath` a whole one, both of which `simplifyPath` now runs on. `simplifyAnchorsAt(set, flatIndexes, tolerance)` refits each unbroken run of the named anchors, and `anchorsUnderBrush(set, from, to, { radiusPx, scale })` answers the anchors within `radiusPx` of a segment, measured on screen.
778
+ - 798e9b0: The Properties W and H fields hold a node to its `data.minSize`, as resize and
779
+ insert already do: typing a smaller width shows and stores the minimum. With
780
+ several nodes selected, each is held to its own minimum.
781
+
782
+ A number leaf takes `minAt` and `maxAt`, bounds read from where its value is
783
+ held, which `prefNumberAt` folds into `min` and `max` for one holder.
784
+ `SelectionPanel` resolves them per node, `PrefsForm` and labkit's
785
+ `ControlPanel` against their values. `prefClampNumber` holds a number to a
786
+ leaf's range.
787
+ - f082c83: A Smudge brush: a round brush that pushes the outline of the selected paths along with the pointer. Points under the brush move with it, most at its center and not at all at its rim, and a segment the brush meets that is longer than a third of its radius is subdivided until it can bend there.
788
+
789
+ `@weasel-js/geom` adds `smudgePath(path, opts)`, one dab of the brush.
790
+
791
+ `@weasel-js/core` adds the `smudgeBrush` action to the `paths` preset and `useSmudgeBrushTool` (key S), whose drag routes to it. The action's `radiusPx` (screen px) and `strength` params are set with `<SceneCanvas tune>` and read on every move, its cursor is the Simplify brush's ring at that radius, and a stroke is one undo step.
792
+ - db8c16e: One snap pipeline for every gesture. Move, resize, rotate, insert (drag and click-place), pen and spiro placement, pen handles, anchor and handle drags in path edit, measure, and the symmetry center all begin a session on the `snap` dep at press and ask it each frame where their point lands. Every kind of target is a snap source, and one resolver ranks all of their candidates together: a point beats a line, a real target beats a fallback such as the grid, then the smaller move on screen wins, then source order. One readout layer draws what the result met. `docs/snapping.md` is the reference.
793
+
794
+ **Breaking: removed APIs, with their replacements.**
795
+
796
+ - `SnapDep.point` is gone: the `snap` dep is `begin(req)`, which returns a `SnapSession` (`at`, `angle`, `end`).
797
+ - `<SceneCanvas toolOptions={{ snapPoint }}>` is gone: register a source in `<SceneCanvas snap={{ sources }}>`, `gridSnapSource` for a grid.
798
+ - `selectTool.snap`, `SnapStrategy`, and core's `snap()` behavior adapter are gone: a grid is `gridSnapSource({ spacing, origin?, unitSystem? })`, ruler guides `guideSnapSource(getGuides)`. A pose that is neither a rect nor a `Path` passes its `OriginProjection` as `snap={{ originProjection }}`. Moving from `selectTool.snap: gridSnapStrategy(…)` to `gridSnapSource` also snaps resize corners, inserts and pen clicks to the grid, not only a move's origin.
799
+ - `@weasel-js/guides`: `gridSnapStrategy`, `guideSnapStrategy`, `GuideSnapOptions`, `DEFAULT_GUIDE_TOLERANCE_PX`, and `pointSnapToGrid` are gone, and so are the `@weasel-js/guides/move`, `/resize` and `/insert` subpaths with their `snapToGrid`, `snapToGuides`, `SnapToGuidesMoveArgs`, `SnapToGuidesResizeArgs` and `SnapToGuidesInsertArgs`: use `gridSnapSource` and `guideSnapSource`. An import of `snapToGrid` from `@weasel-js/core/move` (a subpath that no longer had it) becomes `gridSnapSource` from `@weasel-js/guides`.
800
+ - `@weasel-js/guides`: `alignMoveBehavior`, `alignInsertBehavior`, `alignResizeBehavior`, `AlignMoveArgs`, `AlignmentBehaviorBase`, `matchAlignment`, `MOVE_ANCHORS`, `AlignAnchor` and `AlignMatchResult` are gone: `alignmentSnapSource(opts)` snaps to siblings' edges and centers and `spacingSnapSource(opts)` to equal gaps, on move, resize and insert alike. `matchSpacing` and `measureGaps` stay.
801
+ - `PointSnapBehavior`, `PointSnapContext`, `PointSnapResult`, `PointSnapFrame`, `ResizePolicy.pointSnap`, `useResizePolicy`'s `pointSnap`, and the resize option `pointSnapBehaviors` are gone: a resize snaps its dragged corner or edges through the session, so any source snaps it.
802
+ - `lockAspectWithModifier` (with its `{ key }` option) and `DEFAULT_RESIZE_BEHAVIORS` are gone from `@weasel-js/core/resize`: Shift's aspect lock is the resize's `snap.constrain` role.
803
+ - `snapRotationWithModifier`, `DEFAULT_ROTATION_SNAP_STEP` and `DEFAULT_ROTATE_BEHAVIORS` are gone: rotation snaps through `rotationSnapSource`, which every canvas asks, and the `snap.constrain` role (Shift) adds the 15° steps. `rotate: { behaviors: [] }` no longer turns rotation snapping off; `<SceneCanvas snap={{ omit: ['rotation'] }}>` does, and a source with the id `'rotation'` replaces the default.
804
+ - `constrainTo45` is gone from `@weasel-js/core`: the pen's handle Shift is the session's angle step.
805
+ - `usePenTool`'s `snapPoint` and `anchorSnapRadius` options are gone, and `useDragRect`'s and `useDragRadial`'s `snapPoint`: the pen and the drag gestures snap through the `snap` dep (`pathSnapSource` for anchors, `gridSnapSource` for a grid). A pen anchor joins an open end within `targets.penCloseHitPx` of the press before any snap.
806
+ - kernel3d's `createSnap()` took nothing and snapped nothing; `createSnap(world, { sources?, reachPx?, store? })` takes the world and snaps.
807
+
808
+ **New.**
809
+
810
+ - `<SceneCanvas snap={{ sources, omit, reachPx, originProjection, readout, readoutStyle }}>` (`SceneCanvasSnap`), a feature preset's `snapSources`, and `useSnapSource(source)`.
811
+ - One reach for every source that sets none, the kit setting `targets.snapPx` (8 screen px; `DEFAULT_SNAP_PX`).
812
+ - The snap source contract: `SnapSource`, `SnapCollect`, `SourceCandidate`, `Locus`, `SnapProbeAt`, `SnapGesture` (with `'handle'`), `SnapEdge`, `SnapEdges`, `AngleCollect`, `AngleCandidate`, `SnapMark` and `SnapMarks`; the session types `SnapBegin` (with `reachRad` and `theta0`), `SnapConstrain`, `SnapMods`, `SnapOutcome`, `SnapResizeBox`, `SnapSession`.
813
+ - Sources: `pathSnapSource` with `PathSnapSourceOptions` (and `only`), `measureEndSource` with `MeasureEndSourceOptions` (`reachPx`), and `rotationSnapSource` in core; `gridSnapSource`, `guideSnapSource`, `alignmentSnapSource` and `spacingSnapSource` in guides; `handleSnapSource` and `HandleSnapOptionsInput` in path-tools (`createHandleSnapPreset` and `createHandleSnapExtension` take options or a thunk of them, and the preset registers the source); `boxSnapSource`, `alignPlaneSource`, `groundGridSource` and `GroundGridSourceOptions` in kernel3d.
814
+ - The modifier roles `snap.suspend` (Ctrl) and `snap.constrain` (Shift), declared by every snapping action: `SNAP_ROLES`, `snapMods`, `SNAP_ANGLE_STEP` (the one 15° step for a line insert, a measurement, a rotate and the symmetry axis), `SNAP_AXIS_STEP`, and `stepAngles`.
815
+ - The readout: `createSnapReadoutLayer`, `SnapReadoutStyle`, `createSnapOutcomeStore`, the `snapReadout` dep (`SnapReadoutDep`), and the drawing helpers `tickedSegment`, `pillCommands` and `measuredSegmentCommands`. The debug overlay's `snap` feature draws every candidate the resolver weighed.
816
+ - Building blocks for a host's own session: `resolveSnap` and its types in `@weasel-js/geom/nd`, with `stepLine` and the flat math under it (`Flat`, `Vec`, `flatDim`, `closestOnFlat`, `closestBetweenFlats`, `intersectFlats`); `gatherSnapCandidates`, `resolvedSnapMarks`, `snapSourcesFor`, `GatherSnapOptions`, `SnapCandidateMark` and `SnapGeometry` in core; `pointSnap`/`PointSnap` for a tool placing points.
817
+ - `@weasel-js/geom/3d` gains `vec3`, `distance`, `lerp`, `pointOnRay`, `aabbOfPoints`, `closestPointOnLine`, `closestPointOnSegment` and `closestPointsRayLine`.
818
+ - `@weasel-js/core/test-seams` gains `createSnapSession2dForTests` (with `SnapSession2dOptions`), a 2D session for tests outside core; it is not public API.
819
+ - kernel3d: `projectSnapMarks` with `ScreenLine` and `ScreenPoint`, `projectPoint`, and `Snap3dOptions`.
820
+ - `InsertDep.commit` and `InsertDep.build` take an optional `ends: InsertEnds` (the drag's start, end and `fromCenter`); click-place passes them too. kernel3d's `createInsert` builds its footprint from the two ends cast onto the ground, so a 3D click-place centers its footprint on the snapped ground point.
821
+ - path edit: `PathEditDragStart.snap`, `PathEditDrag.end`, `SnapMods.hold`.
822
+
823
+ **Behavior changes.**
824
+
825
+ - Every `<SceneCanvas>` snaps point gestures to other nodes' anchors — rect and text corners, ellipse quadrants, path anchors — through a default source with `pathSnapSource`'s id, `'path-snap'`: pen placement and handle tips, spiro points, anchor drags, line and box insert, click-place, measure ends and the measurement end drag, and the symmetry center; not move, resize or rotate. `snap={{ omit: ['path-snap'] }}` drops it, and a consumer's own `pathSnapSource()` replaces it rather than doubling. A point target on the gesture's own `origin` is never offered, so a handle tip does not stick to its anchor.
826
+ - A grid gives way to a target in reach on its axis, where alignment used to add its delta on top of the grid's. Guides and alignment reach 8px, not 6.
827
+ - Ties between equally good results break by source order, then by the order a source yields its targets.
828
+ - Ctrl suspends snapping on every snapping gesture, a pen drag and an anchor drag included; a handle drag keeps Ctrl as its length lock.
829
+ - A rotate snaps to quarter turns and to other nodes' angles without Shift (new); near the pivot its reach is capped at 30°.
830
+ - Shift on a move locks it to the horizontal, vertical or 45° line through the press (new), and so does Shift on an anchor drag (new).
831
+ - Shift on a line insert, a measurement or a pen handle puts the end at the pointer's nearest point on the stepped line through the start (it used to keep the drag's length), and that line meets snap targets.
832
+ - An anchor drag meets every point-gesture source, a grid included.
833
+ - A multi-root move snaps each root's origin, the nearest winning, not only the first node's.
834
+ - A move's behaviors run on the snapped delta, and a behavior's translate stands, so a container's slot preview wins over a snap target in reach.
835
+ - A measurement end drag keeps its offset from the press (it used to jump the end to the pointer), and no longer snaps to its own measurement's ends.
836
+ - kernel3d's `translate` puts its plane at `up · position`, the same as before for +y up.
837
+ - e287da2: Spacing hints, as one preset. `createSpacingHintsPreset()` is a `<SceneCanvas features>` entry: a move snaps the selection so its gap to a neighbor equals one already between its siblings and marks the equal gaps, and holding Alt over a shape measures its distance from the selection. Options turn off the spacing snap or the readout, add snapping to siblings' edges and centers, and set the snap distance and color. Turning it off is leaving it out of `features`.
838
+
839
+ A `FeaturePreset` can now carry `moveBehaviors`, folded into every move the presets' ambient bindings run, after the select tool's own.
840
+
841
+ The pieces are exported too. `measureDistances(from, to)` returns the gaps between two boxes on each axis where they separate, or from an inner box to the edges of the one holding it, as `SpacingGap`s, with leader lines where a gap runs past its target. `distanceReadout()`, which the preset brings, is a surface contribution for `<SceneCanvas ambient>`: while Alt (or the `modifier` given) is held over a shape, it draws the distances from the selection to that shape. `siblingBounds`, `worldBoundsOf`, and `worldUnionOf` read world boxes off a scene; `siblingBounds` is the boxes equal spacing measures while some ids move.
842
+
843
+ A modifier going down or up over a resting pointer now dispatches a `hover`, with the new modifiers, so a hover binding that needs a key held answers it without waiting for the pointer to move.
844
+
845
+ Core exports `scenePoseFrame` and `PoseFrame`: world reads and local writes over a scene's own composition.
846
+ - Spiro curves: a curve drawn by its on-curve points alone. `@weasel-js/geom` solves one with `solveSpiro(points, closed)`: an Euler-spiral segment, whose curvature changes evenly along it, runs between each pair of points, and the segments are solved together so tangent and curvature carry straight through every `smooth` point. A `corner` lets its two sides turn independently, `left` continues the straight segment arriving at it, and `right` runs the curve into the straight segment leaving it. `spiroToPath(contours)` writes the solved curve as cubics, splitting a segment wherever one cubic would stray more than a ten-thousandth of its length, and reports which anchor each point became; `spiroContoursOf`, `spiroControlPath` and `spiroContoursFromControl` read the points back out of such a path and in from an edited control path. The `spiro` curve representation in `@weasel-js/geom/curves` now uses the solver.
847
+
848
+ Breaking: `SharedAnchor.spiroType` takes a `SpiroKind` (`'smooth' | 'corner' | 'left' | 'right'`) where it took `'g2-smooth' | 'g4-smooth' | 'corner'`. G4 points were never solved as such.
849
+
850
+ `@weasel-js/core` lets a path be drawn from another form it keeps beside it. A node's `data.representation` holds the form, named by its `kind`, and a `PathEditExtension`'s new `representation` (a `PathRepresentation`) says how path edit reads and writes forms of that kind: `editPath` gives what path edit shows and moves in place of the drawn path, `store` turns an edit of it back into the drawn path and the form, the live drag preview included, `anchorMarkers` shapes each anchor's marker (`AnchorMarkerShape`), and `segmentPress` takes a press on the outline in place of Bend segment. A form no representation on the canvas reads is edited as its drawn path and dropped, and `representation` joins `GEOMETRY_BOUND_DATA`, so a path command that replaces the geometry, such as Join or Simplify, leaves plain geometry. `pathEditPathOf` and `storeEditablePath` take the extensions to consult; the `editAnchors` dep's new optional `getOutlinePath` gives the drawn path the segment affordance hit-tests. The insert dep's `'path'` extras take a `data` laid under the path, and `createPointerFollower` is exported for tools that trail the pointer.
851
+
852
+ `@weasel-js/path-tools` draws and edits spiro curves, all from `src/spiro`. `spiroPreset`, in `pathTools`, brings the spiro representation: a spiro node, `data.path` plus a `{ kind: 'spiro', kinds, at }` form (`spiroNodeData`, `spiroOf`, `withoutSpiro`), is edited through the straight-sided control path through its points, and every edit solves the curve again. Each point draws by its kind: a circle for smooth, a square for a corner, a half-disc facing away from the line for `left` and `right`. Dragging the curve between two points adds a smooth point there and drags it. The preset also brings `setSpiroKind`, which sets the kind of the points selected in path edit, and `releaseSpiro` ("Convert to path"), which turns a spiro curve into an ordinary path. The spiro tool, `useSpiroTool` (Shift+P), mounted through `<SceneCanvas tools>`, places points by clicking, each of the kind its `spiro.placePoint` action's `params.kind` names, Alt-click for a corner, and inserts the curve through the `insert` dep as a `'path'` carrying its form. Its glyph is `path-tools:spiro`.
853
+ - 3eb2abc: A text node can cut its text at its box: `data.overflow: 'clip'` draws the glyphs in a group clipped to the pose box, picks only the lines inside it, cuts the editing overlay to the same box (`TextEditScreenPose.clip`, read through `useSceneTextEdit`'s new `getOverflow`), and exports as an SVG group clipped to the box. Properties offers it as a Clip switch. A node can also carry a minimum size, `data.minSize` (`MinSize`, `minSizeOf`): a resize stops at it whatever the resize policy's constraints, a multi-selection stops where its first member reaches its own, and a scale replayed through transform-again holds to it. An insert or place binding's `minSize` param grows a smaller drag or click to it and is kept on the node. Sticky notes now clip their text and keep a 48 × 48 minimum, both set through `toolOptions.sticky` (`overflow`, `minSize`). An SVG import reads a clipped note back as a clipped group around its text, not as a text node that clips.
854
+ - e554ae5: New: a sticky-note tool. `useStickyTool` is a built-in tool id, so `<SceneCanvas defaultTools={['sticky']}>` mounts it (key S), and `BUILTIN_TOOL_IDS` lists it after `text`. A drag draws a note through `insertAction`; a click places one of `size` through the new `placeAction` (id `place`), which commits a node of its binding's `kind` and `size` centered on the click through the same `insert` dep. Either drops into the new note's caret. The note's look (`background`, `fill`, `padding`, `style`, `verticalAlign`, `size`) is the tool's options and `toolOptions.sticky`; `STICKY_DEFAULTS` holds the rest. `stickyData` builds a note's data and `stickyNodeFactory` is the same as an `InsertNodeFactory`.
855
+
856
+ A note is a plain text node: `kit:text` nodes gain `data.background`, a fill painted over the whole box under the glyphs (and which makes the whole box pickable), and `data.padding`, the inset the text lays out in. `textBoxOf` is that box. `useSceneTextEdit` opens its overlay over the inset box, takes a double-click anywhere in the node's box, and returns `drawOne`, `defaultDrawOne` less the glyphs of the node being edited, for a canvas whose text nodes have a background that should stay painted while the overlay is up. The text properties gain Background and Padding. `svgLeafFromKit` writes a text node with a background as a group of its box and its inset text.
857
+
858
+ `ShapeKindDescriptor` gains `text`, which says a kind's node is text: an insert of it opens its caret, and its properties carry the text groups.
859
+ - 70fe7cc: A stroked shape's box now includes its stroke as drawn, engine-wide. The selection outline and handles sit on the stroke's outer edge (align, joins, markers, variable widths, and screen-pixel widths at the view's scale all counted), and a group's box reaches as far as its members' strokes. Resizing moves that box and keeps the stroke's width, so the stroke's outer edge lands under the pointer: a 100×100 rect with a centered stroke 10 wide shows a 110×110 box at (−5, −5), and dragging its right handle to x = 205 leaves the rect 200 wide. Resize constraints see the box with the stroke. Rotate turns a selection about the center of that box, and flip, align, distribute, and alignment snapping measure it too. Stored geometry is unchanged: a group's derived pose, booleans, outlines, and export still read the pose box.
860
+
861
+ This changes behavior for any stroked shape. `<SceneCanvas geometry={{ boundsIncludeStroke: false }}>` restores geometric boxes; actions read it as the new `boundsIncludeStroke` dep.
862
+
863
+ New in core: `drawnBoundsOf`, `drawnAABBOf`, and `inkExtentsOf` answer the box for any scene node, and `NodeShapeEntry.drawnBounds` lets a painter report its own (the built-in shape and path painters measure miter joins and markers on polygons, stars, and paths). `GestureFrames.drawnBounds` hands that box to gesture behaviors. `SceneCanvasGeometry` names the `geometry` prop's type. A variable-width stroke's picking reach now uses its widest vertex.
864
+
865
+ `@weasel-js/guides`: pass `drawnAABBOf` boxes to `deriveAlignmentGuides` so siblings are measured the same way as the dragged selection.
866
+ - c4e499e: A declared menu is now a prefs schema. `MenuDef` holds `menu: PrefGroup` in place of `sections`, and `MenuDefEntry` and the `actionVariants` entry are gone: an action leaf naming a parametric action already lists one row per variant, and one naming `id:variant` lists that variant alone. `resolveSchemaMenu(schema, sources, at?, params?)` draws any schema subtree as menu entries, so a toolbar can open one as a menu; `resolveMenu` calls it, and core re-exports it with the `MenuSources` type. An `actions` leaf lists every action in its registry group, a group drawn `as` a `menu`, `page`, `tab`, or `panel` is a submenu, and any other group sits inline between separators. Booleans become checked items and enums radio rows, read through the new optional `MenuSources.values` and written through `MenuSources.onChange`; a `readout` one is a disabled row showing its state. An `action` leaf naming no registered action is a disabled row that warns in development, since a menu holds no code. A `label` leaf is a disabled row, a `separator` leaf a separator, an `alias` the leaf it points at (in `MenuSources.over`, else the menu's own schema), and `showIf`/`enableIf` hide and disable rows when `values` is given. Leaves a menu cannot edit, such as numbers and colors, are left out. Menus contributed under one id merge as each contribution's children in turn with a separator between, keeping their keys, so value paths do not move. `pref` gains `action`, `actions`, `label`, and `separator` builders. Breaking for any declared menu written with `sections`.
867
+ - ecdf4d0: Symmetry groups work in a scene that composes frames. Moving a group's center leaves its contents where they drew, though their stored poses are in the group's frame, and `bakeSymmetry` writes every original and copy as a pose local to its new parent. Core exports `scenePoseAdapter`, the `PoseAdapter` over a scene that `composeWorldPose` and `rebaseLocalPose` take.
868
+ - 1efa251: The drags `@weasel-js/ui` starts through `startThresholdDrag` — reordering a list, dragging a `Tree` row, and picking up a node from the schema editor's palette or its live preview — engage at the `gestures.dragPx` kit setting, as the canvas's own drags already did, instead of always at `DRAG_THRESHOLD_PX`. `useReorderDragList`'s own `threshold` option still wins.
869
+ - 1faab2d: Trim segment. `useTrimTool` (key Y) hands a click to the new `trimPath` action, which removes the clicked piece of a stroke between the nearest crossings on either side, with any other node's outline or with the stroke itself. Curves split where they are cut and stay curves, a closed shape opens, an end piece runs back to the first crossing, and a stroke with nothing left is deleted, each as one undo step. While the tool is up it draws the piece under the pointer dashed, from the same `planTrim` the click commits. The action is in the standard actions and the `paths` preset.
870
+
871
+ Extend to next path. The new `extendToMeet` action carries open ends along their tangent to the next stroke they meet: the selection's ends, the selected end anchors in path edit, or, with `useExtendTool` (key U), the end nearest a click. A straight end grows longer and a curved one gains a straight run. It is in the standard actions and the `paths` preset, with no key of its own.
872
+
873
+ `@weasel-js/geom` adds what these stand on: `intersectSegments`, `pathSegments`, `pathCrossings`, `trimPathAt`, and `extendToMeet`, `lengthenOpenEnd`, `openEndRay`, and `openPathEnds`.
874
+ - 15fbffb: `useCommand` takes `variants`, and its callback receives the params it was triggered with, so a parametric command — one entry per variant in a bar, menu or palette — needs no hand-built `Action`. Additive.
875
+ - d705830: A stroke can be drawn with a broad nib. `Stroke.nib` is `{ angle, ratio }`: the nib's edge in radians counterclockwise on screen, and its thinnest width as a fraction of its widest. The stroke is its full width moving across the nib and `ratio` of that moving along it, an elliptical pen's width in between, and it multiplies `vertexWidths` where both are set. Each side of a corner keeps its own width, so a square drawn with a level nib has thin level sides and full upright ones right up to the joins; a round join's arc runs between the two. `strokeToPath`, the renderer's ribbon cache, and SVG export follow it, and since a nib only ever narrows a stroke, bounds and culling are unchanged. `@weasel-js/stroke` adds `nibWidthScale`, the nib as a `WidthScale`, and `widestStrokeWidth`, which culling, picking, and flattening now share; picking used to ignore `vertexWidths`. Draw's stroke properties gain a Nib switch with its angle and thinnest ratio.
876
+
877
+ A `vertexWidths` entry is a `VertexWidth`: a number, the full width centered on the path as before, or a `{ left, right }` pair giving each edge its own distance from the path, `right` being the side the normal `(−dy, dx)` points to, below a path running in +x on screen. Every reader resolves an entry through `vertexHalfWidths(entry, fallback)` in `@weasel-js/paint`: the tessellator, which carries the difference between the sides as the new `Polyline.offsets` through trimming, dashing, and the nib, and centers caps between the two edges; `strokeToPath`; the inner and outer ribbon; bounds, culling, and picking, through `widestHalfWidth`; and SVG, which writes a pair as `left/right` in `wzl:vertex-widths`. `vertexWidthFromSides` writes equal sides back as a number, and `scaleVertexWidth` scales either form. An entry of zero is now a zero width; it used to take the stroke's `width`.
878
+
879
+ `useGirthTool` (Shift+W), in `@weasel-js/path-tools`, edits `vertexWidths` by dragging the stroke's edges. Hovering near either edge marks the grab point on it and the width point a press there moves: the anchor at that spot, or one inserted between two with `insertAnchorOnSegment`, so the path keeps its shape. The grabbed edge follows the pointer along the path's normal and the other mirrors it, writing a number; dragging inward pinches the stroke, down to zero. Alt-drag moves the grabbed edge alone and writes a pair. The drag moves the edge as drawn, so under a nib the stored width changes by more. Every drag is previewed live and committed as one undo entry. Alt-click on a width point clears it, so it takes the stroke's `width` again. The stroke last touched shows its anchors, with a line across the stroke at each that has a width. `strokeEdgeNear` in `@weasel-js/stroke` is the hit test behind it: the edge of a stroke nearest a point, measured along the path's normal, with each side's distance as drawn.
880
+
881
+ A dashed stroke now keeps its per-vertex widths, which it used to drop. The anchor-parameter rule that trimming and dashing share is `anchorParamsBetween` in `@weasel-js/geom/tessellate`.
882
+
883
+ SVG has no variable width. `serializeSvg` writes a stroke with `vertexWidths` or a `nib` as its outline: the path keeps its stroke attributes at `stroke-width="0"`, which draws nothing, with the real width, the per-vertex widths, the nib, and its markers in the `wzl` namespace, and the outline follows as a filled path in the stroke's paint that draws the marker heads. A node with an opacity wraps both in one group carrying it, so they composite as one layer. Other viewers draw the outline; `parseSvg` drops it and reads the stroke back off the path, and a transform it bakes in scales the per-vertex widths with the width.
884
+ - 398d71e: A camera animation that names no duration of its own now takes 0ms while the reader's `prefers-reduced-motion` is `reduce`, in place of the `view.animationMs` kit setting or its default, and follows the preference as it changes. `@weasel-js/react` exports `prefersReducedMotion()` and a `usePrefersReducedMotion()` hook that re-renders when the preference changes; the long-press ring and `@weasel-js/ui`'s components now read the preference through it.
885
+ - ebc9858: `viewport.zoom` lists Zoom In, Zoom Out and Reset Zoom as variants, so a menu or an `actions` group shows three entries, each with its key, where it showed one "Zoom" that zoomed in. Not purely additive: a bar `action` leaf naming bare `viewport.zoom` now draws a dead button, and has to name `viewport.zoom:in`, `viewport.zoom:out` or `viewport.zoom:reset`.
886
+ - 06d23a3: `WeaselProvider` no longer remounts everything below it when `icons` or `iconVariants` is set or cleared. It used to swap the component above its tree between a registry of its own and one that joins the registry in scope; one component now makes that choice inside, so the tree keeps its state. Clearing both props releases the tables they registered and joins the registry in scope again.
887
+ - d8160be: Nudge, Duplicate, Move by, and Transform Again offset a node in world space,
888
+ mapped through the frame its parent defines, the way a drag and an Alt-drag
889
+ clone already did. Inside a turned group, an arrow key now moves the selection
890
+ along the screen rather than along the group's axes, and Cmd+D after a drag
891
+ steps the way the drag went. `translateSelection` and `duplicateSelection`
892
+ take a world offset.
893
+ - Updated dependencies [304f53a]
894
+ - Updated dependencies [3ffe020]
895
+ - Updated dependencies [60d8e39]
896
+ - Updated dependencies [6a53aaa]
897
+ - Updated dependencies [193ba96]
898
+ - Updated dependencies [09c3e5f]
899
+ - Updated dependencies [535aaaa]
900
+ - Updated dependencies [ed0e096]
901
+ - Updated dependencies [65be8d3]
902
+ - Updated dependencies [10b67bb]
903
+ - Updated dependencies [95d22f1]
904
+ - Updated dependencies [5338358]
905
+ - Updated dependencies [b0f392c]
906
+ - Updated dependencies [cf7b009]
907
+ - Updated dependencies [6072e93]
908
+ - Updated dependencies [53ba41a]
909
+ - Updated dependencies [1322a03]
910
+ - Updated dependencies [275714b]
911
+ - Updated dependencies [4da5998]
912
+ - Updated dependencies [7162a7a]
913
+ - Updated dependencies [765cd31]
914
+ - Updated dependencies [eec8a5b]
915
+ - Updated dependencies [1774dc4]
916
+ - Updated dependencies [0a30bde]
917
+ - Updated dependencies [8ff3b4b]
918
+ - Updated dependencies [02cbe1d]
919
+ - Updated dependencies [d2749ce]
920
+ - Updated dependencies [a988460]
921
+ - Updated dependencies [8374354]
922
+ - Updated dependencies [516914b]
923
+ - Updated dependencies [6525caa]
924
+ - Updated dependencies [5adbb76]
925
+ - Updated dependencies [681c3f9]
926
+ - Updated dependencies [63b310c]
927
+ - Updated dependencies [b36ceac]
928
+ - Updated dependencies [34f8b09]
929
+ - Updated dependencies [ebb8804]
930
+ - Updated dependencies [c6a0a52]
931
+ - Updated dependencies [628c62d]
932
+ - Updated dependencies [ad0b069]
933
+ - Updated dependencies [d32cb70]
934
+ - Updated dependencies [98870f1]
935
+ - Updated dependencies [66c7bde]
936
+ - Updated dependencies [fb75358]
937
+ - Updated dependencies [3246831]
938
+ - Updated dependencies [5eda461]
939
+ - Updated dependencies [90851d1]
940
+ - Updated dependencies [797bf34]
941
+ - Updated dependencies [e901a2b]
942
+ - Updated dependencies [da45b33]
943
+ - Updated dependencies [57725cc]
944
+ - Updated dependencies [2f51085]
945
+ - Updated dependencies [c6d61e0]
946
+ - Updated dependencies [3f89d6b]
947
+ - Updated dependencies [86725ed]
948
+ - Updated dependencies [7cbedd8]
949
+ - Updated dependencies [c17c978]
950
+ - Updated dependencies [a4c99c1]
951
+ - Updated dependencies [c53b0ae]
952
+ - Updated dependencies [d4d28ad]
953
+ - Updated dependencies [c4840ed]
954
+ - Updated dependencies [616a4b2]
955
+ - Updated dependencies [0677769]
956
+ - Updated dependencies [974682d]
957
+ - Updated dependencies [7afe8cd]
958
+ - Updated dependencies [71c079d]
959
+ - Updated dependencies [dcca70c]
960
+ - Updated dependencies [cc54285]
961
+ - Updated dependencies [5f12888]
962
+ - Updated dependencies [d18df3e]
963
+ - Updated dependencies [46c731d]
964
+ - Updated dependencies [36eca7a]
965
+ - Updated dependencies [c1680fd]
966
+ - Updated dependencies [0430dcc]
967
+ - Updated dependencies [1be2ea9]
968
+ - Updated dependencies [925dde2]
969
+ - Updated dependencies [a322444]
970
+ - Updated dependencies [39f86d1]
971
+ - Updated dependencies [f3398d4]
972
+ - Updated dependencies [c2048de]
973
+ - Updated dependencies [e562d4b]
974
+ - Updated dependencies [7947fdf]
975
+ - Updated dependencies [9073669]
976
+ - Updated dependencies [798e9b0]
977
+ - Updated dependencies [f082c83]
978
+ - Updated dependencies [db8c16e]
979
+ - Updated dependencies [e287da2]
980
+ - Updated dependencies [4df0749]
981
+ - Updated dependencies
982
+ - Updated dependencies [365ab72]
983
+ - Updated dependencies [59b5936]
984
+ - Updated dependencies [3eb2abc]
985
+ - Updated dependencies [3318cf7]
986
+ - Updated dependencies [c4e499e]
987
+ - Updated dependencies [5ebf7e7]
988
+ - Updated dependencies [7a31f9d]
989
+ - Updated dependencies [4cec295]
990
+ - Updated dependencies [1faab2d]
991
+ - Updated dependencies [e40a56f]
992
+ - Updated dependencies [15fbffb]
993
+ - Updated dependencies [d705830]
994
+ - Updated dependencies [398d71e]
995
+ - Updated dependencies [329aa39]
996
+ - @weasel-js/registry@1.11.0
997
+ - @weasel-js/routing@1.11.0
998
+ - @weasel-js/prefs@1.11.0
999
+ - @weasel-js/geom@1.11.0
1000
+ - @weasel-js/animator@1.11.0
1001
+ - @weasel-js/gestures@1.11.0
1002
+ - @weasel-js/renderer@1.11.0
1003
+ - @weasel-js/stroke@1.11.0
1004
+ - @weasel-js/history@1.11.0
1005
+ - @weasel-js/icons@1.11.0
1006
+ - @weasel-js/react@1.11.0
1007
+ - @weasel-js/text@1.11.0
1008
+ - @weasel-js/quantity@1.11.0
1009
+ - @weasel-js/modes@1.11.0
1010
+ - @weasel-js/paint@1.11.0
1011
+ - @weasel-js/font@1.11.0
1012
+ - @weasel-js/text-dom@1.11.0
1013
+ - @weasel-js/cursor@1.11.0
1014
+ - @weasel-js/select@1.11.0
1015
+ - @weasel-js/simulation@1.11.0
1016
+
3
1017
  ## 1.10.1
4
1018
 
5
1019
  ### Patch Changes