@weasel-js/core 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1433) hide show
  1. package/CHANGELOG.md +755 -0
  2. package/README.md +45 -11
  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 +152 -73
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js +148 -51
  12. package/dist/affordances/pathAnchors.js.map +1 -1
  13. package/dist/affordances/rotateCursor.js +18 -0
  14. package/dist/affordances/rotateCursor.js.map +1 -0
  15. package/dist/affordances/rotationHandle.js +83 -63
  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 -69
  43. package/dist/animation/rig/rigNode.js.map +1 -1
  44. package/dist/animation/rig/rigSeat.js +70 -17
  45. package/dist/animation/rig/rigSeat.js.map +1 -1
  46. package/dist/animation/rig/skinBinding.js +59 -39
  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 +41 -31
  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 +40 -38
  64. package/dist/barrel/paint.js +12 -11
  65. package/dist/barrel/paths.js +39 -12
  66. package/dist/barrel/renderer.js +24 -14
  67. package/dist/barrel/routing.js +69 -57
  68. package/dist/barrel/scene.js +48 -37
  69. package/dist/barrel/text.js +10 -9
  70. package/dist/barrel/viewport.js +47 -42
  71. package/dist/canvas/Canvas.js +189 -317
  72. package/dist/canvas/Canvas.js.map +1 -1
  73. package/dist/canvas/CanvasView.js +273 -202
  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 -36
  96. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  97. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +110 -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/canvasPassThrough.js +72 -0
  102. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -0
  103. package/dist/canvas/SceneCanvas/contributionFrameHooks.js +54 -32
  104. package/dist/canvas/SceneCanvas/contributionFrameHooks.js.map +1 -1
  105. package/dist/canvas/SceneCanvas/coordTrace.js +36 -29
  106. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  107. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +513 -316
  108. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  109. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +39 -13
  110. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  111. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js +83 -47
  112. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  113. package/dist/canvas/SceneCanvas/features.js +83 -127
  114. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  115. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +115 -0
  116. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -0
  117. package/dist/canvas/SceneCanvas/mergeLayers.js +43 -0
  118. package/dist/canvas/SceneCanvas/mergeLayers.js.map +1 -0
  119. package/dist/canvas/SceneCanvas/namedPresets.js +56 -0
  120. package/dist/canvas/SceneCanvas/namedPresets.js.map +1 -0
  121. package/dist/canvas/SceneCanvas/poseGeometry.js +66 -31
  122. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  123. package/dist/canvas/SceneCanvas/poseRegistrars.js +18 -8
  124. package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -1
  125. package/dist/canvas/SceneCanvas/presets/arrange.js +27 -0
  126. package/dist/canvas/SceneCanvas/presets/arrange.js.map +1 -0
  127. package/dist/canvas/SceneCanvas/presets/chrome.js +14 -0
  128. package/dist/canvas/SceneCanvas/presets/chrome.js.map +1 -0
  129. package/dist/canvas/SceneCanvas/presets/edit.js +59 -0
  130. package/dist/canvas/SceneCanvas/presets/edit.js.map +1 -0
  131. package/dist/canvas/SceneCanvas/presets/ingest.js +13 -0
  132. package/dist/canvas/SceneCanvas/presets/ingest.js.map +1 -0
  133. package/dist/canvas/SceneCanvas/presets/paths.js +67 -0
  134. package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -0
  135. package/dist/canvas/SceneCanvas/presets/select.js +19 -0
  136. package/dist/canvas/SceneCanvas/presets/select.js.map +1 -0
  137. package/dist/canvas/SceneCanvas/presets/toolDriven.js +20 -0
  138. package/dist/canvas/SceneCanvas/presets/toolDriven.js.map +1 -0
  139. package/dist/canvas/SceneCanvas/presets/transform.js +41 -0
  140. package/dist/canvas/SceneCanvas/presets/transform.js.map +1 -0
  141. package/dist/canvas/SceneCanvas/presets/view.js +14 -0
  142. package/dist/canvas/SceneCanvas/presets/view.js.map +1 -0
  143. package/dist/canvas/SceneCanvas/props.js +19 -35
  144. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  145. package/dist/canvas/SceneCanvas/scenePointQuery.js +58 -0
  146. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -0
  147. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +59 -0
  148. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -0
  149. package/dist/canvas/SceneCanvas/toolRegistry.js +30 -15
  150. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
  151. package/dist/canvas/SceneCanvas/useActionTunings.js +20 -0
  152. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -0
  153. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +68 -35
  154. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  155. package/dist/canvas/SceneCanvas/useBakedScene.js +17 -0
  156. package/dist/canvas/SceneCanvas/useBakedScene.js.map +1 -0
  157. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +65 -0
  158. package/dist/canvas/SceneCanvas/useBuiltinRigTools.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 +29 -14
  162. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
  163. package/dist/canvas/SceneCanvas/useCanvasCamera.js +55 -32
  164. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -1
  165. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +24 -14
  166. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -1
  167. package/dist/canvas/SceneCanvas/useCanvasSelection.js +30 -12
  168. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
  169. package/dist/canvas/SceneCanvas/useCanvasTools.js +112 -53
  170. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  171. package/dist/canvas/SceneCanvas/useChromeAffordances.js +31 -0
  172. package/dist/canvas/SceneCanvas/useChromeAffordances.js.map +1 -0
  173. package/dist/canvas/SceneCanvas/useContributionRoles.js +107 -56
  174. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
  175. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js +64 -0
  176. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js.map +1 -0
  177. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +105 -136
  178. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  179. package/dist/canvas/SceneCanvas/useHeldModifiers.js +21 -14
  180. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -1
  181. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +21 -19
  182. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -1
  183. package/dist/canvas/SceneCanvas/useNodeKinds.js +28 -19
  184. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
  185. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +93 -53
  186. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  187. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +62 -35
  188. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
  189. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +110 -50
  190. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  191. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js +30 -0
  192. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js.map +1 -0
  193. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +40 -0
  194. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -0
  195. package/dist/canvas/SceneCanvas/useSceneChrome.js +100 -44
  196. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
  197. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +163 -0
  198. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -0
  199. package/dist/canvas/SceneCanvas/useScenePicking.js +69 -0
  200. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -0
  201. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +28 -17
  202. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -1
  203. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +158 -111
  204. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  205. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +38 -26
  206. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -1
  207. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +108 -0
  208. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -0
  209. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +40 -27
  210. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -1
  211. package/dist/canvas/SceneCanvas/useSurfaceRouting.js +29 -0
  212. package/dist/canvas/SceneCanvas/useSurfaceRouting.js.map +1 -0
  213. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js +44 -0
  214. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js.map +1 -0
  215. package/dist/canvas/SceneCanvas/useToolKeybindings.js +28 -0
  216. package/dist/canvas/SceneCanvas/useToolKeybindings.js.map +1 -0
  217. package/dist/canvas/SceneCanvas/useViewportActions.js +52 -28
  218. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  219. package/dist/canvas/SceneCanvas/worldPointAt.js +10 -5
  220. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
  221. package/dist/canvas/SceneCanvas.js +274 -315
  222. package/dist/canvas/SceneCanvas.js.map +1 -1
  223. package/dist/canvas/SceneViewCanvas.js +68 -42
  224. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  225. package/dist/canvas/SurfaceCanvas.js +62 -0
  226. package/dist/canvas/SurfaceCanvas.js.map +1 -0
  227. package/dist/canvas/accentColor.js +8 -5
  228. package/dist/canvas/accentColor.js.map +1 -1
  229. package/dist/canvas/adapterDerivedPath.js +33 -18
  230. package/dist/canvas/adapterDerivedPath.js.map +1 -1
  231. package/dist/canvas/adapterPickSource.js +60 -0
  232. package/dist/canvas/adapterPickSource.js.map +1 -0
  233. package/dist/canvas/affordanceAt.js +106 -50
  234. package/dist/canvas/affordanceAt.js.map +1 -1
  235. package/dist/canvas/buildSceneLayer.js +111 -80
  236. package/dist/canvas/buildSceneLayer.js.map +1 -1
  237. package/dist/canvas/buildSceneTree.js +110 -46
  238. package/dist/canvas/buildSceneTree.js.map +1 -1
  239. package/dist/canvas/canvasRenderer.js +156 -71
  240. package/dist/canvas/canvasRenderer.js.map +1 -1
  241. package/dist/canvas/colorOverrides.js +18 -10
  242. package/dist/canvas/colorOverrides.js.map +1 -1
  243. package/dist/canvas/copiesAbove.js +37 -0
  244. package/dist/canvas/copiesAbove.js.map +1 -0
  245. package/dist/canvas/defaultDrawOne.js +56 -31
  246. package/dist/canvas/defaultDrawOne.js.map +1 -1
  247. package/dist/canvas/deps/areaSelect.js +30 -12
  248. package/dist/canvas/deps/areaSelect.js.map +1 -1
  249. package/dist/canvas/deps/booleans.js +104 -0
  250. package/dist/canvas/deps/booleans.js.map +1 -0
  251. package/dist/canvas/deps/changes.js +17 -9
  252. package/dist/canvas/deps/changes.js.map +1 -1
  253. package/dist/canvas/deps/debug.js +12 -5
  254. package/dist/canvas/deps/debug.js.map +1 -1
  255. package/dist/canvas/deps/dispatchSources.js +27 -0
  256. package/dist/canvas/deps/dispatchSources.js.map +1 -0
  257. package/dist/canvas/deps/dispatcher.js +18 -7
  258. package/dist/canvas/deps/dispatcher.js.map +1 -1
  259. package/dist/canvas/deps/editAnchors.js +253 -68
  260. package/dist/canvas/deps/editAnchors.js.map +1 -1
  261. package/dist/canvas/deps/geometryProjection.js +13 -7
  262. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  263. package/dist/canvas/deps/hitTestArea.js +80 -40
  264. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  265. package/dist/canvas/deps/ingestion.js +18 -13
  266. package/dist/canvas/deps/ingestion.js.map +1 -1
  267. package/dist/canvas/deps/insert.js +205 -111
  268. package/dist/canvas/deps/insert.js.map +1 -1
  269. package/dist/canvas/deps/kitSettings.js +16 -0
  270. package/dist/canvas/deps/kitSettings.js.map +1 -0
  271. package/dist/canvas/deps/lassoSelect.js +25 -13
  272. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  273. package/dist/canvas/deps/layout.js +32 -26
  274. package/dist/canvas/deps/layout.js.map +1 -1
  275. package/dist/canvas/deps/nodeAtPoint.js +28 -14
  276. package/dist/canvas/deps/nodeAtPoint.js.map +1 -1
  277. package/dist/canvas/deps/pathLeaf.js +66 -0
  278. package/dist/canvas/deps/pathLeaf.js.map +1 -0
  279. package/dist/canvas/deps/pathLeafDeps.js +13 -0
  280. package/dist/canvas/deps/pathLeafDeps.js.map +1 -0
  281. package/dist/canvas/deps/poseDescriptor.js +10 -8
  282. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  283. package/dist/canvas/deps/previewPaths.js +44 -0
  284. package/dist/canvas/deps/previewPaths.js.map +1 -0
  285. package/dist/canvas/deps/resizePolicy.js +32 -25
  286. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  287. package/dist/canvas/deps/slice.js +73 -87
  288. package/dist/canvas/deps/slice.js.map +1 -1
  289. package/dist/canvas/deps/snap.js +58 -7
  290. package/dist/canvas/deps/snap.js.map +1 -1
  291. package/dist/canvas/deps/surface.js +30 -0
  292. package/dist/canvas/deps/surface.js.map +1 -0
  293. package/dist/canvas/deps/textEdit.js +21 -13
  294. package/dist/canvas/deps/textEdit.js.map +1 -1
  295. package/dist/canvas/deps/view.js +46 -34
  296. package/dist/canvas/deps/view.js.map +1 -1
  297. package/dist/canvas/derivedPath.js +158 -50
  298. package/dist/canvas/derivedPath.js.map +1 -1
  299. package/dist/canvas/doubleClickTarget.js +20 -0
  300. package/dist/canvas/doubleClickTarget.js.map +1 -0
  301. package/dist/canvas/drawEnvelope.js +26 -17
  302. package/dist/canvas/drawEnvelope.js.map +1 -1
  303. package/dist/canvas/drawnBounds.js +116 -0
  304. package/dist/canvas/drawnBounds.js.map +1 -0
  305. package/dist/canvas/getNodeAtPoint.js +11 -8
  306. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  307. package/dist/canvas/hostAnchor.js +35 -18
  308. package/dist/canvas/hostAnchor.js.map +1 -1
  309. package/dist/canvas/hud.module.js +25 -14
  310. package/dist/canvas/hud.module.js.map +1 -1
  311. package/dist/canvas/insertPreviewExtent.js +81 -58
  312. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  313. package/dist/canvas/kitRequirements.js +154 -115
  314. package/dist/canvas/kitRequirements.js.map +1 -1
  315. package/dist/canvas/layerHover.js +28 -0
  316. package/dist/canvas/layerHover.js.map +1 -0
  317. package/dist/canvas/layerOrder.js +107 -57
  318. package/dist/canvas/layerOrder.js.map +1 -1
  319. package/dist/canvas/layerSlots.js +16 -9
  320. package/dist/canvas/layerSlots.js.map +1 -1
  321. package/dist/canvas/mountedCanvases.js +23 -13
  322. package/dist/canvas/mountedCanvases.js.map +1 -1
  323. package/dist/canvas/nodeShapes/derivedPainter.js +65 -25
  324. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  325. package/dist/canvas/nodeShapes/imagePainter.js +69 -53
  326. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  327. package/dist/canvas/nodeShapes/measurePainter.js +58 -0
  328. package/dist/canvas/nodeShapes/measurePainter.js.map +1 -0
  329. package/dist/canvas/nodeShapes/memo.js +16 -5
  330. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  331. package/dist/canvas/nodeShapes/nodePaint.js +125 -46
  332. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  333. package/dist/canvas/nodeShapes/pathPainter.js +41 -27
  334. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  335. package/dist/canvas/nodeShapes/poseBox.js +20 -13
  336. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  337. package/dist/canvas/nodeShapes/rectFallbackPainter.js +26 -22
  338. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  339. package/dist/canvas/nodeShapes/shapePainter.js +67 -46
  340. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  341. package/dist/canvas/nodeShapes/strokedBounds.js +177 -0
  342. package/dist/canvas/nodeShapes/strokedBounds.js.map +1 -0
  343. package/dist/canvas/nodeShapes/textPainter.js +170 -37
  344. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  345. package/dist/canvas/overChildren.js +40 -0
  346. package/dist/canvas/overChildren.js.map +1 -0
  347. package/dist/canvas/overlayRoleStrokes.js +20 -3
  348. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  349. package/dist/canvas/paintCull.js +24 -12
  350. package/dist/canvas/paintCull.js.map +1 -1
  351. package/dist/canvas/paintedCursorLayer.js +59 -35
  352. package/dist/canvas/paintedCursorLayer.js.map +1 -1
  353. package/dist/canvas/pathOverlay.js +63 -0
  354. package/dist/canvas/pathOverlay.js.map +1 -0
  355. package/dist/canvas/pickReach.js +40 -0
  356. package/dist/canvas/pickReach.js.map +1 -0
  357. package/dist/canvas/pickWalk.js +150 -130
  358. package/dist/canvas/pickWalk.js.map +1 -1
  359. package/dist/canvas/planeClips.js +39 -22
  360. package/dist/canvas/planeClips.js.map +1 -1
  361. package/dist/canvas/poseCascade.js +51 -27
  362. package/dist/canvas/poseCascade.js.map +1 -1
  363. package/dist/canvas/poseRotation.js +24 -14
  364. package/dist/canvas/poseRotation.js.map +1 -1
  365. package/dist/canvas/rasterReadback.js +23 -15
  366. package/dist/canvas/rasterReadback.js.map +1 -1
  367. package/dist/canvas/rasterToPng.js +21 -15
  368. package/dist/canvas/rasterToPng.js.map +1 -1
  369. package/dist/canvas/renderDebugSnapshot.js +36 -19
  370. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  371. package/dist/canvas/renderNeeds.js +33 -18
  372. package/dist/canvas/renderNeeds.js.map +1 -1
  373. package/dist/canvas/renderSceneToPixels.js +202 -87
  374. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  375. package/dist/canvas/sceneAdapter.js +96 -96
  376. package/dist/canvas/sceneAdapter.js.map +1 -1
  377. package/dist/canvas/sceneClipboard.js +141 -92
  378. package/dist/canvas/sceneClipboard.js.map +1 -1
  379. package/dist/canvas/sceneLayerPaint.js +56 -27
  380. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  381. package/dist/canvas/sceneSlotWiring.js +24 -13
  382. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  383. package/dist/canvas/sceneViewRender.js +85 -55
  384. package/dist/canvas/sceneViewRender.js.map +1 -1
  385. package/dist/canvas/slopsDebugLayer.js +58 -49
  386. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  387. package/dist/canvas/surfaceContribution.js +22 -10
  388. package/dist/canvas/surfaceContribution.js.map +1 -1
  389. package/dist/canvas/useCanvasElements.js +31 -0
  390. package/dist/canvas/useCanvasElements.js.map +1 -0
  391. package/dist/canvas/useCanvasHandle.js +69 -0
  392. package/dist/canvas/useCanvasHandle.js.map +1 -0
  393. package/dist/canvas/useCanvasPaint.js +91 -0
  394. package/dist/canvas/useCanvasPaint.js.map +1 -0
  395. package/dist/canvas/useCanvasRenderer.js +45 -23
  396. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  397. package/dist/canvas/useCanvasSurface.js +41 -23
  398. package/dist/canvas/useCanvasSurface.js.map +1 -1
  399. package/dist/canvas/useCanvasView.js +80 -50
  400. package/dist/canvas/useCanvasView.js.map +1 -1
  401. package/dist/canvas/useClientToWorld.js +27 -0
  402. package/dist/canvas/useClientToWorld.js.map +1 -0
  403. package/dist/canvas/useExtraLayers.js +45 -0
  404. package/dist/canvas/useExtraLayers.js.map +1 -0
  405. package/dist/canvas/useFrameLoop.js +109 -49
  406. package/dist/canvas/useFrameLoop.js.map +1 -1
  407. package/dist/canvas/useHitObserver.js +22 -15
  408. package/dist/canvas/useHitObserver.js.map +1 -1
  409. package/dist/canvas/useHostAnchor.js +83 -53
  410. package/dist/canvas/useHostAnchor.js.map +1 -1
  411. package/dist/canvas/useLateContentRedraw.js +21 -14
  412. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  413. package/dist/canvas/useLayerStack.js +72 -0
  414. package/dist/canvas/useLayerStack.js.map +1 -0
  415. package/dist/canvas/usePaintedCursor.js +28 -0
  416. package/dist/canvas/usePaintedCursor.js.map +1 -0
  417. package/dist/canvas/useRedrawOn.js +24 -14
  418. package/dist/canvas/useRedrawOn.js.map +1 -1
  419. package/dist/canvas/useSceneAdapter.js +27 -0
  420. package/dist/canvas/useSceneAdapter.js.map +1 -0
  421. package/dist/canvas/useSceneLayerList.js +15 -7
  422. package/dist/canvas/useSceneLayerList.js.map +1 -1
  423. package/dist/canvas/useSurfaceInput.js +46 -30
  424. package/dist/canvas/useSurfaceInput.js.map +1 -1
  425. package/dist/canvas/useSurfaceSize.js +43 -0
  426. package/dist/canvas/useSurfaceSize.js.map +1 -0
  427. package/dist/canvas/useToolCursor.js +30 -21
  428. package/dist/canvas/useToolCursor.js.map +1 -1
  429. package/dist/canvas/useViewHelpers.js +112 -61
  430. package/dist/canvas/useViewHelpers.js.map +1 -1
  431. package/dist/canvas/useViewLayerGate.js +29 -0
  432. package/dist/canvas/useViewLayerGate.js.map +1 -0
  433. package/dist/canvas/useViewNesting.js +104 -0
  434. package/dist/canvas/useViewNesting.js.map +1 -0
  435. package/dist/canvas/useViewRegistrySurface.js +44 -0
  436. package/dist/canvas/useViewRegistrySurface.js.map +1 -0
  437. package/dist/canvas/viewInputs.js +14 -11
  438. package/dist/canvas/viewInputs.js.map +1 -1
  439. package/dist/canvas/viewRegistry.js +144 -38
  440. package/dist/canvas/viewRegistry.js.map +1 -1
  441. package/dist/canvas/watchElementMove.js +71 -33
  442. package/dist/canvas/watchElementMove.js.map +1 -1
  443. package/dist/canvas/wrapNodeOutput.js +21 -9
  444. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  445. package/dist/clipboard.d.ts +7 -3
  446. package/dist/clipboard.js +4 -3
  447. package/dist/{clone-2a5hVbBd.d.ts → clone-DZDrfIlU.d.ts} +31 -64
  448. package/dist/clone.d.ts +5 -4
  449. package/dist/core/adapters/testing/rootsTree.js +17 -0
  450. package/dist/core/adapters/testing/rootsTree.js.map +1 -0
  451. package/dist/core/applyOps.js +23 -7
  452. package/dist/core/applyOps.js.map +1 -1
  453. package/dist/core/device/index.js +6 -5
  454. package/dist/core/device/targets.js +29 -8
  455. package/dist/core/device/targets.js.map +1 -1
  456. package/dist/core/device/useDeviceProfile.js +86 -52
  457. package/dist/core/device/useDeviceProfile.js.map +1 -1
  458. package/dist/core/device/useTargetBasePx.js +23 -0
  459. package/dist/core/device/useTargetBasePx.js.map +1 -0
  460. package/dist/core/device/watchDevicePixelRatio.js +27 -10
  461. package/dist/core/device/watchDevicePixelRatio.js.map +1 -1
  462. package/dist/core/geometry/autoPoseDescriptor.js +38 -24
  463. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -1
  464. package/dist/core/geometry/inkExtents.js +60 -0
  465. package/dist/core/geometry/inkExtents.js.map +1 -0
  466. package/dist/core/geometry/pathPoseDescriptor.js +101 -76
  467. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -1
  468. package/dist/core/geometry/poseDescriptor.js +209 -120
  469. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  470. package/dist/core/geometry/regionHit.js +127 -79
  471. package/dist/core/geometry/regionHit.js.map +1 -1
  472. package/dist/core/geometry/targetFrame.js +84 -60
  473. package/dist/core/geometry/targetFrame.js.map +1 -1
  474. package/dist/core/geometry/unionBounds.js +103 -48
  475. package/dist/core/geometry/unionBounds.js.map +1 -1
  476. package/dist/core/isPlainObject.js +3 -2
  477. package/dist/core/layers/backgroundFill.js +23 -15
  478. package/dist/core/layers/backgroundFill.js.map +1 -1
  479. package/dist/core/layers/children.js +16 -15
  480. package/dist/core/layers/children.js.map +1 -1
  481. package/dist/core/layers/gateLayer.js +24 -9
  482. package/dist/core/layers/gateLayer.js.map +1 -1
  483. package/dist/core/layers/layerGroup.js +42 -29
  484. package/dist/core/layers/layerGroup.js.map +1 -1
  485. package/dist/core/layers/redrawSource.js +15 -0
  486. package/dist/core/layers/redrawSource.js.map +1 -0
  487. package/dist/core/layers/render.js +183 -93
  488. package/dist/core/layers/render.js.map +1 -1
  489. package/dist/core/layers/retain.js +38 -0
  490. package/dist/core/layers/retain.js.map +1 -0
  491. package/dist/core/ops/arrange.js +30 -19
  492. package/dist/core/ops/arrange.js.map +1 -1
  493. package/dist/core/ops/create.js +32 -23
  494. package/dist/core/ops/create.js.map +1 -1
  495. package/dist/core/ops/createHistory.js +23 -14
  496. package/dist/core/ops/createHistory.js.map +1 -1
  497. package/dist/core/ops/delete.js +80 -57
  498. package/dist/core/ops/delete.js.map +1 -1
  499. package/dist/core/ops/nodeFlags.js +44 -0
  500. package/dist/core/ops/nodeFlags.js.map +1 -0
  501. package/dist/core/ops/registry.js +26 -11
  502. package/dist/core/ops/registry.js.map +1 -1
  503. package/dist/core/ops/reorder/algorithms.js +62 -38
  504. package/dist/core/ops/reorder/algorithms.js.map +1 -1
  505. package/dist/core/ops/reorder/index.js +124 -88
  506. package/dist/core/ops/reorder/index.js.map +1 -1
  507. package/dist/core/ops/reorder/setChildOrder.js +32 -25
  508. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  509. package/dist/core/ops/reparent.js +63 -38
  510. package/dist/core/ops/reparent.js.map +1 -1
  511. package/dist/core/ops/select.js +23 -20
  512. package/dist/core/ops/select.js.map +1 -1
  513. package/dist/core/ops/setData.js +23 -21
  514. package/dist/core/ops/setData.js.map +1 -1
  515. package/dist/core/ops/setLayer.js +26 -21
  516. package/dist/core/ops/setLayer.js.map +1 -1
  517. package/dist/core/ops/setLayout.js +27 -18
  518. package/dist/core/ops/setLayout.js.map +1 -1
  519. package/dist/core/ops/setPath.js +60 -41
  520. package/dist/core/ops/setPath.js.map +1 -1
  521. package/dist/core/ops/setText.js +26 -21
  522. package/dist/core/ops/setText.js.map +1 -1
  523. package/dist/core/ops/slot.js +36 -25
  524. package/dist/core/ops/slot.js.map +1 -1
  525. package/dist/core/ops/transform.js +35 -28
  526. package/dist/core/ops/transform.js.map +1 -1
  527. package/dist/core/pages/fitViewToPage.js +17 -0
  528. package/dist/core/pages/fitViewToPage.js.map +1 -0
  529. package/dist/core/pages/pages.js +96 -0
  530. package/dist/core/pages/pages.js.map +1 -0
  531. package/dist/core/pages/pagesLayer.js +33 -0
  532. package/dist/core/pages/pagesLayer.js.map +1 -0
  533. package/dist/core/paint/meshKind.js +16 -11
  534. package/dist/core/paint/meshKind.js.map +1 -1
  535. package/dist/core/paint/meshKindLazy.js +3 -3
  536. package/dist/core/paint/meshKindLazy.js.map +1 -1
  537. package/dist/core/paint/paintKindEntry.js +13 -4
  538. package/dist/core/paint/paintKindEntry.js.map +1 -1
  539. package/dist/core/paint/paintKinds.js +149 -88
  540. package/dist/core/paint/paintKinds.js.map +1 -1
  541. package/dist/core/paint/registerMesh.js +6 -4
  542. package/dist/core/paint/registerMesh.js.map +1 -1
  543. package/dist/core/scene/NodeProperties.js +15 -10
  544. package/dist/core/scene/NodeProperties.js.map +1 -1
  545. package/dist/core/scene/NodeRouting.js +16 -12
  546. package/dist/core/scene/NodeRouting.js.map +1 -1
  547. package/dist/core/scene/annotation.js +28 -0
  548. package/dist/core/scene/annotation.js.map +1 -0
  549. package/dist/core/scene/appliedLog.js +31 -23
  550. package/dist/core/scene/appliedLog.js.map +1 -1
  551. package/dist/core/scene/arrivalWindow.js +120 -75
  552. package/dist/core/scene/arrivalWindow.js.map +1 -1
  553. package/dist/core/scene/arrivals.js +17 -6
  554. package/dist/core/scene/arrivals.js.map +1 -1
  555. package/dist/core/scene/boundOps.js +42 -23
  556. package/dist/core/scene/boundOps.js.map +1 -1
  557. package/dist/core/scene/composeFrame.js +51 -21
  558. package/dist/core/scene/composeFrame.js.map +1 -1
  559. package/dist/core/scene/composePose.js +129 -39
  560. package/dist/core/scene/composePose.js.map +1 -1
  561. package/dist/core/scene/depFrame.js +94 -0
  562. package/dist/core/scene/depFrame.js.map +1 -0
  563. package/dist/core/scene/depMemo.js +44 -19
  564. package/dist/core/scene/depMemo.js.map +1 -1
  565. package/dist/core/scene/dependents.js +73 -45
  566. package/dist/core/scene/dependents.js.map +1 -1
  567. package/dist/core/scene/derivedParts.js +58 -0
  568. package/dist/core/scene/derivedParts.js.map +1 -0
  569. package/dist/core/scene/derivedPath.js +52 -22
  570. package/dist/core/scene/derivedPath.js.map +1 -1
  571. package/dist/core/scene/editMode.js +11 -11
  572. package/dist/core/scene/editMode.js.map +1 -1
  573. package/dist/core/scene/effectivePose.js +168 -48
  574. package/dist/core/scene/effectivePose.js.map +1 -1
  575. package/dist/core/scene/fieldEdits.js +95 -75
  576. package/dist/core/scene/fieldEdits.js.map +1 -1
  577. package/dist/core/scene/historyFacade.js +130 -85
  578. package/dist/core/scene/historyFacade.js.map +1 -1
  579. package/dist/core/scene/historyForm.js +7 -3
  580. package/dist/core/scene/historyForm.js.map +1 -1
  581. package/dist/core/scene/kitOps.js +203 -131
  582. package/dist/core/scene/kitOps.js.map +1 -1
  583. package/dist/core/scene/kitRegistry.js +49 -22
  584. package/dist/core/scene/kitRegistry.js.map +1 -1
  585. package/dist/core/scene/layerStack.js +123 -92
  586. package/dist/core/scene/layerStack.js.map +1 -1
  587. package/dist/core/scene/layoutPass.js +118 -72
  588. package/dist/core/scene/layoutPass.js.map +1 -1
  589. package/dist/core/scene/lockGuard.js +32 -24
  590. package/dist/core/scene/lockGuard.js.map +1 -1
  591. package/dist/core/scene/minSize.js +17 -0
  592. package/dist/core/scene/minSize.js.map +1 -0
  593. package/dist/core/scene/nestedHit.js +45 -31
  594. package/dist/core/scene/nestedHit.js.map +1 -1
  595. package/dist/core/scene/nodeFlags.js +43 -0
  596. package/dist/core/scene/nodeFlags.js.map +1 -0
  597. package/dist/core/scene/nodeFnFields.js +64 -40
  598. package/dist/core/scene/nodeFnFields.js.map +1 -1
  599. package/dist/core/scene/nodeGates.js +58 -0
  600. package/dist/core/scene/nodeGates.js.map +1 -0
  601. package/dist/core/scene/nodeMemo.js +92 -40
  602. package/dist/core/scene/nodeMemo.js.map +1 -1
  603. package/dist/core/scene/nodeStore.js +179 -99
  604. package/dist/core/scene/nodeStore.js.map +1 -1
  605. package/dist/core/scene/notifier.js +30 -19
  606. package/dist/core/scene/notifier.js.map +1 -1
  607. package/dist/core/scene/opTable.js +42 -36
  608. package/dist/core/scene/opTable.js.map +1 -1
  609. package/dist/core/scene/outerOps.js +50 -43
  610. package/dist/core/scene/outerOps.js.map +1 -1
  611. package/dist/core/scene/pathEffects/blend.js +80 -0
  612. package/dist/core/scene/pathEffects/blend.js.map +1 -0
  613. package/dist/core/scene/pathEffects/derive.js +112 -0
  614. package/dist/core/scene/pathEffects/derive.js.map +1 -0
  615. package/dist/core/scene/pathEffects/effects.js +40 -0
  616. package/dist/core/scene/pathEffects/effects.js.map +1 -0
  617. package/dist/core/scene/poseFeed.js +95 -60
  618. package/dist/core/scene/poseFeed.js.map +1 -1
  619. package/dist/core/scene/poseHold.js +33 -24
  620. package/dist/core/scene/poseHold.js.map +1 -1
  621. package/dist/core/scene/poseOverrides.js +86 -49
  622. package/dist/core/scene/poseOverrides.js.map +1 -1
  623. package/dist/core/scene/poseRemovals.js +58 -0
  624. package/dist/core/scene/poseRemovals.js.map +1 -0
  625. package/dist/core/scene/poseSnapshot.js +62 -41
  626. package/dist/core/scene/poseSnapshot.js.map +1 -1
  627. package/dist/core/scene/poseWrites.js +151 -0
  628. package/dist/core/scene/poseWrites.js.map +1 -0
  629. package/dist/core/scene/reconcileSpecs.js +63 -34
  630. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  631. package/dist/core/scene/recorder.js +90 -57
  632. package/dist/core/scene/recorder.js.map +1 -1
  633. package/dist/core/scene/renderOrder.js +105 -59
  634. package/dist/core/scene/renderOrder.js.map +1 -1
  635. package/dist/core/scene/scene.js +133 -80
  636. package/dist/core/scene/scene.js.map +1 -1
  637. package/dist/core/scene/sceneEdits.js +62 -49
  638. package/dist/core/scene/sceneEdits.js.map +1 -1
  639. package/dist/core/scene/sceneMutators.js +44 -36
  640. package/dist/core/scene/sceneMutators.js.map +1 -1
  641. package/dist/core/scene/scenePoseAdapter.js +13 -9
  642. package/dist/core/scene/scenePoseAdapter.js.map +1 -1
  643. package/dist/core/scene/sceneRecording.js +89 -72
  644. package/dist/core/scene/sceneRecording.js.map +1 -1
  645. package/dist/core/scene/sceneSelection.js +23 -16
  646. package/dist/core/scene/sceneSelection.js.map +1 -1
  647. package/dist/core/scene/sceneState.js +54 -36
  648. package/dist/core/scene/sceneState.js.map +1 -1
  649. package/dist/core/scene/serialization.js +87 -50
  650. package/dist/core/scene/serialization.js.map +1 -1
  651. package/dist/core/scene/staleReplay.js +35 -26
  652. package/dist/core/scene/staleReplay.js.map +1 -1
  653. package/dist/core/scene/statedFields.js +10 -5
  654. package/dist/core/scene/statedFields.js.map +1 -1
  655. package/dist/core/scene/treeEdits.js +129 -98
  656. package/dist/core/scene/treeEdits.js.map +1 -1
  657. package/dist/core/scene/treeOrder.js +13 -8
  658. package/dist/core/scene/treeOrder.js.map +1 -1
  659. package/dist/core/scene/treeReads.js +25 -16
  660. package/dist/core/scene/treeReads.js.map +1 -1
  661. package/dist/core/scene/types.js +4 -3
  662. package/dist/core/scene/types.js.map +1 -1
  663. package/dist/core/scene/unionOfChildren.js +20 -10
  664. package/dist/core/scene/unionOfChildren.js.map +1 -1
  665. package/dist/core/scene/unitScopes.js +15 -8
  666. package/dist/core/scene/unitScopes.js.map +1 -1
  667. package/dist/core/scene/useScene.js +32 -24
  668. package/dist/core/scene/useScene.js.map +1 -1
  669. package/dist/core/selection/chromeState.js +41 -17
  670. package/dist/core/selection/chromeState.js.map +1 -1
  671. package/dist/core/selection/readOnlySelection.js +39 -24
  672. package/dist/core/selection/readOnlySelection.js.map +1 -1
  673. package/dist/core/selection/selectionTarget.js +14 -3
  674. package/dist/core/selection/selectionTarget.js.map +1 -1
  675. package/dist/core/selection/usePublishSceneSelection.js +25 -18
  676. package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
  677. package/dist/core/selection/useSelection.js +90 -57
  678. package/dist/core/selection/useSelection.js.map +1 -1
  679. package/dist/core/shapeKinds.js +43 -28
  680. package/dist/core/shapeKinds.js.map +1 -1
  681. package/dist/core/stableStringify.js +5 -4
  682. package/dist/core/stableStringify.js.map +1 -1
  683. package/dist/core/stylus/stylus.js +49 -25
  684. package/dist/core/stylus/stylus.js.map +1 -1
  685. package/dist/core/stylus/usePointerStylus.js +61 -34
  686. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  687. package/dist/core/usePaintKinds.js +21 -11
  688. package/dist/core/usePaintKinds.js.map +1 -1
  689. package/dist/core/viewport/clampView.js +31 -15
  690. package/dist/core/viewport/clampView.js.map +1 -1
  691. package/dist/core/viewport/clientToWorld.js +15 -4
  692. package/dist/core/viewport/clientToWorld.js.map +1 -1
  693. package/dist/core/viewport/createVelocityTracker.js +23 -19
  694. package/dist/core/viewport/createVelocityTracker.js.map +1 -1
  695. package/dist/core/viewport/fitToBounds.js +28 -11
  696. package/dist/core/viewport/fitToBounds.js.map +1 -1
  697. package/dist/core/viewport/fitViewToBounds.js +45 -19
  698. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  699. package/dist/core/viewport/interpolateView.js +40 -20
  700. package/dist/core/viewport/interpolateView.js.map +1 -1
  701. package/dist/core/viewport/parallax.js +89 -56
  702. package/dist/core/viewport/parallax.js.map +1 -1
  703. package/dist/core/viewport/sceneNodeClientRect.js +21 -12
  704. package/dist/core/viewport/sceneNodeClientRect.js.map +1 -1
  705. package/dist/core/viewport/screenSlop.js +40 -17
  706. package/dist/core/viewport/screenSlop.js.map +1 -1
  707. package/dist/core/viewport/useAutoCenter.js +36 -22
  708. package/dist/core/viewport/useAutoCenter.js.map +1 -1
  709. package/dist/core/viewport/useCanvasSize.js +43 -22
  710. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  711. package/dist/core/viewport/useDecayLoop.js +120 -50
  712. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  713. package/dist/core/viewport/useNodeOverlayFrame.js +93 -58
  714. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -1
  715. package/dist/core/viewport/useVelocityTracker.js +9 -6
  716. package/dist/core/viewport/useVelocityTracker.js.map +1 -1
  717. package/dist/core/viewport/useViewAnimation.js +159 -99
  718. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  719. package/dist/core/viewport/view.js +49 -22
  720. package/dist/core/viewport/view.js.map +1 -1
  721. package/dist/core/viewport/viewTransform.js +8 -6
  722. package/dist/core/viewport/viewTransform.js.map +1 -1
  723. package/dist/core/viewport/viewportWorldRect.js +15 -7
  724. package/dist/core/viewport/viewportWorldRect.js.map +1 -1
  725. package/dist/core/viewport/wheelHandler.js +31 -20
  726. package/dist/core/viewport/wheelHandler.js.map +1 -1
  727. package/dist/core/viewport/zoomAt.js +50 -13
  728. package/dist/core/viewport/zoomAt.js.map +1 -1
  729. package/dist/core/viewport/zoomBounds.js +33 -17
  730. package/dist/core/viewport/zoomBounds.js.map +1 -1
  731. package/dist/cornerHandles-Camw_yeu.d.ts +169 -0
  732. package/dist/debug/createDebugOverlayLayer.js +303 -215
  733. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  734. package/dist/debug/createDebugSink.js +68 -47
  735. package/dist/debug/createDebugSink.js.map +1 -1
  736. package/dist/debug/defaultTheme.js +16 -4
  737. package/dist/debug/defaultTheme.js.map +1 -1
  738. package/dist/debug/flag.js +3 -2
  739. package/dist/debug/frameStats.js +11 -9
  740. package/dist/debug/frameStats.js.map +1 -1
  741. package/dist/debug/parseDebugFlags.js +25 -17
  742. package/dist/debug/parseDebugFlags.js.map +1 -1
  743. package/dist/debug/useDebugSink.js +52 -33
  744. package/dist/debug/useDebugSink.js.map +1 -1
  745. package/dist/depSchema-Cgfu_G9s.d.ts +3581 -0
  746. package/dist/features/chrome-caps/buildChromeCtx.js +12 -10
  747. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  748. package/dist/features/chrome-caps/conditions.js +103 -25
  749. package/dist/features/chrome-caps/conditions.js.map +1 -1
  750. package/dist/features/chrome-caps/defaults.js +18 -10
  751. package/dist/features/chrome-caps/defaults.js.map +1 -1
  752. package/dist/features/chrome-caps/index.js +8 -7
  753. package/dist/features/chrome-caps/resolve.js +28 -16
  754. package/dist/features/chrome-caps/resolve.js.map +1 -1
  755. package/dist/features/chrome-caps/useChromeCaps.js +52 -44
  756. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -1
  757. package/dist/features/chrome-caps/useHoverTracking.js +52 -26
  758. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  759. package/dist/features/ingestion/contentHandlers.js +80 -34
  760. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  761. package/dist/features/ingestion/imageHandler.js +49 -29
  762. package/dist/features/ingestion/imageHandler.js.map +1 -1
  763. package/dist/features/ingestion/openFilePicker.js +27 -9
  764. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  765. package/dist/features/ingestion/placement.js +20 -11
  766. package/dist/features/ingestion/placement.js.map +1 -1
  767. package/dist/features/ingestion/registerKitHandlers.js +35 -18
  768. package/dist/features/ingestion/registerKitHandlers.js.map +1 -1
  769. package/dist/features/ingestion/svgHandler.js +60 -34
  770. package/dist/features/ingestion/svgHandler.js.map +1 -1
  771. package/dist/features/ingestion/textHandler.js +37 -16
  772. package/dist/features/ingestion/textHandler.js.map +1 -1
  773. package/dist/features/ingestion/useCanvasIngestion.js +57 -39
  774. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -1
  775. package/dist/features/ingestion/weaselJsonHandler.js +38 -28
  776. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  777. package/dist/features/longPress/longPressFeedback.js +110 -81
  778. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  779. package/dist/features/measure/actionIds.js +22 -0
  780. package/dist/features/measure/actionIds.js.map +1 -0
  781. package/dist/features/measure/measureCommands.js +178 -0
  782. package/dist/features/measure/measureCommands.js.map +1 -0
  783. package/dist/features/measure/measureContribution.js +57 -0
  784. package/dist/features/measure/measureContribution.js.map +1 -0
  785. package/dist/features/measure/measureEdits.js +82 -0
  786. package/dist/features/measure/measureEdits.js.map +1 -0
  787. package/dist/features/measure/measureGestures.js +185 -0
  788. package/dist/features/measure/measureGestures.js.map +1 -0
  789. package/dist/features/measure/measureHit.js +80 -0
  790. package/dist/features/measure/measureHit.js.map +1 -0
  791. package/dist/features/measure/measureLayer.js +86 -0
  792. package/dist/features/measure/measureLayer.js.map +1 -0
  793. package/dist/features/measure/measurement.js +79 -0
  794. package/dist/features/measure/measurement.js.map +1 -0
  795. package/dist/features/measure/measurements.js +41 -0
  796. package/dist/features/measure/measurements.js.map +1 -0
  797. package/dist/features/modes/modeLayers.js +81 -55
  798. package/dist/features/modes/modeLayers.js.map +1 -1
  799. package/dist/features/modes/modeTriggers.js +66 -0
  800. package/dist/features/modes/modeTriggers.js.map +1 -0
  801. package/dist/features/pathEffects/index.js +35 -0
  802. package/dist/features/pathEffects/index.js.map +1 -0
  803. package/dist/features/pathEffects/readSource.js +46 -0
  804. package/dist/features/pathEffects/readSource.js.map +1 -0
  805. package/dist/features/paths/anchorData.js +65 -0
  806. package/dist/features/paths/anchorData.js.map +1 -0
  807. package/dist/features/paths/anchorMarkers.js +137 -0
  808. package/dist/features/paths/anchorMarkers.js.map +1 -0
  809. package/dist/features/paths/editablePath.js +155 -36
  810. package/dist/features/paths/editablePath.js.map +1 -1
  811. package/dist/features/paths/index.js +12 -9
  812. package/dist/features/paths/originProjection.js +16 -9
  813. package/dist/features/paths/originProjection.js.map +1 -1
  814. package/dist/features/paths/pathEditExtension.js +26 -0
  815. package/dist/features/paths/pathEditExtension.js.map +1 -0
  816. package/dist/features/paths/pathEditState.js +107 -26
  817. package/dist/features/paths/pathEditState.js.map +1 -1
  818. package/dist/features/paths/pathEditingOverlayLayer.js +58 -110
  819. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  820. package/dist/features/paths/pathLayer.js +79 -29
  821. package/dist/features/paths/pathLayer.js.map +1 -1
  822. package/dist/features/paths/pathRepresentation.js +27 -0
  823. package/dist/features/paths/pathRepresentation.js.map +1 -0
  824. package/dist/features/paths/pathSnap/glyphs.js +39 -0
  825. package/dist/features/paths/pathSnap/glyphs.js.map +1 -0
  826. package/dist/features/paths/pathSnap/pathSnapSource.js +82 -0
  827. package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -0
  828. package/dist/features/paths/pathSnap/sceneIndex.js +78 -0
  829. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -0
  830. package/dist/features/paths/pathSnap/snapGeometry.js +47 -0
  831. package/dist/features/paths/pathSnap/snapGeometry.js.map +1 -0
  832. package/dist/features/paths/penPreviewLayer.js +135 -102
  833. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  834. package/dist/features/paths/shapeGenerator.js +141 -0
  835. package/dist/features/paths/shapeGenerator.js.map +1 -0
  836. package/dist/features/paths/strokeOutline.js +15 -0
  837. package/dist/features/paths/strokeOutline.js.map +1 -0
  838. package/dist/features/paths/useAnchorFields.js +35 -0
  839. package/dist/features/paths/useAnchorFields.js.map +1 -0
  840. package/dist/features/paths/usePathEdit.js +58 -28
  841. package/dist/features/paths/usePathEdit.js.map +1 -1
  842. package/dist/features/poseRun/usePoseRun.js +111 -44
  843. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  844. package/dist/features/selection/handleCommands.js +116 -0
  845. package/dist/features/selection/handleCommands.js.map +1 -0
  846. package/dist/features/selection/overlay.js +288 -328
  847. package/dist/features/selection/overlay.js.map +1 -1
  848. package/dist/features/selection/selectionPose.js +109 -0
  849. package/dist/features/selection/selectionPose.js.map +1 -0
  850. package/dist/features/snap/angle2d.js +158 -0
  851. package/dist/features/snap/angle2d.js.map +1 -0
  852. package/dist/features/snap/debugCandidates.js +27 -0
  853. package/dist/features/snap/debugCandidates.js.map +1 -0
  854. package/dist/features/snap/gather.js +71 -0
  855. package/dist/features/snap/gather.js.map +1 -0
  856. package/dist/features/snap/inputSubspace.js +46 -0
  857. package/dist/features/snap/inputSubspace.js.map +1 -0
  858. package/dist/features/snap/marks.js +29 -0
  859. package/dist/features/snap/marks.js.map +1 -0
  860. package/dist/features/snap/outcomeStore.js +25 -0
  861. package/dist/features/snap/outcomeStore.js.map +1 -0
  862. package/dist/features/snap/pointSnap.js +48 -0
  863. package/dist/features/snap/pointSnap.js.map +1 -0
  864. package/dist/features/snap/probes2d.js +91 -0
  865. package/dist/features/snap/probes2d.js.map +1 -0
  866. package/dist/features/snap/readoutDraw.js +93 -0
  867. package/dist/features/snap/readoutDraw.js.map +1 -0
  868. package/dist/features/snap/readoutLayer.js +49 -0
  869. package/dist/features/snap/readoutLayer.js.map +1 -0
  870. package/dist/features/snap/registry.js +27 -0
  871. package/dist/features/snap/registry.js.map +1 -0
  872. package/dist/features/snap/resizeBox.js +137 -0
  873. package/dist/features/snap/resizeBox.js.map +1 -0
  874. package/dist/features/snap/roles.js +31 -0
  875. package/dist/features/snap/roles.js.map +1 -0
  876. package/dist/features/snap/rotationSource.js +30 -0
  877. package/dist/features/snap/rotationSource.js.map +1 -0
  878. package/dist/features/snap/sceneReads.js +45 -0
  879. package/dist/features/snap/sceneReads.js.map +1 -0
  880. package/dist/features/snap/sceneSession2d.js +79 -0
  881. package/dist/features/snap/sceneSession2d.js.map +1 -0
  882. package/dist/features/snap/screen.js +23 -0
  883. package/dist/features/snap/screen.js.map +1 -0
  884. package/dist/features/snap/session2d.js +129 -0
  885. package/dist/features/snap/session2d.js.map +1 -0
  886. package/dist/features/snap/spanSnap.js +77 -0
  887. package/dist/features/snap/spanSnap.js.map +1 -0
  888. package/dist/features/snap/stepAngles.js +15 -0
  889. package/dist/features/snap/stepAngles.js.map +1 -0
  890. package/dist/features/text/editingDrawOne.js +32 -0
  891. package/dist/features/text/editingDrawOne.js.map +1 -0
  892. package/dist/features/text/index.js +7 -6
  893. package/dist/features/text/textHitAt.js +51 -0
  894. package/dist/features/text/textHitAt.js.map +1 -0
  895. package/dist/features/text/textLayer.js +21 -27
  896. package/dist/features/text/textLayer.js.map +1 -1
  897. package/dist/features/text/useSceneTextEdit.js +203 -123
  898. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  899. package/dist/features/viewports/viewResolver.js +51 -38
  900. package/dist/features/viewports/viewResolver.js.map +1 -1
  901. package/dist/features/viewports/viewportLayer.js +60 -29
  902. package/dist/features/viewports/viewportLayer.js.map +1 -1
  903. package/dist/iconRegistry/IconRegistryProvider.js +73 -0
  904. package/dist/iconRegistry/IconRegistryProvider.js.map +1 -0
  905. package/dist/iconRegistry/useIconGlyph.js +14 -0
  906. package/dist/iconRegistry/useIconGlyph.js.map +1 -0
  907. package/dist/iconRegistry/useIconVariant.js +29 -0
  908. package/dist/iconRegistry/useIconVariant.js.map +1 -0
  909. package/dist/icons.d.ts +6 -0
  910. package/dist/icons.js +3 -0
  911. package/dist/icons.table.js +13 -0
  912. package/dist/icons.table.js.map +1 -0
  913. package/dist/icons.table.json +556 -0
  914. package/dist/icons2.table.js +9 -0
  915. package/dist/icons2.table.js.map +1 -0
  916. package/dist/index.d.ts +4552 -4992
  917. package/dist/index.js +340 -276
  918. package/dist/input/keyState.js +118 -54
  919. package/dist/input/keyState.js.map +1 -1
  920. package/dist/input/useKeyModifiers.js +13 -7
  921. package/dist/input/useKeyModifiers.js.map +1 -1
  922. package/dist/input/useKeyState.js +23 -16
  923. package/dist/input/useKeyState.js.map +1 -1
  924. package/dist/interactions/actions/align/action.js +76 -45
  925. package/dist/interactions/actions/align/action.js.map +1 -1
  926. package/dist/interactions/actions/align/align.js +86 -48
  927. package/dist/interactions/actions/align/align.js.map +1 -1
  928. package/dist/interactions/actions/booleans/action.js +67 -33
  929. package/dist/interactions/actions/booleans/action.js.map +1 -1
  930. package/dist/interactions/actions/booleans/booleans.js +77 -70
  931. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  932. package/dist/interactions/actions/booleans/commit.js +49 -0
  933. package/dist/interactions/actions/booleans/commit.js.map +1 -0
  934. package/dist/interactions/actions/booleans/custom.js +48 -0
  935. package/dist/interactions/actions/booleans/custom.js.map +1 -0
  936. package/dist/interactions/actions/booleans/operands.js +43 -32
  937. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  938. package/dist/interactions/actions/booleans/pieces.js +29 -23
  939. package/dist/interactions/actions/booleans/pieces.js.map +1 -1
  940. package/dist/interactions/actions/booleans/placement.js +30 -17
  941. package/dist/interactions/actions/booleans/placement.js.map +1 -1
  942. package/dist/interactions/actions/booleans/useBooleans.js +30 -17
  943. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  944. package/dist/interactions/actions/booleans/useBooleansAdapter.js +8 -5
  945. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  946. package/dist/interactions/actions/clipboard/action.js +81 -40
  947. package/dist/interactions/actions/clipboard/action.js.map +1 -1
  948. package/dist/interactions/actions/clipboard/clipboardOps.js +100 -72
  949. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  950. package/dist/interactions/actions/clipboard/materializePaste.js +38 -19
  951. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  952. package/dist/interactions/actions/clipboard/wireFormat.js +66 -28
  953. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  954. package/dist/interactions/actions/clone/action.js +102 -65
  955. package/dist/interactions/actions/clone/action.js.map +1 -1
  956. package/dist/interactions/actions/clone/behaviors.js +55 -38
  957. package/dist/interactions/actions/clone/behaviors.js.map +1 -1
  958. package/dist/interactions/actions/defaultCommitAdapter.js +32 -10
  959. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  960. package/dist/interactions/actions/defaults/anchorEditing.js +253 -115
  961. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  962. package/dist/interactions/actions/defaults/anchorFields.js +54 -0
  963. package/dist/interactions/actions/defaults/anchorFields.js.map +1 -0
  964. package/dist/interactions/actions/defaults/anchorHandles.js +46 -0
  965. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -0
  966. package/dist/interactions/actions/defaults/anchorJoin.js +110 -0
  967. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -0
  968. package/dist/interactions/actions/defaults/areaSelect.js +56 -40
  969. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  970. package/dist/interactions/actions/defaults/bendSegment.js +82 -0
  971. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -0
  972. package/dist/interactions/actions/defaults/cancelGesture.js +12 -5
  973. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  974. package/dist/interactions/actions/defaults/clearSelection.js +22 -7
  975. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  976. package/dist/interactions/actions/defaults/contextMenu.js +149 -0
  977. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -0
  978. package/dist/interactions/actions/defaults/copySubtree.js +43 -29
  979. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  980. package/dist/interactions/actions/defaults/createPaintAction.js +79 -54
  981. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  982. package/dist/interactions/actions/defaults/delete.js +61 -33
  983. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  984. package/dist/interactions/actions/defaults/duplicate.js +65 -22
  985. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  986. package/dist/interactions/actions/defaults/enterPathEdit.js +29 -13
  987. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  988. package/dist/interactions/actions/defaults/enterTextEdit.js +20 -8
  989. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  990. package/dist/interactions/actions/defaults/escape.js +16 -7
  991. package/dist/interactions/actions/defaults/escape.js.map +1 -1
  992. package/dist/interactions/actions/defaults/exitPathEdit.js +6 -6
  993. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
  994. package/dist/interactions/actions/defaults/group.js +122 -73
  995. package/dist/interactions/actions/defaults/group.js.map +1 -1
  996. package/dist/interactions/actions/defaults/ingest.js +52 -35
  997. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  998. package/dist/interactions/actions/defaults/insertPathAnchor.js +39 -33
  999. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  1000. package/dist/interactions/actions/defaults/nudge.js +80 -48
  1001. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  1002. package/dist/interactions/actions/defaults/nudgeSteps.js +17 -12
  1003. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -1
  1004. package/dist/interactions/actions/defaults/pathEditMarks.js +60 -0
  1005. package/dist/interactions/actions/defaults/pathEditMarks.js.map +1 -0
  1006. package/dist/interactions/actions/defaults/pathEditTools.js +57 -0
  1007. package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -0
  1008. package/dist/interactions/actions/defaults/pinchZoom.js +54 -38
  1009. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  1010. package/dist/interactions/actions/defaults/reorder.js +71 -40
  1011. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  1012. package/dist/interactions/actions/defaults/requiresSelection.js +13 -6
  1013. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  1014. package/dist/interactions/actions/defaults/segmentUnder.js +30 -0
  1015. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -0
  1016. package/dist/interactions/actions/defaults/selectAll.js +21 -7
  1017. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  1018. package/dist/interactions/actions/defaults/setFill.js +37 -21
  1019. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  1020. package/dist/interactions/actions/defaults/setFillOpacity.js +19 -10
  1021. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  1022. package/dist/interactions/actions/defaults/setStroke.js +46 -25
  1023. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  1024. package/dist/interactions/actions/defaults/setStrokeOpacity.js +19 -11
  1025. package/dist/interactions/actions/defaults/setStrokeOpacity.js.map +1 -1
  1026. package/dist/interactions/actions/defaults/slice.js +42 -17
  1027. package/dist/interactions/actions/defaults/slice.js.map +1 -1
  1028. package/dist/interactions/actions/defaults/sliceOps.js +63 -42
  1029. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  1030. package/dist/interactions/actions/defaults/toolActivate.js +34 -16
  1031. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  1032. package/dist/interactions/actions/defaults/toolResetToDefault.js +29 -10
  1033. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  1034. package/dist/interactions/actions/defaults/undoRedo.js +26 -20
  1035. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
  1036. package/dist/interactions/actions/defaults/viewportDragPan.js +91 -58
  1037. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  1038. package/dist/interactions/actions/defaults/viewportWheelPan.js +42 -23
  1039. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  1040. package/dist/interactions/actions/defaults/viewportZoom.js +142 -91
  1041. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  1042. package/dist/interactions/actions/distribute/action.js +62 -39
  1043. package/dist/interactions/actions/distribute/action.js.map +1 -1
  1044. package/dist/interactions/actions/distribute/distribute.js +53 -34
  1045. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  1046. package/dist/interactions/actions/distribute/plan.js +40 -22
  1047. package/dist/interactions/actions/distribute/plan.js.map +1 -1
  1048. package/dist/interactions/actions/drawnBoxes.js +31 -0
  1049. package/dist/interactions/actions/drawnBoxes.js.map +1 -0
  1050. package/dist/interactions/actions/edit-anchors/action.js +254 -75
  1051. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  1052. package/dist/interactions/actions/edit-anchors/extensionDrags.js +50 -0
  1053. package/dist/interactions/actions/edit-anchors/extensionDrags.js.map +1 -0
  1054. package/dist/interactions/actions/edit-anchors/geometry.js +74 -47
  1055. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  1056. package/dist/interactions/actions/edit-anchors/handleDrag.js +101 -0
  1057. package/dist/interactions/actions/edit-anchors/handleDrag.js.map +1 -0
  1058. package/dist/interactions/actions/edit-anchors/handles.js +41 -27
  1059. package/dist/interactions/actions/edit-anchors/handles.js.map +1 -1
  1060. package/dist/interactions/actions/edit-anchors/params.js +12 -0
  1061. package/dist/interactions/actions/edit-anchors/params.js.map +1 -0
  1062. package/dist/interactions/actions/edit-anchors/preview.js +68 -0
  1063. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -0
  1064. package/dist/interactions/actions/edit-anchors/symmetry.js +16 -0
  1065. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -0
  1066. package/dist/interactions/actions/flip/action.js +119 -61
  1067. package/dist/interactions/actions/flip/action.js.map +1 -1
  1068. package/dist/interactions/actions/flip/helpers.js +69 -36
  1069. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  1070. package/dist/interactions/actions/geometryProjection.js +17 -12
  1071. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  1072. package/dist/interactions/actions/gestureFrames.js +20 -11
  1073. package/dist/interactions/actions/gestureFrames.js.map +1 -1
  1074. package/dist/interactions/actions/gestureLifecycle.js +93 -48
  1075. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  1076. package/dist/interactions/actions/hitSelection.js +6 -4
  1077. package/dist/interactions/actions/hitSelection.js.map +1 -1
  1078. package/dist/interactions/actions/insert/action.js +75 -39
  1079. package/dist/interactions/actions/insert/action.js.map +1 -1
  1080. package/dist/interactions/actions/insert/commit.js +44 -22
  1081. package/dist/interactions/actions/insert/commit.js.map +1 -1
  1082. package/dist/interactions/actions/insert/extras.js +60 -38
  1083. package/dist/interactions/actions/insert/extras.js.map +1 -1
  1084. package/dist/interactions/actions/insert/frame.js +59 -33
  1085. package/dist/interactions/actions/insert/frame.js.map +1 -1
  1086. package/dist/interactions/actions/insert/geometry.js +29 -25
  1087. package/dist/interactions/actions/insert/geometry.js.map +1 -1
  1088. package/dist/interactions/actions/insert/placeAction.js +108 -0
  1089. package/dist/interactions/actions/insert/placeAction.js.map +1 -0
  1090. package/dist/interactions/actions/insert/repositionAction.js +46 -0
  1091. package/dist/interactions/actions/insert/repositionAction.js.map +1 -0
  1092. package/dist/interactions/actions/insert/rotateAction.js +19 -8
  1093. package/dist/interactions/actions/insert/rotateAction.js.map +1 -1
  1094. package/dist/interactions/actions/insert/session.js +57 -41
  1095. package/dist/interactions/actions/insert/session.js.map +1 -1
  1096. package/dist/interactions/actions/insert/shape.js +83 -25
  1097. package/dist/interactions/actions/insert/shape.js.map +1 -1
  1098. package/dist/interactions/actions/lasso-select/action.js +160 -100
  1099. package/dist/interactions/actions/lasso-select/action.js.map +1 -1
  1100. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +44 -25
  1101. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
  1102. package/dist/interactions/actions/move/action.js +87 -48
  1103. package/dist/interactions/actions/move/action.js.map +1 -1
  1104. package/dist/interactions/actions/move/behaviors/layoutDrop.js +56 -36
  1105. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
  1106. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +20 -10
  1107. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -1
  1108. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +40 -24
  1109. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
  1110. package/dist/interactions/actions/move/behaviors/snapToContainer.js +107 -63
  1111. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  1112. package/dist/interactions/actions/move/capture.js +106 -72
  1113. package/dist/interactions/actions/move/capture.js.map +1 -1
  1114. package/dist/interactions/actions/move/commit/index.js +43 -34
  1115. package/dist/interactions/actions/move/commit/index.js.map +1 -1
  1116. package/dist/interactions/actions/move/commit/layoutDrop.js +43 -32
  1117. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -1
  1118. package/dist/interactions/actions/move/commit/layoutRelease.js +97 -77
  1119. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -1
  1120. package/dist/interactions/actions/move/commit/rebase.js +16 -13
  1121. package/dist/interactions/actions/move/commit/rebase.js.map +1 -1
  1122. package/dist/interactions/actions/move/commit/reparent.js +83 -57
  1123. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  1124. package/dist/interactions/actions/move/delta.js +58 -36
  1125. package/dist/interactions/actions/move/delta.js.map +1 -1
  1126. package/dist/interactions/actions/move/frame.js +73 -48
  1127. package/dist/interactions/actions/move/frame.js.map +1 -1
  1128. package/dist/interactions/actions/move/gestureAdapter.js +30 -20
  1129. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  1130. package/dist/interactions/actions/move/landedDescendants.js +40 -25
  1131. package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
  1132. package/dist/interactions/actions/move/layout/container.js +92 -72
  1133. package/dist/interactions/actions/move/layout/container.js.map +1 -1
  1134. package/dist/interactions/actions/move/layout/dragged.js +61 -39
  1135. package/dist/interactions/actions/move/layout/dragged.js.map +1 -1
  1136. package/dist/interactions/actions/move/layout/dropPass.js +136 -94
  1137. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
  1138. package/dist/interactions/actions/move/layout/exits.js +58 -30
  1139. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  1140. package/dist/interactions/actions/move/layout/glide.js +55 -34
  1141. package/dist/interactions/actions/move/layout/glide.js.map +1 -1
  1142. package/dist/interactions/actions/move/session.js +85 -56
  1143. package/dist/interactions/actions/move/session.js.map +1 -1
  1144. package/dist/interactions/actions/move/translate.js +58 -43
  1145. package/dist/interactions/actions/move/translate.js.map +1 -1
  1146. package/dist/interactions/actions/outlines/createOutlines.js +28 -20
  1147. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  1148. package/dist/interactions/actions/outlines/createOutlinesAction.js +43 -31
  1149. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
  1150. package/dist/interactions/actions/outlines/outlineStroke.js +68 -45
  1151. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
  1152. package/dist/interactions/actions/outlines/outlineStrokeAction.js +24 -19
  1153. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -1
  1154. package/dist/interactions/actions/outlines/replaceWithPaths.js +57 -42
  1155. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -1
  1156. package/dist/interactions/actions/outlines/strokeRegion.js +37 -22
  1157. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -1
  1158. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js +8 -5
  1159. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js.map +1 -1
  1160. package/dist/interactions/actions/pathCommands/cutJoin.js +149 -0
  1161. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -0
  1162. package/dist/interactions/actions/pathCommands/livePathEdit.js +98 -0
  1163. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -0
  1164. package/dist/interactions/actions/pathCommands/pathNodes.js +108 -0
  1165. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -0
  1166. package/dist/interactions/actions/pathCommands/simplifyOffset.js +66 -0
  1167. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -0
  1168. package/dist/interactions/actions/pathGestureTags.js +29 -0
  1169. package/dist/interactions/actions/pathGestureTags.js.map +1 -0
  1170. package/dist/interactions/actions/planeInput.js +198 -123
  1171. package/dist/interactions/actions/planeInput.js.map +1 -1
  1172. package/dist/interactions/actions/pointerState.js +12 -7
  1173. package/dist/interactions/actions/pointerState.js.map +1 -1
  1174. package/dist/interactions/actions/poseDescriptorDep.js +24 -14
  1175. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  1176. package/dist/interactions/actions/poseFrame.js +45 -28
  1177. package/dist/interactions/actions/poseFrame.js.map +1 -1
  1178. package/dist/interactions/actions/resize/action.js +70 -30
  1179. package/dist/interactions/actions/resize/action.js.map +1 -1
  1180. package/dist/interactions/actions/resize/aspect.js +44 -0
  1181. package/dist/interactions/actions/resize/aspect.js.map +1 -0
  1182. package/dist/interactions/actions/resize/behaviors/clampMinSize.js +38 -13
  1183. package/dist/interactions/actions/resize/behaviors/clampMinSize.js.map +1 -1
  1184. package/dist/interactions/actions/resize/boxFrame.js +15 -11
  1185. package/dist/interactions/actions/resize/boxFrame.js.map +1 -1
  1186. package/dist/interactions/actions/resize/capture.js +105 -62
  1187. package/dist/interactions/actions/resize/capture.js.map +1 -1
  1188. package/dist/interactions/actions/resize/commit.js +75 -56
  1189. package/dist/interactions/actions/resize/commit.js.map +1 -1
  1190. package/dist/interactions/actions/resize/cornerHandles.js +154 -17
  1191. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
  1192. package/dist/interactions/actions/resize/frame.js +138 -57
  1193. package/dist/interactions/actions/resize/frame.js.map +1 -1
  1194. package/dist/interactions/actions/resize/minimum.js +35 -0
  1195. package/dist/interactions/actions/resize/minimum.js.map +1 -0
  1196. package/dist/interactions/actions/resize/replay.js +57 -0
  1197. package/dist/interactions/actions/resize/replay.js.map +1 -0
  1198. package/dist/interactions/actions/resize/ruleBounds.js +8 -5
  1199. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -1
  1200. package/dist/interactions/actions/resize/session.js +100 -41
  1201. package/dist/interactions/actions/resize/session.js.map +1 -1
  1202. package/dist/interactions/actions/resolveOverlays.js +48 -32
  1203. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  1204. package/dist/interactions/actions/resolvePreviews.js +63 -46
  1205. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  1206. package/dist/interactions/actions/rotate/action.js +71 -30
  1207. package/dist/interactions/actions/rotate/action.js.map +1 -1
  1208. package/dist/interactions/actions/rotate/commit.js +39 -31
  1209. package/dist/interactions/actions/rotate/commit.js.map +1 -1
  1210. package/dist/interactions/actions/rotate/frame.js +75 -47
  1211. package/dist/interactions/actions/rotate/frame.js.map +1 -1
  1212. package/dist/interactions/actions/rotate/geometry.js +36 -24
  1213. package/dist/interactions/actions/rotate/geometry.js.map +1 -1
  1214. package/dist/interactions/actions/rotate/handle.js +28 -15
  1215. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  1216. package/dist/interactions/actions/rotate/replay.js +26 -0
  1217. package/dist/interactions/actions/rotate/replay.js.map +1 -0
  1218. package/dist/interactions/actions/rotate/session.js +122 -73
  1219. package/dist/interactions/actions/rotate/session.js.map +1 -1
  1220. package/dist/interactions/actions/selectionSubtree.js +124 -53
  1221. package/dist/interactions/actions/selectionSubtree.js.map +1 -1
  1222. package/dist/interactions/actions/spatialReference.js +33 -26
  1223. package/dist/interactions/actions/spatialReference.js.map +1 -1
  1224. package/dist/interactions/actions/testUtils.js +53 -0
  1225. package/dist/interactions/actions/testUtils.js.map +1 -0
  1226. package/dist/interactions/actions/transform-again/action.js +78 -0
  1227. package/dist/interactions/actions/transform-again/action.js.map +1 -0
  1228. package/dist/interactions/actions/transform-again/memory.js +46 -0
  1229. package/dist/interactions/actions/transform-again/memory.js.map +1 -0
  1230. package/dist/interactions/actions/useActionSet.js +83 -0
  1231. package/dist/interactions/actions/useActionSet.js.map +1 -0
  1232. package/dist/interactions/actions/useStandardActions.js +23 -147
  1233. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  1234. package/dist/interactions/gestures/dragGesture/dragGesture.js +109 -68
  1235. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
  1236. package/dist/interactions/gestures/dragGesture/dragPointOf.js +17 -10
  1237. package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -1
  1238. package/dist/interactions/gestures/dragRadial/dragRadial.js +129 -93
  1239. package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -1
  1240. package/dist/interactions/gestures/dragRect/dragRect.js +155 -111
  1241. package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -1
  1242. package/dist/interactions/gestures/handleDrag/handleDrag.js +52 -30
  1243. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
  1244. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +168 -97
  1245. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  1246. package/dist/interactions/gestures/shared/originProjection.js +32 -25
  1247. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  1248. package/dist/interactions/gestures/shared/screenTolerance.js +26 -17
  1249. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  1250. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +39 -21
  1251. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  1252. package/dist/kitSettingsSchema.js +80 -0
  1253. package/dist/kitSettingsSchema.js.map +1 -0
  1254. package/dist/{math-CYUjoyyU.d.ts → math-CrJULaZI.d.ts} +5 -6
  1255. package/dist/math.d.ts +4 -5
  1256. package/dist/math.js +7 -6
  1257. package/dist/mesh.js +3 -2
  1258. package/dist/move.d.ts +7 -6
  1259. package/dist/move.js +4 -3
  1260. package/dist/{originProjection-PPT88jZv.d.ts → options-p9GZMXbY.d.ts} +4 -27
  1261. package/dist/originProjection-gY0jb4Wb.d.ts +24 -0
  1262. package/dist/patterns-builtin.js +3 -2
  1263. package/dist/{poseDescriptor-Bqk-11Rl.d.ts → poseDescriptor-DN2yfnq_.d.ts} +7 -7
  1264. package/dist/renderer.d.ts +1 -1
  1265. package/dist/renderer.js +3 -2
  1266. package/dist/resize.d.ts +10 -28
  1267. package/dist/resize.js +6 -7
  1268. package/dist/routing.js +3 -2
  1269. package/dist/style.css +88 -1
  1270. package/dist/test-hook/createTestHook.js +23 -20
  1271. package/dist/test-hook/createTestHook.js.map +1 -1
  1272. package/dist/test-hook/install.js +32 -13
  1273. package/dist/test-hook/install.js.map +1 -1
  1274. package/dist/test-hook/useTestHook.js +22 -16
  1275. package/dist/test-hook/useTestHook.js.map +1 -1
  1276. package/dist/test-seams.d.ts +164 -1
  1277. package/dist/test-seams.js +8 -3
  1278. package/dist/tools/builtin/bone/boneActions.js +96 -70
  1279. package/dist/tools/builtin/bone/boneActions.js.map +1 -1
  1280. package/dist/tools/builtin/bone/boneOverlay.js +49 -36
  1281. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -1
  1282. package/dist/tools/builtin/bone/placedRig.js +18 -14
  1283. package/dist/tools/builtin/bone/placedRig.js.map +1 -1
  1284. package/dist/tools/builtin/bone/rigEditState.js +22 -13
  1285. package/dist/tools/builtin/bone/rigEditState.js.map +1 -1
  1286. package/dist/tools/builtin/bone/useBoneTool.js +68 -41
  1287. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -1
  1288. package/dist/tools/builtin/ellipse/useEllipseTool.js +22 -16
  1289. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  1290. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +44 -28
  1291. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  1292. package/dist/tools/builtin/hand/dragPanContribution.js +12 -7
  1293. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
  1294. package/dist/tools/builtin/hand/useHandTool.js +21 -13
  1295. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  1296. package/dist/tools/builtin/image/useImageTool.js +28 -19
  1297. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  1298. package/dist/tools/builtin/lasso/useLassoTool.js +48 -36
  1299. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  1300. package/dist/tools/builtin/line/useLineTool.js +24 -16
  1301. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  1302. package/dist/tools/builtin/measure/useMeasureTool.js +84 -0
  1303. package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -0
  1304. package/dist/tools/builtin/pen/penHandle.js +60 -0
  1305. package/dist/tools/builtin/pen/penHandle.js.map +1 -0
  1306. package/dist/tools/builtin/pen/usePenTool.js +463 -305
  1307. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  1308. package/dist/tools/builtin/pencil/usePencilTool.js +20 -15
  1309. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  1310. package/dist/tools/builtin/pickTopMostHit.js +51 -34
  1311. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  1312. package/dist/tools/builtin/polygon/usePolygonTool.js +45 -26
  1313. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  1314. package/dist/tools/builtin/rect/useRectTool.js +24 -15
  1315. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  1316. package/dist/tools/builtin/select/adapterPointQuery.js +48 -27
  1317. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  1318. package/dist/tools/builtin/select/selectionContributions.js +94 -56
  1319. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  1320. package/dist/tools/builtin/select/useSelectTool.js +155 -107
  1321. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  1322. package/dist/tools/builtin/shared/insertToolOptions.js +5 -4
  1323. package/dist/tools/builtin/shared/insertToolOptions.js.map +1 -1
  1324. package/dist/tools/builtin/shared/pointerFollower.js +15 -8
  1325. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  1326. package/dist/tools/builtin/slice/useSliceTool.js +148 -99
  1327. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  1328. package/dist/tools/builtin/star/useStarTool.js +48 -29
  1329. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  1330. package/dist/tools/builtin/sticky/stickyNode.js +49 -0
  1331. package/dist/tools/builtin/sticky/stickyNode.js.map +1 -0
  1332. package/dist/tools/builtin/sticky/useStickyTool.js +86 -0
  1333. package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -0
  1334. package/dist/tools/builtin/text/useTextTool.js +61 -36
  1335. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  1336. package/dist/tools/builtin/weight/useWeightTool.js +66 -42
  1337. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -1
  1338. package/dist/tools/builtin/weight/weightActions.js +93 -65
  1339. package/dist/tools/builtin/weight/weightActions.js.map +1 -1
  1340. package/dist/tools/builtin/weight/weightOverlay.js +47 -30
  1341. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -1
  1342. package/dist/tools/overlayBinding.js +7 -5
  1343. package/dist/tools/overlayBinding.js.map +1 -1
  1344. package/dist/tools/useKeybindings.js +62 -46
  1345. package/dist/tools/useKeybindings.js.map +1 -1
  1346. package/dist/{types-CIKDwlsP.d.ts → types-CHVXGfYm.d.ts} +27 -20
  1347. package/dist/util/color.js +39 -18
  1348. package/dist/util/color.js.map +1 -1
  1349. package/dist/util/paint.js +93 -38
  1350. package/dist/util/paint.js.map +1 -1
  1351. package/dist/version.js +11 -3
  1352. package/dist/version.js.map +1 -1
  1353. package/package.json +35 -23
  1354. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +0 -126
  1355. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +0 -1
  1356. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +0 -64
  1357. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +0 -1
  1358. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +0 -16
  1359. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +0 -1
  1360. package/dist/canvas/SceneCanvas/isDev.js +0 -12
  1361. package/dist/canvas/SceneCanvas/isDev.js.map +0 -1
  1362. package/dist/canvas/SceneCanvas/useViewLayerGate.js +0 -20
  1363. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +0 -1
  1364. package/dist/canvas/surface.module.js +0 -6
  1365. package/dist/canvas/surface.module.js.map +0 -1
  1366. package/dist/canvas/surfaceBox.js +0 -16
  1367. package/dist/canvas/surfaceBox.js.map +0 -1
  1368. package/dist/cornerHandles-BEshc4z3.d.ts +0 -104
  1369. package/dist/icons/ArrowIcon.js +0 -23
  1370. package/dist/icons/ArrowIcon.js.map +0 -1
  1371. package/dist/icons/EllipseIcon.js +0 -21
  1372. package/dist/icons/EllipseIcon.js.map +0 -1
  1373. package/dist/icons/EyedropperIcon.js +0 -49
  1374. package/dist/icons/EyedropperIcon.js.map +0 -1
  1375. package/dist/icons/HandIcon.js +0 -59
  1376. package/dist/icons/HandIcon.js.map +0 -1
  1377. package/dist/icons/ImageIcon.js +0 -34
  1378. package/dist/icons/ImageIcon.js.map +0 -1
  1379. package/dist/icons/LassoIcon.js +0 -22
  1380. package/dist/icons/LassoIcon.js.map +0 -1
  1381. package/dist/icons/LineIcon.js +0 -22
  1382. package/dist/icons/LineIcon.js.map +0 -1
  1383. package/dist/icons/PenIcon.js +0 -36
  1384. package/dist/icons/PenIcon.js.map +0 -1
  1385. package/dist/icons/PencilIcon.js +0 -25
  1386. package/dist/icons/PencilIcon.js.map +0 -1
  1387. package/dist/icons/PolygonIcon.js +0 -19
  1388. package/dist/icons/PolygonIcon.js.map +0 -1
  1389. package/dist/icons/RectIcon.js +0 -37
  1390. package/dist/icons/RectIcon.js.map +0 -1
  1391. package/dist/icons/SelectIcon.js +0 -20
  1392. package/dist/icons/SelectIcon.js.map +0 -1
  1393. package/dist/icons/StarIcon.js +0 -19
  1394. package/dist/icons/StarIcon.js.map +0 -1
  1395. package/dist/icons/TextIcon.js +0 -19
  1396. package/dist/icons/TextIcon.js.map +0 -1
  1397. package/dist/icons/UnknownIcon.js +0 -33
  1398. package/dist/icons/UnknownIcon.js.map +0 -1
  1399. package/dist/icons/_base.js +0 -12
  1400. package/dist/icons/_base.js.map +0 -1
  1401. package/dist/interactions/actions/actionShortcuts.js +0 -32
  1402. package/dist/interactions/actions/actionShortcuts.js.map +0 -1
  1403. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js +0 -40
  1404. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js.map +0 -1
  1405. package/dist/interactions/actions/defaults/icons/actionGlyphs.js +0 -10
  1406. package/dist/interactions/actions/defaults/icons/actionGlyphs.js.map +0 -1
  1407. package/dist/interactions/actions/defaults/icons/alignIcons.js +0 -173
  1408. package/dist/interactions/actions/defaults/icons/alignIcons.js.map +0 -1
  1409. package/dist/interactions/actions/defaults/icons/booleanIcons.js +0 -194
  1410. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +0 -1
  1411. package/dist/interactions/actions/defaults/icons/distributeIcons.js +0 -63
  1412. package/dist/interactions/actions/defaults/icons/distributeIcons.js.map +0 -1
  1413. package/dist/interactions/actions/defaults/icons/editIcons.js +0 -280
  1414. package/dist/interactions/actions/defaults/icons/editIcons.js.map +0 -1
  1415. package/dist/interactions/actions/defaults/icons/outlineIcons.js +0 -91
  1416. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +0 -1
  1417. package/dist/interactions/actions/resize/behaviors/index.js +0 -8
  1418. package/dist/interactions/actions/resize/behaviors/index.js.map +0 -1
  1419. package/dist/interactions/actions/resize/behaviors/lockAspect.js +0 -24
  1420. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +0 -1
  1421. package/dist/interactions/actions/resize/pointSnap.js +0 -111
  1422. package/dist/interactions/actions/resize/pointSnap.js.map +0 -1
  1423. package/dist/interactions/actions/rotate/behaviors/index.js +0 -7
  1424. package/dist/interactions/actions/rotate/behaviors/index.js.map +0 -1
  1425. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +0 -12
  1426. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +0 -1
  1427. package/dist/interactions/gestures/shared/snap.js +0 -24
  1428. package/dist/interactions/gestures/shared/snap.js.map +0 -1
  1429. package/dist/layout/arrivals.js +0 -33
  1430. package/dist/layout/arrivals.js.map +0 -1
  1431. package/dist/test-seams-D0pyV3pR.d.ts +0 -149
  1432. package/dist/util/constrainTo45.js +0 -17
  1433. package/dist/util/constrainTo45.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,760 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.11.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 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.
8
+
9
+ 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.
10
+
11
+ <!-- bump-approved: minor: maintainer — 1.11.0 release requested 2026-10-18 -->
12
+
13
+ ### Patch Changes
14
+
15
+ - 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.
16
+ - 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`.
17
+ - 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.
18
+
19
+ `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`.
20
+
21
+ `<ActionBar only>` keeps just the named entries of those its `group` or `tag` picks, each an action id or an `id:variant` key.
22
+
23
+ `<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`.
24
+ - 60d8e39: `@weasel-js/path-tools` adds three presets, each also in `pathTools`:
25
+
26
+ - `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.
27
+ - `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.
28
+ - `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.
29
+
30
+ `ActionParamSchema` types the params of `selectEveryNthAnchor` and `resamplePath`.
31
+
32
+ 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.
33
+
34
+ `@weasel-js/geom` adds `resamplePath`, `addExtremaAnchors`, `segmentExtremaTs`, `cubicAxisExtremaTs`, and the selection walks `growAnchorSelection`, `shrinkAnchorSelection`, `everyNthAnchor`, `anchorsWhere`, `cornerAnchors`, `smoothAnchors`, and `invertAnchorSelection`.
35
+ - 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.
36
+
37
+ `@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`.
38
+ - 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.
39
+ - 327fb63: `bridgePaths` and `bridgeAnchors` gain an icon, `core:bridge`: two open ends joined by a curve that leaves each along its heading.
40
+ - 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.
41
+ - 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.
42
+ - 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.
43
+ - 4447e67: A canvas host given no `width`/`height` fills its parent and follows it as it resizes: `Canvas`,
44
+ `SceneCanvas`, `LeanSceneCanvas`, `DrawCanvas`, `SceneViewCanvas` and `MinimapCanvas`, each with a new
45
+ `onResize` reporting every size. Nothing paints until the first measure. On a resize the view keeps
46
+ its transform, so more or less of the world shows; `DiagramView` and `EffectChart` refit until the
47
+ user pans or zooms, and `MinimapCanvas` refits its overview. `DrawCanvas`'s `draw(size)` gets the
48
+ measured size. Core exports `SurfaceSizeProps` and `viewportWorldRect`; labkit's
49
+ `TrialSceneCanvas` fills through `SceneCanvas` instead of measuring its own trial.
50
+
51
+ `createGridLayer`'s `bounds` is now optional and receives the paint's view and canvas size. Omitted,
52
+ the grid covers whatever the canvas shows, its lines held on world multiples of `spacing` as the view
53
+ pans, and any set of lines that would sit closer than 4px on screen is left out.
54
+ - 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.
55
+ - e0608bf: `<Canvas>`, and so `<SceneCanvas>`, repaints after every committed render
56
+ instead of only when a prop on a fixed list changed. A prop that reaches the
57
+ paint through a ref or a memo — `chromeVisibility` is one, since the
58
+ chrome-caps resolver reads its rules live — used to change on screen only when
59
+ something else happened to draw a frame. Renders that land before a frame
60
+ still paint once in it; a hover that changes nothing and a drag paint exactly
61
+ as many frames as before. `<CanvasView>` asks its surface for a frame on every
62
+ committed render for the same reason, so a change to its `bounds`, `layers`,
63
+ or layer gate alone now shows.
64
+ - b0f392c: `<Canvas retain>` sets how a canvas retains its layers: `minCommands` is the
65
+ threshold a layer must reach, `budget` the GPU memory retained layers share,
66
+ and `false` retains no layer on the canvas. `<SceneCanvas>` passes it through.
67
+ `WeaselRenderer.setRetainBudget` changes the budget after construction. New
68
+ API; nothing existing changes.
69
+ - 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.
70
+
71
+ 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.
72
+ - 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.
73
+
74
+ `@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.
75
+
76
+ 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.
77
+
78
+ 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.
79
+ - 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`).
80
+
81
+ 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.
82
+
83
+ `<LayerList>` takes `onRowContextMenu(id, event)`, called on a right-click on a row, so an app can open a context menu for a layer.
84
+
85
+ `PropertyGroup` and `MotifFrame` take an `onContextMenu` prop.
86
+
87
+ `@weasel-js/ui` exports `actionIcon`, which turns an action's icon name into the node to draw.
88
+ - 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`.
89
+
90
+ `@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.
91
+
92
+ 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.
93
+
94
+ 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.
95
+ - 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`.
96
+
97
+ `@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`.
98
+ - 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.
99
+ - 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`.
100
+
101
+ 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.
102
+
103
+ 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.
104
+
105
+ 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.
106
+
107
+ 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.
108
+
109
+ 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.
110
+ - 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.
111
+
112
+ 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.
113
+ - 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.
114
+
115
+ `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.
116
+
117
+ 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`.
118
+
119
+ `lanes` widens a source or sink stretched taller than it measured, so its round ends no longer eat into its rows.
120
+ - 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.
121
+ - 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.
122
+ - 02cbe1d: More of the kit boxes a stroked node by its stroke as drawn, through `drawnBoundsOf`:
123
+
124
+ - 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`.
125
+ - `composeSelectionPose` takes a `scene` and a `viewScale`, so a selected container's pose reaches its members' strokes.
126
+ - `useAlign` takes a `scene` and a `viewScale`, and lines up drawn edges when given them.
127
+ - `<Canvas>` takes `nodes`, and its default bounds then box each node as drawn.
128
+ - `kit:text` reports a `drawnBounds`: a stroked line that reaches its layout box's edge grows the box by the stroke's reach.
129
+
130
+ 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.
131
+
132
+ `@weasel-js/renderer` exports `resolveStrokeLengths`, which resolves a stroke's `{ px }` lengths against a transform and names the spaces each part is built in.
133
+ - Export three types that public signatures already named: `PreviewPathsDep` (the `previewPaths` action dep), `EditingDrawOne` (`useSceneTextEdit`'s `drawOne`), and `BoxPose` (what `carryPose` takes).
134
+ - 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.
135
+
136
+ 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.
137
+ - 516914b: Curves on the live canvas now flatten against the zoom. `flattenTolerance` on
138
+ `WeaselRenderer`, `<Canvas>`, and `<SceneCanvas>` accepts `{ px }` in device
139
+ pixels as well as a world length, and defaults to `{ px: 0.5 }`: each path is
140
+ flattened to stay within half a device pixel under the transform it draws
141
+ with, so a curve at 8x no longer shows 4 px facets, and a scene whose world
142
+ unit is not a pixel no longer needs a tolerance of its own. The tolerance is
143
+ snapped down to a power of two and fill meshes are cached per tolerance, so a
144
+ continuous zoom rebuilds a path's mesh once per octave rather than every frame;
145
+ a fixed world tolerance is now cached too instead of tessellated every frame.
146
+ `renderSceneToPixels` resolves its `flattenTolerancePx` the same way.
147
+ - 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.
148
+
149
+ `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.
150
+
151
+ `OverlayRole` names one more kit role, with a stroke in core's overlay painter: `falloff`, the reach of a soft-selection drag.
152
+ - 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.
153
+ - 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`.
154
+
155
+ `@weasel-js/geom` adds the edit underneath: `harmonizeAnchors(set, flatIndexes?)`.
156
+ - 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.
157
+ - 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.
158
+ - 63b310c: Icons are named, not drawn, by the code that uses them. This is breaking.
159
+
160
+ `@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.
161
+
162
+ `@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.
163
+
164
+ What breaks:
165
+
166
+ - 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.
167
+ - 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"`.
168
+ - 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`.
169
+ - 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.
170
+ - 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.
171
+ - 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.
172
+
173
+ `@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.
174
+ - 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.
175
+ - 6812344: `layered` routes long edges and leaves labels room on a live scene too.
176
+
177
+ - **Under `order: 'seeded'`.** An edge spanning ranks now stands in each rank it crosses and a
178
+ labeled edge gets a rank of its own, as under `'barycenter'`. An edge keeps its place in a rank
179
+ the way a node does, from where its route crosses that rank now (`GraphEdge.waypoints`, which
180
+ `buildGraph` fills in), so a second run still moves nothing. This changes where a seeded layout
181
+ puts nodes in any graph with a long or labeled edge.
182
+ - **Written to the scene.** The layout action and a live `layered` run write each long edge's
183
+ waypoints, and station its label in the room left for it, in the same undo entry as the moves.
184
+ `buildGraph` reads a scene label's size as its edge's label room.
185
+ - **Whose route it is.** `DiagramEdge.laidOut` records the waypoints layout wrote, and layout
186
+ rewrites a route only while the edge's waypoints still match them (`layoutOwnsRoute`). An edge
187
+ someone has bent, and the label on it, are left alone, and get no room in the ranks the edge
188
+ crosses (`GraphEdge.authored`); so is a label put at `'start'`, `'end'` or a fraction.
189
+ `diagramScene` marks the routes it lays out the same way. A layout that routes nothing
190
+ (`tree`, `force`, `chain`) takes layered's routes back off.
191
+ - **`diagramScene`.** A label whose edge sets `labelPlacement` at `'mid'` now gets room beside
192
+ its wire like an unplaced one, at that placement's offset. Routes come from any layout with a
193
+ `plan`, not only `layered`.
194
+ - **Locked layers.** `applyLayout` skips a node, edge or label on a locked layer instead of
195
+ throwing.
196
+ - **New surface.** `LayoutFn` may carry a `plan` returning `LayoutPlan` (`moves`, `waypoints`,
197
+ `labels`); `layered.plan` is `layeredPlan`, and `planOf` reads any layout's. `routesOf` and
198
+ `routeWrites` turn a plan into scene edits, and `applyLayout` takes them as `routes`.
199
+ `usePoseRun` takes `commitWith`, writes of the caller's own made inside the commit's batch.
200
+ - `expand`'s `placeholders` and `labels` options are gone; it always adds both.
201
+ - 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.
202
+
203
+ `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.
204
+
205
+ 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.
206
+ - 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.
207
+
208
+ 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°.
209
+
210
+ `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:
211
+
212
+ - `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.
213
+ - `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.
214
+ - `<MeasureReadout scene measurements>` in `@weasel-js/ui`: the current measurement's distance, offset, and angle, with Move by, Rotate by, Delete, and Clear all.
215
+
216
+ `@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.
217
+ - 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.
218
+ - 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`.
219
+ - 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.
220
+ - 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.
221
+ - 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.
222
+
223
+ 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.
224
+
225
+ Breaking: `locksInForce` takes the invocation context in place of its `ModifierState`, so it can read the roles.
226
+ - f34b290: A `<CanvasView>` can nest in another through `parent`: its `bounds` are measured from that view's
227
+ rect, a thunked `bounds` or `view` receives that view's camera and size, it paints cut to that view
228
+ and only the layers that view paints, and input inside it lands in its world before that view's.
229
+ `SceneCanvasApi.viewAt` names the innermost view under a canvas point. An interactive or
230
+ view-backed loupe now magnifies the camera of the view under its aim, so over a panel it shows and
231
+ edits the panel's world. `createViewportLayer` and `ResolvableView` take an optional `clip`.
232
+ - 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.
233
+
234
+ `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.
235
+
236
+ `@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.
237
+ - 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.
238
+ - 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.
239
+ - 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`.
240
+ - 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.
241
+ - 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`.
242
+ - c4840ed: Geometric constraints on a path's anchors that hold while it is edited. Additive throughout.
243
+
244
+ `@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.
245
+
246
+ 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.
247
+ - 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.
248
+
249
+ 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.
250
+
251
+ `@weasel-js/geom` adds `handleAtItsLength`, the length-holding counterpart of `handleAlongItsAngle`.
252
+ - 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.
253
+
254
+ - **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.
255
+ - **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.
256
+
257
+ 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.
258
+
259
+ `@weasel-js/geom` adds the geometry: `measureAnchorPath`, `softSelectionWeights`, `softSelectionBand` and `softFalloff` for soft selection.
260
+ - 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.
261
+
262
+ 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>`.
263
+
264
+ 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.
265
+
266
+ 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.
267
+
268
+ `@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.
269
+
270
+ `@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`.
271
+ - 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.
272
+ - 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.
273
+ - 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`).
274
+
275
+ `@weasel-js/geom` adds `createPathSnapIndex`, `findPathSnap`, `findPathSnaps`, `PATH_SNAP_KINDS`, and `pathAwayFromAnchors`.
276
+ - 3378ade: Two path-tools presets for a path's structure, both in `pathTools`:
277
+
278
+ - `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`.
279
+ - `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.
280
+
281
+ 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.
282
+
283
+ 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.
284
+ - 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`.
285
+ - 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.
286
+
287
+ 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.
288
+ - 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.
289
+
290
+ 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.
291
+
292
+ `@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.
293
+ - 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.
294
+ - bfb566c: A leaf drawn as its rect pose alone, with no `data.path`, now has an editable
295
+ path: `classifyPathStorage` and `resolveEditablePathOf` read it as a rect
296
+ `data.path` the size of its pose, and its first edit writes one, as a drawn
297
+ rectangle's does. Trim segment, Extend to next path, path edit, and the other
298
+ path commands reach it. `EditableShape` takes the node's `kind`, since only a
299
+ leaf drawn by the kit's rect fallback qualifies.
300
+ - 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.
301
+ - 79b65f5: `<SceneCanvas poseTransition>` glides the poses a scene writes on screen instead of snapping them:
302
+ a button's `scene.setPose`, an undo, a redo, and with `enter` a node the scene adds. It takes the
303
+ same kind of transition as `reflowTransition` (`useAnimatedReflow`), and `glides` picks which
304
+ writes move — by default direct scene calls and history steps, not an action's commit. The
305
+ document takes each write at once; only what is shown travels.
306
+
307
+ `scene.onPoseWrite(listener)` is new: once per change, it reports each node whose pose the change
308
+ wrote or that it added, with the pose it left, where the write came from (`'call'`, `'ops'`,
309
+ `'undo'`, `'redo'`, `'layout'` or `'untracked'`), and the edit's label. Also new:
310
+ `bindPoseTransition`, `usePoseTransition`, `glidesByDefault`, and the `PoseWrite`,
311
+ `PoseWriteOrigin`, `ScenePoseReports`, `PoseTransitionSeat` and `PoseTransitionScene` types.
312
+ - 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.
313
+ - e021579: `contextMenuAction` (`menu.context`) and `openContextMenu` are public from `@weasel-js/core`. They
314
+ need only `menuHost`, `view` and `worldToClient` to open a menu at a right-click or, from Shift+F10
315
+ and the ContextMenu key, at the middle of the view; a scene's selection and hit testing refine the
316
+ hit where they are supplied. labkit's trial cameras now register this action instead of their own
317
+ copy.
318
+ - 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.
319
+ - 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.
320
+ - 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.
321
+ - 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`.
322
+ - 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.
323
+
324
+ `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.
325
+
326
+ `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.
327
+ - 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.
328
+ - 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.
329
+
330
+ 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.
331
+ - 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.
332
+
333
+ 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.
334
+
335
+ `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.
336
+
337
+ 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.
338
+
339
+ `@weasel-js/geom` adds `pathFacePieces(...paths)`: `pathDividePieces` with a region that falls apart split into one piece per connected part.
340
+ - 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.
341
+
342
+ 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.
343
+
344
+ 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`.
345
+
346
+ 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`.
347
+
348
+ `@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.
349
+
350
+ `@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.
351
+ - 798e9b0: The Properties W and H fields hold a node to its `data.minSize`, as resize and
352
+ insert already do: typing a smaller width shows and stores the minimum. With
353
+ several nodes selected, each is held to its own minimum.
354
+
355
+ A number leaf takes `minAt` and `maxAt`, bounds read from where its value is
356
+ held, which `prefNumberAt` folds into `min` and `max` for one holder.
357
+ `SelectionPanel` resolves them per node, `PrefsForm` and labkit's
358
+ `ControlPanel` against their values. `prefClampNumber` holds a number to a
359
+ leaf's range.
360
+ - 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.
361
+
362
+ `@weasel-js/geom` adds `smudgePath(path, opts)`, one dab of the brush.
363
+
364
+ `@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.
365
+ - 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.
366
+
367
+ **Breaking: removed APIs, with their replacements.**
368
+
369
+ - `SnapDep.point` is gone: the `snap` dep is `begin(req)`, which returns a `SnapSession` (`at`, `angle`, `end`).
370
+ - `<SceneCanvas toolOptions={{ snapPoint }}>` is gone: register a source in `<SceneCanvas snap={{ sources }}>`, `gridSnapSource` for a grid.
371
+ - `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.
372
+ - `@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`.
373
+ - `@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.
374
+ - `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.
375
+ - `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.
376
+ - `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.
377
+ - `constrainTo45` is gone from `@weasel-js/core`: the pen's handle Shift is the session's angle step.
378
+ - `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.
379
+ - kernel3d's `createSnap()` took nothing and snapped nothing; `createSnap(world, { sources?, reachPx?, store? })` takes the world and snaps.
380
+
381
+ **New.**
382
+
383
+ - `<SceneCanvas snap={{ sources, omit, reachPx, originProjection, readout, readoutStyle }}>` (`SceneCanvasSnap`), a feature preset's `snapSources`, and `useSnapSource(source)`.
384
+ - One reach for every source that sets none, the kit setting `targets.snapPx` (8 screen px; `DEFAULT_SNAP_PX`).
385
+ - 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`.
386
+ - 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.
387
+ - 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`.
388
+ - 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.
389
+ - 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.
390
+ - `@weasel-js/geom/3d` gains `vec3`, `distance`, `lerp`, `pointOnRay`, `aabbOfPoints`, `closestPointOnLine`, `closestPointOnSegment` and `closestPointsRayLine`.
391
+ - `@weasel-js/core/test-seams` gains `createSnapSession2dForTests` (with `SnapSession2dOptions`), a 2D session for tests outside core; it is not public API.
392
+ - kernel3d: `projectSnapMarks` with `ScreenLine` and `ScreenPoint`, `projectPoint`, and `Snap3dOptions`.
393
+ - `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.
394
+ - path edit: `PathEditDragStart.snap`, `PathEditDrag.end`, `SnapMods.hold`.
395
+
396
+ **Behavior changes.**
397
+
398
+ - 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.
399
+ - 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.
400
+ - Ties between equally good results break by source order, then by the order a source yields its targets.
401
+ - Ctrl suspends snapping on every snapping gesture, a pen drag and an anchor drag included; a handle drag keeps Ctrl as its length lock.
402
+ - A rotate snaps to quarter turns and to other nodes' angles without Shift (new); near the pivot its reach is capped at 30°.
403
+ - 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).
404
+ - 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.
405
+ - An anchor drag meets every point-gesture source, a grid included.
406
+ - A multi-root move snaps each root's origin, the nearest winning, not only the first node's.
407
+ - 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.
408
+ - 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.
409
+ - kernel3d's `translate` puts its plane at `up · position`, the same as before for +y up.
410
+ - 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`.
411
+
412
+ A `FeaturePreset` can now carry `moveBehaviors`, folded into every move the presets' ambient bindings run, after the select tool's own.
413
+
414
+ 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.
415
+
416
+ 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.
417
+
418
+ Core exports `scenePoseFrame` and `PoseFrame`: world reads and local writes over a scene's own composition.
419
+ - 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.
420
+
421
+ 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.
422
+
423
+ `@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.
424
+
425
+ `@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`.
426
+ - 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.
427
+ - 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`.
428
+
429
+ 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.
430
+
431
+ `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.
432
+ - 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.
433
+
434
+ This changes behavior for any stroked shape. `<SceneCanvas geometry={{ boundsIncludeStroke: false }}>` restores geometric boxes; actions read it as the new `boundsIncludeStroke` dep.
435
+
436
+ 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.
437
+
438
+ `@weasel-js/guides`: pass `drawnAABBOf` boxes to `deriveAlignmentGuides` so siblings are measured the same way as the dragged selection.
439
+ - 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`.
440
+ - 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.
441
+ - 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.
442
+ - 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.
443
+
444
+ 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.
445
+
446
+ `@weasel-js/geom` adds what these stand on: `intersectSegments`, `pathSegments`, `pathCrossings`, `trimPathAt`, and `extendToMeet`, `lengthenOpenEnd`, `openEndRay`, and `openPathEnds`.
447
+ - 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.
448
+ - 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.
449
+
450
+ 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`.
451
+
452
+ `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.
453
+
454
+ 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`.
455
+
456
+ 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.
457
+ - 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.
458
+ - 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`.
459
+ - 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.
460
+ - d8160be: Nudge, Duplicate, Move by, and Transform Again offset a node in world space,
461
+ mapped through the frame its parent defines, the way a drag and an Alt-drag
462
+ clone already did. Inside a turned group, an arrow key now moves the selection
463
+ along the screen rather than along the group's axes, and Cmd+D after a drag
464
+ steps the way the drag went. `translateSelection` and `duplicateSelection`
465
+ take a world offset.
466
+ - Updated dependencies [304f53a]
467
+ - Updated dependencies [3ffe020]
468
+ - Updated dependencies [60d8e39]
469
+ - Updated dependencies [6a53aaa]
470
+ - Updated dependencies [193ba96]
471
+ - Updated dependencies [09c3e5f]
472
+ - Updated dependencies [535aaaa]
473
+ - Updated dependencies [ed0e096]
474
+ - Updated dependencies [65be8d3]
475
+ - Updated dependencies [10b67bb]
476
+ - Updated dependencies [95d22f1]
477
+ - Updated dependencies [5338358]
478
+ - Updated dependencies [b0f392c]
479
+ - Updated dependencies [cf7b009]
480
+ - Updated dependencies [6072e93]
481
+ - Updated dependencies [53ba41a]
482
+ - Updated dependencies [1322a03]
483
+ - Updated dependencies [275714b]
484
+ - Updated dependencies [4da5998]
485
+ - Updated dependencies [7162a7a]
486
+ - Updated dependencies [765cd31]
487
+ - Updated dependencies [eec8a5b]
488
+ - Updated dependencies [1774dc4]
489
+ - Updated dependencies [0a30bde]
490
+ - Updated dependencies [8ff3b4b]
491
+ - Updated dependencies [02cbe1d]
492
+ - Updated dependencies [d2749ce]
493
+ - Updated dependencies [a988460]
494
+ - Updated dependencies [8374354]
495
+ - Updated dependencies [516914b]
496
+ - Updated dependencies [6525caa]
497
+ - Updated dependencies [5adbb76]
498
+ - Updated dependencies [681c3f9]
499
+ - Updated dependencies [63b310c]
500
+ - Updated dependencies [b36ceac]
501
+ - Updated dependencies [34f8b09]
502
+ - Updated dependencies [ebb8804]
503
+ - Updated dependencies [c6a0a52]
504
+ - Updated dependencies [628c62d]
505
+ - Updated dependencies [ad0b069]
506
+ - Updated dependencies [d32cb70]
507
+ - Updated dependencies [98870f1]
508
+ - Updated dependencies [66c7bde]
509
+ - Updated dependencies [fb75358]
510
+ - Updated dependencies [3246831]
511
+ - Updated dependencies [5eda461]
512
+ - Updated dependencies [90851d1]
513
+ - Updated dependencies [797bf34]
514
+ - Updated dependencies [e901a2b]
515
+ - Updated dependencies [da45b33]
516
+ - Updated dependencies [57725cc]
517
+ - Updated dependencies [2f51085]
518
+ - Updated dependencies [c6d61e0]
519
+ - Updated dependencies [3f89d6b]
520
+ - Updated dependencies [86725ed]
521
+ - Updated dependencies [7cbedd8]
522
+ - Updated dependencies [c17c978]
523
+ - Updated dependencies [a4c99c1]
524
+ - Updated dependencies [c53b0ae]
525
+ - Updated dependencies [d4d28ad]
526
+ - Updated dependencies [c4840ed]
527
+ - Updated dependencies [616a4b2]
528
+ - Updated dependencies [0677769]
529
+ - Updated dependencies [974682d]
530
+ - Updated dependencies [7afe8cd]
531
+ - Updated dependencies [71c079d]
532
+ - Updated dependencies [dcca70c]
533
+ - Updated dependencies [cc54285]
534
+ - Updated dependencies [5f12888]
535
+ - Updated dependencies [d18df3e]
536
+ - Updated dependencies [46c731d]
537
+ - Updated dependencies [36eca7a]
538
+ - Updated dependencies [c1680fd]
539
+ - Updated dependencies [0430dcc]
540
+ - Updated dependencies [1be2ea9]
541
+ - Updated dependencies [925dde2]
542
+ - Updated dependencies [a322444]
543
+ - Updated dependencies [39f86d1]
544
+ - Updated dependencies [f3398d4]
545
+ - Updated dependencies [c2048de]
546
+ - Updated dependencies [e562d4b]
547
+ - Updated dependencies [7947fdf]
548
+ - Updated dependencies [9073669]
549
+ - Updated dependencies [798e9b0]
550
+ - Updated dependencies [f082c83]
551
+ - Updated dependencies [db8c16e]
552
+ - Updated dependencies [e287da2]
553
+ - Updated dependencies [4df0749]
554
+ - Updated dependencies
555
+ - Updated dependencies [365ab72]
556
+ - Updated dependencies [59b5936]
557
+ - Updated dependencies [3eb2abc]
558
+ - Updated dependencies [3318cf7]
559
+ - Updated dependencies [c4e499e]
560
+ - Updated dependencies [5ebf7e7]
561
+ - Updated dependencies [7a31f9d]
562
+ - Updated dependencies [4cec295]
563
+ - Updated dependencies [1faab2d]
564
+ - Updated dependencies [e40a56f]
565
+ - Updated dependencies [15fbffb]
566
+ - Updated dependencies [d705830]
567
+ - Updated dependencies [398d71e]
568
+ - Updated dependencies [329aa39]
569
+ - @weasel-js/registry@1.11.0
570
+ - @weasel-js/routing@1.11.0
571
+ - @weasel-js/prefs@1.11.0
572
+ - @weasel-js/geom@1.11.0
573
+ - @weasel-js/animator@1.11.0
574
+ - @weasel-js/gestures@1.11.0
575
+ - @weasel-js/renderer@1.11.0
576
+ - @weasel-js/stroke@1.11.0
577
+ - @weasel-js/history@1.11.0
578
+ - @weasel-js/icons@1.11.0
579
+ - @weasel-js/react@1.11.0
580
+ - @weasel-js/text@1.11.0
581
+ - @weasel-js/quantity@1.11.0
582
+ - @weasel-js/modes@1.11.0
583
+ - @weasel-js/paint@1.11.0
584
+ - @weasel-js/font@1.11.0
585
+ - @weasel-js/text-dom@1.11.0
586
+ - @weasel-js/cursor@1.11.0
587
+ - @weasel-js/select@1.11.0
588
+ - @weasel-js/simulation@1.11.0
589
+
590
+ ## 1.10.1
591
+
592
+ ### Patch Changes
593
+
594
+ - 113c088: Every adapter carries the tree. `getParent` and `getChildren` are required on `MoveAdapter` (and so on `SelectAdapter`), `getNode`, `getParent`, and `getChildren` on `InsertAdapter`, both methods on `OrderedAdapter`, and `getParent` on `AlignAdapter`, `DistributeAdapter`, and `PickTopMostHitAdapter`. `BooleansAdapter` and `CreateOutlinesAdapter` require `getNode`, `getParent`, and `getChildren`, and `BooleansAdapter` requires `setChildOrder` too. The readers no longer carry a second path for an adapter that leaves one out: the default pick of `useSelectTool` walks `getChildren` and never `getNodes()`, and the insert, delete, reparent, and reorder ops call the tree reads without checking for them.
595
+
596
+ Breaking: an adapter written by hand without these methods no longer compiles, and an op applied against an object without them throws where it used to skip the step. A store with no nesting answers as a tree of roots: `getParent: () => null` and `getChildren: (parentId) => (parentId === null ? ids : [])`. A node with no children must answer `[]`; an adapter that answers the whole list for every parent makes a delete op recurse until the stack overflows.
597
+
598
+ Also breaking: `BooleansAdapter.getZOrder` is removed, since the slot it overrode is now always read through `getParent` and `getChildren`, and `pickTopMostHit` takes an adapter, no longer `null` or `undefined`.
599
+
600
+ `sceneAdapter.ts` no longer imports React (`useSceneAdapter` lives in its own module, exported as before), and a detached scene view (`renderSceneToCanvas`, `renderSceneToPixels`) reads the scene through `sceneToAdapter`.
601
+ - cbd5b4d: `@weasel-js/geom`'s six-number affine type is `Affine`, no longer `Mat3`. It sat one capital letter from `mat3`, the namespace over the nine-element column-major `GlMat3` a GL uniform takes, and the two are different matrices. `mat3.toAffine` and `mat3.fromAffine` already named the conversion this way.
602
+
603
+ Breaking: `import type { Mat3 } from '@weasel-js/geom'` becomes `import type { Affine }`. The values are unchanged, and so are the free functions beside the type (`identity`, `multiply`, `invert`, and the rest).
604
+ - d3b73b9: The text Align bar no longer lights Left for `align: 'start'` (or Right for `'end'`) when the style states no `direction`. An omitted direction is `auto`, each paragraph's own, so right-to-left text aligned `start` painted from the right under a bar reading Left. The bar now lights nothing for `start` / `end` unless `direction` is `ltr` or `rtl`, and resolves them to an edge as before when it is.
605
+ - aaa2b4f: Path edit has two commands for the selected anchors' handles. `retractHandles` collapses them onto their anchors, making sharp corners; a segment whose ends both lose their handles turns straight. `makeHandlesSymmetric` gives each anchor two handles of equal length pointing opposite ways, making it smooth: the shared direction splits the difference between the two handles' own, the shared length is their mean, and an anchor with one handle mirrors it. The ends of an open path are skipped. Both are in the standard actions and the `paths` feature preset, in the `anchors` group, with icons `RetractHandlesIcon` and `SymmetricHandlesIcon`, and are disabled when they would change nothing.
606
+
607
+ Dragging a control handle with Shift held keeps it at the angle it had at the press and changes only its length; it can shrink onto its anchor but not flip through it.
608
+
609
+ `@weasel-js/geom` adds the edits underneath: `retractHandles(set, flatIndexes)`, `makeHandlesSymmetric(set, flatIndexes)`, and `handleAlongItsAngle(anchor, handle, to)`.
610
+ - c7b7ed5: In path edit, dragging a segment bends it: the point pressed follows the pointer and the segment's two handles move to carry it, and a straight segment becomes a curve. An end anchor that was smooth stays smooth, its other handle turning at its own length. It is the `bendSegment` action, in the standard actions and the `paths` feature preset. A drag that starts on an anchor or off the path still moves anchors or draws the marquee, and on a canvas with no mode registry a drag that starts on the edge no longer moves the shape.
611
+
612
+ Path edit now lays a `segment` affordance along the edited path's outline, under its anchors and controls, and `bendSegment` binds to it. Affordance regions take a new shape for it, `{ kind: 'outline', path, hitRadiusPx }`: hit within that many screen pixels of the path's outline. `@weasel-js/routing` adds `isSegment` for that hit and `isPathEditPart` for any anchor, control, or segment hit; `move` turns down a press on any of them.
613
+
614
+ `bendSegment(set, grip, dx, dy)` (`@weasel-js/geom`) is the edit underneath, taking the `{ sub, segIdx, t }` that `segmentAt` reports.
615
+ - faf8ff3: A kit canvas brings its own size rule. `<Canvas>`, `<SceneViewCanvas>`, and `<DrawCanvas>` used to take their CSS size from a class in `@weasel-js/core/style.css`, so a page that did not load that stylesheet showed each one at its drawing buffer's size, `dpr` times too large. Each canvas now adopts the one rule into the document or shadow root it mounts in, so a popout window and a shadow root are covered too. The rule keys on a `data-wzl-surface` attribute at zero specificity, as before, so a class passed to the canvas still resizes it. The rule is gone from `style.css`, and the canvas no longer carries the kit's `surface` class.
616
+ - 8bee821: `SceneCanvasApi.ingest` works from the canvas's first render. It reached the action registry through a ref an effect filled, so a call made before that effect ran was dropped with a warning.
617
+ - 67a7de8: On a controlled `<SceneCanvas>`, writing `view` in your own state now stops a camera glide in flight, the way `setView` and input already did; before, the glide's next frame overwrote the write. The canvas tells the write from your handling of the glide's own frames by order, not by value: a `view` prop that moves when the glide has written no frame since the prop last moved is yours. So a consumer who clamps or rounds inside `onViewChange` still gets a whole glide, and one who moves the prop a second time for one frame (from an effect, or a deferred value) stops it. A write that lands in the same render as a frame's is not seen, and the glide carries on. Behavior change.
618
+ - f6e3e90: Duplicate and Alt-drag clone point a copied node's `dependsOn` list at the copy of each dependency that was copied with it, and at the original of each that was not. A copy used to follow the copies only when every dependency was copied, so duplicating an edge with one of its endpoints left the new edge on both original endpoints, drawn over the first. A copy none of whose dependencies were copied still follows the originals.
619
+
620
+ Changes behavior: a copied derived node with some of its dependencies in the copy now derives from a mix of copies and originals.
621
+ - 74ba77e: Additive: a document's pages as geometry. `layoutPages` places a list of `Page`s in one world space, in a row or a column; `pageAt` and `pageOfBounds` answer which page a point or an object is on; `pagesBounds` is the box around all of them; `adjacentPage` steps the page order, for a next-slide move; `pagesLayer` is a world-space render layer that paints each sheet; and `fitViewToPage` is the view that frames one.
622
+ - a8e8048: A node that derives from a skinned path follows it as it bends. `DerivedDep.path` now answers the path a pose override shows the dependency by, ahead of one the dependency derives, so a `derivePose` or `derivePath` reading `deps[0].path` gets a skinned path as its rig bends it where it used to get `null`. A derivation is run again when that path is replaced, even inside the same bounds. The document reading (`documentPose`) and a lookup through a scene slot's `toPose` still answer the derived path alone.
623
+
624
+ Changes behavior: a derivation that took a non-null `path` to mean "this dependency derives one" now also sees one on any node a pose override gives a `path`.
625
+ - 755b7ff: A painter can draw over a container's children. `overChildren(commands)` wraps part of what a `drawOne` returns, and the scene walk (`buildSceneTree`, so `<SceneCanvas>` and `buildSceneViewCommands` alike) paints that part after the node's children, in the node's own layer, with the node's rotation, alpha, and clips. `defaultDrawOne` uses it for a container's `data.label`, which the container's children used to cover: a group made by Outline Stroke from a labeled rect shows its label again. Additive: `overChildren`, `isOverChildren`, and `splitOverChildren` are new exports, and outside a scene walk the wrapped part is an ordinary group painted where it sits.
626
+ - 1d3ca5c: A drawn polygon or star stays editable as one. The `insert` dep stores the parameters it was drawn with on the node as `data.generator` (`{ kind: 'polygon', sides, rotation }` or `{ kind: 'star', points, innerRadiusRatio, rotation }`) beside `data.path`, which stays the geometry every reader uses. The `polygon`, `star`, and inferred `path` entries of `defaultNodeProperties` / `inferredNodeProperties` show Sides, or Points and Inner, for a node holding one, and changing one makes the shape again on the same circle, under the same rotation, in the same undo step.
627
+
628
+ Editing the path in path edit drops the generator, leaving plain geometry; so does changing a parameter of a shape whose path no longer matches its generator.
629
+
630
+ `NodePropertiesEntry` gains `settle(next, prev)`: what a property write stores, given the node as the write left it and as it was. `SelectionPanel` applies it to commits and to slider drafts. Core exports the generator helpers: `regenerateShape`, `settleShapeGenerator`, `shapeGeneratorOf`, `shapeGeneratorPath`, `clampShapeGenerator`, `isShapeGenerator`, `withoutShapeGenerator`, `SHAPE_COUNT_RANGE`, `STAR_RATIO_RANGE`, and the `ShapeGenerator` types.
631
+
632
+ A committed polygon or star is no longer stretched: its pose was the box of its circle, and the stored path's own box was stretched to fill it, so a five-point star came out stretched 5% along one axis and 10% along the other, unlike its preview. The pose, and the insert's reported bounds, are now the box of the shape itself.
633
+ - 566f15e: A double-click on a path with several nodes selected now opens the path under the pointer for anchor editing. Before, `enterPathEdit` opened the first editable path in the selection, which need not be the one double-clicked. It still falls back to that path when no editable path is under the pointer. The action now requires the `nodeAtPoint` dep, which `<SceneCanvas>` sources.
634
+ - ee59ccd: Deleting an anchor keeps the curve's shape. The segment that replaces the two either side of it keeps the directions they left and arrived with, and its handle lengths are now fitted to them rather than set to a third of the chord, so deleting one anchor of a circle leaves a round arc instead of a flat lobe. An anchor that was inserted on a curve and then deleted gives back the original curve. A gap between two straight segments closes with a straight one.
635
+
636
+ `fitCubicWithTangents` (`@weasel-js/geom`) is the fit underneath: the one cubic through a run of samples whose control points keep given end tangents.
637
+
638
+ Breaking: `fitCubicThroughDeletion(prev, next)` becomes `fitCubicThroughDeletion(prev, removed, next)`, since the fit needs the anchor being removed.
639
+ - f22f5ce: Resizing several nodes at once keeps a turned or skewed one's shape. A non-uniform resize makes a parallelogram of a turned box, and `remapRotatedLeaf` now writes that to the leaf's `pose.transform` where it used to drop it; it also reads a `transform` the leaf already carries, and a skewed leaf with no rotation goes through it too. Breaking for a caller that relied on the result never carrying a `transform`: a turned leaf resized unevenly now has one. A uniform resize, an upright plain leaf, and a leaf turned by a quarter turn still get none.
640
+ - 92e6291: A container's layout is the one its scene node declares, and nothing else. The `layouts` prop of `<SceneCanvas>` and the `layouts` option of `sceneToAdapter` and `useSceneAdapter` are removed, along with `useLayoutArrivals`, `layoutArrivalHandler`, `LayoutSource`, and `LayoutArrivalOptions`, which existed to carry that map into the scene's layout pass.
641
+
642
+ Breaking: declare the layout on the node (`scene.add({ kind: 'container', layout })`) or set it with `scene.setLayout(id, layout)`, which is undoable. The scene's own layout pass arranges it, measured by `useScene({ layoutFrame })`; a canvas's `poseDescriptor` no longer measures a layout, so a scene whose poses are not rects passes `layoutFrame`. `scene.setArrivalHandler` is unchanged.
643
+ - 2216d1b: A marquee and a lasso now agree on a node whose pose descriptor bounds reach past what it draws. A marquee took such a node as soon as its bounds overlapped the rect, and an enclosing lasso refused it when its bounds poked out; both now decide by the drawn outline, as an `intersect` lasso already did.
644
+
645
+ Changes behavior: a node whose descriptor (`forNode` included) reports a box larger than its painter's silhouette is no longer taken by a marquee over the part of that box where nothing is drawn. Give the node a painter whose `silhouette` covers what it draws.
646
+ - a7144f4: Breaking: a move behavior moves the drag by returning `transform`, and nothing else. `BehaviorResult.pose`, the deprecated override that was turned into a translate for the first dragged id, is gone, and so is the deprecated `BehaviorMoveResult` alias of `BehaviorResult`. Return `{ transform: { kind: 'translate', dx, dy } }`.
647
+
648
+ A move gesture's context carries `offset(from, to)`, the translation between two poses' bounds, so a behavior that knows where a node lands can return it as a `transform`. `snapToContainer` does.
649
+ - 35c4879: One answer to "is a pointer held on this canvas". `heldPointers(element)` is new in `@weasel-js/gestures` (additive): it counts the pointers pressed on an element with any button and not yet released, and every reader of one element shares its listeners. The dispatcher's `hover` gesture and hover cursor, a layer's `onUncapturedMove`, and the `pointer` dep's published position all read it, where each used to track a press its own way.
650
+
651
+ What changes: a move with a secondary or middle button held is no longer a `hover`; `onUncapturedMove` stays off until the last of several pointers is released, and through a `pointerleave` mid-press; and the `pointer` dep no longer reports a position for a drag that began outside the canvas and passed over the page.
652
+
653
+ `giveKeys` (`@weasel-js/react/testing/giveKeys`) releases the middle-button press it makes.
654
+ - 886380f: Each README's "API reference" link now opens the package's page on the site, `https://orochi235.github.io/weasel/#pkg/<name>`, where it used to open the TypeDoc site at `/weasel/api/`, which is no longer built. A file comment that sat on an `export { … }` list is now marked as the file's, so an entry's description no longer shows up as the summary of each function the entry re-exports. No code changed. `@weasel-js/labkit` drops `vitepress` from its devDependencies, which nothing used.
655
+ - f8faa63: The default node properties show a typed number to at most two decimal places: position, size, font size, tracking, leading, and tab size. A node left at `123.45678901234567` by a drag read that way in the panel. Only the text changes; the stored value keeps its digits until someone types a new one.
656
+ - 3bc85c9: Path commands as kit actions, in the `paths` feature preset. `simplifyPath` and `offsetPath` are ongoing actions driven by one number — `tolerance` and `distance` — so a slider can preview them live with `useOngoingAction` and commit once: Simplify refits each selected path in place, and Offset Path adds the grown or shrunk outline beside each, behind its source when grown and in front when shrunk, and selects the new paths. `snipAtCrossings` (Cut at Crossings) replaces each selected path with its pieces wherever another selected path crosses it. `joinPaths` (Cmd/Ctrl+J) closes a selected open path or joins two at their nearest open ends. In path edit, `joinAnchors` (Cmd/Ctrl+J) joins the two selected end anchors and `averageAnchors` (Cmd/Ctrl+Alt+J) moves the selected anchors to their mean, with variants that average one axis only. The object commands are in a new `path` group; the anchor ones join the `anchors` group.
657
+
658
+ These commands drop a node's `skin` and shape generator, since the new geometry has neither the anchors the skin follows nor the shape the generator makes. The geometry behind them — `simplifyPath`, `offsetPath`, `snipPathsAtCrossings`, `averageAnchorsAt`, `joinAnchorsAt` — is exported too.
659
+ - d0c3896: Delete, Backspace, and the arrow keys in path edit now act on the selected anchors in a `<SceneCanvas>` with no mode registry. They used to delete or nudge the whole shape, because the node-level `delete` and `nudge.*` actions were registered ahead of `deleteAnchors` and `nudgeAnchors.*` and took the keystroke. The anchor actions now register first and still decline when no anchor is selected, so the same keys reach the node then.
660
+ - 3448831: The default node properties have a Skew row for `pose.transform`, in Layout under Rotation. It reads on while a node's pose carries a skew or a per-axis scale, and turning it off removes the transform, so `SelectionPanel` can show and clear one. Additive: the row is a switch, not a matrix editor, and turning it on writes nothing new.
661
+ - 27fe0fb: `useRigNode` keeps a rig moving when its skeleton's joints are added, removed, or reordered. The rig still gets a new `target`, but that target takes over the placement and the committed pose of every joint the skeleton still names, where it used to start at the bind pose, and an animation that was running goes on running on the target it was started on and shows through the new one. A joint that was renamed is a different joint, and stops moving.
662
+ - 8bbf878: `composeRigidPose` composes a container's `transform` into its children, and `decomposeRigidPose` takes it back out. A child under a skewed or unevenly scaled container now answers a world pose whose box center, rotation, and `transform` draw it where the container's frame puts it; what the child's box and rotation cannot hold of the result is written to the child's own `transform`. Breaking for a scene that set a `transform` on a container under `RIGID_POSE_COMPOSITION` and relied on its children ignoring it. `composeRectPose` is unchanged: under it a container's pose only offsets its children, so neither its rotation nor its `transform` reaches them.
663
+ - b5267f9: The rotate cursor now turns with the pointer, so the opening of its arc faces the selection's pivot from wherever the pointer is: over the rotation ring, and through the rotate drag, which used to show no rotate cursor at all. It used to be turned to match the target's own rotation.
664
+
665
+ Two new surfaces carry it. An `AffordanceRegion`'s `cursor` may be a function of the pointer's world point and the view, worked out on each hit and reported on `AffordanceRegionHit.cursor`; read the cursor there rather than off `region.cursor`, which may now be a function. An `OngoingHandle` may declare `cursor()`, read after every move and ahead of its action's `activeCursor`.
666
+ - 62e766c: Editing the points of a skinned path keeps its weights with its points. Inserting, deleting, cutting, nudging, and dragging anchors, and continuing or joining the path with the pen, now write the node's `data.skin` in the same undo entry as its path, so one undo restores both. Before, the weight arrays kept their old numbering and every point after the edit followed the wrong joints. A new point takes weights between those of the anchors either side of it, by its distance to each; a point drawn past an end takes the end's. Hand-painted weights are kept: nothing is weighed again from the bones.
667
+
668
+ Adds API: `editAnchorSetTracked(path, edit)` is `editAnchorSet` that also answers `origins`, where each point of the new path came from in the old one, and `remapPointValues(values, origins)` carries an array kept per point through that edit. `remapSkin(skin, origins)` does the same for a skin. `EditAnchorsDep.applyEdit` and `editOps` take `origins` as an optional fourth argument; a dep of your own that ignores it leaves a skin as it was.
669
+ - 5485d35: The slice tool declares a palette icon: `SliceIcon`, a knife, exported from `@weasel-js/core` and `@weasel-js/ui` beside the other tool icons. A `ToolPalette` drew its placeholder `?` for the tool before. Additive.
670
+ - 690ea72: Hold Space while drawing a rectangle, ellipse, line, polygon, or star to move the shape instead of resizing it; let go and the drag resizes again from where the shape now sits. It is the `insert.reposition` action, which each kit shape tool binds through `INSERT_REPOSITION_BINDING` (a Space hold gated to the tool's own engaged phase), so a consumer's own drag-to-draw tool can bind it the same way. A grid-snapped start stays on the grid as it moves.
671
+
672
+ An offhand tool now engages only between gestures: `buildToolOffhandBindings` gates its key-held specs to `[{ channel: '*', phase: 'initial' }]`. Before, pressing Space mid-drag pushed the hand tool, and the tool switch canceled the drag.
673
+ - e962494: New package, `@weasel-js/symmetry`: live symmetry groups. A group's copies (a mirror at any angle, both axes, a point, radial, kaleidoscope, or a repeat with an optional glide) are drawn from its real children. Every edit to a child therefore reaches every copy, a click on a copy selects the child it copies, and `bakeSymmetry` turns the copies into real nodes. `createSymmetry(scene).contribution` draws the guide with draggable center, axis, and step handles, sends every tool's shapes into the active group, and keeps a path that is its own image under its group symmetric while its anchors are dragged or nudged.
674
+
675
+ Core gains what the package is built on, and each piece is usable on its own:
676
+
677
+ - `ContainerNode.copiesFromPose`: a container draws its subtree again under each affine it returns. Hit tests reach into the copies, and the clip travels with each one. Additive.
678
+ - The `insertInto` dep: the container the `insert` dep puts new nodes into.
679
+ - The `pathSymmetry` dep: transforms that anchor drags and nudges keep a path symmetric under.
680
+
681
+ `@weasel-js/geom` adds `anchorSymmetry`, `anchorSymmetries`, `translateAnchorsSymmetric`, and `moveHandleSymmetric`. `@weasel-js/svg` writes a container's copies as transformed groups.
682
+ - bad37cf: `useSceneTextEdit` edits text where it is drawn. The overlay and the double-click test both read the pose a node is painted at, so text inside a container whose pose is a frame (`RIGID_POSE_COMPOSITION`) opens over the turned or skewed text and takes a click there; it used to open where the text would sit without the container. Under a view whose `scale.x` and `scale.y` differ, the overlay is stretched to match the canvas, where it used to scale both axes by `scale.x`.
683
+ - 9e84e5d: Additive: `useTextEdit` and `useSceneTextEdit` take `onStart(id)` and `onEnd(id)`. `onStart` is called as an edit opens, whichever way it was started (`startEdit`, a double-click, the `textEdit` dep). `onEnd` is called as it closes, however it does: a commit, a cancel, Escape, a click away, or another edit opening over it, and after any commit has been written. Both are called from the call that changes the edit, not from an effect, so state that follows the edit is never a render behind it. Neither is called when the hook unmounts with an edit open.
684
+ - ef29364: A scene slot's `toPose` is handed each node as the scene shows it: its `pose` is a pose override's or a derived one, where it used to be the stored pose. A view drawn through a `toPose` now shows a drag in flight, a rig's bound nodes, and a skinned path, whose override `path` is carried from the box the scene shows the node at into the box `toPose` answers. A dependency read through such a slot answers the carried path too, and so does one in a scene that composes frames. Breaking for a `toPose` that relied on seeing the document's pose mid-gesture; one that places a node from its data alone, ignoring `node.pose`, still shows no motion.
685
+ - 2f48645: Cmd/Ctrl+D is now Transform Again: it repeats the last move, nudge, rotate, resize, duplicate, or Alt-drag clone on whatever is selected, as one undo entry. A rotate repeats about the new selection's center and a resize repeats as the same scale held at the same handle's opposite corner. Duplicating and then moving the copies makes the copies' offset the step, so pressing Cmd+D again lays down another copy one step further each time. With nothing to repeat it duplicates, as Cmd+D did before.
686
+
687
+ Duplicate moves to Cmd/Ctrl+Shift+D. This changes a default binding: an app relying on Cmd+D to duplicate after a move now gets the move repeated.
688
+
689
+ The kit keeps the last transform per scene: `lastTransform(scene)`, `recordTransform(scene, transform, selectedIds)`, and `forgetTransform(scene)`, with the `RepeatableTransform` type. The action is `transformAgain` in the standard actions and the `edit` feature preset, in the `edit` group with a new `TransformAgainIcon`.
690
+ - 92c2e8e: `<SceneCanvas tune>` changes a built-in action on one canvas without restating it. Keyed by action id, an entry sets `params` every invocation starts from (a thunk is read on each call, so a value changed mid-drag reaches an ongoing action) and adds `bindings` beside the action's own. A binding's or a `trigger` call's own params are laid over the tuned ones. The tuning applies to whichever descriptor holds the id, from a preset or a tool, so setting a param no longer means copying the gesture that reaches the action. Additive: `ActionsRegistry.tune(id, tuning)` underneath it, `tuneAction`, the types `ActionTuning`, `ActionTunings`, `ActionParams` and `TunedBinding`, and `ActionParamSchema`, which types params by action id for the kit's parametric actions and takes an app's own entries by declaration merging, as `DepSchema` does. `BoundGesture` is no longer marked experimental.
691
+
692
+ `SceneCanvasViewport` names the type of `<SceneCanvas viewport>`.
693
+ - 711ae46: While a scene has an active journal (`getActiveJournal` / `setActiveJournalAccessor`), `scene.undo`, `scene.redo`, `canUndo`, and `canRedo` (and the same on `scene.history`) now step that journal, the same place `applyBatch` sends edits. Before, undo stepped the scene's own history and skipped the journal's edits entirely: the `undo` action took back whatever came before the journal opened instead of the edit just made. Once the journal is suspended, committed, or canceled, undo steps the scene's history again. `historyEntries`, `historyIndex`, and `jumpToHistoryIndex` still read the scene's own history.
694
+ - 365eae0: A linear unit stores a decimal typed at a decimal `scale` as the decimal the two multiply to: 33.3 at a scale of 0.01 is 0.333, where it was 0.33299999999999996. Nothing is rounded away, and a scale that is no short decimal (degrees over radians) converts as before.
695
+
696
+ The text tool's percent unit for `fontScale` and `baselineShift` is that data now (`{ scale: 0.01, precision: 1, suffix: '%' }`) and no longer a pair of functions, so the run properties print as a literal. Breaking in one detail: a percentage typed to more than three places is stored as typed, where it was cut to five places of the stored fraction.
697
+
698
+ labkit's one-line summary of a compound leaf writes each number that has a unit as its field shows it, in an object's fields, a list's and a map's entries, and a union's variant, and writes a list of objects entry by entry where it wrote `[object Object]`. Additive: `summarizeLeaf(leaf, value)` is exported beside `summarizeValue`, and `inDialog`'s default summary is the leaf's.
699
+ - 781a15e: A canvas's `clientToWorld` override reaches the views declared on it. Which `<CanvasView>` a client point is in, where it lands in that view's world, and the `pointer` dep's position over a view were all worked out from the element's bounding rect, so a canvas under a CSS transform routed a press to the wrong view or converted it wrong.
700
+
701
+ Breaking, in the experimental view resolver: `createViewResolver` takes `toLocal(clientX, clientY)`, a client point in the canvas's own pixels, where it took `canvasOrigin`; and a `ViewTarget` carries `world`, the point in the resolved view's world, where it carried `origin`.
702
+ - a092978: Zoom can be held to one axis. `viewport={{ zoom: { axis: 'x' } }}` makes the wheel, the trackpad pinch, and Cmd+=/- scale only x, leaving y's scale and translation alone; `pinchZoom: { axis }` does the same for a two-finger pinch, which still pans on both. `makeViewportZoomAction` and `makePinchZoomAction` take the same option, and `axisZoomFactor` and the `ZoomAxis` type are exported for a host calling `zoomAt` itself. Additive.
703
+ - Updated dependencies [b6e04e2]
704
+ - Updated dependencies [cbd5b4d]
705
+ - Updated dependencies [aaa2b4f]
706
+ - Updated dependencies [c7b7ed5]
707
+ - Updated dependencies [3fda6e6]
708
+ - Updated dependencies [906fd19]
709
+ - Updated dependencies [7c5af8a]
710
+ - Updated dependencies [ee59ccd]
711
+ - Updated dependencies [789e80d]
712
+ - Updated dependencies [924edc4]
713
+ - Updated dependencies [b8bfb2d]
714
+ - Updated dependencies [35c4879]
715
+ - Updated dependencies [b67b6cd]
716
+ - Updated dependencies [9eefcc7]
717
+ - Updated dependencies [886380f]
718
+ - Updated dependencies [0db6d9a]
719
+ - Updated dependencies [d8b51a4]
720
+ - Updated dependencies [10449af]
721
+ - Updated dependencies [e05a5f9]
722
+ - Updated dependencies [d30823f]
723
+ - Updated dependencies [0be7a53]
724
+ - Updated dependencies [b5267f9]
725
+ - Updated dependencies [9253a8b]
726
+ - Updated dependencies [62e766c]
727
+ - Updated dependencies [f4100e9]
728
+ - Updated dependencies [690ea72]
729
+ - Updated dependencies [ab9ea7a]
730
+ - Updated dependencies [e962494]
731
+ - Updated dependencies [8a9ed26]
732
+ - Updated dependencies [9e84e5d]
733
+ - Updated dependencies [f5870a4]
734
+ - Updated dependencies [bd6c203]
735
+ - Updated dependencies [92c2e8e]
736
+ - Updated dependencies [365eae0]
737
+ - Updated dependencies [10c5d41]
738
+ - @weasel-js/prefs@1.10.1
739
+ - @weasel-js/geom@1.10.1
740
+ - @weasel-js/stroke@1.10.1
741
+ - @weasel-js/text@1.10.1
742
+ - @weasel-js/routing@1.10.1
743
+ - @weasel-js/animator@1.10.1
744
+ - @weasel-js/renderer@1.10.1
745
+ - @weasel-js/gestures@1.10.1
746
+ - @weasel-js/history@1.10.1
747
+ - @weasel-js/select@1.10.1
748
+ - @weasel-js/cursor@1.10.1
749
+ - @weasel-js/react@1.10.1
750
+ - @weasel-js/font@1.10.1
751
+ - @weasel-js/modes@1.10.1
752
+ - @weasel-js/paint@1.10.1
753
+ - @weasel-js/quantity@1.10.1
754
+ - @weasel-js/registry@1.10.1
755
+ - @weasel-js/simulation@1.10.1
756
+ - @weasel-js/text-dom@1.10.1
757
+
3
758
  ## 1.10.0
4
759
 
5
760
  ### Patch Changes