@weasel-js/core 1.9.4 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1191) hide show
  1. package/CHANGELOG.md +918 -0
  2. package/README.md +38 -3
  3. package/dist/WeaselProvider.js +5 -7
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +92 -84
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +3 -2
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +71 -101
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js +50 -28
  12. package/dist/affordances/pathAnchors.js.map +1 -1
  13. package/dist/affordances/rotateCursor.js +12 -0
  14. package/dist/affordances/rotateCursor.js.map +1 -0
  15. package/dist/affordances/rotationHandle.js +44 -46
  16. package/dist/affordances/rotationHandle.js.map +1 -1
  17. package/dist/animation/behaviors/coast.js +21 -0
  18. package/dist/animation/behaviors/coast.js.map +1 -0
  19. package/dist/animation/behaviors/coastByWrite.js +107 -0
  20. package/dist/animation/behaviors/coastByWrite.js.map +1 -0
  21. package/dist/animation/behaviors/coastOnTargets.js +94 -0
  22. package/dist/animation/behaviors/coastOnTargets.js.map +1 -0
  23. package/dist/animation/behaviors/momentum.js +48 -136
  24. package/dist/animation/behaviors/momentum.js.map +1 -1
  25. package/dist/animation/clipTargets.js +12 -0
  26. package/dist/animation/clipTargets.js.map +1 -0
  27. package/dist/animation/index.js +15 -20
  28. package/dist/animation/poseHelpers.js +112 -33
  29. package/dist/animation/poseHelpers.js.map +1 -1
  30. package/dist/animation/poseTarget.js +115 -0
  31. package/dist/animation/poseTarget.js.map +1 -0
  32. package/dist/animation/reflow.js +113 -83
  33. package/dist/animation/reflow.js.map +1 -1
  34. package/dist/animation/rewind.js +66 -0
  35. package/dist/animation/rewind.js.map +1 -0
  36. package/dist/animation/rig/bindRig.js +85 -53
  37. package/dist/animation/rig/bindRig.js.map +1 -1
  38. package/dist/animation/rig/rigNode.js +99 -0
  39. package/dist/animation/rig/rigNode.js.map +1 -0
  40. package/dist/animation/rig/rigSeat.js +59 -0
  41. package/dist/animation/rig/rigSeat.js.map +1 -0
  42. package/dist/animation/rig/skinBinding.js +64 -0
  43. package/dist/animation/rig/skinBinding.js.map +1 -0
  44. package/dist/animation/rig/useRig.js +31 -16
  45. package/dist/animation/rig/useRig.js.map +1 -1
  46. package/dist/animation/wrappers/animateLifecycle.js +8 -7
  47. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  48. package/dist/animation/wrappers/animateOnSetPose.js +31 -31
  49. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  50. package/dist/animation/wrappers/instantPose.js.map +1 -1
  51. package/dist/animation/writtenPoseTarget.js +33 -0
  52. package/dist/animation/writtenPoseTarget.js.map +1 -0
  53. package/dist/autoPoseDescriptor-DHg5KqaJ.d.ts +27 -0
  54. package/dist/barrel/canvas.js +32 -0
  55. package/dist/barrel/chrome.js +10 -10
  56. package/dist/barrel/input.js +16 -17
  57. package/dist/barrel/interactions.js +34 -37
  58. package/dist/barrel/paint.js +11 -18
  59. package/dist/barrel/paths.js +13 -19
  60. package/dist/barrel/renderer.js +14 -20
  61. package/dist/barrel/routing.js +54 -47
  62. package/dist/barrel/scene.js +37 -0
  63. package/dist/barrel/text.js +9 -18
  64. package/dist/barrel/viewport.js +44 -51
  65. package/dist/canvas/Canvas.js +270 -475
  66. package/dist/canvas/Canvas.js.map +1 -1
  67. package/dist/canvas/CanvasView.js +168 -190
  68. package/dist/canvas/CanvasView.js.map +1 -1
  69. package/dist/canvas/CursorCoordsHud.js +24 -25
  70. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  71. package/dist/canvas/DrawCanvas.js +39 -56
  72. package/dist/canvas/DrawCanvas.js.map +1 -1
  73. package/dist/canvas/ModalityHud.js.map +1 -1
  74. package/dist/canvas/NodeShape.js +28 -29
  75. package/dist/canvas/NodeShape.js.map +1 -1
  76. package/dist/canvas/PickHud.js.map +1 -1
  77. package/dist/canvas/SceneCanvas/DevHuds.js +40 -0
  78. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -0
  79. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +66 -107
  80. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -1
  81. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +33 -36
  82. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  83. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +38 -50
  84. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -1
  85. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +3 -3
  86. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/coordTrace.js +37 -1
  88. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  89. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +319 -270
  90. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  91. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +1 -1
  92. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  94. package/dist/canvas/SceneCanvas/features.js +71 -62
  95. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  96. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +97 -0
  97. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -0
  98. package/dist/canvas/SceneCanvas/isDev.js.map +1 -1
  99. package/dist/canvas/SceneCanvas/poseGeometry.js +33 -37
  100. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  101. package/dist/canvas/SceneCanvas/props.js +15 -14
  102. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  103. package/dist/canvas/SceneCanvas/scenePointQuery.js +50 -0
  104. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -0
  105. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +52 -0
  106. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -0
  107. package/dist/canvas/SceneCanvas/toolRegistry.js +23 -0
  108. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -0
  109. package/dist/canvas/SceneCanvas/useActionTunings.js +17 -0
  110. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -0
  111. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +6 -1
  112. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  113. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  114. package/dist/canvas/SceneCanvas/useBuiltinTools.js +21 -0
  115. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -0
  116. package/dist/canvas/SceneCanvas/useCanvasCamera.js +46 -0
  117. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -0
  118. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +20 -0
  119. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -0
  120. package/dist/canvas/SceneCanvas/useCanvasSelection.js +16 -0
  121. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -0
  122. package/dist/canvas/SceneCanvas/useCanvasTools.js +67 -0
  123. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -0
  124. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +49 -113
  125. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  126. package/dist/canvas/SceneCanvas/useHeldModifiers.js +20 -0
  127. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -0
  128. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +26 -0
  129. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -0
  130. package/dist/canvas/SceneCanvas/useNodeKinds.js +26 -0
  131. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -0
  132. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +51 -41
  133. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  134. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +47 -0
  135. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -0
  136. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +66 -0
  137. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -0
  138. package/dist/canvas/SceneCanvas/useSceneChrome.js +59 -0
  139. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -0
  140. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +23 -0
  141. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -0
  142. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +65 -101
  143. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  144. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +37 -0
  145. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -0
  146. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +38 -0
  147. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -0
  148. package/dist/canvas/SceneCanvas/useViewLayerGate.js +20 -0
  149. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +1 -0
  150. package/dist/canvas/SceneCanvas/useViewportActions.js +9 -1
  151. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  152. package/dist/canvas/SceneCanvas/worldPointAt.js +8 -0
  153. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -0
  154. package/dist/canvas/SceneCanvas.js +301 -708
  155. package/dist/canvas/SceneCanvas.js.map +1 -1
  156. package/dist/canvas/SceneViewCanvas.js +41 -47
  157. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  158. package/dist/canvas/SurfaceCanvas.js +40 -0
  159. package/dist/canvas/SurfaceCanvas.js.map +1 -0
  160. package/dist/canvas/adapterDerivedPath.js +26 -0
  161. package/dist/canvas/adapterDerivedPath.js.map +1 -0
  162. package/dist/canvas/adapterPickSource.js +34 -0
  163. package/dist/canvas/adapterPickSource.js.map +1 -0
  164. package/dist/canvas/affordanceAt.js +12 -2
  165. package/dist/canvas/affordanceAt.js.map +1 -1
  166. package/dist/canvas/buildSceneLayer.js +81 -61
  167. package/dist/canvas/buildSceneLayer.js.map +1 -1
  168. package/dist/canvas/buildSceneTree.js +56 -34
  169. package/dist/canvas/buildSceneTree.js.map +1 -1
  170. package/dist/canvas/canvasRenderer.js +40 -44
  171. package/dist/canvas/canvasRenderer.js.map +1 -1
  172. package/dist/canvas/colorOverrides.js.map +1 -1
  173. package/dist/canvas/copiesAbove.js +27 -0
  174. package/dist/canvas/copiesAbove.js.map +1 -0
  175. package/dist/canvas/defaultDrawOne.js +25 -24
  176. package/dist/canvas/defaultDrawOne.js.map +1 -1
  177. package/dist/canvas/deps/areaSelect.js +4 -4
  178. package/dist/canvas/deps/areaSelect.js.map +1 -1
  179. package/dist/canvas/deps/debug.js.map +1 -1
  180. package/dist/canvas/deps/editAnchors.js +47 -71
  181. package/dist/canvas/deps/editAnchors.js.map +1 -1
  182. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  183. package/dist/canvas/deps/hitTestArea.js +45 -25
  184. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  185. package/dist/canvas/deps/insert.js +149 -104
  186. package/dist/canvas/deps/insert.js.map +1 -1
  187. package/dist/canvas/deps/lassoSelect.js +5 -5
  188. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  189. package/dist/canvas/deps/layout.js +9 -15
  190. package/dist/canvas/deps/layout.js.map +1 -1
  191. package/dist/canvas/deps/poseDescriptor.js +1 -1
  192. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  193. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  194. package/dist/canvas/deps/slice.js +44 -45
  195. package/dist/canvas/deps/slice.js.map +1 -1
  196. package/dist/canvas/deps/textEdit.js +8 -8
  197. package/dist/canvas/deps/textEdit.js.map +1 -1
  198. package/dist/canvas/deps/view.js.map +1 -1
  199. package/dist/canvas/derivedPath.js +69 -43
  200. package/dist/canvas/derivedPath.js.map +1 -1
  201. package/dist/canvas/drawEnvelope.js +8 -4
  202. package/dist/canvas/drawEnvelope.js.map +1 -1
  203. package/dist/canvas/getNodeAtPoint.js +2 -6
  204. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  205. package/dist/canvas/hud.module.js.map +1 -1
  206. package/dist/canvas/insertPreviewExtent.js +33 -31
  207. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  208. package/dist/canvas/layerOrder.js.map +1 -1
  209. package/dist/canvas/layerSlots.js +6 -1
  210. package/dist/canvas/layerSlots.js.map +1 -1
  211. package/dist/canvas/nodeShapes/derivedPainter.js +12 -12
  212. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  213. package/dist/canvas/nodeShapes/imagePainter.js +10 -10
  214. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  215. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  216. package/dist/canvas/nodeShapes/nodePaint.js +34 -23
  217. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  218. package/dist/canvas/nodeShapes/pathPainter.js +23 -22
  219. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  220. package/dist/canvas/nodeShapes/poseBox.js +6 -6
  221. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  222. package/dist/canvas/nodeShapes/rectFallbackPainter.js +8 -8
  223. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  224. package/dist/canvas/nodeShapes/shapePainter.js +16 -16
  225. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  226. package/dist/canvas/nodeShapes/textPainter.js +1 -1
  227. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  228. package/dist/canvas/overChildren.js +29 -0
  229. package/dist/canvas/overChildren.js.map +1 -0
  230. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  231. package/dist/canvas/paintCull.js +6 -8
  232. package/dist/canvas/paintCull.js.map +1 -1
  233. package/dist/{features/cursor → canvas}/paintedCursorLayer.js +2 -2
  234. package/dist/canvas/paintedCursorLayer.js.map +1 -0
  235. package/dist/canvas/pickReach.js +23 -0
  236. package/dist/canvas/pickReach.js.map +1 -0
  237. package/dist/canvas/pickWalk.js +43 -70
  238. package/dist/canvas/pickWalk.js.map +1 -1
  239. package/dist/canvas/planeClips.js +18 -19
  240. package/dist/canvas/planeClips.js.map +1 -1
  241. package/dist/canvas/poseCascade.js +41 -0
  242. package/dist/canvas/poseCascade.js.map +1 -0
  243. package/dist/canvas/poseRotation.js +1 -3
  244. package/dist/canvas/poseRotation.js.map +1 -1
  245. package/dist/canvas/rasterReadback.js +22 -0
  246. package/dist/canvas/rasterReadback.js.map +1 -0
  247. package/dist/canvas/renderDebugSnapshot.js +12 -12
  248. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  249. package/dist/canvas/renderNeeds.js +3 -3
  250. package/dist/canvas/renderNeeds.js.map +1 -1
  251. package/dist/canvas/renderSceneToPixels.js +64 -83
  252. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  253. package/dist/canvas/sceneAdapter.js +59 -144
  254. package/dist/canvas/sceneAdapter.js.map +1 -1
  255. package/dist/canvas/sceneClipboard.js +1 -1
  256. package/dist/canvas/sceneClipboard.js.map +1 -1
  257. package/dist/canvas/sceneLayerPaint.js +4 -4
  258. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  259. package/dist/canvas/sceneSlotWiring.js +10 -9
  260. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  261. package/dist/canvas/sceneViewRender.js +37 -42
  262. package/dist/canvas/sceneViewRender.js.map +1 -1
  263. package/dist/canvas/slopsDebugLayer.js +4 -4
  264. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  265. package/dist/canvas/useCanvasRenderer.js +23 -11
  266. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  267. package/dist/canvas/useCanvasSurface.js +31 -0
  268. package/dist/canvas/useCanvasSurface.js.map +1 -0
  269. package/dist/canvas/useCanvasView.js +51 -44
  270. package/dist/canvas/useCanvasView.js.map +1 -1
  271. package/dist/canvas/useFrameLoop.js +11 -12
  272. package/dist/canvas/useFrameLoop.js.map +1 -1
  273. package/dist/canvas/useHostAnchor.js +35 -33
  274. package/dist/canvas/useHostAnchor.js.map +1 -1
  275. package/dist/canvas/useLateContentRedraw.js +8 -8
  276. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  277. package/dist/canvas/useSceneAdapter.js +22 -0
  278. package/dist/canvas/useSceneAdapter.js.map +1 -0
  279. package/dist/canvas/useSceneLayerList.js +4 -14
  280. package/dist/canvas/useSceneLayerList.js.map +1 -1
  281. package/dist/canvas/useSurfaceInput.js +39 -0
  282. package/dist/canvas/useSurfaceInput.js.map +1 -0
  283. package/dist/canvas/useToolCursor.js +29 -0
  284. package/dist/canvas/useToolCursor.js.map +1 -0
  285. package/dist/canvas/useViewHelpers.js +46 -85
  286. package/dist/canvas/useViewHelpers.js.map +1 -1
  287. package/dist/canvas/viewInputs.js.map +1 -1
  288. package/dist/canvas/viewRegistry.js +40 -34
  289. package/dist/canvas/viewRegistry.js.map +1 -1
  290. package/dist/canvas/watchElementMove.js +43 -0
  291. package/dist/canvas/watchElementMove.js.map +1 -0
  292. package/dist/canvas/wrapNodeOutput.js +7 -2
  293. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  294. package/dist/clipboard.d.ts +7 -14
  295. package/dist/{types-B4iJRHC3.d.ts → clone-C0eADtS0.d.ts} +129 -84
  296. package/dist/clone.d.ts +4 -8
  297. package/dist/clone.js +0 -2
  298. package/dist/core/device/targets.js.map +1 -1
  299. package/dist/core/device/useDeviceProfile.js +13 -13
  300. package/dist/core/device/useDeviceProfile.js.map +1 -1
  301. package/dist/{interactions/actions/resize → core/geometry}/autoPoseDescriptor.js +8 -7
  302. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -0
  303. package/dist/core/geometry/pathPoseDescriptor.js +88 -0
  304. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -0
  305. package/dist/core/geometry/poseDescriptor.js +102 -29
  306. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  307. package/dist/core/geometry/regionHit.js +35 -37
  308. package/dist/core/geometry/regionHit.js.map +1 -1
  309. package/dist/core/geometry/targetFrame.js +94 -0
  310. package/dist/core/geometry/targetFrame.js.map +1 -0
  311. package/dist/core/geometry/unionBounds.js +4 -5
  312. package/dist/core/geometry/unionBounds.js.map +1 -1
  313. package/dist/core/layers/backgroundFill.js +31 -0
  314. package/dist/core/layers/backgroundFill.js.map +1 -0
  315. package/dist/{features/groups → core/layers}/children.js +2 -4
  316. package/dist/core/layers/children.js.map +1 -0
  317. package/dist/{features/focus → core/layers}/gateLayer.js +2 -2
  318. package/dist/core/layers/gateLayer.js.map +1 -0
  319. package/dist/core/layers/layerGroup.js +40 -0
  320. package/dist/core/layers/layerGroup.js.map +1 -0
  321. package/dist/core/layers/render.js +50 -76
  322. package/dist/core/layers/render.js.map +1 -1
  323. package/dist/core/ops/create.js +2 -2
  324. package/dist/core/ops/create.js.map +1 -1
  325. package/dist/core/ops/createHistory.js +9 -9
  326. package/dist/core/ops/createHistory.js.map +1 -1
  327. package/dist/core/ops/delete.js +19 -23
  328. package/dist/core/ops/delete.js.map +1 -1
  329. package/dist/core/ops/reorder/index.js +3 -7
  330. package/dist/core/ops/reorder/index.js.map +1 -1
  331. package/dist/core/ops/reorder/setChildOrder.js +2 -4
  332. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  333. package/dist/core/ops/reparent.js +0 -1
  334. package/dist/core/ops/reparent.js.map +1 -1
  335. package/dist/core/ops/slot.js +3 -6
  336. package/dist/core/ops/slot.js.map +1 -1
  337. package/dist/core/pages/fitViewToPage.js +15 -0
  338. package/dist/core/pages/fitViewToPage.js.map +1 -0
  339. package/dist/core/pages/pages.js +65 -0
  340. package/dist/core/pages/pages.js.map +1 -0
  341. package/dist/core/pages/pagesLayer.js +27 -0
  342. package/dist/core/pages/pagesLayer.js.map +1 -0
  343. package/dist/core/paint/meshKind.js +16 -0
  344. package/dist/core/paint/meshKind.js.map +1 -0
  345. package/dist/{features/meshPaint/lazyKind.js → core/paint/meshKindLazy.js} +104 -93
  346. package/dist/core/paint/meshKindLazy.js.map +1 -0
  347. package/dist/core/paint/paintKindEntry.js +8 -0
  348. package/dist/core/paint/paintKindEntry.js.map +1 -0
  349. package/dist/core/paint/paintKinds.js +144 -0
  350. package/dist/core/paint/paintKinds.js.map +1 -0
  351. package/dist/core/paint/registerMesh.js +7 -0
  352. package/dist/core/paint/registerMesh.js.map +1 -0
  353. package/dist/core/scene/NodeProperties.js.map +1 -1
  354. package/dist/core/scene/NodeRouting.js.map +1 -1
  355. package/dist/core/scene/arrivalWindow.js +65 -64
  356. package/dist/core/scene/arrivalWindow.js.map +1 -1
  357. package/dist/core/scene/boundOps.js +40 -0
  358. package/dist/core/scene/boundOps.js.map +1 -0
  359. package/dist/core/scene/composeFrame.js +9 -6
  360. package/dist/core/scene/composeFrame.js.map +1 -1
  361. package/dist/core/scene/composePose.js +105 -0
  362. package/dist/core/scene/composePose.js.map +1 -0
  363. package/dist/core/scene/depMemo.js +31 -6
  364. package/dist/core/scene/depMemo.js.map +1 -1
  365. package/dist/core/scene/derivedPath.js +19 -20
  366. package/dist/core/scene/derivedPath.js.map +1 -1
  367. package/dist/core/scene/editMode.js +26 -0
  368. package/dist/core/scene/editMode.js.map +1 -0
  369. package/dist/core/scene/effectivePose.js +42 -39
  370. package/dist/core/scene/effectivePose.js.map +1 -1
  371. package/dist/core/scene/fieldEdits.js +98 -0
  372. package/dist/core/scene/fieldEdits.js.map +1 -0
  373. package/dist/core/scene/historyFacade.js +122 -70
  374. package/dist/core/scene/historyFacade.js.map +1 -1
  375. package/dist/core/scene/historyForm.js +6 -0
  376. package/dist/core/scene/historyForm.js.map +1 -0
  377. package/dist/core/scene/kitOps.js +83 -71
  378. package/dist/core/scene/kitOps.js.map +1 -1
  379. package/dist/core/scene/kitRegistry.js.map +1 -1
  380. package/dist/core/scene/layerStack.js +105 -12
  381. package/dist/core/scene/layerStack.js.map +1 -1
  382. package/dist/core/scene/layoutPass.js +58 -59
  383. package/dist/core/scene/layoutPass.js.map +1 -1
  384. package/dist/{features/groups → core/scene}/nestedHit.js +3 -3
  385. package/dist/core/scene/nestedHit.js.map +1 -0
  386. package/dist/core/scene/nodeFnFields.js +16 -9
  387. package/dist/core/scene/nodeFnFields.js.map +1 -1
  388. package/dist/core/scene/nodeMemo.js.map +1 -1
  389. package/dist/core/scene/nodeStore.js +72 -71
  390. package/dist/core/scene/nodeStore.js.map +1 -1
  391. package/dist/core/scene/notifier.js +37 -0
  392. package/dist/core/scene/notifier.js.map +1 -0
  393. package/dist/core/scene/opTable.js +50 -0
  394. package/dist/core/scene/opTable.js.map +1 -0
  395. package/dist/core/scene/outerOps.js +67 -0
  396. package/dist/core/scene/outerOps.js.map +1 -0
  397. package/dist/core/scene/poseHold.js +39 -0
  398. package/dist/core/scene/poseHold.js.map +1 -0
  399. package/dist/core/scene/poseOverrides.js +44 -36
  400. package/dist/core/scene/poseOverrides.js.map +1 -1
  401. package/dist/core/scene/poseSnapshot.js.map +1 -1
  402. package/dist/core/scene/reconcileSpecs.js +4 -3
  403. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  404. package/dist/core/scene/recorder.js +86 -0
  405. package/dist/core/scene/recorder.js.map +1 -0
  406. package/dist/core/scene/renderOrder.js.map +1 -1
  407. package/dist/core/scene/scene.js +81 -690
  408. package/dist/core/scene/scene.js.map +1 -1
  409. package/dist/core/scene/sceneEdits.js +58 -0
  410. package/dist/core/scene/sceneEdits.js.map +1 -0
  411. package/dist/core/scene/sceneMutators.js +49 -0
  412. package/dist/core/scene/sceneMutators.js.map +1 -0
  413. package/dist/core/scene/scenePoseAdapter.js +16 -0
  414. package/dist/core/scene/scenePoseAdapter.js.map +1 -0
  415. package/dist/core/scene/sceneRecording.js +91 -0
  416. package/dist/core/scene/sceneRecording.js.map +1 -0
  417. package/dist/core/scene/sceneSelection.js +28 -0
  418. package/dist/core/scene/sceneSelection.js.map +1 -0
  419. package/dist/core/scene/sceneState.js +49 -0
  420. package/dist/core/scene/sceneState.js.map +1 -0
  421. package/dist/core/scene/serialization.js +8 -5
  422. package/dist/core/scene/serialization.js.map +1 -1
  423. package/dist/core/scene/staleReplay.js +51 -0
  424. package/dist/core/scene/staleReplay.js.map +1 -0
  425. package/dist/core/scene/statedFields.js +9 -0
  426. package/dist/core/scene/statedFields.js.map +1 -0
  427. package/dist/core/scene/treeEdits.js +127 -0
  428. package/dist/core/scene/treeEdits.js.map +1 -0
  429. package/dist/core/scene/treeReads.js +26 -0
  430. package/dist/core/scene/treeReads.js.map +1 -0
  431. package/dist/core/scene/types.js.map +1 -1
  432. package/dist/{features/groups → core/scene}/unionOfChildren.js +3 -3
  433. package/dist/core/scene/unionOfChildren.js.map +1 -0
  434. package/dist/core/scene/unitScopes.js +13 -0
  435. package/dist/core/scene/unitScopes.js.map +1 -0
  436. package/dist/core/scene/useScene.js.map +1 -1
  437. package/dist/core/selection/readOnlySelection.js +32 -0
  438. package/dist/core/selection/readOnlySelection.js.map +1 -0
  439. package/dist/core/selection/usePublishSceneSelection.js +26 -0
  440. package/dist/core/selection/usePublishSceneSelection.js.map +1 -0
  441. package/dist/core/selection/useSelection.js +34 -25
  442. package/dist/core/selection/useSelection.js.map +1 -1
  443. package/dist/core/shapeKinds.js.map +1 -1
  444. package/dist/core/stylus/stylus.js.map +1 -1
  445. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  446. package/dist/core/usePaintKinds.js +1 -1
  447. package/dist/core/usePaintKinds.js.map +1 -1
  448. package/dist/core/viewport/clientToWorld.js.map +1 -1
  449. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  450. package/dist/core/viewport/parallax.js.map +1 -1
  451. package/dist/core/viewport/screenSlop.js +11 -11
  452. package/dist/core/viewport/screenSlop.js.map +1 -1
  453. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  454. package/dist/core/viewport/useDecayLoop.js +31 -33
  455. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  456. package/dist/core/viewport/useNodeOverlayFrame.js +84 -0
  457. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -0
  458. package/dist/core/viewport/useViewAnimation.js +113 -53
  459. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  460. package/dist/core/viewport/view.js +14 -11
  461. package/dist/core/viewport/view.js.map +1 -1
  462. package/dist/core/viewport/wheelHandler.js.map +1 -1
  463. package/dist/core/viewport/zoomAt.js +11 -2
  464. package/dist/core/viewport/zoomAt.js.map +1 -1
  465. package/dist/{cornerHandles-CtCb8a3G.d.ts → cornerHandles-BSKbyuvQ.d.ts} +11 -24
  466. package/dist/debug/createDebugOverlayLayer.js +100 -100
  467. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  468. package/dist/debug/createDebugSink.js.map +1 -1
  469. package/dist/debug/frameStats.js.map +1 -1
  470. package/dist/debug/useDebugSink.js +52 -0
  471. package/dist/debug/useDebugSink.js.map +1 -0
  472. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  473. package/dist/features/chrome-caps/conditions.js.map +1 -1
  474. package/dist/features/chrome-caps/defaults.js.map +1 -1
  475. package/dist/features/chrome-caps/resolve.js.map +1 -1
  476. package/dist/features/chrome-caps/useChromeCaps.js +54 -0
  477. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -0
  478. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  479. package/dist/features/ingestion/contentHandlers.js +25 -19
  480. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  481. package/dist/features/ingestion/imageHandler.js +21 -24
  482. package/dist/features/ingestion/imageHandler.js.map +1 -1
  483. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  484. package/dist/features/ingestion/placement.js +16 -0
  485. package/dist/features/ingestion/placement.js.map +1 -0
  486. package/dist/features/ingestion/svgHandler.js +5 -0
  487. package/dist/features/ingestion/svgHandler.js.map +1 -1
  488. package/dist/features/ingestion/textHandler.js +28 -0
  489. package/dist/features/ingestion/textHandler.js.map +1 -0
  490. package/dist/features/ingestion/useCanvasIngestion.js +48 -0
  491. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -0
  492. package/dist/features/ingestion/weaselJsonHandler.js +5 -0
  493. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  494. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  495. package/dist/features/modes/modeLayers.js +7 -7
  496. package/dist/features/modes/modeLayers.js.map +1 -1
  497. package/dist/features/paths/editablePath.js +63 -0
  498. package/dist/features/paths/editablePath.js.map +1 -0
  499. package/dist/features/paths/index.js +9 -16
  500. package/dist/features/paths/pathEditState.js +41 -0
  501. package/dist/features/paths/pathEditState.js.map +1 -0
  502. package/dist/features/paths/pathEditingOverlayLayer.js +36 -38
  503. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  504. package/dist/features/paths/pathLayer.js +3 -2
  505. package/dist/features/paths/pathLayer.js.map +1 -1
  506. package/dist/features/paths/penPreviewLayer.js +86 -88
  507. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  508. package/dist/features/paths/shapeGenerator.js +89 -0
  509. package/dist/features/paths/shapeGenerator.js.map +1 -0
  510. package/dist/features/paths/usePathEdit.js +34 -0
  511. package/dist/features/paths/usePathEdit.js.map +1 -0
  512. package/dist/features/poseRun/usePoseRun.js +44 -57
  513. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  514. package/dist/features/selection/overlay.js +170 -178
  515. package/dist/features/selection/overlay.js.map +1 -1
  516. package/dist/features/text/index.js +6 -0
  517. package/dist/features/text/textLayer.js +1 -1
  518. package/dist/features/text/textLayer.js.map +1 -1
  519. package/dist/features/text/useSceneTextEdit.js +119 -88
  520. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  521. package/dist/features/viewports/viewResolver.js +28 -24
  522. package/dist/features/viewports/viewResolver.js.map +1 -1
  523. package/dist/features/viewports/viewportLayer.js +25 -36
  524. package/dist/features/viewports/viewportLayer.js.map +1 -1
  525. package/dist/icons/SliceIcon.js +24 -0
  526. package/dist/icons/SliceIcon.js.map +1 -0
  527. package/dist/index.d.ts +5200 -8777
  528. package/dist/index.js +284 -320
  529. package/dist/input/keyState.js +14 -14
  530. package/dist/interactions/actions/actionShortcuts.js.map +1 -1
  531. package/dist/interactions/actions/{defaults/align.js → align/action.js} +15 -16
  532. package/dist/interactions/actions/align/action.js.map +1 -0
  533. package/dist/interactions/actions/align/align.js +24 -24
  534. package/dist/interactions/actions/align/align.js.map +1 -1
  535. package/dist/interactions/actions/booleans/action.js +65 -0
  536. package/dist/interactions/actions/booleans/action.js.map +1 -0
  537. package/dist/interactions/actions/booleans/booleans.js +74 -83
  538. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  539. package/dist/interactions/actions/booleans/operands.js +40 -0
  540. package/dist/interactions/actions/booleans/operands.js.map +1 -0
  541. package/dist/interactions/actions/booleans/pieces.js +45 -0
  542. package/dist/interactions/actions/booleans/pieces.js.map +1 -0
  543. package/dist/interactions/actions/booleans/placement.js +24 -0
  544. package/dist/interactions/actions/booleans/placement.js.map +1 -0
  545. package/dist/interactions/actions/booleans/useBooleans.js +11 -9
  546. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  547. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  548. package/dist/interactions/actions/{defaults/clipboard.js → clipboard/action.js} +19 -19
  549. package/dist/interactions/actions/clipboard/action.js.map +1 -0
  550. package/dist/interactions/actions/clipboard/clipboardOps.js +15 -15
  551. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  552. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  553. package/dist/interactions/actions/clone/action.js +103 -0
  554. package/dist/interactions/actions/clone/action.js.map +1 -0
  555. package/dist/interactions/actions/clone/behaviors.js +52 -0
  556. package/dist/interactions/actions/clone/behaviors.js.map +1 -0
  557. package/dist/interactions/actions/defaultCommitAdapter.js +10 -37
  558. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  559. package/dist/interactions/actions/defaults/anchorEditing.js +69 -74
  560. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  561. package/dist/interactions/actions/defaults/anchorHandles.js +42 -0
  562. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -0
  563. package/dist/interactions/actions/defaults/anchorJoin.js +92 -0
  564. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -0
  565. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  566. package/dist/interactions/actions/defaults/bendSegment.js +46 -0
  567. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -0
  568. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  569. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  570. package/dist/interactions/actions/defaults/copySubtree.js +1 -1
  571. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  572. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  573. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  574. package/dist/interactions/actions/defaults/duplicate.js +36 -21
  575. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  576. package/dist/interactions/actions/defaults/enterPathEdit.js +19 -7
  577. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  578. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  579. package/dist/interactions/actions/defaults/group.js +35 -40
  580. package/dist/interactions/actions/defaults/group.js.map +1 -1
  581. package/dist/interactions/actions/defaults/icons/anchorIcons.js +75 -0
  582. package/dist/interactions/actions/defaults/icons/anchorIcons.js.map +1 -0
  583. package/dist/interactions/actions/defaults/icons/booleanIcons.js +24 -1
  584. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -1
  585. package/dist/interactions/actions/defaults/icons/editIcons.js +35 -8
  586. package/dist/interactions/actions/defaults/icons/editIcons.js.map +1 -1
  587. package/dist/interactions/actions/defaults/icons/outlineIcons.js +39 -1
  588. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -1
  589. package/dist/interactions/actions/defaults/ingest.js +19 -15
  590. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  591. package/dist/interactions/actions/defaults/insertPathAnchor.js +18 -34
  592. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  593. package/dist/interactions/actions/defaults/nudge.js +43 -39
  594. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  595. package/dist/interactions/actions/defaults/pinchZoom.js +29 -29
  596. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  597. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  598. package/dist/interactions/actions/defaults/segmentUnder.js +22 -0
  599. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -0
  600. package/dist/interactions/actions/defaults/setFill.js +9 -3
  601. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  602. package/dist/interactions/actions/defaults/setFillOpacity.js +4 -1
  603. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  604. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  605. package/dist/interactions/actions/defaults/sliceOps.js +20 -22
  606. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  607. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  608. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  609. package/dist/interactions/actions/defaults/viewportDragPan.js +1 -1
  610. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  611. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  612. package/dist/interactions/actions/defaults/viewportZoom.js +82 -79
  613. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  614. package/dist/interactions/actions/{defaults/distribute.js → distribute/action.js} +18 -19
  615. package/dist/interactions/actions/distribute/action.js.map +1 -0
  616. package/dist/interactions/actions/distribute/distribute.js +15 -15
  617. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  618. package/dist/interactions/actions/edit-anchors/action.js +101 -0
  619. package/dist/interactions/actions/edit-anchors/action.js.map +1 -0
  620. package/dist/interactions/actions/edit-anchors/geometry.js +2 -4
  621. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  622. package/dist/interactions/actions/edit-anchors/preview.js +26 -0
  623. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -0
  624. package/dist/interactions/actions/edit-anchors/symmetry.js +11 -0
  625. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -0
  626. package/dist/interactions/actions/flip/action.js +124 -0
  627. package/dist/interactions/actions/flip/action.js.map +1 -0
  628. package/dist/interactions/actions/flip/helpers.js +1 -1
  629. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  630. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  631. package/dist/interactions/actions/gestureFrames.js +18 -0
  632. package/dist/interactions/actions/gestureFrames.js.map +1 -0
  633. package/dist/interactions/actions/gestureLifecycle.js +47 -20
  634. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  635. package/dist/interactions/actions/insert/action.js +79 -0
  636. package/dist/interactions/actions/insert/action.js.map +1 -0
  637. package/dist/interactions/actions/insert/commit.js +28 -0
  638. package/dist/interactions/actions/insert/commit.js.map +1 -0
  639. package/dist/interactions/actions/insert/extras.js +65 -0
  640. package/dist/interactions/actions/insert/extras.js.map +1 -0
  641. package/dist/interactions/actions/insert/frame.js +55 -0
  642. package/dist/interactions/actions/insert/frame.js.map +1 -0
  643. package/dist/interactions/actions/insert/geometry.js +35 -0
  644. package/dist/interactions/actions/insert/geometry.js.map +1 -0
  645. package/dist/interactions/actions/insert/repositionAction.js +31 -0
  646. package/dist/interactions/actions/insert/repositionAction.js.map +1 -0
  647. package/dist/interactions/actions/insert/rotateAction.js +21 -0
  648. package/dist/interactions/actions/insert/rotateAction.js.map +1 -0
  649. package/dist/interactions/actions/insert/session.js +59 -0
  650. package/dist/interactions/actions/insert/session.js.map +1 -0
  651. package/dist/interactions/actions/insert/shape.js +34 -0
  652. package/dist/interactions/actions/insert/shape.js.map +1 -0
  653. package/dist/interactions/actions/lasso-select/action.js +143 -0
  654. package/dist/interactions/actions/lasso-select/action.js.map +1 -0
  655. package/dist/interactions/actions/move/action.js +91 -0
  656. package/dist/interactions/actions/move/action.js.map +1 -0
  657. package/dist/interactions/actions/move/behaviors/layoutDrop.js +51 -0
  658. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -0
  659. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +15 -0
  660. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -0
  661. package/dist/interactions/actions/move/behaviors/snapToContainer.js +35 -28
  662. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  663. package/dist/interactions/actions/move/capture.js +108 -0
  664. package/dist/interactions/actions/move/capture.js.map +1 -0
  665. package/dist/interactions/actions/move/commit/index.js +41 -0
  666. package/dist/interactions/actions/move/commit/index.js.map +1 -0
  667. package/dist/interactions/actions/move/commit/layoutDrop.js +44 -0
  668. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -0
  669. package/dist/interactions/actions/move/commit/layoutRelease.js +100 -0
  670. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -0
  671. package/dist/interactions/actions/move/commit/rebase.js +18 -0
  672. package/dist/interactions/actions/move/commit/rebase.js.map +1 -0
  673. package/dist/interactions/actions/move/commit/reparent.js +65 -0
  674. package/dist/interactions/actions/move/commit/reparent.js.map +1 -0
  675. package/dist/interactions/actions/move/delta.js +51 -0
  676. package/dist/interactions/actions/move/delta.js.map +1 -0
  677. package/dist/interactions/actions/move/frame.js +47 -0
  678. package/dist/interactions/actions/move/frame.js.map +1 -0
  679. package/dist/interactions/actions/move/gestureAdapter.js +15 -40
  680. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  681. package/dist/interactions/actions/move/landedDescendants.js +8 -8
  682. package/dist/interactions/actions/move/layout/container.js +94 -0
  683. package/dist/interactions/actions/move/layout/container.js.map +1 -0
  684. package/dist/interactions/actions/move/layout/dragged.js +58 -0
  685. package/dist/interactions/actions/move/layout/dragged.js.map +1 -0
  686. package/dist/interactions/actions/move/layout/dropPass.js +122 -0
  687. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -0
  688. package/dist/interactions/actions/move/layout/exits.js +38 -0
  689. package/dist/interactions/actions/move/layout/exits.js.map +1 -0
  690. package/dist/interactions/actions/move/layout/glide.js +48 -0
  691. package/dist/interactions/actions/move/layout/glide.js.map +1 -0
  692. package/dist/interactions/actions/move/session.js +63 -0
  693. package/dist/interactions/actions/move/session.js.map +1 -0
  694. package/dist/interactions/actions/move/translate.js +61 -0
  695. package/dist/interactions/actions/move/translate.js.map +1 -0
  696. package/dist/interactions/actions/outlines/createOutlines.js +17 -64
  697. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  698. package/dist/interactions/actions/outlines/createOutlinesAction.js +51 -0
  699. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -0
  700. package/dist/interactions/actions/outlines/outlineStroke.js +72 -0
  701. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -0
  702. package/dist/interactions/actions/outlines/outlineStrokeAction.js +37 -0
  703. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -0
  704. package/dist/interactions/actions/outlines/replaceWithPaths.js +54 -0
  705. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -0
  706. package/dist/interactions/actions/outlines/strokeRegion.js +27 -0
  707. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -0
  708. package/dist/interactions/actions/pathCommands/cutJoin.js +102 -0
  709. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -0
  710. package/dist/interactions/actions/pathCommands/livePathEdit.js +64 -0
  711. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -0
  712. package/dist/interactions/actions/pathCommands/pathNodes.js +99 -0
  713. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -0
  714. package/dist/interactions/actions/pathCommands/simplifyOffset.js +42 -0
  715. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -0
  716. package/dist/interactions/actions/planeInput.js.map +1 -1
  717. package/dist/interactions/actions/pointerState.js +12 -0
  718. package/dist/interactions/actions/pointerState.js.map +1 -0
  719. package/dist/interactions/actions/poseDescriptorDep.js +1 -1
  720. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  721. package/dist/interactions/actions/poseFrame.js +26 -26
  722. package/dist/interactions/actions/poseFrame.js.map +1 -1
  723. package/dist/interactions/actions/resize/action.js +66 -0
  724. package/dist/interactions/actions/resize/action.js.map +1 -0
  725. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -1
  726. package/dist/interactions/actions/resize/boxFrame.js +16 -0
  727. package/dist/interactions/actions/resize/boxFrame.js.map +1 -0
  728. package/dist/interactions/actions/resize/capture.js +85 -0
  729. package/dist/interactions/actions/resize/capture.js.map +1 -0
  730. package/dist/interactions/actions/resize/commit.js +69 -0
  731. package/dist/interactions/actions/resize/commit.js.map +1 -0
  732. package/dist/interactions/actions/resize/frame.js +88 -0
  733. package/dist/interactions/actions/resize/frame.js.map +1 -0
  734. package/dist/interactions/actions/resize/pointSnap.js +111 -0
  735. package/dist/interactions/actions/resize/pointSnap.js.map +1 -0
  736. package/dist/interactions/actions/resize/replay.js +47 -0
  737. package/dist/interactions/actions/resize/replay.js.map +1 -0
  738. package/dist/interactions/actions/resize/ruleBounds.js +9 -0
  739. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -0
  740. package/dist/interactions/actions/resize/session.js +63 -0
  741. package/dist/interactions/actions/resize/session.js.map +1 -0
  742. package/dist/interactions/actions/resolveOverlays.js +2 -1
  743. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  744. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  745. package/dist/interactions/actions/rotate/action.js +71 -0
  746. package/dist/interactions/actions/rotate/action.js.map +1 -0
  747. package/dist/interactions/actions/rotate/behaviors/index.js +7 -0
  748. package/dist/interactions/actions/rotate/behaviors/index.js.map +1 -0
  749. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +12 -0
  750. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +1 -0
  751. package/dist/interactions/actions/rotate/commit.js +40 -0
  752. package/dist/interactions/actions/rotate/commit.js.map +1 -0
  753. package/dist/interactions/actions/rotate/frame.js +65 -0
  754. package/dist/interactions/actions/rotate/frame.js.map +1 -0
  755. package/dist/interactions/actions/rotate/handle.js +12 -12
  756. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  757. package/dist/interactions/actions/rotate/replay.js +22 -0
  758. package/dist/interactions/actions/rotate/replay.js.map +1 -0
  759. package/dist/interactions/actions/rotate/session.js +102 -0
  760. package/dist/interactions/actions/rotate/session.js.map +1 -0
  761. package/dist/interactions/actions/spatialReference.js.map +1 -1
  762. package/dist/interactions/actions/transform-again/action.js +63 -0
  763. package/dist/interactions/actions/transform-again/action.js.map +1 -0
  764. package/dist/interactions/actions/transform-again/memory.js +35 -0
  765. package/dist/interactions/actions/transform-again/memory.js.map +1 -0
  766. package/dist/interactions/actions/useStandardActions.js +84 -61
  767. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  768. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +61 -42
  769. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  770. package/dist/interactions/gestures/shared/originProjection.js +1 -1
  771. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  772. package/dist/interactions/gestures/shared/screenTolerance.js +8 -2
  773. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  774. package/dist/interactions/gestures/shared/snap.js.map +1 -1
  775. package/dist/math-CYUjoyyU.d.ts +33 -0
  776. package/dist/math.d.ts +5 -2
  777. package/dist/math.js +6 -6
  778. package/dist/mesh.d.ts +4 -268
  779. package/dist/mesh.js +3 -7
  780. package/dist/move.d.ts +6 -4
  781. package/dist/{originProjection-gHnOup4e.d.ts → originProjection-CoNVpITV.d.ts} +1 -1
  782. package/dist/patterns-builtin.d.ts +1 -118
  783. package/dist/patterns-builtin.js +2 -3
  784. package/dist/poseDescriptor-Bqk-11Rl.d.ts +73 -0
  785. package/dist/renderer.d.ts +1 -92
  786. package/dist/renderer.js +2 -19
  787. package/dist/resize.d.ts +11 -22
  788. package/dist/resize.js +1 -1
  789. package/dist/style.css +1 -1
  790. package/dist/test-hook/install.js.map +1 -1
  791. package/dist/test-hook/useTestHook.js +22 -0
  792. package/dist/test-hook/useTestHook.js.map +1 -0
  793. package/dist/test-seams-D0pyV3pR.d.ts +149 -0
  794. package/dist/test-seams.d.ts +4 -4
  795. package/dist/test-seams.js +2 -2
  796. package/dist/tools/builtin/bone/boneActions.js +130 -0
  797. package/dist/tools/builtin/bone/boneActions.js.map +1 -0
  798. package/dist/tools/builtin/bone/boneOverlay.js +58 -0
  799. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -0
  800. package/dist/tools/builtin/bone/placedRig.js +24 -0
  801. package/dist/tools/builtin/bone/placedRig.js.map +1 -0
  802. package/dist/tools/builtin/bone/rigEditState.js +21 -0
  803. package/dist/tools/builtin/bone/rigEditState.js.map +1 -0
  804. package/dist/tools/builtin/bone/useBoneTool.js +98 -0
  805. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -0
  806. package/dist/tools/builtin/ellipse/useEllipseTool.js +16 -15
  807. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  808. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  809. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  810. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  811. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  812. package/dist/tools/builtin/line/useLineTool.js +16 -15
  813. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  814. package/dist/tools/builtin/pen/usePenTool.js +162 -164
  815. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  816. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  817. package/dist/tools/builtin/pickTopMostHit.js +11 -14
  818. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  819. package/dist/tools/builtin/polygon/usePolygonTool.js +17 -15
  820. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  821. package/dist/tools/builtin/rect/useRectTool.js +15 -14
  822. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  823. package/dist/tools/builtin/select/adapterPointQuery.js +40 -0
  824. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -0
  825. package/dist/tools/builtin/select/selectionContributions.js +5 -5
  826. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  827. package/dist/tools/builtin/select/useSelectTool.js +44 -71
  828. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  829. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  830. package/dist/tools/builtin/slice/useSliceTool.js +69 -72
  831. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  832. package/dist/tools/builtin/star/useStarTool.js +18 -16
  833. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  834. package/dist/tools/builtin/text/useTextTool.js +10 -2
  835. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  836. package/dist/tools/builtin/weight/useWeightTool.js +77 -0
  837. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -0
  838. package/dist/tools/builtin/weight/weightActions.js +112 -0
  839. package/dist/tools/builtin/weight/weightActions.js.map +1 -0
  840. package/dist/tools/builtin/weight/weightOverlay.js +61 -0
  841. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -0
  842. package/dist/tools/overlayBinding.js.map +1 -1
  843. package/dist/tools/useKeybindings.js +20 -14
  844. package/dist/tools/useKeybindings.js.map +1 -1
  845. package/dist/{types-k-5Oqh-U.d.ts → types-DBbbCy0i.d.ts} +103 -176
  846. package/dist/util/paint.js +1 -1
  847. package/dist/util/paint.js.map +1 -1
  848. package/dist/version.js +1 -1
  849. package/package.json +26 -21
  850. package/dist/animation/colorHelpers.js +0 -135
  851. package/dist/animation/colorHelpers.js.map +0 -1
  852. package/dist/animation/colorRegistry.js +0 -37
  853. package/dist/animation/colorRegistry.js.map +0 -1
  854. package/dist/animation/engine/axes.js +0 -36
  855. package/dist/animation/engine/axes.js.map +0 -1
  856. package/dist/animation/engine/codec.js +0 -170
  857. package/dist/animation/engine/codec.js.map +0 -1
  858. package/dist/animation/engine/integrator.js +0 -12
  859. package/dist/animation/engine/integrator.js.map +0 -1
  860. package/dist/animation/loop.js +0 -60
  861. package/dist/animation/loop.js.map +0 -1
  862. package/dist/animation/observe.js +0 -23
  863. package/dist/animation/observe.js.map +0 -1
  864. package/dist/animation/rig/blendPoses.js +0 -43
  865. package/dist/animation/rig/blendPoses.js.map +0 -1
  866. package/dist/animation/rig/mirrorPose.js +0 -19
  867. package/dist/animation/rig/mirrorPose.js.map +0 -1
  868. package/dist/animation/rig/resolveSkeleton.js +0 -33
  869. package/dist/animation/rig/resolveSkeleton.js.map +0 -1
  870. package/dist/animation/rig/solveIk.js +0 -103
  871. package/dist/animation/rig/solveIk.js.map +0 -1
  872. package/dist/animation/rig/types.js +0 -12
  873. package/dist/animation/rig/types.js.map +0 -1
  874. package/dist/animation/slew.js +0 -27
  875. package/dist/animation/slew.js.map +0 -1
  876. package/dist/animation/stagger.js +0 -146
  877. package/dist/animation/stagger.js.map +0 -1
  878. package/dist/animation/timeline/booking.js +0 -114
  879. package/dist/animation/timeline/booking.js.map +0 -1
  880. package/dist/animation/timeline/createTimeline.js +0 -125
  881. package/dist/animation/timeline/createTimeline.js.map +0 -1
  882. package/dist/animation/timeline/sampleTrack.js +0 -79
  883. package/dist/animation/timeline/sampleTrack.js.map +0 -1
  884. package/dist/animation/useAnimator.js +0 -388
  885. package/dist/animation/useAnimator.js.map +0 -1
  886. package/dist/autoPoseDescriptor-Ct7yqivU.d.ts +0 -108
  887. package/dist/builtins-DPcdghtB.d.ts +0 -1223
  888. package/dist/canvas/MinimapCanvas.js +0 -140
  889. package/dist/canvas/MinimapCanvas.js.map +0 -1
  890. package/dist/canvas/deps/poseComposition.js +0 -11
  891. package/dist/canvas/deps/poseComposition.js.map +0 -1
  892. package/dist/canvas/minimapMath.js +0 -82
  893. package/dist/canvas/minimapMath.js.map +0 -1
  894. package/dist/canvas/toolPreview.js +0 -39
  895. package/dist/canvas/toolPreview.js.map +0 -1
  896. package/dist/core/adapters/arrayAdapter.js +0 -94
  897. package/dist/core/adapters/arrayAdapter.js.map +0 -1
  898. package/dist/core/adapters/useArrayAdapter.js +0 -13
  899. package/dist/core/adapters/useArrayAdapter.js.map +0 -1
  900. package/dist/core/fillInPoseFrame.js +0 -102
  901. package/dist/core/fillInPoseFrame.js.map +0 -1
  902. package/dist/core/geometry/poseFrame.js +0 -44
  903. package/dist/core/geometry/poseFrame.js.map +0 -1
  904. package/dist/core/geometry/poseRotation.js +0 -58
  905. package/dist/core/geometry/poseRotation.js.map +0 -1
  906. package/dist/core/gradient.js +0 -136
  907. package/dist/core/gradient.js.map +0 -1
  908. package/dist/core/markerInset.js +0 -24
  909. package/dist/core/markerInset.js.map +0 -1
  910. package/dist/core/mixed.js +0 -6
  911. package/dist/core/mixed.js.map +0 -1
  912. package/dist/core/paintKinds.js +0 -156
  913. package/dist/core/paintKinds.js.map +0 -1
  914. package/dist/core/scene/pickability.js +0 -6
  915. package/dist/core/scene/pickability.js.map +0 -1
  916. package/dist/core/strokeMarkerShapes.js +0 -139
  917. package/dist/core/strokeMarkerShapes.js.map +0 -1
  918. package/dist/core/strokeMarkers.js +0 -28
  919. package/dist/core/strokeMarkers.js.map +0 -1
  920. package/dist/core/viewport/meanScale.js +0 -8
  921. package/dist/core/viewport/meanScale.js.map +0 -1
  922. package/dist/core/viewport/pxExtent.js +0 -42
  923. package/dist/core/viewport/pxExtent.js.map +0 -1
  924. package/dist/features/cursor/paintedCursorLayer.js.map +0 -1
  925. package/dist/features/focus/gateLayer.js.map +0 -1
  926. package/dist/features/focus/useCanvasFocus.js +0 -29
  927. package/dist/features/focus/useCanvasFocus.js.map +0 -1
  928. package/dist/features/groups/children.js.map +0 -1
  929. package/dist/features/groups/composePose.js +0 -67
  930. package/dist/features/groups/composePose.js.map +0 -1
  931. package/dist/features/groups/nestedHit.js.map +0 -1
  932. package/dist/features/groups/unionOfChildren.js.map +0 -1
  933. package/dist/features/images/imageCache.js +0 -104
  934. package/dist/features/images/imageCache.js.map +0 -1
  935. package/dist/features/ingestion/index.js +0 -8
  936. package/dist/features/meshPaint/bake.js +0 -79
  937. package/dist/features/meshPaint/bake.js.map +0 -1
  938. package/dist/features/meshPaint/bakeCache.js +0 -59
  939. package/dist/features/meshPaint/bakeCache.js.map +0 -1
  940. package/dist/features/meshPaint/handles.js +0 -86
  941. package/dist/features/meshPaint/handles.js.map +0 -1
  942. package/dist/features/meshPaint/lazyKind.js.map +0 -1
  943. package/dist/features/meshPaint/meshPaint.js +0 -239
  944. package/dist/features/meshPaint/meshPaint.js.map +0 -1
  945. package/dist/features/meshPaint/meshShader.js +0 -6
  946. package/dist/features/meshPaint/meshShader.js.map +0 -1
  947. package/dist/features/meshPaint/register.js +0 -7
  948. package/dist/features/meshPaint/register.js.map +0 -1
  949. package/dist/features/meshPaint/surface.js +0 -110
  950. package/dist/features/meshPaint/surface.js.map +0 -1
  951. package/dist/features/minimap/actions.js +0 -53
  952. package/dist/features/minimap/actions.js.map +0 -1
  953. package/dist/features/minimap/createMinimapContribution.js +0 -96
  954. package/dist/features/minimap/createMinimapContribution.js.map +0 -1
  955. package/dist/features/minimap/layers.js +0 -85
  956. package/dist/features/minimap/layers.js.map +0 -1
  957. package/dist/features/overlays/useNodeOverlayFrame.js +0 -103
  958. package/dist/features/overlays/useNodeOverlayFrame.js.map +0 -1
  959. package/dist/features/parallax/createParallaxLayer.js +0 -26
  960. package/dist/features/parallax/createParallaxLayer.js.map +0 -1
  961. package/dist/features/parallax/createParallaxPlane.js +0 -22
  962. package/dist/features/parallax/createParallaxPlane.js.map +0 -1
  963. package/dist/features/paths/anchorEdits.js +0 -167
  964. package/dist/features/paths/anchorEdits.js.map +0 -1
  965. package/dist/features/paths/anchors.js +0 -159
  966. package/dist/features/paths/anchors.js.map +0 -1
  967. package/dist/features/paths/booleans.js +0 -2
  968. package/dist/features/paths/markerCommands.js +0 -149
  969. package/dist/features/paths/markerCommands.js.map +0 -1
  970. package/dist/features/paths/markerSites.js +0 -59
  971. package/dist/features/paths/markerSites.js.map +0 -1
  972. package/dist/features/paths/markers.js +0 -95
  973. package/dist/features/paths/markers.js.map +0 -1
  974. package/dist/features/paths/nearestAnchor.js +0 -36
  975. package/dist/features/paths/nearestAnchor.js.map +0 -1
  976. package/dist/features/paths/pathInWorld.js +0 -41
  977. package/dist/features/paths/pathInWorld.js.map +0 -1
  978. package/dist/features/paths/poseDescriptor.js +0 -39
  979. package/dist/features/paths/poseDescriptor.js.map +0 -1
  980. package/dist/features/paths/strokeToPath.js +0 -40
  981. package/dist/features/paths/strokeToPath.js.map +0 -1
  982. package/dist/features/paths/tessellate/dash.js +0 -52
  983. package/dist/features/paths/tessellate/dash.js.map +0 -1
  984. package/dist/features/paths/tessellate/insets.js +0 -32
  985. package/dist/features/paths/tessellate/insets.js.map +0 -1
  986. package/dist/features/paths/tessellate/metric.js +0 -72
  987. package/dist/features/paths/tessellate/metric.js.map +0 -1
  988. package/dist/features/paths/tessellate/stroke.js +0 -170
  989. package/dist/features/paths/tessellate/stroke.js.map +0 -1
  990. package/dist/features/paths/tessellate/vertexWidths.js +0 -32
  991. package/dist/features/paths/tessellate/vertexWidths.js.map +0 -1
  992. package/dist/features/patterns/commandPaint.js +0 -18
  993. package/dist/features/patterns/commandPaint.js.map +0 -1
  994. package/dist/features/patterns/index.js +0 -11
  995. package/dist/features/patterns/index.js.map +0 -1
  996. package/dist/features/patterns/patterns-builtin.js +0 -38
  997. package/dist/features/patterns/patterns-builtin.js.map +0 -1
  998. package/dist/features/patterns/rasterizeTile.js +0 -17
  999. package/dist/features/patterns/rasterizeTile.js.map +0 -1
  1000. package/dist/features/patterns/resolveSpec.js +0 -65
  1001. package/dist/features/patterns/resolveSpec.js.map +0 -1
  1002. package/dist/features/patterns/tileGeometry.js +0 -158
  1003. package/dist/features/patterns/tileGeometry.js.map +0 -1
  1004. package/dist/features/pointer/PointerContext.js +0 -45
  1005. package/dist/features/pointer/PointerContext.js.map +0 -1
  1006. package/dist/features/selection/SelectionContext.js +0 -51
  1007. package/dist/features/selection/SelectionContext.js.map +0 -1
  1008. package/dist/features/simulation/createSimulation.js +0 -61
  1009. package/dist/features/simulation/createSimulation.js.map +0 -1
  1010. package/dist/features/simulation/types.js +0 -6
  1011. package/dist/features/simulation/types.js.map +0 -1
  1012. package/dist/features/simulation/useSimulation.js +0 -74
  1013. package/dist/features/simulation/useSimulation.js.map +0 -1
  1014. package/dist/features/text/domOffsets.js +0 -82
  1015. package/dist/features/text/domOffsets.js.map +0 -1
  1016. package/dist/features/text/domRuns.js +0 -230
  1017. package/dist/features/text/domRuns.js.map +0 -1
  1018. package/dist/features/text/fitTextPose.js +0 -38
  1019. package/dist/features/text/fitTextPose.js.map +0 -1
  1020. package/dist/features/text/hitTest.js +0 -48
  1021. package/dist/features/text/hitTest.js.map +0 -1
  1022. package/dist/features/text/isTextData.js +0 -8
  1023. package/dist/features/text/isTextData.js.map +0 -1
  1024. package/dist/features/text/overlayDirection.js +0 -15
  1025. package/dist/features/text/overlayDirection.js.map +0 -1
  1026. package/dist/features/text/renderLabel.js +0 -14
  1027. package/dist/features/text/renderLabel.js.map +0 -1
  1028. package/dist/features/text/runs/effectiveRangeStyle.js +0 -66
  1029. package/dist/features/text/runs/effectiveRangeStyle.js.map +0 -1
  1030. package/dist/features/text/runs/flagRange.js +0 -53
  1031. package/dist/features/text/runs/flagRange.js.map +0 -1
  1032. package/dist/features/text/runs/rangeStyle.js +0 -133
  1033. package/dist/features/text/runs/rangeStyle.js.map +0 -1
  1034. package/dist/features/text/textCommand.js +0 -60
  1035. package/dist/features/text/textCommand.js.map +0 -1
  1036. package/dist/features/text/textToPath.js +0 -181
  1037. package/dist/features/text/textToPath.js.map +0 -1
  1038. package/dist/features/text/useTextEdit.js +0 -491
  1039. package/dist/features/text/useTextEdit.js.map +0 -1
  1040. package/dist/features/tiling/createTiledLayer.js +0 -65
  1041. package/dist/features/tiling/createTiledLayer.js.map +0 -1
  1042. package/dist/features/tiling/tiledProject.js +0 -14
  1043. package/dist/features/tiling/tiledProject.js.map +0 -1
  1044. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +0 -26
  1045. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +0 -1
  1046. package/dist/interactions/actions/defaults/align.js.map +0 -1
  1047. package/dist/interactions/actions/defaults/booleans.js +0 -52
  1048. package/dist/interactions/actions/defaults/booleans.js.map +0 -1
  1049. package/dist/interactions/actions/defaults/clipboard.js.map +0 -1
  1050. package/dist/interactions/actions/defaults/clone.js +0 -91
  1051. package/dist/interactions/actions/defaults/clone.js.map +0 -1
  1052. package/dist/interactions/actions/defaults/createOutlines.js +0 -47
  1053. package/dist/interactions/actions/defaults/createOutlines.js.map +0 -1
  1054. package/dist/interactions/actions/defaults/distribute.js.map +0 -1
  1055. package/dist/interactions/actions/defaults/editAnchors.js +0 -100
  1056. package/dist/interactions/actions/defaults/editAnchors.js.map +0 -1
  1057. package/dist/interactions/actions/defaults/flip.js +0 -125
  1058. package/dist/interactions/actions/defaults/flip.js.map +0 -1
  1059. package/dist/interactions/actions/defaults/insert.js +0 -287
  1060. package/dist/interactions/actions/defaults/insert.js.map +0 -1
  1061. package/dist/interactions/actions/defaults/lassoSelect.js +0 -153
  1062. package/dist/interactions/actions/defaults/lassoSelect.js.map +0 -1
  1063. package/dist/interactions/actions/defaults/move.js +0 -778
  1064. package/dist/interactions/actions/defaults/move.js.map +0 -1
  1065. package/dist/interactions/actions/defaults/resize.js +0 -341
  1066. package/dist/interactions/actions/defaults/resize.js.map +0 -1
  1067. package/dist/interactions/actions/defaults/rotate.js +0 -185
  1068. package/dist/interactions/actions/defaults/rotate.js.map +0 -1
  1069. package/dist/interactions/actions/previewOverrides.js +0 -25
  1070. package/dist/interactions/actions/previewOverrides.js.map +0 -1
  1071. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +0 -1
  1072. package/dist/layout/arrivals.js +0 -36
  1073. package/dist/layout/arrivals.js.map +0 -1
  1074. package/dist/math-J-ACHyEg.d.ts +0 -159
  1075. package/dist/registerProgram-T9S_PfAX.d.ts +0 -208
  1076. package/dist/renderer/DrawCommand.js +0 -6
  1077. package/dist/renderer/DrawCommand.js.map +0 -1
  1078. package/dist/renderer/WeaselRenderer.js +0 -333
  1079. package/dist/renderer/WeaselRenderer.js.map +0 -1
  1080. package/dist/renderer/batchClip.js +0 -46
  1081. package/dist/renderer/batchClip.js.map +0 -1
  1082. package/dist/renderer/cache/GLImageCache.js +0 -74
  1083. package/dist/renderer/cache/GLImageCache.js.map +0 -1
  1084. package/dist/renderer/cache/GLMeshCache.js +0 -102
  1085. package/dist/renderer/cache/GLMeshCache.js.map +0 -1
  1086. package/dist/renderer/cache/GLTextureCache.js +0 -68
  1087. package/dist/renderer/cache/GLTextureCache.js.map +0 -1
  1088. package/dist/renderer/cache/GradientRampAtlas.js +0 -82
  1089. package/dist/renderer/cache/GradientRampAtlas.js.map +0 -1
  1090. package/dist/renderer/cache/cache.js +0 -13
  1091. package/dist/renderer/cache/cache.js.map +0 -1
  1092. package/dist/renderer/cache/markerCommandCache.js +0 -63
  1093. package/dist/renderer/cache/markerCommandCache.js.map +0 -1
  1094. package/dist/renderer/cache/outlineMeshCache.js +0 -15
  1095. package/dist/renderer/cache/outlineMeshCache.js.map +0 -1
  1096. package/dist/renderer/cache/outlineStrokeMeshCache.js +0 -36
  1097. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +0 -1
  1098. package/dist/renderer/cache/strokeMeshCache.js +0 -55
  1099. package/dist/renderer/cache/strokeMeshCache.js.map +0 -1
  1100. package/dist/renderer/cullDrawCommands.js +0 -90
  1101. package/dist/renderer/cullDrawCommands.js.map +0 -1
  1102. package/dist/renderer/draw/batch.js +0 -133
  1103. package/dist/renderer/draw/batch.js.map +0 -1
  1104. package/dist/renderer/draw/clip.js +0 -89
  1105. package/dist/renderer/draw/clip.js.map +0 -1
  1106. package/dist/renderer/draw/customShader.js +0 -230
  1107. package/dist/renderer/draw/customShader.js.map +0 -1
  1108. package/dist/renderer/draw/drawTriangles.js +0 -8
  1109. package/dist/renderer/draw/drawTriangles.js.map +0 -1
  1110. package/dist/renderer/draw/effects.js +0 -28
  1111. package/dist/renderer/draw/effects.js.map +0 -1
  1112. package/dist/renderer/draw/flushBatch.js +0 -35
  1113. package/dist/renderer/draw/flushBatch.js.map +0 -1
  1114. package/dist/renderer/draw/gradient.js +0 -90
  1115. package/dist/renderer/draw/gradient.js.map +0 -1
  1116. package/dist/renderer/draw/image.js +0 -38
  1117. package/dist/renderer/draw/image.js.map +0 -1
  1118. package/dist/renderer/draw/mesh.js +0 -16
  1119. package/dist/renderer/draw/mesh.js.map +0 -1
  1120. package/dist/renderer/draw/paintBind.js +0 -70
  1121. package/dist/renderer/draw/paintBind.js.map +0 -1
  1122. package/dist/renderer/draw/pathPaint.js +0 -142
  1123. package/dist/renderer/draw/pathPaint.js.map +0 -1
  1124. package/dist/renderer/draw/scratchPass.js +0 -83
  1125. package/dist/renderer/draw/scratchPass.js.map +0 -1
  1126. package/dist/renderer/draw/stencil.js +0 -28
  1127. package/dist/renderer/draw/stencil.js.map +0 -1
  1128. package/dist/renderer/draw/text.js +0 -167
  1129. package/dist/renderer/draw/text.js.map +0 -1
  1130. package/dist/renderer/draw/uniforms.js +0 -77
  1131. package/dist/renderer/draw/uniforms.js.map +0 -1
  1132. package/dist/renderer/draw.js +0 -79
  1133. package/dist/renderer/draw.js.map +0 -1
  1134. package/dist/renderer/drawBatch.js +0 -198
  1135. package/dist/renderer/drawBatch.js.map +0 -1
  1136. package/dist/renderer/effects/EffectTargets.js +0 -48
  1137. package/dist/renderer/effects/EffectTargets.js.map +0 -1
  1138. package/dist/renderer/effects/builtins.js +0 -31
  1139. package/dist/renderer/effects/builtins.js.map +0 -1
  1140. package/dist/renderer/effects/composite.js +0 -11
  1141. package/dist/renderer/effects/composite.js.map +0 -1
  1142. package/dist/renderer/effects/effectPrelude.js +0 -10
  1143. package/dist/renderer/effects/effectPrelude.js.map +0 -1
  1144. package/dist/renderer/effects/types.js +0 -10
  1145. package/dist/renderer/effects/types.js.map +0 -1
  1146. package/dist/renderer/glyphOutlineMesh.js +0 -67
  1147. package/dist/renderer/glyphOutlineMesh.js.map +0 -1
  1148. package/dist/renderer/index.js +0 -20
  1149. package/dist/renderer/math/color.js +0 -321
  1150. package/dist/renderer/math/color.js.map +0 -1
  1151. package/dist/renderer/math/mat3.js +0 -80
  1152. package/dist/renderer/math/mat3.js.map +0 -1
  1153. package/dist/renderer/math/patternSpace.js +0 -22
  1154. package/dist/renderer/math/patternSpace.js.map +0 -1
  1155. package/dist/renderer/math/viewToMat3.js +0 -19
  1156. package/dist/renderer/math/viewToMat3.js.map +0 -1
  1157. package/dist/renderer/paintResources.js +0 -18
  1158. package/dist/renderer/paintResources.js.map +0 -1
  1159. package/dist/renderer/paintScratch.js +0 -37
  1160. package/dist/renderer/paintScratch.js.map +0 -1
  1161. package/dist/renderer/shaders/ShaderProgram.js +0 -74
  1162. package/dist/renderer/shaders/ShaderProgram.js.map +0 -1
  1163. package/dist/renderer/shaders/batchFill.js +0 -119
  1164. package/dist/renderer/shaders/batchFill.js.map +0 -1
  1165. package/dist/renderer/shaders/customPrelude.js +0 -34
  1166. package/dist/renderer/shaders/customPrelude.js.map +0 -1
  1167. package/dist/renderer/shaders/extractUniformNames.js +0 -184
  1168. package/dist/renderer/shaders/extractUniformNames.js.map +0 -1
  1169. package/dist/renderer/shaders/glyphPaint.js +0 -61
  1170. package/dist/renderer/shaders/glyphPaint.js.map +0 -1
  1171. package/dist/renderer/shaders/gradFill.js +0 -31
  1172. package/dist/renderer/shaders/gradFill.js.map +0 -1
  1173. package/dist/renderer/shaders/pathFill.js +0 -14
  1174. package/dist/renderer/shaders/pathFill.js.map +0 -1
  1175. package/dist/renderer/shaders/patternFill.js +0 -25
  1176. package/dist/renderer/shaders/patternFill.js.map +0 -1
  1177. package/dist/renderer/shaders/registerProgram.js +0 -18
  1178. package/dist/renderer/shaders/registerProgram.js.map +0 -1
  1179. package/dist/renderer/spriteSheet.js +0 -14
  1180. package/dist/renderer/spriteSheet.js.map +0 -1
  1181. package/dist/renderer/state/GroupState.js +0 -77
  1182. package/dist/renderer/state/GroupState.js.map +0 -1
  1183. package/dist/renderer/strokeLengths.js +0 -50
  1184. package/dist/renderer/strokeLengths.js.map +0 -1
  1185. package/dist/renderer/syntheticItalic.js +0 -6
  1186. package/dist/renderer/syntheticItalic.js.map +0 -1
  1187. package/dist/renderer/textures/registerTexture.js +0 -34
  1188. package/dist/renderer/textures/registerTexture.js.map +0 -1
  1189. package/dist/scheduling/useVisibleRaf.js +0 -69
  1190. package/dist/scheduling/useVisibleRaf.js.map +0 -1
  1191. package/dist/test-seams-DM2B87-g.d.ts +0 -356
@@ -1 +1 @@
1
- {"version":3,"file":"usePenTool.js","names":["p","PenIcon","freshScratch","resetScratch","anchorCount","s","n","sp","buildPath","all","subpaths","trailing","anchorsToPath","usePenTool","options","scratchRef","useRef","optsRef","useLatest","forceRender","useReducer","x","commitContinuation","useCallback","edit","deps","cont","drawn","added","addedClosed","pathToAnchors","reverseAnchors","set","next","samePath","asNodeId","commit","open","allClosed","path","id","boundsOfPath","joinable","hit","scene","commitJoin","current","other","otherSet","tail","joined","joint","out","sameNode","rest","i","label","ops","keptId","built","createDeleteOp","applyOps","defaultCommitAdapter","pickUpEndpoint","scratch","radius","scale","viewScale","nearestPathAnchor","pathsNear","wx","wy","h","original","picked","reversed","snap","fn","placeAt","y","withinCloseRadius","withinPxRadius","ax","ay","trail","useMemo","view","follower","createPointerFollower","track","at","first","actions","p","params","join","ActionDisabledReason","origin","ctx","pickedUp","joinHit","linked","applyOutHandle","sm","moveCtx","se","reason","endCtx","defineTool","cursorFor","createElement","anchor","to","target","dx","dy","shift","c","constrainTo45","area","e","pxExtent","px","ids","a","b"],"sources":["../../../../src/tools/builtin/pen/usePenTool.ts"],"sourcesContent":["import { useCallback, useMemo, useReducer, useRef, createElement } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { PrefGroup } from '@weasel-js/prefs';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { Action } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { ActionDeps, InvocationCtx } from '@weasel-js/routing';\nimport { asNodeId } from 'core/scene/types';\nimport { pxExtent, withinPxRadius } from 'core/viewport/pxExtent';\nimport { PenIcon } from '../../../icons';\nimport { boundsOfPath, type PolygonPath } from '@weasel-js/geom';\nimport { anchorsToPath, pathToAnchors } from 'features/paths/anchors';\nimport { nearestPathAnchor, reverseAnchors, type PathAnchorHit } from 'features/paths/nearestAnchor';\nimport type { Op } from 'core/ops/types';\nimport { createDeleteOp } from 'core/ops/delete';\nimport { defaultCommitAdapter } from 'interactions/actions/defaultCommitAdapter';\nimport { constrainTo45 } from '../../../util/constrainTo45';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { createPointerFollower } from '../shared/pointerFollower';\n\n/**\n * In-progress pen anchor. A click places a corner, with no handles. A drag\n * sets `outHandle` to the drag point and `inHandle` to its mirror through\n * the anchor, which shapes the segment coming into it.\n */\nexport interface PenAnchor {\n x: number;\n y: number;\n outHandle?: { x: number; y: number };\n inHandle?: { x: number; y: number };\n /** True once Alt is held during the placement drag: from then on the\n * in-handle stays where it is, and an anchor dragged with Alt down from\n * the start gets none. */\n altBroken?: boolean;\n}\n\n/** One in-progress subpath of the pen tool: its anchors so far, and whether\n * the user has closed it. */\nexport interface PenSubpath {\n anchors: PenAnchor[]; // LOCAL PenAnchor — in-progress\n closed: boolean;\n}\n\n/**\n * Mutable scratch shared across pen-tool gestures. The hook keeps a stable\n * reference to a single instance and `initScratch` returns it on every call,\n * so click-by-click state survives gesture boundaries and the preview layer\n * can read the same object.\n *\n * ## The pen draws paths; it does not reshape them\n *\n * It draws new nodes, and extends an existing node's open subpath from one\n * of its ends (see `continuing`). Reshaping an existing path is anchor\n * editing: double-click a path to\n * enter edit mode, then use the `editAnchors` / `insertPathAnchor` /\n * `nudgeAnchors` / `deleteAnchors` / `marqueeAnchors` / `cutPathAtAnchor`\n * Actions.\n *\n * The pen used to carry a second, private implementation of all of that,\n * with its own scratch mode, hit-test override, overlay, and undo\n * plumbing. It was reachable only through a `getPathObj` option whose\n * contract required `pose.kind` to be `'polygon'` or `'rect'` — which no\n * kit-created node has, including the ones the pen itself creates. So it\n * was dead in every consumer while shadowing the live implementation, and\n * the two had drifted. Its geometry now lives in\n * `features/paths/anchorEdits.ts`, driven by those Actions.\n */\nexport interface PenScratch {\n finishedSubpaths: PenSubpath[];\n current: PenSubpath | null;\n cursor: { x: number; y: number } | null;\n draggingHandleAt: number | null;\n closeHintActive: boolean;\n /** Set while the pen is extending an existing node's open subpath rather\n * than drawing a new node. `current` then starts as that subpath (turned\n * around when it was picked up by its first anchor), and the commit\n * writes back into the node. */\n continuing: PenContinuation | null;\n}\n\n/** Which existing subpath the pen picked up, and the node's path as it was. */\nexport interface PenContinuation {\n id: string;\n /** Index of the picked-up subpath within `original`. */\n sub: number;\n /** True when it was picked up by its first anchor, so `current` runs\n * backwards and is turned around again on commit. */\n reversed: boolean;\n /** The node's path in world coords at pick-up. */\n original: PolygonPath;\n}\n\n/** Options for `usePenTool`: when a closed subpath commits, and how anchors\n * snap. A finished path is inserted through the `insert` dep as kind\n * `'path'`, the route every shape tool takes, so a consumer shapes the node\n * by overriding that dep. */\nexport interface UsePenToolOptions {\n /** Auto-select the new object after commit. Default `true`. */\n autoSelect?: boolean;\n /** When true (default), clicking the first anchor to close a subpath\n * commits immediately — the closed region renders with its fill right\n * away. When false, the closed subpath stays in scratch so the user can\n * start another subpath; commit then fires on Enter / ⌘-click /\n * double-click, producing a compound path. Switching tools first discards\n * it, as Escape does. */\n autoCommitOnClose?: boolean;\n /** Screen-px hit radius for \"click first anchor to close\". Default `8`.\n * Measured as a screen-space circle, so it stays round under non-uniform\n * zoom; aligns with `useSelectTool.handleHitRadius`. */\n closeHitRadius?: number;\n /** Screen-px radius within which a placed anchor lands exactly on an\n * existing path's anchor. Default `8`; `0` turns it off. Takes precedence\n * over `snapPoint`, which applies only when no anchor is in range. */\n anchorSnapRadius?: number;\n /** Optional point snapper applied to every world-space coordinate the\n * pen records or previews — anchor positions (corner clicks, smooth-\n * drag base point), the rubber-band cursor, and the outgoing-handle\n * target. Receives raw world coords; returns snapped world coords.\n * Wire to `gridSnapStrategy`-style spacing via the consumer:\n *\n * snapPoint: (p) => ({\n * x: Math.round(p.x / SPACING) * SPACING,\n * y: Math.round(p.y / SPACING) * SPACING,\n * })\n *\n * Pen state (anchor handles, etc.) is computed AFTER snapping so the\n * visible geometry stays grid-aligned. */\n snapPoint?: (p: { x: number; y: number }) => { x: number; y: number };\n}\n\nfunction freshScratch(): PenScratch {\n return {\n finishedSubpaths: [],\n current: null,\n cursor: null,\n draggingHandleAt: null,\n closeHintActive: false,\n continuing: null,\n };\n}\n\nfunction resetScratch(s: PenScratch): void {\n s.finishedSubpaths = [];\n s.current = null;\n s.cursor = null;\n s.draggingHandleAt = null;\n s.closeHintActive = false;\n s.continuing = null;\n}\n\n/** Total anchors across finished subpaths plus the in-progress one. */\nfunction anchorCount(s: PenScratch): number {\n return (s.current ? s.current.anchors.length : 0)\n + s.finishedSubpaths.reduce((n, sp) => n + sp.anchors.length, 0);\n}\n\n/** Build a PolygonPath from the pen's accumulated subpaths, by the same\n * rule as any anchor set: segment A→B is a cubic through A's out-handle and\n * B's in-handle when either exists, else a line. */\nfunction buildPath(\n subpaths: PenSubpath[],\n trailing: PenSubpath | null,\n): PolygonPath {\n const all = [...subpaths];\n if (trailing && trailing.anchors.length > 0) all.push(trailing);\n return anchorsToPath(all.map((sp) => sp.anchors), all.map((sp) => sp.closed));\n}\n\n/**\n * Active-slot Tool: click + drag to build a `PolygonPath` Illustrator-style.\n *\n * State machine: Idle / Drawing / BetweenSubpaths (see design doc).\n * Click places a corner anchor; click-drag places an anchor with an\n * outgoing bezier handle; click-the-first-anchor closes the subpath; Enter\n * open-finishes; Esc discards, and so does a tool switch. Shift constrains the placement-drag handle to 0/45/90/135°;\n * Alt during drag breaks the handle mirror for the next segment.\n *\n * Reshaping an existing path is not this tool's job — see {@link PenScratch}.\n */\nexport function usePenTool(\n options: UsePenToolOptions = {},\n): Tool<PenScratch> {\n const { autoSelect = true, autoCommitOnClose = true, closeHitRadius = 8, anchorSnapRadius = 8, snapPoint } = options;\n\n // Persistent scratch: single ref reused across gestures so multi-click\n // state survives the dispatcher's per-gesture initScratch contract.\n const scratchRef = useRef<PenScratch | null>(null);\n if (scratchRef.current === null) scratchRef.current = freshScratch();\n\n // Latest options stashed so handlers see fresh values without rebuilding\n // the Tool record (which would lose scratch identity in the dispatcher).\n const optsRef = useLatest({ autoSelect, autoCommitOnClose, closeHitRadius, anchorSnapRadius, snapPoint });\n\n // Scratch is a mutable ref (so click-by-click state survives the\n // dispatcher's per-gesture initScratch contract). Mutations alone don't\n // trigger React re-renders, so Canvas never re-paints and the preview\n // layer stays invisible until something else (e.g. commit) bumps host\n // state. Force a render after every scratch mutation so the host's\n // <Canvas layers={{...}}> literal gets a new identity and the paint\n // useEffect fires. Pull the trigger via ref so the memoized Tool record\n // doesn't need to rebuild.\n const [, forceRender] = useReducer((x: number) => x + 1, 0);\n\n // Geometry helpers shared by the actions below. They read `optsRef` so a\n // re-render with new options is visible without rebuilding the actions\n // (which would lose the scratch identity `penPreviewLayer` reads through\n // `Tool.initScratch`).\n\n /** Write the pen's subpaths back into the node it picked up: the first\n * replaces the subpath it continued, any later ones are appended. Skips\n * the write when nothing changed, so an empty pick-up leaves no undo\n * entry. */\n const commitContinuation = useCallback(\n (s: PenScratch, trailing: PenSubpath | null, deps: ActionDeps): void => {\n const edit = deps.editAnchors;\n const cont = s.continuing!;\n const drawn = [...s.finishedSubpaths, ...(trailing ? [trailing] : [])];\n if (!edit || drawn.length === 0) return;\n const { anchors: added, closed: addedClosed } = pathToAnchors(buildPath(drawn, null));\n if (cont.reversed) added[0] = reverseAnchors(added[0]);\n const set = pathToAnchors(cont.original);\n set.anchors.splice(cont.sub, 1, added[0]);\n set.closed.splice(cont.sub, 1, addedClosed[0]);\n set.anchors.push(...added.slice(1));\n set.closed.push(...addedClosed.slice(1));\n const next: PolygonPath = { ...anchorsToPath(set.anchors, set.closed), fillRule: cont.original.fillRule };\n if (samePath(next, cont.original)) return;\n edit.applyEdit(cont.id, next, 'Continue path');\n if (optsRef.current.autoSelect) deps.selection?.set([asNodeId(cont.id)]);\n },\n [optsRef],\n );\n\n const commit = useCallback((s: PenScratch, deps: ActionDeps): void => {\n const trailing = s.current && s.current.anchors.length > 0 ? s.current : null;\n if (s.continuing) {\n commitContinuation(s, trailing, deps);\n resetScratch(s);\n return;\n }\n // One anchor draws nothing; committing it would leave an invisible node.\n const open = trailing && trailing.anchors.length >= 2 ? trailing : null;\n if (s.finishedSubpaths.length === 0 && !open) {\n resetScratch(s);\n return;\n }\n const allClosed =\n s.finishedSubpaths.every((sp) => sp.closed) &&\n (open === null || open.closed);\n const path = buildPath(s.finishedSubpaths, open);\n const id = deps.insert?.commit(boundsOfPath(path), { kind: 'path', path, closed: allClosed }) ?? null;\n if (id !== null && optsRef.current.autoSelect) deps.selection?.set([id]);\n resetScratch(s);\n }, [commitContinuation, optsRef]);\n\n /** Whether an anchor about to land on `hit` finishes the path by joining\n * onto another open subpath. Its own continued subpath never counts —\n * reaching that one's far end is a close. Declines when the deps can't\n * commit the join as one op batch. */\n const joinable = useCallback((s: PenScratch, deps: ActionDeps, hit: PathAnchorHit | null): hit is PathAnchorHit => {\n if (!hit || hit.end === null || !s.current || s.current.anchors.length === 0) return false;\n const cont = s.continuing;\n if (cont && hit.id === cont.id && hit.sub === cont.sub) return false;\n const scene = deps.scene;\n if (!scene && !deps.applyOps) return false;\n if (!(cont ? deps.editAnchors?.editOps : deps.insert?.build)) return false;\n return cont?.id === hit.id || scene?.get(hit.id as never) !== undefined;\n }, []);\n\n /** Finish the path onto `hit`, the endpoint its last anchor was just placed\n * on: the other subpath's anchors follow on from it, turned around when\n * `hit` is its last anchor, and its node is deleted. The path being drawn\n * keeps its identity — a continued node keeps its id and style, and a new\n * path is minted the way any pen path is. One op batch, so one undo. */\n const commitJoin = useCallback((s: PenScratch, deps: ActionDeps, hit: PathAnchorHit): void => {\n const edit = deps.editAnchors!;\n const scene = deps.scene;\n const current = s.current!;\n const { anchors: added, closed: addedClosed } = pathToAnchors(buildPath([...s.finishedSubpaths, current], null));\n\n const other = edit.getEditablePath(hit.id) as PolygonPath;\n const otherSet = pathToAnchors(other);\n const tail = hit.end === 'last' ? reverseAnchors(otherSet.anchors[hit.sub]) : otherSet.anchors[hit.sub];\n const joined = added[added.length - 1];\n const joint = joined[joined.length - 1];\n const out = current.anchors[current.anchors.length - 1].outHandle ?? tail[0].outHandle;\n if (out) joint.outHandle = { ...out };\n joined.push(...tail.slice(1));\n\n const cont = s.continuing;\n const sameNode = cont?.id === hit.id;\n const rest = sameNode ? { anchors: [], closed: [] } : {\n anchors: otherSet.anchors.filter((_, i) => i !== hit.sub),\n closed: otherSet.closed.filter((_, i) => i !== hit.sub),\n };\n const label = 'Join paths';\n const ops: Op[] = [];\n let keptId: string;\n if (cont) {\n if (cont.reversed) added[0] = reverseAnchors(added[0]);\n const set = pathToAnchors(cont.original);\n set.anchors.splice(cont.sub, 1, added[0]);\n set.closed.splice(cont.sub, 1, addedClosed[0]);\n set.anchors.push(...added.slice(1), ...rest.anchors);\n set.closed.push(...addedClosed.slice(1), ...rest.closed);\n if (sameNode) {\n set.anchors.splice(hit.sub, 1);\n set.closed.splice(hit.sub, 1);\n }\n const next: PolygonPath = { ...anchorsToPath(set.anchors, set.closed), fillRule: cont.original.fillRule };\n ops.push(...edit.editOps!(cont.id, next, label));\n keptId = cont.id;\n } else {\n const path = anchorsToPath([...added, ...rest.anchors], [...addedClosed, ...rest.closed]);\n const built = deps.insert!.build!(boundsOfPath(path), { kind: 'path', path, closed: false });\n if (built === null) return;\n ops.push(...built.ops);\n keptId = built.id;\n }\n if (!sameNode) ops.push(createDeleteOp({ node: scene!.get(hit.id as never) as { id: string } }));\n\n const applyOps = deps.applyOps;\n if (applyOps) applyOps(ops, label);\n else scene!.applyBatch(ops, label, defaultCommitAdapter(scene!));\n if (optsRef.current.autoSelect) deps.selection?.set([asNodeId(keptId)]);\n resetScratch(s);\n }, [optsRef]);\n\n /** From idle, a press on an open subpath's end anchor picks that subpath\n * up: it becomes `current`, turned so the pressed end is last. Returns\n * whether it did. */\n const pickUpEndpoint = useCallback((deps: ActionDeps, wx: number, wy: number): boolean => {\n const scratch = scratchRef.current!;\n if (scratch.current || scratch.finishedSubpaths.length > 0) return false;\n const radius = optsRef.current.closeHitRadius;\n const scale = viewScale(deps);\n const hit = nearestPathAnchor(pathsNear(deps, wx, wy, radius), { x: wx, y: wy }, radius, scale, (h) => h.end !== null);\n if (!hit) return false;\n const original = deps.editAnchors!.getEditablePath(hit.id) as PolygonPath;\n const picked = pathToAnchors(original).anchors[hit.sub];\n const reversed = hit.end === 'first' && picked.length > 1;\n scratch.current = { anchors: reversed ? reverseAnchors(picked) : picked, closed: false };\n scratch.continuing = { id: hit.id, sub: hit.sub, reversed, original };\n return true;\n }, [optsRef]);\n\n const snap = useCallback((x: number, y: number): { x: number; y: number } => {\n const fn = optsRef.current.snapPoint;\n return fn ? fn({ x, y }) : { x, y };\n }, [optsRef]);\n\n /** Where an anchor pressed at `(x, y)` lands: on an existing path's anchor\n * when one is within `anchorSnapRadius`, else wherever `snapPoint` puts it.\n * `hit` names the anchor it snapped to. */\n const placeAt = useCallback((deps: ActionDeps, x: number, y: number): { x: number; y: number; hit: PathAnchorHit | null } => {\n const radius = optsRef.current.anchorSnapRadius;\n if (radius > 0) {\n const hit = nearestPathAnchor(pathsNear(deps, x, y, radius), { x, y }, radius, viewScale(deps));\n if (hit) return { x: hit.x, y: hit.y, hit };\n }\n return { ...snap(x, y), hit: null };\n }, [snap, optsRef]);\n\n /** Is a world point within the close-hit radius of `(ax, ay)`? Measured as a\n * screen-space circle, so the zone stays round under non-uniform zoom. */\n const withinCloseRadius = useCallback(\n (deps: ActionDeps, ax: number, ay: number, wx: number, wy: number): boolean => {\n return withinPxRadius(ax - wx, ay - wy, optsRef.current.closeHitRadius, viewScale(deps));\n },\n [optsRef],\n );\n\n // The rubber band and the close hint trail the `pointer` dep while a path is\n // in progress. `view` is the camera of the deps last followed through.\n const trail = useMemo(() => {\n let view: ActionDeps['view'];\n const follower = createPointerFollower(() => track());\n const track = (): void => {\n const s = scratchRef.current!;\n if (!s.current && s.finishedSubpaths.length === 0) follower.unfollow();\n const at = s.current ? follower.pointer()?.get() ?? null : null;\n s.cursor = at ? snap(at.worldX, at.worldY) : null;\n const first = s.current && s.current.anchors.length >= 3 ? s.current.anchors[0] : null;\n s.closeHintActive = first !== null && s.cursor !== null && withinPxRadius(\n first.x - s.cursor.x, first.y - s.cursor.y,\n optsRef.current.closeHitRadius, view?.get().scale ?? { x: 1, y: 1 },\n );\n forceRender();\n };\n return {\n /** Repaint after a scratch change. */\n refresh: track,\n /** The same, following `deps`' pointer from here on. */\n update(deps: ActionDeps): void {\n view = deps.view;\n follower.follow(deps.pointer);\n track();\n },\n stop(): void {\n follower.unfollow();\n forceRender();\n },\n };\n }, [snap, optsRef]);\n\n /**\n * Actions the pen owns, registered by `useToolActions` from inside the\n * ActionsProvider — see `ToolDef.actions`.\n *\n * They close over `scratchRef`, which is why the pen needs no `Selector`\n * exposing tool scratch to the action layer: the state never leaves the\n * hook. `useMemo([])` keeps their identity stable for the same reason\n * `scratchRef` is a ref — the preview layer reads that one object.\n */\n const actions = useMemo<Action[]>(() => {\n const s = () => scratchRef.current!;\n\n return [\n {\n id: 'pen.placeAnchor',\n label: 'Pen — place anchor',\n eligible: { capability: 'creates-paths' },\n requires: ['view', 'pointer', 'areaSelect', 'editAnchors', 'scene', 'applyOps', 'insert', 'selection'],\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const p = params as { pressX?: number; pressY?: number } | undefined;\n if (p?.pressX === undefined || p.pressY === undefined) return;\n // The press point, not the release: a click may drift up to the\n // drag threshold, and an anchor should land where you put the\n // pointer down. Snapping happens here rather than at press time\n // so the snapped value is what the geometry records.\n if (pickUpEndpoint(deps, p.pressX, p.pressY)) {\n trail.update(deps);\n return;\n }\n const { x: wx, y: wy, hit } = placeAt(deps, p.pressX, p.pressY);\n const scratch = s();\n\n // Close-on-first-anchor (>= 3 anchors). With `autoCommitOnClose`\n // on (default) this commits right away so the closed region\n // renders with its fill — Illustrator-style. With it off the\n // closed subpath stays in scratch for compound-path builds and\n // commits on Enter.\n if (scratch.current && scratch.current.anchors.length >= 3) {\n const first = scratch.current.anchors[0];\n if (withinCloseRadius(deps, first.x, first.y, wx, wy)) {\n scratch.current.closed = true;\n scratch.finishedSubpaths.push(scratch.current);\n scratch.current = null;\n scratch.closeHintActive = false;\n if (optsRef.current.autoCommitOnClose) commit(scratch, deps);\n trail.update(deps);\n return;\n }\n }\n\n const join = joinable(scratch, deps, hit);\n // Otherwise: append a corner anchor, starting a subpath if needed.\n if (!scratch.current) scratch.current = { anchors: [], closed: false };\n scratch.current.anchors.push({ x: wx, y: wy });\n if (join) commitJoin(scratch, deps, hit);\n trail.update(deps);\n },\n },\n },\n\n {\n id: 'pen.finishOpen',\n label: 'Pen — finish open path',\n eligible: { capability: 'creates-paths' },\n requires: ['editAnchors', 'insert', 'selection'],\n // Needs an actual path to commit. Declining also lets the gesture\n // fall through: a ⌘-click with fewer than two anchors reaches the\n // plain-click binding and places an anchor instead.\n enabled: () => (anchorCount(s()) >= 2 ? true : ActionDisabledReason.NotApplicable),\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const scratch = s();\n const p = params as { viaDoubleClick?: boolean } | undefined;\n\n // A double click arrives AFTER both of its clicks, so the second\n // one has already appended an anchor. Undo exactly that before\n // committing: pop it, and drop the subpath entirely if it was the\n // only anchor in it (which happens when the FIRST click closed a\n // subpath and the second started a fresh one). The net effect\n // matches the pen's old private 300ms detector — one anchor\n // placed, path finished — while using the dispatcher's single\n // definition of a double click.\n //\n // No position check is needed: the anchor to drop is by\n // construction the one the second click just appended.\n if (p?.viaDoubleClick && scratch.current) {\n scratch.current.anchors.pop();\n if (scratch.current.anchors.length === 0) scratch.current = null;\n }\n\n commit(scratch, deps);\n trail.refresh();\n },\n },\n },\n\n {\n id: 'pen.dragHandle',\n label: 'Pen — drag out a bezier handle',\n eligible: { capability: 'creates-paths' },\n requires: ['view', 'pointer', 'areaSelect', 'editAnchors', 'scene', 'applyOps', 'insert', 'selection'],\n invoker: {\n timing: 'ongoing' as const,\n start: (ctx: InvocationCtx) => {\n const scratch = s();\n // `drag.start` is the pointerdown position — the dispatcher\n // buffers the press and releases it at the drag threshold, so the\n // anchor lands where the user pressed rather than where the\n // threshold happened to be crossed.\n const origin = ctx.drag?.start ?? ctx.world;\n // Dragging from an open path's end picks the path up and pulls\n // that end's own handle rather than placing a new anchor on it.\n const pickedUp = pickUpEndpoint(ctx.deps, origin.x, origin.y);\n // Dragging on another open path's endpoint joins onto it once\n // the handle is set.\n let joinHit: PathAnchorHit | null = null;\n if (!pickedUp) {\n const { x: ax, y: ay, hit } = placeAt(ctx.deps, origin.x, origin.y);\n if (joinable(scratch, ctx.deps, hit)) joinHit = hit;\n if (!scratch.current) scratch.current = { anchors: [], closed: false };\n scratch.current.anchors.push({ x: ax, y: ay });\n }\n scratch.draggingHandleAt = scratch.current!.anchors.length - 1;\n if (ctx.modifiers.alt) {\n scratch.current!.anchors[scratch.draggingHandleAt].altBroken = true;\n }\n // A picked-up endpoint's in-handle belongs to the existing\n // segment into it, which the pen does not reshape.\n const linked = !pickedUp;\n applyOutHandle(scratch, ctx.world, ctx.modifiers.shift, linked, optsRef.current.snapPoint);\n trail.update(ctx.deps);\n\n return {\n onMove: (moveCtx: InvocationCtx) => {\n const sm = s();\n if (sm.draggingHandleAt === null) return;\n if (moveCtx.modifiers.alt && sm.current) {\n sm.current.anchors[sm.draggingHandleAt].altBroken = true;\n }\n applyOutHandle(sm, moveCtx.world, moveCtx.modifiers.shift, linked, optsRef.current.snapPoint);\n forceRender();\n },\n onEnd: (endCtx: InvocationCtx, reason: 'commit' | 'cancel') => {\n const se = s();\n if (reason === 'cancel') {\n // `start` appended the anchor (or picked a path up); a\n // cancel (pointercancel is the reachable one — Escape and a\n // tool switch both reset the whole scratch first) has to\n // take it back out.\n if (pickedUp) {\n resetScratch(se);\n } else if (se.current && se.draggingHandleAt === se.current.anchors.length - 1) {\n se.current.anchors.pop();\n if (se.current.anchors.length === 0) se.current = null;\n }\n se.draggingHandleAt = null;\n trail.refresh();\n return;\n }\n if (se.draggingHandleAt !== null) {\n if (endCtx.modifiers.alt && se.current) {\n se.current.anchors[se.draggingHandleAt].altBroken = true;\n }\n applyOutHandle(se, endCtx.world, endCtx.modifiers.shift, linked, optsRef.current.snapPoint);\n se.draggingHandleAt = null;\n }\n if (joinHit && se.current) commitJoin(se, ctx.deps, joinHit);\n trail.refresh();\n },\n };\n },\n },\n },\n\n {\n id: 'pen.finish',\n label: 'Pen — finish path',\n eligible: { capability: 'creates-paths' },\n requires: ['editAnchors', 'insert', 'selection'],\n enabled: () => (anchorCount(s()) > 0 ? true : ActionDisabledReason.NotApplicable),\n invoker: {\n timing: 'immediate' as const,\n run: (deps) => {\n commit(s(), deps);\n trail.refresh();\n },\n },\n },\n\n {\n id: 'pen.cancel',\n label: 'Pen — discard path',\n eligible: { capability: 'creates-paths' },\n // Declining with nothing drawn is what keeps Escape's first-match\n // ladder intact: an empty pen passes the key to `escape`, which goes\n // on to clear the selection / return to the default tool.\n enabled: () => {\n const scratch = s();\n return scratch.current !== null || scratch.finishedSubpaths.length > 0\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n invoker: {\n timing: 'immediate' as const,\n run: () => {\n resetScratch(s());\n trail.refresh();\n },\n },\n },\n ];\n }, [commit, placeAt, withinCloseRadius, pickUpEndpoint, joinable, commitJoin, optsRef, trail]);\n\n return useMemo(() => {\n return defineTool<PenScratch>({\n id: 'pen',\n keybinding: { key: 'P' },\n capabilities: ['creates-paths'],\n hookName: 'usePenTool',\n // Reads the tool's own ref rather than a scratch handed in by a\n // dispatcher — the pen owns this state and nothing else needs it.\n cursor: () =>\n scratchRef.current?.closeHintActive\n ? 'pointer'\n : cursorFor('pen', { fallback: 'crosshair' }),\n presentation: {\n label: 'Pen',\n icon: createElement(PenIcon),\n group: 'draw',\n },\n // Persistent-ref scratch. `penPreviewLayer` reads the in-progress path\n // by calling `Tool.initScratch()` and getting this same object back, so\n // the identity is load-bearing.\n initScratch: () => scratchRef.current!,\n actions,\n\n onDeactivate: () => {\n // Anything still in scratch is by definition incomplete — the user\n // hasn't closed it (close-on-first-anchor), open-finished it\n // (cmd-click), or pressed Enter. Switching tools mid-path should\n // discard, not auto-commit a stub polyline that the user didn't\n // ask for. Mirrors Escape's behavior so \"stop drawing\" is\n // consistent across exits.\n resetScratch(scratchRef.current!);\n trail.stop();\n },\n\n bindings: [\n // Plain click places an anchor; ⌘/Ctrl-click open-finishes\n // (Illustrator). Strict modifier matching keeps the two apart, and\n // `mod` resolves to meta on mac / ctrl elsewhere — the tool-route\n // grammar's modifier matcher accepted either key on either platform.\n { spec: { kind: 'click' as const, mods: { shift: 'optional' as const, alt: 'optional' as const } }, actionId: 'pen.placeAnchor' },\n { spec: { kind: 'click' as const, mods: { mod: true, shift: 'optional' as const, alt: 'optional' as const } }, actionId: 'pen.finishOpen' },\n // Double-click on the last anchor also open-finishes. This used to be\n // a private 300ms/radius check inside the click route — a fourth\n // double-click detector in a codebase that had just collapsed three\n // into one (audit 3.3).\n {\n spec: { kind: 'doubleClick' as const, mods: { shift: 'optional' as const, alt: 'optional' as const } },\n actionId: 'pen.finishOpen',\n opts: { params: { viaDoubleClick: true } },\n },\n { spec: { kind: 'drag' as const, mods: { shift: 'optional' as const, alt: 'optional' as const } }, actionId: 'pen.dragHandle' },\n { spec: { kind: 'key' as const, key: 'Enter' }, actionId: 'pen.finish' },\n { spec: { kind: 'key' as const, key: 'Escape' }, actionId: 'pen.cancel' },\n ],\n });\n }, [actions, trail]);\n}\n\nusePenTool.prefs = {\n name: 'Pen',\n description: 'Pen-tool behavior.',\n children: {\n autoCommitOnClose: {\n kind: 'boolean',\n name: 'Auto-commit pen on close',\n description: \"When you click the pen tool's first anchor to close a region, commit immediately so it renders with its fill. Off: keep the path in preview until you press Enter (lets you build a compound path from multiple closed subpaths).\",\n default: true,\n },\n },\n} satisfies PrefGroup;\n\n/** Point the anchor's outgoing handle at `target`, optionally snapped and\n * optionally constrained to 45° steps. When `linked` and not Alt-broken,\n * the in-handle follows as its mirror through the anchor. */\nfunction applyOutHandle<S extends PenScratch>(\n s: S,\n target: { x: number; y: number },\n shift: boolean,\n linked: boolean,\n snap?: (p: { x: number; y: number }) => { x: number; y: number },\n): void {\n if (s.current === null || s.draggingHandleAt === null) return;\n const anchor = s.current.anchors[s.draggingHandleAt];\n const to = snap ? snap(target) : target;\n let dx = to.x - anchor.x;\n let dy = to.y - anchor.y;\n if (shift) {\n const c = constrainTo45(dx, dy);\n dx = c.dx;\n dy = c.dy;\n }\n anchor.outHandle = { x: anchor.x + dx, y: anchor.y + dy };\n if (linked && !anchor.altBroken) anchor.inHandle = { x: anchor.x - dx, y: anchor.y - dy };\n}\n\nfunction viewScale(deps: ActionDeps): { x: number; y: number } {\n return deps.view?.get().scale ?? { x: 1, y: 1 };\n}\n\n/** Existing editable paths, world coords, with ink within `px` screen\n * pixels of `(wx, wy)` — front-to-back, as the area query returns them.\n * Empty when the host publishes no `areaSelect` or `editAnchors` dep. */\nfunction pathsNear(\n deps: ActionDeps,\n wx: number,\n wy: number,\n px: number,\n): Array<{ id: string; path: PolygonPath }> {\n const area = deps.areaSelect;\n const edit = deps.editAnchors;\n if (!area || !edit) return [];\n const view = deps.view;\n const e = pxExtent(px, viewScale(deps));\n const ids = area.hitTestArea({ x: wx - e.x, y: wy - e.y, width: 2 * e.x, height: 2 * e.y }, view);\n const out: Array<{ id: string; path: PolygonPath }> = [];\n for (const id of ids) {\n const path = edit.getEditablePath(id) as PolygonPath | null;\n if (path?.kind === 'polygon') out.push({ id, path });\n }\n return out;\n}\n\nfunction samePath(a: PolygonPath, b: PolygonPath): boolean {\n if (a.commands.length !== b.commands.length || a.coords.length !== b.coords.length) return false;\n for (let i = 0; i < a.commands.length; i++) if (a.commands[i] !== b.commands[i]) return false;\n for (let i = 0; i < a.coords.length; i++) if (a.coords[i] !== b.coords[i]) return false;\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"usePenTool.js","names":["p","PenIcon","freshScratch","resetScratch","anchorCount","s","n","sp","buildPath","all","subpaths","trailing","anchorsToPath","usePenTool","options","scratchRef","useRef","optsRef","useLatest","forceRender","useReducer","x","overlay","useState","createPenPreviewLayer","commitContinuation","useCallback","edit","deps","cont","drawn","added","addedClosed","pathToAnchors","reverseAnchors","next","editAnchorSetTracked","set","samePath","asNodeId","commit","open","allClosed","path","id","boundsOfPath","joinable","hit","scene","commitJoin","current","other","otherSet","tail","joined","joint","out","sameNode","rest","i","label","ops","keptId","built","createDeleteOp","applyOps","defaultCommitAdapter","pickUpEndpoint","scratch","radius","scale","viewScale","nearestPathAnchor","pathsNear","wx","wy","h","original","picked","reversed","snap","fn","placeAt","y","withinCloseRadius","withinPxRadius","ax","ay","trail","useMemo","view","follower","createPointerFollower","track","at","first","actions","p","params","join","ActionDisabledReason","origin","ctx","pickedUp","joinHit","linked","applyOutHandle","sm","moveCtx","se","reason","endCtx","defineTool","cursorFor","createElement","anchor","to","target","dx","dy","shift","c","constrainTo45","area","e","pxExtent","px","ids","a","b"],"sources":["../../../../src/tools/builtin/pen/usePenTool.ts"],"sourcesContent":["import { useCallback, useMemo, useReducer, useRef, useState, createElement } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { PrefGroup } from '@weasel-js/prefs';\nimport { defineTool } from '../../overlayBinding';\nimport type { Tool } from '../../overlayBinding';\nimport type { Action } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { ActionDeps, InvocationCtx } from '@weasel-js/routing';\nimport { asNodeId } from 'core/scene/types';\nimport { pxExtent, withinPxRadius, nearestPathAnchor, reverseAnchors, type PathAnchorHit } from '@weasel-js/geom';\nimport { PenIcon } from '../../../icons';\nimport { boundsOfPath, type PolygonPath, anchorsToPath, editAnchorSetTracked, pathToAnchors } from '@weasel-js/geom';\nimport { createPenPreviewLayer } from 'features/paths/penPreviewLayer';\nimport type { Op } from 'core/ops/types';\nimport { createDeleteOp } from 'core/ops/delete';\nimport { defaultCommitAdapter } from 'interactions/actions/defaultCommitAdapter';\nimport { constrainTo45 } from '../../../util/constrainTo45';\nimport { cursorFor } from '@weasel-js/cursor';\nimport { createPointerFollower } from '../shared/pointerFollower';\n\n/**\n * In-progress pen anchor. A click places a corner, with no handles. A drag\n * sets `outHandle` to the drag point and `inHandle` to its mirror through\n * the anchor, which shapes the segment coming into it.\n */\nexport interface PenAnchor {\n x: number;\n y: number;\n outHandle?: { x: number; y: number };\n inHandle?: { x: number; y: number };\n /** True once Alt is held during the placement drag: from then on the\n * in-handle stays where it is, and an anchor dragged with Alt down from\n * the start gets none. */\n altBroken?: boolean;\n}\n\n/** One in-progress subpath of the pen tool: its anchors so far, and whether\n * the user has closed it. */\nexport interface PenSubpath {\n anchors: PenAnchor[]; // LOCAL PenAnchor — in-progress\n closed: boolean;\n}\n\n/**\n * Mutable state shared across pen-tool gestures. The hook keeps a single\n * instance for its life and changes it in place, so click-by-click state\n * survives gesture boundaries and the tool's preview overlay reads the same\n * object.\n *\n * The pen draws new nodes, and extends an existing node's open subpath from\n * one of its ends (see `continuing`). Reshaping an existing path is anchor\n * editing: double-click a path to enter edit mode.\n */\nexport interface PenScratch {\n finishedSubpaths: PenSubpath[];\n current: PenSubpath | null;\n cursor: { x: number; y: number } | null;\n draggingHandleAt: number | null;\n closeHintActive: boolean;\n /** Set while the pen is extending an existing node's open subpath rather\n * than drawing a new node. `current` then starts as that subpath (turned\n * around when it was picked up by its first anchor), and the commit\n * writes back into the node. */\n continuing: PenContinuation | null;\n}\n\n/** Which existing subpath the pen picked up, and the node's path as it was. */\nexport interface PenContinuation {\n id: string;\n /** Index of the picked-up subpath within `original`. */\n sub: number;\n /** True when it was picked up by its first anchor, so `current` runs\n * backwards and is turned around again on commit. */\n reversed: boolean;\n /** The node's path in world coords at pick-up. */\n original: PolygonPath;\n}\n\n/** Options for `usePenTool`: when a closed subpath commits, and how anchors\n * snap. A finished path is inserted through the `insert` dep as kind\n * `'path'`, the route every shape tool takes, so a consumer shapes the node\n * by overriding that dep. */\nexport interface UsePenToolOptions {\n /** Auto-select the new object after commit. Default `true`. */\n autoSelect?: boolean;\n /** When true (default), clicking the first anchor to close a subpath\n * commits immediately — the closed region renders with its fill right\n * away. When false, the closed subpath stays in scratch so the user can\n * start another subpath; commit then fires on Enter / ⌘-click /\n * double-click, producing a compound path. Switching tools first discards\n * it, as Escape does. */\n autoCommitOnClose?: boolean;\n /** Screen-px hit radius for \"click first anchor to close\". Default `8`.\n * Measured as a screen-space circle, so it stays round under non-uniform\n * zoom; aligns with `useSelectTool.handleHitRadius`. */\n closeHitRadius?: number;\n /** Screen-px radius within which a placed anchor lands exactly on an\n * existing path's anchor. Default `8`; `0` turns it off. Takes precedence\n * over `snapPoint`, which applies only when no anchor is in range. */\n anchorSnapRadius?: number;\n /** Optional point snapper applied to every world-space coordinate the\n * pen records or previews — anchor positions (corner clicks, smooth-\n * drag base point), the rubber-band cursor, and the outgoing-handle\n * target. Receives raw world coords; returns snapped world coords.\n * Pen state (anchor handles, etc.) is computed AFTER snapping so the\n * visible geometry stays grid-aligned. */\n snapPoint?: (p: { x: number; y: number }) => { x: number; y: number };\n}\n\nfunction freshScratch(): PenScratch {\n return {\n finishedSubpaths: [],\n current: null,\n cursor: null,\n draggingHandleAt: null,\n closeHintActive: false,\n continuing: null,\n };\n}\n\nfunction resetScratch(s: PenScratch): void {\n s.finishedSubpaths = [];\n s.current = null;\n s.cursor = null;\n s.draggingHandleAt = null;\n s.closeHintActive = false;\n s.continuing = null;\n}\n\n/** Total anchors across finished subpaths plus the in-progress one. */\nfunction anchorCount(s: PenScratch): number {\n return (s.current ? s.current.anchors.length : 0)\n + s.finishedSubpaths.reduce((n, sp) => n + sp.anchors.length, 0);\n}\n\n/** Build a PolygonPath from the pen's accumulated subpaths, by the same\n * rule as any anchor set: segment A→B is a cubic through A's out-handle and\n * B's in-handle when either exists, else a line. */\nfunction buildPath(\n subpaths: PenSubpath[],\n trailing: PenSubpath | null,\n): PolygonPath {\n const all = [...subpaths];\n if (trailing && trailing.anchors.length > 0) all.push(trailing);\n return anchorsToPath(all.map((sp) => sp.anchors), all.map((sp) => sp.closed));\n}\n\n/**\n * Active-slot Tool: click + drag to build a `PolygonPath` Illustrator-style.\n *\n * Click places a corner anchor; click-drag places an anchor with an\n * outgoing bezier handle; click-the-first-anchor closes the subpath; Enter\n * open-finishes; Esc discards, and so does a tool switch. Shift constrains the placement-drag handle to 0/45/90/135°;\n * Alt during drag breaks the handle mirror for the next segment.\n *\n * Reshaping an existing path is not this tool's job — see {@link PenScratch}.\n */\nexport function usePenTool(\n options: UsePenToolOptions = {},\n): Tool {\n const { autoSelect = true, autoCommitOnClose = true, closeHitRadius = 8, anchorSnapRadius = 8, snapPoint } = options;\n\n const scratchRef = useRef<PenScratch | null>(null);\n if (scratchRef.current === null) scratchRef.current = freshScratch();\n\n // Latest options stashed so handlers see fresh values without rebuilding\n // the Tool record.\n const optsRef = useLatest({ autoSelect, autoCommitOnClose, closeHitRadius, anchorSnapRadius, snapPoint });\n\n // Scratch mutations alone don't trigger React re-renders, so the preview\n // layer would not repaint. Force a render after every scratch mutation.\n const [, forceRender] = useReducer((x: number) => x + 1, 0);\n const [overlay] = useState(() => createPenPreviewLayer({ state: scratchRef.current! }));\n\n /** Write the pen's subpaths back into the node it picked up: the first\n * replaces the subpath it continued, any later ones are appended. Skips\n * the write when nothing changed, so an empty pick-up leaves no undo\n * entry. */\n const commitContinuation = useCallback(\n (s: PenScratch, trailing: PenSubpath | null, deps: ActionDeps): void => {\n const edit = deps.editAnchors;\n const cont = s.continuing!;\n const drawn = [...s.finishedSubpaths, ...(trailing ? [trailing] : [])];\n if (!edit || drawn.length === 0) return;\n const { anchors: added, closed: addedClosed } = pathToAnchors(buildPath(drawn, null));\n if (cont.reversed) added[0] = reverseAnchors(added[0]);\n const next = editAnchorSetTracked(cont.original, (set) => {\n set.anchors.splice(cont.sub, 1, added[0]);\n set.closed.splice(cont.sub, 1, addedClosed[0]);\n set.anchors.push(...added.slice(1));\n set.closed.push(...addedClosed.slice(1));\n })!;\n if (samePath(next.path, cont.original)) return;\n edit.applyEdit(cont.id, next.path, 'Continue path', next.origins);\n if (optsRef.current.autoSelect) deps.selection?.set([asNodeId(cont.id)]);\n },\n [optsRef],\n );\n\n const commit = useCallback((s: PenScratch, deps: ActionDeps): void => {\n const trailing = s.current && s.current.anchors.length > 0 ? s.current : null;\n if (s.continuing) {\n commitContinuation(s, trailing, deps);\n resetScratch(s);\n return;\n }\n // One anchor draws nothing; committing it would leave an invisible node.\n const open = trailing && trailing.anchors.length >= 2 ? trailing : null;\n if (s.finishedSubpaths.length === 0 && !open) {\n resetScratch(s);\n return;\n }\n const allClosed =\n s.finishedSubpaths.every((sp) => sp.closed) &&\n (open === null || open.closed);\n const path = buildPath(s.finishedSubpaths, open);\n const id = deps.insert?.commit(boundsOfPath(path), { kind: 'path', path, closed: allClosed }) ?? null;\n if (id !== null && optsRef.current.autoSelect) deps.selection?.set([id]);\n resetScratch(s);\n }, [commitContinuation, optsRef]);\n\n /** Whether an anchor about to land on `hit` finishes the path by joining\n * onto another open subpath. Its own continued subpath never counts —\n * reaching that one's far end is a close. Declines when the deps can't\n * commit the join as one op batch. */\n const joinable = useCallback((s: PenScratch, deps: ActionDeps, hit: PathAnchorHit | null): hit is PathAnchorHit => {\n if (!hit || hit.end === null || !s.current || s.current.anchors.length === 0) return false;\n const cont = s.continuing;\n if (cont && hit.id === cont.id && hit.sub === cont.sub) return false;\n const scene = deps.scene;\n if (!scene && !deps.applyOps) return false;\n if (!(cont ? deps.editAnchors?.editOps : deps.insert?.build)) return false;\n return cont?.id === hit.id || scene?.get(hit.id as never) !== undefined;\n }, []);\n\n /** Finish the path onto `hit`, the endpoint its last anchor was just placed\n * on: the other subpath's anchors follow on from it, turned around when\n * `hit` is its last anchor, and its node is deleted. The path being drawn\n * keeps its identity — a continued node keeps its id and style, and a new\n * path is minted the way any pen path is. One op batch, so one undo. */\n const commitJoin = useCallback((s: PenScratch, deps: ActionDeps, hit: PathAnchorHit): void => {\n const edit = deps.editAnchors!;\n const scene = deps.scene;\n const current = s.current!;\n const { anchors: added, closed: addedClosed } = pathToAnchors(buildPath([...s.finishedSubpaths, current], null));\n\n const other = edit.getEditablePath(hit.id) as PolygonPath;\n const otherSet = pathToAnchors(other);\n const tail = hit.end === 'last' ? reverseAnchors(otherSet.anchors[hit.sub]) : otherSet.anchors[hit.sub];\n const joined = added[added.length - 1];\n const joint = joined[joined.length - 1];\n const out = current.anchors[current.anchors.length - 1].outHandle ?? tail[0].outHandle;\n if (out) joint.outHandle = { ...out };\n joined.push(...tail.slice(1));\n\n const cont = s.continuing;\n const sameNode = cont?.id === hit.id;\n const rest = sameNode ? { anchors: [], closed: [] } : {\n anchors: otherSet.anchors.filter((_, i) => i !== hit.sub),\n closed: otherSet.closed.filter((_, i) => i !== hit.sub),\n };\n const label = 'Join paths';\n const ops: Op[] = [];\n let keptId: string;\n if (cont) {\n if (cont.reversed) added[0] = reverseAnchors(added[0]);\n const next = editAnchorSetTracked(cont.original, (set) => {\n set.anchors.splice(cont.sub, 1, added[0]);\n set.closed.splice(cont.sub, 1, addedClosed[0]);\n set.anchors.push(...added.slice(1), ...rest.anchors);\n set.closed.push(...addedClosed.slice(1), ...rest.closed);\n if (!sameNode) return;\n set.anchors.splice(hit.sub, 1);\n set.closed.splice(hit.sub, 1);\n })!;\n ops.push(...edit.editOps!(cont.id, next.path, label, next.origins));\n keptId = cont.id;\n } else {\n const path = anchorsToPath([...added, ...rest.anchors], [...addedClosed, ...rest.closed]);\n const built = deps.insert!.build!(boundsOfPath(path), { kind: 'path', path, closed: false });\n if (built === null) return;\n ops.push(...built.ops);\n keptId = built.id;\n }\n if (!sameNode) ops.push(createDeleteOp({ node: scene!.get(hit.id as never) as { id: string } }));\n\n const applyOps = deps.applyOps;\n if (applyOps) applyOps(ops, label);\n else scene!.applyBatch(ops, label, defaultCommitAdapter(scene!));\n if (optsRef.current.autoSelect) deps.selection?.set([asNodeId(keptId)]);\n resetScratch(s);\n }, [optsRef]);\n\n /** From idle, a press on an open subpath's end anchor picks that subpath\n * up: it becomes `current`, turned so the pressed end is last. Returns\n * whether it did. */\n const pickUpEndpoint = useCallback((deps: ActionDeps, wx: number, wy: number): boolean => {\n const scratch = scratchRef.current!;\n if (scratch.current || scratch.finishedSubpaths.length > 0) return false;\n const radius = optsRef.current.closeHitRadius;\n const scale = viewScale(deps);\n const hit = nearestPathAnchor(pathsNear(deps, wx, wy, radius), { x: wx, y: wy }, radius, scale, (h) => h.end !== null);\n if (!hit) return false;\n const original = deps.editAnchors!.getEditablePath(hit.id) as PolygonPath;\n const picked = pathToAnchors(original).anchors[hit.sub];\n const reversed = hit.end === 'first' && picked.length > 1;\n scratch.current = { anchors: reversed ? reverseAnchors(picked) : picked, closed: false };\n scratch.continuing = { id: hit.id, sub: hit.sub, reversed, original };\n return true;\n }, [optsRef]);\n\n const snap = useCallback((x: number, y: number): { x: number; y: number } => {\n const fn = optsRef.current.snapPoint;\n return fn ? fn({ x, y }) : { x, y };\n }, [optsRef]);\n\n /** Where an anchor pressed at `(x, y)` lands: on an existing path's anchor\n * when one is within `anchorSnapRadius`, else wherever `snapPoint` puts it.\n * `hit` names the anchor it snapped to. */\n const placeAt = useCallback((deps: ActionDeps, x: number, y: number): { x: number; y: number; hit: PathAnchorHit | null } => {\n const radius = optsRef.current.anchorSnapRadius;\n if (radius > 0) {\n const hit = nearestPathAnchor(pathsNear(deps, x, y, radius), { x, y }, radius, viewScale(deps));\n if (hit) return { x: hit.x, y: hit.y, hit };\n }\n return { ...snap(x, y), hit: null };\n }, [snap, optsRef]);\n\n /** Is a world point within the close-hit radius of `(ax, ay)`? Measured as a\n * screen-space circle, so the zone stays round under non-uniform zoom. */\n const withinCloseRadius = useCallback(\n (deps: ActionDeps, ax: number, ay: number, wx: number, wy: number): boolean => {\n return withinPxRadius(ax - wx, ay - wy, optsRef.current.closeHitRadius, viewScale(deps));\n },\n [optsRef],\n );\n\n // The rubber band and the close hint trail the `pointer` dep while a path is\n // in progress. `view` is the camera of the deps last followed through.\n const trail = useMemo(() => {\n let view: ActionDeps['view'];\n const follower = createPointerFollower(() => track());\n const track = (): void => {\n const s = scratchRef.current!;\n if (!s.current && s.finishedSubpaths.length === 0) follower.unfollow();\n const at = s.current ? follower.pointer()?.get() ?? null : null;\n s.cursor = at ? snap(at.worldX, at.worldY) : null;\n const first = s.current && s.current.anchors.length >= 3 ? s.current.anchors[0] : null;\n s.closeHintActive = first !== null && s.cursor !== null && withinPxRadius(\n first.x - s.cursor.x, first.y - s.cursor.y,\n optsRef.current.closeHitRadius, view?.get().scale ?? { x: 1, y: 1 },\n );\n forceRender();\n };\n return {\n /** Repaint after a scratch change. */\n refresh: track,\n /** The same, following `deps`' pointer from here on. */\n update(deps: ActionDeps): void {\n view = deps.view; // eslint-disable-line react-hooks/immutability -- the trail's own camera, read by `track`\n follower.follow(deps.pointer);\n track();\n },\n stop(): void {\n follower.unfollow();\n forceRender();\n },\n };\n }, [snap, optsRef]);\n\n /**\n * Actions the pen owns, registered by `useToolActions` from inside the\n * ActionsProvider — see `ToolDef.actions`. They close over `scratchRef`,\n * so the state never leaves the hook.\n */\n const actions = useMemo<Action[]>(() => {\n const s = () => scratchRef.current!;\n\n return [\n {\n id: 'pen.placeAnchor',\n label: 'Pen — place anchor',\n eligible: { capability: 'creates-paths' },\n requires: ['view', 'pointer', 'areaSelect', 'editAnchors', 'scene', 'applyOps', 'insert', 'selection'],\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const p = params as { pressX?: number; pressY?: number } | undefined;\n if (p?.pressX === undefined || p.pressY === undefined) return;\n // The press point, not the release: a click may drift up to the\n // drag threshold.\n if (pickUpEndpoint(deps, p.pressX, p.pressY)) {\n trail.update(deps);\n return;\n }\n const { x: wx, y: wy, hit } = placeAt(deps, p.pressX, p.pressY);\n const scratch = s();\n\n // Close-on-first-anchor (>= 3 anchors). With `autoCommitOnClose`\n // off the closed subpath stays in scratch for compound-path builds.\n if (scratch.current && scratch.current.anchors.length >= 3) {\n const first = scratch.current.anchors[0];\n if (withinCloseRadius(deps, first.x, first.y, wx, wy)) {\n scratch.current.closed = true;\n scratch.finishedSubpaths.push(scratch.current);\n scratch.current = null;\n scratch.closeHintActive = false;\n if (optsRef.current.autoCommitOnClose) commit(scratch, deps);\n trail.update(deps);\n return;\n }\n }\n\n const join = joinable(scratch, deps, hit);\n // Otherwise: append a corner anchor, starting a subpath if needed.\n if (!scratch.current) scratch.current = { anchors: [], closed: false };\n scratch.current.anchors.push({ x: wx, y: wy });\n if (join) commitJoin(scratch, deps, hit);\n trail.update(deps);\n },\n },\n },\n\n {\n id: 'pen.finishOpen',\n label: 'Pen — finish open path',\n eligible: { capability: 'creates-paths' },\n requires: ['editAnchors', 'insert', 'selection'],\n // Needs an actual path to commit. Declining also lets the gesture\n // fall through: a ⌘-click with fewer than two anchors reaches the\n // plain-click binding and places an anchor instead.\n enabled: () => (anchorCount(s()) >= 2 ? true : ActionDisabledReason.NotApplicable),\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const scratch = s();\n const p = params as { viaDoubleClick?: boolean } | undefined;\n\n // A double click arrives AFTER both of its clicks, so the second\n // one has already appended an anchor. Undo exactly that before\n // committing: pop it, and drop the subpath entirely if it was the\n // only anchor in it (which happens when the FIRST click closed a\n // subpath and the second started a fresh one).\n if (p?.viaDoubleClick && scratch.current) {\n scratch.current.anchors.pop();\n if (scratch.current.anchors.length === 0) scratch.current = null;\n }\n\n commit(scratch, deps);\n trail.refresh();\n },\n },\n },\n\n {\n id: 'pen.dragHandle',\n label: 'Pen — drag out a bezier handle',\n eligible: { capability: 'creates-paths' },\n requires: ['view', 'pointer', 'areaSelect', 'editAnchors', 'scene', 'applyOps', 'insert', 'selection'],\n invoker: {\n timing: 'ongoing' as const,\n start: (ctx: InvocationCtx) => {\n const scratch = s();\n // `drag.start` is the pointerdown position, so the anchor lands\n // where the user pressed rather than where the drag threshold\n // happened to be crossed.\n const origin = ctx.drag?.start ?? ctx.world;\n // Dragging from an open path's end picks the path up and pulls\n // that end's own handle rather than placing a new anchor on it.\n const pickedUp = pickUpEndpoint(ctx.deps, origin.x, origin.y);\n // Dragging on another open path's endpoint joins onto it once\n // the handle is set.\n let joinHit: PathAnchorHit | null = null;\n if (!pickedUp) {\n const { x: ax, y: ay, hit } = placeAt(ctx.deps, origin.x, origin.y);\n if (joinable(scratch, ctx.deps, hit)) joinHit = hit;\n if (!scratch.current) scratch.current = { anchors: [], closed: false };\n scratch.current.anchors.push({ x: ax, y: ay });\n }\n scratch.draggingHandleAt = scratch.current!.anchors.length - 1;\n if (ctx.modifiers.alt) {\n scratch.current!.anchors[scratch.draggingHandleAt].altBroken = true;\n }\n // A picked-up endpoint's in-handle belongs to the existing\n // segment into it, which the pen does not reshape.\n const linked = !pickedUp;\n applyOutHandle(scratch, ctx.world, ctx.modifiers.shift, linked, optsRef.current.snapPoint);\n trail.update(ctx.deps);\n\n return {\n onMove: (moveCtx: InvocationCtx) => {\n const sm = s();\n if (sm.draggingHandleAt === null) return;\n if (moveCtx.modifiers.alt && sm.current) {\n sm.current.anchors[sm.draggingHandleAt].altBroken = true;\n }\n applyOutHandle(sm, moveCtx.world, moveCtx.modifiers.shift, linked, optsRef.current.snapPoint);\n forceRender();\n },\n onEnd: (endCtx: InvocationCtx, reason: 'commit' | 'cancel') => {\n const se = s();\n if (reason === 'cancel') {\n // `start` appended the anchor (or picked a path up); a\n // cancel has to take it back out.\n if (pickedUp) {\n resetScratch(se);\n } else if (se.current && se.draggingHandleAt === se.current.anchors.length - 1) {\n se.current.anchors.pop();\n if (se.current.anchors.length === 0) se.current = null;\n }\n se.draggingHandleAt = null;\n trail.refresh();\n return;\n }\n if (se.draggingHandleAt !== null) {\n if (endCtx.modifiers.alt && se.current) {\n se.current.anchors[se.draggingHandleAt].altBroken = true;\n }\n applyOutHandle(se, endCtx.world, endCtx.modifiers.shift, linked, optsRef.current.snapPoint);\n se.draggingHandleAt = null;\n }\n if (joinHit && se.current) commitJoin(se, ctx.deps, joinHit);\n trail.refresh();\n },\n };\n },\n },\n },\n\n {\n id: 'pen.finish',\n label: 'Pen — finish path',\n eligible: { capability: 'creates-paths' },\n requires: ['editAnchors', 'insert', 'selection'],\n enabled: () => (anchorCount(s()) > 0 ? true : ActionDisabledReason.NotApplicable),\n invoker: {\n timing: 'immediate' as const,\n run: (deps) => {\n commit(s(), deps);\n trail.refresh();\n },\n },\n },\n\n {\n id: 'pen.cancel',\n label: 'Pen — discard path',\n eligible: { capability: 'creates-paths' },\n // Declining with nothing drawn is what keeps Escape's first-match\n // ladder intact: an empty pen passes the key to `escape`, which goes\n // on to clear the selection / return to the default tool.\n enabled: () => {\n const scratch = s();\n return scratch.current !== null || scratch.finishedSubpaths.length > 0\n ? true\n : ActionDisabledReason.NotApplicable;\n },\n invoker: {\n timing: 'immediate' as const,\n run: () => {\n resetScratch(s());\n trail.refresh();\n },\n },\n },\n ];\n }, [commit, placeAt, withinCloseRadius, pickUpEndpoint, joinable, commitJoin, optsRef, trail, forceRender]);\n\n return useMemo(() => {\n return defineTool({\n id: 'pen',\n keybinding: { key: 'P' },\n capabilities: ['creates-paths'],\n hookName: 'usePenTool',\n cursor: () =>\n scratchRef.current?.closeHintActive\n ? 'pointer'\n : cursorFor('pen', { fallback: 'crosshair' }),\n presentation: {\n label: 'Pen',\n icon: createElement(PenIcon),\n group: 'draw',\n },\n actions,\n overlay,\n overlayPosition: 'before-selection',\n\n onDeactivate: () => {\n // Anything still in scratch is incomplete. Switching tools mid-path\n // discards it, as Escape does, rather than committing a stub polyline.\n resetScratch(scratchRef.current!);\n trail.stop();\n },\n\n bindings: [\n // Plain click places an anchor; ⌘/Ctrl-click open-finishes. Strict\n // modifier matching keeps the two apart.\n { spec: { kind: 'click' as const, mods: { shift: 'optional' as const, alt: 'optional' as const } }, actionId: 'pen.placeAnchor' },\n { spec: { kind: 'click' as const, mods: { mod: true, shift: 'optional' as const, alt: 'optional' as const } }, actionId: 'pen.finishOpen' },\n // Double-click on the last anchor also open-finishes.\n {\n spec: { kind: 'doubleClick' as const, mods: { shift: 'optional' as const, alt: 'optional' as const } },\n actionId: 'pen.finishOpen',\n opts: { params: { viaDoubleClick: true } },\n },\n { spec: { kind: 'drag' as const, mods: { shift: 'optional' as const, alt: 'optional' as const } }, actionId: 'pen.dragHandle' },\n { spec: { kind: 'key' as const, key: 'Enter' }, actionId: 'pen.finish' },\n { spec: { kind: 'key' as const, key: 'Escape' }, actionId: 'pen.cancel' },\n ],\n });\n }, [actions, trail, overlay]);\n}\n\nusePenTool.prefs = {\n name: 'Pen',\n description: 'Pen-tool behavior.',\n children: {\n autoCommitOnClose: {\n kind: 'boolean',\n name: 'Auto-commit pen on close',\n description: \"When you click the pen tool's first anchor to close a region, commit immediately so it renders with its fill. Off: keep the path in preview until you press Enter (lets you build a compound path from multiple closed subpaths).\",\n default: true,\n },\n },\n} satisfies PrefGroup;\n\n/** Point the anchor's outgoing handle at `target`, optionally snapped and\n * optionally constrained to 45° steps. When `linked` and not Alt-broken,\n * the in-handle follows as its mirror through the anchor. */\nfunction applyOutHandle<S extends PenScratch>(\n s: S,\n target: { x: number; y: number },\n shift: boolean,\n linked: boolean,\n snap?: (p: { x: number; y: number }) => { x: number; y: number },\n): void {\n if (s.current === null || s.draggingHandleAt === null) return;\n const anchor = s.current.anchors[s.draggingHandleAt];\n const to = snap ? snap(target) : target;\n let dx = to.x - anchor.x;\n let dy = to.y - anchor.y;\n if (shift) {\n const c = constrainTo45(dx, dy);\n dx = c.dx;\n dy = c.dy;\n }\n anchor.outHandle = { x: anchor.x + dx, y: anchor.y + dy };\n if (linked && !anchor.altBroken) anchor.inHandle = { x: anchor.x - dx, y: anchor.y - dy };\n}\n\nfunction viewScale(deps: ActionDeps): { x: number; y: number } {\n return deps.view?.get().scale ?? { x: 1, y: 1 };\n}\n\n/** Existing editable paths, world coords, with ink within `px` screen\n * pixels of `(wx, wy)` — front-to-back, as the area query returns them.\n * Empty when the host publishes no `areaSelect` or `editAnchors` dep. */\nfunction pathsNear(\n deps: ActionDeps,\n wx: number,\n wy: number,\n px: number,\n): Array<{ id: string; path: PolygonPath }> {\n const area = deps.areaSelect;\n const edit = deps.editAnchors;\n if (!area || !edit) return [];\n const view = deps.view;\n const e = pxExtent(px, viewScale(deps));\n const ids = area.hitTestArea({ x: wx - e.x, y: wy - e.y, width: 2 * e.x, height: 2 * e.y }, view);\n const out: Array<{ id: string; path: PolygonPath }> = [];\n for (const id of ids) {\n const path = edit.getEditablePath(id) as PolygonPath | null;\n if (path?.kind === 'polygon') out.push({ id, path });\n }\n return out;\n}\n\nfunction samePath(a: PolygonPath, b: PolygonPath): boolean {\n if (a.commands.length !== b.commands.length || a.coords.length !== b.coords.length) return false;\n for (let i = 0; i < a.commands.length; i++) if (a.commands[i] !== b.commands[i]) return false;\n for (let i = 0; i < a.coords.length; i++) if (a.coords[i] !== b.coords[i]) return false;\n return true;\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePencilTool.js","names":["PencilIcon","usePencilTool","options","useMemo","defineTool","cursorFor","insertBindingBehaviors","behaviors"],"sources":["../../../../src/tools/builtin/pencil/usePencilTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { PencilIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/** A single pointer sample captured during a freehand pencil stroke.\n *\n * `pressure` / `tiltX` / `tiltY` come straight from the underlying\n * `PointerEvent` and let downstream consumers modulate stroke width or\n * opacity by stylus input. Mouse and ordinary touch report\n * `pressure: 0.5` while a button is held, `0` otherwise (per the Pointer\n * Events spec), so a consumer that wants stylus-only modulation should\n * gate on `pointerType` from the originating event — the kit exposes\n * `usePointerStylus()` for that.\n *\n * The dispatcher accumulates these on the drag trail and hands the whole\n * array to `insertAction`, which forwards it as the `pencil` insert\n * extras' `samples`. A consumer that wants pressure-driven\n * `Stroke.vertexWidths` reads it off the samples in its own `insert` dep\n * (`useDepSource('insert', …)`) — see `apps/site/demos/StrokeAndFillDemo.tsx`.\n */\nexport interface PencilPoint {\n x: number;\n y: number;\n /** 0..1. Absent when the originating event carried no pressure. */\n pressure?: number;\n /** Degrees, ±90. Zero for mouse/touch. */\n tiltX?: number;\n /** Degrees, ±90. Zero for mouse/touch. */\n tiltY?: number;\n}\n\n/**\n * Freehand pencil tool. The `drag` binding routes to `insertAction`,\n * which accumulates the pointer trail and commits it as\n * `{ kind: 'pencil', samples }`. The kit's default `insert` dep runs\n * `schneiderFit` over the samples to produce a cubic-Bezier path.\n */\nexport function usePencilTool(options: InsertToolOptions = {}): Tool<null> {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool<null>({\n id: 'pencil',\n keybinding: { key: 'N' },\n capabilities: ['creates-paths'],\n hookName: 'usePencilTool',\n cursor: cursorFor('pencil', { fallback: 'crosshair' }),\n presentation: {\n label: 'Pencil',\n group: 'draw',\n icon: <PencilIcon />,\n },\n bindings: [\n {\n spec: { kind: 'drag', target: 'empty' },\n actionId: 'insert',\n opts: { params: { kind: 'pencil' } , ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":";;;;;;;AAwCA,SAAgBC,EAAc,IAA6B,CAAC,GAAe;CACzE,IAAM,EAAE,iBAAcC;CACtB,OAAOC,QAEHC,EAAiB;EACf,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,eAAe;EAC9B,UAAU;EACV,QAAQC,EAAU,UAAU,EAAE,UAAU,YAAY,CAAC;EACrD,cAAc;GACZ,OAAO;GACP,OAAO;GACP,MAAM,kBAACL,GAAD,CAAa,CAAA;EACrB;EACA,UAAU,CACR;GACE,MAAM;IAAE,MAAM;IAAQ,QAAQ;GAAQ;GACtC,UAAU;GACV,MAAM;IAAE,QAAQ,EAAE,MAAM,SAAS;IAAI,GAAGM,EAAuBC,CAAS;GAAE;EAC5E,CACF;CACF,CAAC,GACH,CAACA,CAAS,CACZ;AACF"}
1
+ {"version":3,"file":"usePencilTool.js","names":["PencilIcon","usePencilTool","options","useMemo","defineTool","cursorFor","insertBindingBehaviors","behaviors"],"sources":["../../../../src/tools/builtin/pencil/usePencilTool.tsx"],"sourcesContent":["import { useMemo } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { PencilIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/** A single pointer sample captured during a freehand pencil stroke.\n *\n * `pressure` / `tiltX` / `tiltY` come straight from the underlying\n * `PointerEvent`. Mouse and ordinary touch report `pressure: 0.5` while a\n * button is held, `0` otherwise (per the Pointer Events spec), so a consumer\n * that wants stylus-only modulation should gate on `pointerType` — the kit\n * exposes `usePointerStylus()` for that.\n *\n * The samples reach the `insert` dep as the `pencil` insert extras'\n * `samples`; a consumer that wants pressure-driven `Stroke.vertexWidths`\n * reads it off them in its own `insert` dep (`useDepSource('insert', …)`).\n */\nexport interface PencilPoint {\n x: number;\n y: number;\n /** 0..1. Absent when the originating event carried no pressure. */\n pressure?: number;\n /** Degrees, ±90. Zero for mouse/touch. */\n tiltX?: number;\n /** Degrees, ±90. Zero for mouse/touch. */\n tiltY?: number;\n}\n\n/**\n * Freehand pencil tool. The `drag` binding routes to `insertAction`,\n * which accumulates the pointer trail and commits it as\n * `{ kind: 'pencil', samples }`. The kit's default `insert` dep runs\n * `schneiderFit` over the samples to produce a cubic-Bezier path.\n */\nexport function usePencilTool(options: InsertToolOptions = {}): Tool {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'pencil',\n keybinding: { key: 'N' },\n capabilities: ['creates-paths'],\n hookName: 'usePencilTool',\n cursor: cursorFor('pencil', { fallback: 'crosshair' }),\n presentation: {\n label: 'Pencil',\n group: 'draw',\n icon: <PencilIcon />,\n },\n bindings: [\n {\n spec: { kind: 'drag', target: 'empty' },\n actionId: 'insert',\n opts: { params: { kind: 'pencil' } , ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":";;;;;;;AAoCA,SAAgBC,EAAc,IAA6B,CAAC,GAAS;CACnE,IAAM,EAAE,iBAAcC;CACtB,OAAOC,QAEHC,EAAW;EACT,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,eAAe;EAC9B,UAAU;EACV,QAAQC,EAAU,UAAU,EAAE,UAAU,YAAY,CAAC;EACrD,cAAc;GACZ,OAAO;GACP,OAAO;GACP,MAAM,kBAACL,GAAD,CAAa,CAAA;EACrB;EACA,UAAU,CACR;GACE,MAAM;IAAE,MAAM;IAAQ,QAAQ;GAAQ;GACtC,UAAU;GACV,MAAM;IAAE,QAAQ,EAAE,MAAM,SAAS;IAAI,GAAGM,EAAuBC,CAAS;GAAE;EAC5E,CACF;CACF,CAAC,GACH,CAACA,CAAS,CACZ;AACF"}
@@ -2,29 +2,26 @@
2
2
  function e(e, n) {
3
3
  if (e.length === 0) return null;
4
4
  if (e.length === 1) return e[0];
5
- let r = e, i = n?.getParent;
6
- if (typeof i == "function") {
7
- let t = new Set(e), n = /* @__PURE__ */ new Set();
8
- for (let r of e) {
9
- let e = i(r), a = 0;
10
- for (; e != null && a++ < 1e4;) t.has(e) && n.add(e), e = i(e);
11
- }
12
- if (n.size > 0) {
13
- let t = e.filter((e) => !n.has(e));
14
- if (t.length === 1) return t[0];
15
- t.length > 1 && (r = t);
16
- }
5
+ let r = e, i = new Set(e), a = /* @__PURE__ */ new Set();
6
+ for (let t of e) {
7
+ let e = n.getParent(t), r = 0;
8
+ for (; e != null && r++ < 1e4;) i.has(e) && a.add(e), e = n.getParent(e);
9
+ }
10
+ if (a.size > 0) {
11
+ let t = e.filter((e) => !a.has(e));
12
+ if (t.length === 1) return t[0];
13
+ t.length > 1 && (r = t);
17
14
  }
18
15
  return t(r, n);
19
16
  }
20
17
  function t(e, t) {
21
- let r = t?.compareZ;
18
+ let r = t.compareZ;
22
19
  if (typeof r == "function") {
23
20
  let t = e[0];
24
21
  for (let n = 1; n < e.length; n++) r(e[n], t) >= 0 && (t = e[n]);
25
22
  return t;
26
23
  }
27
- let i = t?.getZIndex;
24
+ let i = t.getZIndex;
28
25
  if (typeof i == "function") {
29
26
  let t = e[0], r = n(i, t);
30
27
  for (let a = 1; a < e.length; a++) {
@@ -1 +1 @@
1
- {"version":3,"file":"pickTopMostHit.js","names":["pickTopMostHit","ids","candidates","getParent","adapter","set","dropped","id","p","depth","filtered","pickHighestZ","compareZ","best","i","getZIndex","bestZ","zOf","z"],"sources":["../../../src/tools/builtin/pickTopMostHit.ts"],"sourcesContent":["/**\n * Pick the topmost id from a body-hit list, using whatever signal the\n * adapter exposes.\n *\n * Why this exists: `pickEvery` returns every id whose body covers the pointer.\n * Naively taking `ids[0]` makes containers swallow clicks on their children\n * (the container's bounds also cover the hit point, and demo iteration\n * order tends to put parents before children). This helper resolves the\n * ambiguity in a way that's correct by default for the common parent/child\n * case, while remaining a no-op for the trivial single-hit case.\n *\n * Resolution rules (in order):\n *\n * 1. **Empty / single hit.** Return `null` / the lone id.\n * 2. **Parent/child collapse.** When `adapter.getParent` is present, drop\n * any id in the hit set that is an ancestor of another id in the hit\n * set. After the collapse, if exactly one id remains, return it.\n * 3. **Sibling z-order.** When the adapter exposes `compareZ` or `getZIndex`,\n * the survivors of the collapse are ranked by it and the highest wins.\n * This composes with step 2 rather than replacing it: a child still beats\n * its own ancestor regardless of what z the two report.\n * 4. **Tiebreaker.** Return the LAST id in the (collapsed) array. Scenes\n * walked forward (`renderOrder()`, `Object.keys`, `for of items`) come\n * back bottom-first by convention, so \"last\" gives the topmost. A caller\n * that z-sorts topmost-first and exposes neither z hook should resolve\n * before calling — this helper doesn't try to detect that.\n */\nexport interface PickTopMostHitAdapter {\n getParent?: (id: string) => string | null;\n /** Paint depth of `id`; higher draws later, so higher wins a hit. Ids the\n * adapter doesn't know sort below every id it does. */\n getZIndex?: (id: string) => number | null | undefined;\n /** Full ordering, for scenes whose depth isn't a number (a path through a\n * tree, say). Negative when `a` paints below `b`. Takes precedence over\n * `getZIndex` when both are present. */\n compareZ?: (a: string, b: string) => number;\n}\n\n/** Reduce a set of hit ids to the single one a click should act on: drop any\n * id that is an ancestor of another in the set, then take the topmost of what\n * remains. */\nexport function pickTopMostHit(\n ids: readonly string[],\n adapter: PickTopMostHitAdapter | undefined | null,\n): string | null {\n if (ids.length === 0) return null;\n if (ids.length === 1) return ids[0];\n\n let candidates = ids;\n\n const getParent = adapter?.getParent;\n if (typeof getParent === 'function') {\n const set = new Set(ids);\n const dropped = new Set<string>();\n for (const id of ids) {\n let p: string | null = getParent(id);\n // Cap walk to avoid pathological cycles in malformed adapters.\n let depth = 0;\n while (p != null && depth++ < 10_000) {\n if (set.has(p)) dropped.add(p);\n p = getParent(p);\n }\n }\n if (dropped.size > 0) {\n const filtered = ids.filter((id) => !dropped.has(id));\n // A pathological adapter (cyclic `getParent`) can drop everything;\n // keep the original array rather than answering null.\n if (filtered.length === 1) return filtered[0];\n if (filtered.length > 1) candidates = filtered;\n }\n }\n\n return pickHighestZ(candidates, adapter);\n}\n\n/** Highest-z survivor, or the last one when the adapter exposes no z signal.\n * Scanning forward and taking strictly-greater makes the array's own order\n * the tiebreaker, so equal-z ids resolve the same way as no-z ones. */\nfunction pickHighestZ(\n ids: readonly string[],\n adapter: PickTopMostHitAdapter | undefined | null,\n): string {\n const compareZ = adapter?.compareZ;\n if (typeof compareZ === 'function') {\n let best = ids[0];\n for (let i = 1; i < ids.length; i++) {\n if (compareZ(ids[i], best) >= 0) best = ids[i];\n }\n return best;\n }\n\n const getZIndex = adapter?.getZIndex;\n if (typeof getZIndex === 'function') {\n let best = ids[0];\n let bestZ = zOf(getZIndex, best);\n for (let i = 1; i < ids.length; i++) {\n const z = zOf(getZIndex, ids[i]);\n if (z >= bestZ) { best = ids[i]; bestZ = z; }\n }\n return best;\n }\n\n return ids[ids.length - 1];\n}\n\nfunction zOf(getZIndex: (id: string) => number | null | undefined, id: string): number {\n const z = getZIndex(id);\n return typeof z === 'number' && Number.isFinite(z) ? z : -Infinity;\n}\n"],"mappings":";AAyCA,SAAgBA,EACd,GACA,GACe;CACf,IAAIC,EAAI,WAAW,GAAG,OAAO;CAC7B,IAAIA,EAAI,WAAW,GAAG,OAAOA,EAAI;CAEjC,IAAIC,IAAaD,GAEXE,IAAYC,GAAS;CAC3B,IAAI,OAAOD,KAAc,YAAY;EACnC,IAAME,IAAM,IAAI,IAAIJ,CAAG,GACjBK,oBAAU,IAAI,IAAY;EAChC,KAAK,IAAMC,KAAMN,GAAK;GACpB,IAAIO,IAAmBL,EAAUI,CAAE,GAE/BE,IAAQ;GACZ,OAAOD,KAAK,QAAQ,MAAU,MAE5B,AADIH,EAAI,IAAIG,CAAC,KAAGF,EAAQ,IAAIE,CAAC,GAC7B,IAAIL,EAAUK,CAAC;EAEnB;EACA,IAAIF,EAAQ,OAAO,GAAG;GACpB,IAAMI,IAAWT,EAAI,QAAQ,MAAO,CAACK,EAAQ,IAAIC,CAAE,CAAC;GAGpD,IAAIG,EAAS,WAAW,GAAG,OAAOA,EAAS;GAC3C,AAAIA,EAAS,SAAS,MAAG,IAAaA;EACxC;CACF;CAEA,OAAOC,EAAaT,GAAYE,CAAO;AACzC;AAKA,SAASO,EACP,GACA,GACQ;CACR,IAAMC,IAAWR,GAAS;CAC1B,IAAI,OAAOQ,KAAa,YAAY;EAClC,IAAIC,IAAOZ,EAAI;EACf,KAAK,IAAIa,IAAI,GAAGA,IAAIb,EAAI,QAAQ,KAC9B,AAAIW,EAASX,EAAIa,IAAID,CAAI,KAAK,MAAG,IAAOZ,EAAIa;EAE9C,OAAOD;CACT;CAEA,IAAME,IAAYX,GAAS;CAC3B,IAAI,OAAOW,KAAc,YAAY;EACnC,IAAIF,IAAOZ,EAAI,IACXe,IAAQC,EAAIF,GAAWF,CAAI;EAC/B,KAAK,IAAIC,IAAI,GAAGA,IAAIb,EAAI,QAAQ,KAAK;GACnC,IAAMiB,IAAID,EAAIF,GAAWd,EAAIa,EAAE;GAC/B,AAAII,KAAKF,MAAS,IAAOf,EAAIa,IAAI,IAAQI;EAC3C;EACA,OAAOL;CACT;CAEA,OAAOZ,EAAIA,EAAI,SAAS;AAC1B;AAEA,SAASgB,EAAI,GAAsD,GAAoB;CACrF,IAAMC,IAAIH,EAAUR,CAAE;CACtB,OAAO,OAAOW,KAAM,YAAY,OAAO,SAASA,CAAC,IAAIA,IAAI;AAC3D"}
1
+ {"version":3,"file":"pickTopMostHit.js","names":["pickTopMostHit","ids","candidates","set","dropped","id","p","adapter","depth","filtered","pickHighestZ","compareZ","best","i","getZIndex","bestZ","zOf","z"],"sources":["../../../src/tools/builtin/pickTopMostHit.ts"],"sourcesContent":["/** What `pickTopMostHit` ranks a hit list by: the tree, and a z signal where\n * the adapter has one. */\nexport interface PickTopMostHitAdapter {\n getParent: (id: string) => string | null;\n /** Paint depth of `id`; higher draws later, so higher wins a hit. Ids the\n * adapter doesn't know sort below every id it does. */\n getZIndex?: (id: string) => number | null | undefined;\n /** Full ordering, for scenes whose depth isn't a number (a path through a\n * tree, say). Negative when `a` paints below `b`. Takes precedence over\n * `getZIndex` when both are present. */\n compareZ?: (a: string, b: string) => number;\n}\n\n/** Reduce a set of hit ids to the single one a click should act on: drop any\n * id that is an ancestor of another in the set, then take the topmost of what\n * remains. A child beats its own ancestor regardless of what z the two report.\n *\n * With no z signal the LAST id wins: scenes walked forward come back\n * bottom-first by convention. A caller that z-sorts topmost-first and exposes\n * neither z hook should resolve before calling. */\nexport function pickTopMostHit(\n ids: readonly string[],\n adapter: PickTopMostHitAdapter,\n): string | null {\n if (ids.length === 0) return null;\n if (ids.length === 1) return ids[0];\n\n let candidates = ids;\n\n const set = new Set(ids);\n const dropped = new Set<string>();\n for (const id of ids) {\n let p: string | null = adapter.getParent(id);\n // Cap walk to avoid pathological cycles in malformed adapters.\n let depth = 0;\n while (p != null && depth++ < 10_000) {\n if (set.has(p)) dropped.add(p);\n p = adapter.getParent(p);\n }\n }\n if (dropped.size > 0) {\n const filtered = ids.filter((id) => !dropped.has(id));\n // A pathological adapter (cyclic `getParent`) can drop everything;\n // keep the original array rather than answering null.\n if (filtered.length === 1) return filtered[0];\n if (filtered.length > 1) candidates = filtered;\n }\n\n return pickHighestZ(candidates, adapter);\n}\n\n/** Highest-z survivor, or the last one when the adapter exposes no z signal.\n * Scanning forward and taking strictly-greater makes the array's own order\n * the tiebreaker, so equal-z ids resolve the same way as no-z ones. */\nfunction pickHighestZ(\n ids: readonly string[],\n adapter: PickTopMostHitAdapter,\n): string {\n const compareZ = adapter.compareZ;\n if (typeof compareZ === 'function') {\n let best = ids[0];\n for (let i = 1; i < ids.length; i++) {\n if (compareZ(ids[i], best) >= 0) best = ids[i];\n }\n return best;\n }\n\n const getZIndex = adapter.getZIndex;\n if (typeof getZIndex === 'function') {\n let best = ids[0];\n let bestZ = zOf(getZIndex, best);\n for (let i = 1; i < ids.length; i++) {\n const z = zOf(getZIndex, ids[i]);\n if (z >= bestZ) { best = ids[i]; bestZ = z; }\n }\n return best;\n }\n\n return ids[ids.length - 1];\n}\n\nfunction zOf(getZIndex: (id: string) => number | null | undefined, id: string): number {\n const z = getZIndex(id);\n return typeof z === 'number' && Number.isFinite(z) ? z : -Infinity;\n}\n"],"mappings":";AAoBA,SAAgBA,EACd,GACA,GACe;CACf,IAAIC,EAAI,WAAW,GAAG,OAAO;CAC7B,IAAIA,EAAI,WAAW,GAAG,OAAOA,EAAI;CAEjC,IAAIC,IAAaD,GAEXE,IAAM,IAAI,IAAIF,CAAG,GACjBG,oBAAU,IAAI,IAAY;CAChC,KAAK,IAAMC,KAAMJ,GAAK;EACpB,IAAIK,IAAmBC,EAAQ,UAAUF,CAAE,GAEvCG,IAAQ;EACZ,OAAOF,KAAK,QAAQ,MAAU,MAE5B,AADIH,EAAI,IAAIG,CAAC,KAAGF,EAAQ,IAAIE,CAAC,GAC7B,IAAIC,EAAQ,UAAUD,CAAC;CAE3B;CACA,IAAIF,EAAQ,OAAO,GAAG;EACpB,IAAMK,IAAWR,EAAI,QAAQ,MAAO,CAACG,EAAQ,IAAIC,CAAE,CAAC;EAGpD,IAAII,EAAS,WAAW,GAAG,OAAOA,EAAS;EAC3C,AAAIA,EAAS,SAAS,MAAG,IAAaA;CACxC;CAEA,OAAOC,EAAaR,GAAYK,CAAO;AACzC;AAKA,SAASG,EACP,GACA,GACQ;CACR,IAAMC,IAAWJ,EAAQ;CACzB,IAAI,OAAOI,KAAa,YAAY;EAClC,IAAIC,IAAOX,EAAI;EACf,KAAK,IAAIY,IAAI,GAAGA,IAAIZ,EAAI,QAAQ,KAC9B,AAAIU,EAASV,EAAIY,IAAID,CAAI,KAAK,MAAG,IAAOX,EAAIY;EAE9C,OAAOD;CACT;CAEA,IAAME,IAAYP,EAAQ;CAC1B,IAAI,OAAOO,KAAc,YAAY;EACnC,IAAIF,IAAOX,EAAI,IACXc,IAAQC,EAAIF,GAAWF,CAAI;EAC/B,KAAK,IAAIC,IAAI,GAAGA,IAAIZ,EAAI,QAAQ,KAAK;GACnC,IAAMgB,IAAID,EAAIF,GAAWb,EAAIY,EAAE;GAC/B,AAAII,KAAKF,MAAS,IAAOd,EAAIY,IAAI,IAAQI;EAC3C;EACA,OAAOL;CACT;CAEA,OAAOX,EAAIA,EAAI,SAAS;AAC1B;AAEA,SAASe,EAAI,GAAsD,GAAoB;CACrF,IAAMC,IAAIH,EAAUT,CAAE;CACtB,OAAO,OAAOY,KAAM,YAAY,OAAO,SAASA,CAAC,IAAIA,IAAI;AAC3D"}
@@ -1,34 +1,35 @@
1
- import { defineTool as e } from "../../overlayBinding.js";
2
- import t from "../../../icons/PolygonIcon.js";
3
- import { insertBindingBehaviors as n } from "../shared/insertToolOptions.js";
4
- import { useCallback as r, useMemo as i, useRef as a, useState as o } from "react";
5
- import { jsx as s } from "react/jsx-runtime";
6
- import { cursorFor as c } from "@weasel-js/cursor";
1
+ import { INSERT_REPOSITION_BINDING as e } from "../../../interactions/actions/insert/repositionAction.js";
2
+ import { SHAPE_COUNT_RANGE as t } from "../../../features/paths/shapeGenerator.js";
3
+ import { defineTool as n } from "../../overlayBinding.js";
4
+ import r from "../../../icons/PolygonIcon.js";
5
+ import { insertBindingBehaviors as i } from "../shared/insertToolOptions.js";
6
+ import { useCallback as a, useMemo as o, useRef as s, useState as c } from "react";
7
+ import { jsx as l } from "react/jsx-runtime";
8
+ import { cursorFor as u } from "@weasel-js/cursor";
7
9
  //#region src/tools/builtin/polygon/usePolygonTool.tsx
8
- var l = 3, u = 32;
9
10
  function d(d = {}) {
10
- let { sides: f = 6, label: p = "Polygon", behaviors: m } = d, h = a(f), [, g] = o(0), _ = r(() => g((e) => e + 1), []), v = i(() => ({
11
+ let { sides: f = 6, label: p = "Polygon", behaviors: m } = d, h = s(f), [, g] = c(0), _ = a(() => g((e) => e + 1), []), v = o(() => ({
11
12
  id: "polygon.adjustSides",
12
13
  label: "Polygon — adjust sides",
13
14
  invoker: {
14
15
  timing: "immediate",
15
- run: (e, t) => {
16
- let n = t, r = n?.delta ?? (n?.deltaY !== void 0 && n.deltaY !== 0 ? n.deltaY > 0 ? 1 : -1 : 0);
17
- r !== 0 && (h.current = r > 0 ? Math.min(u, h.current + 1) : Math.max(l, h.current - 1), _());
16
+ run: (e, n) => {
17
+ let r = n, i = r?.delta ?? (r?.deltaY !== void 0 && r.deltaY !== 0 ? r.deltaY > 0 ? 1 : -1 : 0);
18
+ i !== 0 && (h.current = i > 0 ? Math.min(t.max, h.current + 1) : Math.max(t.min, h.current - 1), _());
18
19
  }
19
20
  }
20
21
  }), [_]);
21
- return i(() => e({
22
+ return o(() => n({
22
23
  id: "polygon",
23
24
  keybinding: { key: "G" },
24
25
  capabilities: ["creates-shapes"],
25
26
  hookName: "usePolygonTool",
26
- cursor: c("crosshairPolygon", { fallback: "crosshair" }),
27
+ cursor: u("crosshairPolygon", { fallback: "crosshair" }),
27
28
  actions: [v],
28
29
  presentation: {
29
30
  label: p,
30
31
  group: "shape",
31
- icon: /* @__PURE__ */ s(t, {})
32
+ icon: /* @__PURE__ */ l(r, {})
32
33
  },
33
34
  bindings: [
34
35
  {
@@ -39,9 +40,10 @@ function d(d = {}) {
39
40
  kind: "polygon",
40
41
  sides: h.current
41
42
  }),
42
- ...n(m)
43
+ ...i(m)
43
44
  }
44
45
  },
46
+ e,
45
47
  {
46
48
  spec: {
47
49
  kind: "wheel",
@@ -1 +1 @@
1
- {"version":3,"file":"usePolygonTool.js","names":["PolygonIcon","MIN_SIDES","MAX_SIDES","usePolygonTool","initialSides","options","sidesRef","useRef","setSidesTick","useState","bumpSides","useCallback","n","adjustSidesAction","useMemo","p","params","step","defineTool","cursorFor","insertBindingBehaviors","behaviors","label"],"sources":["../../../../src/tools/builtin/polygon/usePolygonTool.tsx"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { PolygonIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport type { Action } from '@weasel-js/routing';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/** A point in world coordinates. */\nexport interface PolygonPoint { x: number; y: number }\n\n/** Options for `usePolygonTool`. */\nexport interface UsePolygonToolOptions extends InsertToolOptions {\n label?: string;\n /** Initial side count. Side count persists across gestures\n * (Illustrator convention) and is adjustable mid-drag via\n * ArrowUp/Down or wheel (range 3–32). */\n sides?: number;\n}\n\nconst MIN_SIDES = 3;\nconst MAX_SIDES = 32;\n\n/**\n * Drag-from-center polygon tool. Pointerdown sets center; drag\n * determines radius + rotation; release commits via `insertAction` (the\n * kit's standard insert dep, sourced by `<SceneCanvas>`). Side count\n * defaults to 6, adjustable mid-gesture via ArrowUp/Down or wheel.\n *\n * The live preview is painted by the dispatcher overlay layer reading\n * `insertAction.overlay()` — the action returns `{ kind:'insertPreview',\n * shape:'polygon', bounds, extras: { sides, ... } }`. Consumers wanting\n * a custom polygon node shape override the `insert` dep.\n */\nexport function usePolygonTool<TNode extends { id: string } = { id: string }>(\n options: UsePolygonToolOptions = {},\n): Tool<null> {\n const { sides: initialSides = 6, label = 'Polygon', behaviors } = options;\n // Side count in a ref so keyDown / wheel mutations are visible\n // synchronously to the insert binding's thunked params (re-resolved\n // every frame for the live preview and at commit time). A useState\n // tick alongside forces a render so the dispatcher overlay layer\n // repaints when the count changes between pointer events.\n const sidesRef = useRef(initialSides);\n const [, setSidesTick] = useState(0);\n const bumpSides = useCallback(() => setSidesTick((n) => n + 1), []);\n\n // Wheel-to-adjust-sides action. Bound to `[engaged] wheel` so it only\n // fires while a polygon insert drag is in flight — outside that window\n // wheel falls through to ambient viewport.pan/zoom. The action's run\n // body reads the dispatcher-injected wheel delta from params.\n const adjustSidesAction = useMemo<Action>(\n () => ({\n id: 'polygon.adjustSides',\n label: 'Polygon — adjust sides',\n invoker: {\n timing: 'immediate' as const,\n run: (_deps, params) => {\n const p = params as { deltaY?: number; delta?: number } | undefined;\n // `delta` comes from the ArrowUp/ArrowDown key bindings; `deltaY`\n // is the dispatcher-injected wheel delta. Wheel \"up\" (deltaY > 0\n // under Mac natural scrolling / page-scrolls-up gesture) adds a\n // side; wheel \"down\" removes one. Matches the user's mental model:\n // scroll up = more.\n const step = p?.delta ?? (p?.deltaY !== undefined && p.deltaY !== 0\n ? (p.deltaY > 0 ? 1 : -1)\n : 0);\n if (step === 0) return;\n sidesRef.current = step > 0\n ? Math.min(MAX_SIDES, sidesRef.current + 1)\n : Math.max(MIN_SIDES, sidesRef.current - 1);\n bumpSides();\n },\n },\n }),\n [bumpSides],\n );\n\n // `TNode` is retained for source-compat with callers that previously\n // threaded a node-record type through; the tool no longer mints nodes\n // (insertAction does), so the parameter has no runtime effect.\n void ({} as TNode);\n\n return useMemo(\n () =>\n defineTool<null>({\n id: 'polygon',\n keybinding: { key: 'G' },\n capabilities: ['creates-shapes'],\n hookName: 'usePolygonTool',\n cursor: cursorFor('crosshairPolygon', { fallback: 'crosshair' }),\n // Registered by <ToolActionsMounter>, inside the ActionsProvider —\n // see `ToolDef.actions` for why the hook can't register it itself.\n actions: [adjustSidesAction],\n presentation: {\n label,\n group: 'shape',\n icon: <PolygonIcon />,\n },\n bindings: [\n // Default = drag from corner, consistent with rect/ellipse.\n // The dispatcher overlay paints an anchorPoint dot at the\n // click so the radial shape reads as anchored even though no\n // polygon vertex sits at the AABB corner. Alt held flips to\n // center mode (insertAction reads live modifier state).\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n // Thunked params re-evaluated at commit time (and on every\n // overlay() call for live preview) so mid-gesture\n // ArrowUp/Down/wheel side-count changes flow through both\n // the ghost and the committed geometry.\n opts: {\n params: () => ({\n kind: 'polygon',\n sides: sidesRef.current,\n }),\n ...insertBindingBehaviors(behaviors),\n },\n },\n // Wheel-during-drag → adjust side count. Phase-gated to\n // `engaged` so wheel while the tool is idle still falls\n // through to ambient viewport.pan / viewport.zoom.\n {\n spec: { kind: 'wheel', phase: 'engaged' },\n actionId: 'polygon.adjustSides',\n },\n // Shift+wheel during engaged drag → rotate the in-flight\n // shape in place. Strict modifier matching means this\n // doesn't conflict with the unmodified wheel binding above.\n {\n spec: { kind: 'wheel', phase: 'engaged', mods: { shift: true } },\n actionId: 'insert.adjustRotation',\n },\n // ArrowUp/Down → adjust side count. These were phase-table\n // `initial.keyDown` routes, which put them on the OTHER dispatch\n // pipeline: the tool route claimed the key but its `claim()` never\n // reached the DOM as preventDefault/stopPropagation, so `nudge.up`\n // matched the same keypress on the interactions dispatcher and\n // moved the selection at the same time (audit §4 — derived there,\n // reproduced and now covered by a smoke test). As active-scope\n // bindings they out-prioritize ambient `nudge.*` and the\n // dispatcher's first-match-wins settles it.\n {\n spec: { kind: 'key', key: 'ArrowUp' },\n actionId: 'polygon.adjustSides',\n opts: { params: { delta: 1 } },\n },\n {\n spec: { kind: 'key', key: 'ArrowDown' },\n actionId: 'polygon.adjustSides',\n opts: { params: { delta: -1 } },\n },\n ],\n }),\n [adjustSidesAction, behaviors, label],\n );\n}\n"],"mappings":";;;;;;;AAoBA,IAAMC,IAAY,GACZC,IAAY;AAalB,SAAgBC,EACd,IAAiC,CAAC,GACtB;CACZ,IAAM,EAAE,OAAOC,IAAe,GAAG,WAAQ,WAAW,iBAAcC,GAM5DC,IAAWC,EAAOH,CAAY,GAC9B,GAAGI,KAAgBC,EAAS,CAAC,GAC7BC,IAAYC,QAAkBH,GAAc,MAAMI,IAAI,CAAC,GAAG,CAAC,CAAC,GAM5DC,IAAoBC,SACjB;EACL,IAAI;EACJ,OAAO;EACP,SAAS;GACP,QAAQ;GACR,MAAM,GAAO,MAAW;IACtB,IAAMC,IAAIC,GAMJC,IAAOF,GAAG,UAAUA,GAAG,WAAW,KAAA,KAAaA,EAAE,WAAW,IAC7DA,EAAE,SAAS,IAAI,IAAI,KACpB;IACJ,AAAIE,MAAS,MACb,EAAS,UAAUA,IAAO,IACtB,KAAK,IAAIf,GAAWI,EAAS,UAAU,CAAC,IACxC,KAAK,IAAIL,GAAWK,EAAS,UAAU,CAAC,GAC5CI,EAAU;GACZ;EACF;CACF,IACA,CAACA,CAAS,CACZ;CAOA,OAAOI,QAEHI,EAAiB;EACf,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,gBAAgB;EAC/B,UAAU;EACV,QAAQC,EAAU,oBAAoB,EAAE,UAAU,YAAY,CAAC;EAG/D,SAAS,CAACN,CAAiB;EAC3B,cAAc;GACZ;GACA,OAAO;GACP,MAAM,kBAACb,GAAD,CAAc,CAAA;EACtB;EACA,UAAU;GAMR;IACE,MAAM,EAAE,MAAM,OAAO;IACrB,UAAU;IAKV,MAAM;KACJ,eAAe;MACb,MAAM;MACN,OAAOM,EAAS;KAClB;KACA,GAAGc,EAAuBC,CAAS;IACrC;GACF;GAIA;IACE,MAAM;KAAE,MAAM;KAAS,OAAO;IAAU;IACxC,UAAU;GACZ;GAIA;IACE,MAAM;KAAE,MAAM;KAAS,OAAO;KAAW,MAAM,EAAE,OAAO,GAAK;IAAE;IAC/D,UAAU;GACZ;GAUA;IACE,MAAM;KAAE,MAAM;KAAO,KAAK;IAAU;IACpC,UAAU;IACV,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;GAC/B;GACA;IACE,MAAM;KAAE,MAAM;KAAO,KAAK;IAAY;IACtC,UAAU;IACV,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE;GAChC;EACF;CACF,CAAC,GACH;EAACR;EAAmBQ;EAAWC;CAAK,CACtC;AACF"}
1
+ {"version":3,"file":"usePolygonTool.js","names":["PolygonIcon","usePolygonTool","initialSides","options","sidesRef","useRef","setSidesTick","useState","bumpSides","useCallback","n","adjustSidesAction","useMemo","p","params","step","SHAPE_COUNT_RANGE","defineTool","cursorFor","insertBindingBehaviors","behaviors","INSERT_REPOSITION_BINDING","label"],"sources":["../../../../src/tools/builtin/polygon/usePolygonTool.tsx"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { PolygonIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { INSERT_REPOSITION_BINDING } from 'interactions/actions/insert/repositionAction';\nimport { SHAPE_COUNT_RANGE } from 'features/paths/shapeGenerator';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport type { Action } from '@weasel-js/routing';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/** A point in world coordinates. */\nexport interface PolygonPoint { x: number; y: number }\n\n/** Options for `usePolygonTool`. */\nexport interface UsePolygonToolOptions extends InsertToolOptions {\n label?: string;\n /** Initial side count. Side count persists across gestures\n * (Illustrator convention) and is adjustable mid-drag via\n * ArrowUp/Down or wheel (range 3–32). */\n sides?: number;\n}\n\n/**\n * Drag-from-center polygon tool. Pointerdown sets center; drag\n * determines radius + rotation; release commits via `insertAction` (the\n * kit's standard insert dep, sourced by `<SceneCanvas>`). Side count\n * defaults to 6, adjustable mid-gesture via ArrowUp/Down or wheel.\n *\n * The live preview is painted by the dispatcher overlay layer reading\n * `insertAction.overlay()` — the action returns `{ kind:'insertPreview',\n * shape:'polygon', bounds, extras: { sides, ... } }`. Consumers wanting\n * a custom polygon node shape override the `insert` dep.\n */\nexport function usePolygonTool<TNode extends { id: string } = { id: string }>(\n options: UsePolygonToolOptions = {},\n): Tool {\n const { sides: initialSides = 6, label = 'Polygon', behaviors } = options;\n // Side count in a ref so keyDown / wheel mutations are visible\n // synchronously to the insert binding's thunked params (re-resolved\n // every frame for the live preview and at commit time). A useState\n // tick alongside forces a render so the dispatcher overlay layer\n // repaints when the count changes between pointer events.\n const sidesRef = useRef(initialSides);\n const [, setSidesTick] = useState(0);\n const bumpSides = useCallback(() => setSidesTick((n) => n + 1), []);\n\n // Wheel-to-adjust-sides action. Bound to `[engaged] wheel` so it only\n // fires while a polygon insert drag is in flight — outside that window\n // wheel falls through to ambient viewport.pan/zoom. The action's run\n // body reads the dispatcher-injected wheel delta from params.\n const adjustSidesAction = useMemo<Action>(\n () => ({\n id: 'polygon.adjustSides',\n label: 'Polygon — adjust sides',\n invoker: {\n timing: 'immediate' as const,\n run: (_deps, params) => {\n const p = params as { deltaY?: number; delta?: number } | undefined;\n // `delta` comes from the ArrowUp/ArrowDown key bindings; `deltaY`\n // from the wheel. Wheel up (deltaY > 0 under natural scrolling)\n // adds a side.\n const step = p?.delta ?? (p?.deltaY !== undefined && p.deltaY !== 0\n ? (p.deltaY > 0 ? 1 : -1)\n : 0);\n if (step === 0) return;\n sidesRef.current = step > 0\n ? Math.min(SHAPE_COUNT_RANGE.max, sidesRef.current + 1)\n : Math.max(SHAPE_COUNT_RANGE.min, sidesRef.current - 1);\n bumpSides();\n },\n },\n }),\n [bumpSides],\n );\n\n // `TNode` is retained for source-compat with callers that previously\n // threaded a node-record type through; the tool no longer mints nodes\n // (insertAction does), so the parameter has no runtime effect.\n void ({} as TNode);\n\n return useMemo(\n () =>\n defineTool({\n id: 'polygon',\n keybinding: { key: 'G' },\n capabilities: ['creates-shapes'],\n hookName: 'usePolygonTool',\n cursor: cursorFor('crosshairPolygon', { fallback: 'crosshair' }),\n // Registered by <ToolActionsMounter>, inside the ActionsProvider —\n // see `ToolDef.actions` for why the hook can't register it itself.\n actions: [adjustSidesAction],\n presentation: {\n label,\n group: 'shape',\n icon: <PolygonIcon />,\n },\n bindings: [\n // Default = drag from corner, consistent with rect/ellipse.\n // The dispatcher overlay paints an anchorPoint dot at the\n // click so the radial shape reads as anchored even though no\n // polygon vertex sits at the AABB corner. Alt held flips to\n // center mode (insertAction reads live modifier state).\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n // Thunked params re-evaluated at commit time (and on every\n // overlay() call for live preview) so mid-gesture\n // ArrowUp/Down/wheel side-count changes flow through both\n // the ghost and the committed geometry.\n opts: {\n params: () => ({\n kind: 'polygon',\n sides: sidesRef.current,\n }),\n ...insertBindingBehaviors(behaviors),\n },\n },\n INSERT_REPOSITION_BINDING,\n // Wheel-during-drag → adjust side count. Phase-gated to\n // `engaged` so wheel while the tool is idle still falls\n // through to ambient viewport.pan / viewport.zoom.\n {\n spec: { kind: 'wheel', phase: 'engaged' },\n actionId: 'polygon.adjustSides',\n },\n // Shift+wheel during engaged drag → rotate the in-flight\n // shape in place. Strict modifier matching means this\n // doesn't conflict with the unmodified wheel binding above.\n {\n spec: { kind: 'wheel', phase: 'engaged', mods: { shift: true } },\n actionId: 'insert.adjustRotation',\n },\n // ArrowUp/Down → adjust side count. These were phase-table\n // `initial.keyDown` routes, which put them on the OTHER dispatch\n // pipeline: the tool route claimed the key but its `claim()` never\n // reached the DOM as preventDefault/stopPropagation, so `nudge.up`\n // matched the same keypress on the interactions dispatcher and\n // moved the selection at the same time (audit §4 — derived there,\n // reproduced and now covered by a smoke test). As active-scope\n // bindings they out-prioritize ambient `nudge.*` and the\n // dispatcher's first-match-wins settles it.\n {\n spec: { kind: 'key', key: 'ArrowUp' },\n actionId: 'polygon.adjustSides',\n opts: { params: { delta: 1 } },\n },\n {\n spec: { kind: 'key', key: 'ArrowDown' },\n actionId: 'polygon.adjustSides',\n opts: { params: { delta: -1 } },\n },\n ],\n }),\n [adjustSidesAction, behaviors, label],\n );\n}\n"],"mappings":";;;;;;;;;AAiCA,SAAgBC,EACd,IAAiC,CAAC,GAC5B;CACN,IAAM,EAAE,OAAOC,IAAe,GAAG,WAAQ,WAAW,iBAAcC,GAM5DC,IAAWC,EAAOH,CAAY,GAC9B,GAAGI,KAAgBC,EAAS,CAAC,GAC7BC,IAAYC,QAAkBH,GAAc,MAAMI,IAAI,CAAC,GAAG,CAAC,CAAC,GAM5DC,IAAoBC,SACjB;EACL,IAAI;EACJ,OAAO;EACP,SAAS;GACP,QAAQ;GACR,MAAM,GAAO,MAAW;IACtB,IAAMC,IAAIC,GAIJC,IAAOF,GAAG,UAAUA,GAAG,WAAW,KAAA,KAAaA,EAAE,WAAW,IAC7DA,EAAE,SAAS,IAAI,IAAI,KACpB;IACJ,AAAIE,MAAS,MACb,EAAS,UAAUA,IAAO,IACtB,KAAK,IAAIC,EAAkB,KAAKZ,EAAS,UAAU,CAAC,IACpD,KAAK,IAAIY,EAAkB,KAAKZ,EAAS,UAAU,CAAC,GACxDI,EAAU;GACZ;EACF;CACF,IACA,CAACA,CAAS,CACZ;CAOA,OAAOI,QAEHK,EAAW;EACT,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,gBAAgB;EAC/B,UAAU;EACV,QAAQC,EAAU,oBAAoB,EAAE,UAAU,YAAY,CAAC;EAG/D,SAAS,CAACP,CAAiB;EAC3B,cAAc;GACZ;GACA,OAAO;GACP,MAAM,kBAACX,GAAD,CAAc,CAAA;EACtB;EACA,UAAU;GAMR;IACE,MAAM,EAAE,MAAM,OAAO;IACrB,UAAU;IAKV,MAAM;KACJ,eAAe;MACb,MAAM;MACN,OAAOI,EAAS;KAClB;KACA,GAAGe,EAAuBC,CAAS;IACrC;GACF;GACAC;GAIA;IACE,MAAM;KAAE,MAAM;KAAS,OAAO;IAAU;IACxC,UAAU;GACZ;GAIA;IACE,MAAM;KAAE,MAAM;KAAS,OAAO;KAAW,MAAM,EAAE,OAAO,GAAK;IAAE;IAC/D,UAAU;GACZ;GAUA;IACE,MAAM;KAAE,MAAM;KAAO,KAAK;IAAU;IACpC,UAAU;IACV,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;GAC/B;GACA;IACE,MAAM;KAAE,MAAM;KAAO,KAAK;IAAY;IACtC,UAAU;IACV,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE;GAChC;EACF;CACF,CAAC,GACH;EAACV;EAAmBS;EAAWE;CAAK,CACtC;AACF"}
@@ -1,20 +1,21 @@
1
- import { defineTool as e } from "../../overlayBinding.js";
2
- import t from "../../../icons/RectIcon.js";
3
- import { insertBindingBehaviors as n } from "../shared/insertToolOptions.js";
4
- import { createElement as r, useMemo as i } from "react";
5
- import { cursorFor as a } from "@weasel-js/cursor";
1
+ import { INSERT_REPOSITION_BINDING as e } from "../../../interactions/actions/insert/repositionAction.js";
2
+ import { defineTool as t } from "../../overlayBinding.js";
3
+ import n from "../../../icons/RectIcon.js";
4
+ import { insertBindingBehaviors as r } from "../shared/insertToolOptions.js";
5
+ import { createElement as i, useMemo as a } from "react";
6
+ import { cursorFor as o } from "@weasel-js/cursor";
6
7
  //#region src/tools/builtin/rect/useRectTool.ts
7
- function o(o = {}) {
8
- let { behaviors: s } = o;
9
- return i(() => e({
8
+ function s(s = {}) {
9
+ let { behaviors: c } = s;
10
+ return a(() => t({
10
11
  id: "rect",
11
12
  keybinding: { key: "R" },
12
13
  capabilities: ["creates-shapes"],
13
14
  hookName: "useRectTool",
14
- cursor: a("crosshairRect", { fallback: "crosshair" }),
15
+ cursor: o("crosshairRect", { fallback: "crosshair" }),
15
16
  presentation: {
16
17
  label: "Rectangle",
17
- icon: r(t),
18
+ icon: i(n),
18
19
  group: "shape"
19
20
  },
20
21
  bindings: [{
@@ -22,12 +23,12 @@ function o(o = {}) {
22
23
  actionId: "insert",
23
24
  opts: {
24
25
  params: { kind: "rect" },
25
- ...n(s)
26
+ ...r(c)
26
27
  }
27
- }]
28
- }), [s]);
28
+ }, e]
29
+ }), [c]);
29
30
  }
30
31
  //#endregion
31
- export { o as useRectTool };
32
+ export { s as useRectTool };
32
33
 
33
34
  //# sourceMappingURL=useRectTool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useRectTool.js","names":["RectIcon","useRectTool","options","useMemo","defineTool","cursorFor","createElement","insertBindingBehaviors","behaviors"],"sources":["../../../../src/tools/builtin/rect/useRectTool.ts"],"sourcesContent":["import { useMemo, createElement } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { RectIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/**\n * Drag-to-draw rectangle tool.\n *\n * The gesture is owned end-to-end by the dispatcher: the `drag` binding\n * routes to `insertAction`, which tracks the live bounds, paints the\n * preview through its `overlay()` surface, and commits via the `insert`\n * dep on release. `<SceneCanvas>` sources that dep from\n * `useInsertDepSource`; consumers wanting a custom node factory override\n * the dep (`useDepSource('insert', …)`) rather than the tool.\n *\n * Grid snapping comes from the `snap` dep, also read by `insertAction` —\n * see `SnapDep` in `interactions/actions/depSchema.ts`.\n */\nexport function useRectTool(options: InsertToolOptions = {}): Tool<null> {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool<null>({\n id: 'rect',\n keybinding: { key: 'R' },\n capabilities: ['creates-shapes'],\n hookName: 'useRectTool',\n cursor: cursorFor('crosshairRect', { fallback: 'crosshair' }),\n presentation: {\n label: 'Rectangle',\n icon: createElement(RectIcon),\n group: 'shape',\n },\n // Single binding; insertAction toggles corner ⇄ center based on\n // live Alt state so users can engage/disengage Alt mid-drag and\n // see the bounds snap between the two modes.\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'rect' } , ...insertBindingBehaviors(behaviors) },\n },\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":";;;;;;AAoBA,SAAgBC,EAAY,IAA6B,CAAC,GAAe;CACvE,IAAM,EAAE,iBAAcC;CACtB,OAAOC,QAEHC,EAAiB;EACf,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,gBAAgB;EAC/B,UAAU;EACV,QAAQC,EAAU,iBAAiB,EAAE,UAAU,YAAY,CAAC;EAC5D,cAAc;GACZ,OAAO;GACP,MAAMC,EAAcN,CAAQ;GAC5B,OAAO;EACT;EAIA,UAAU,CACR;GACE,MAAM,EAAE,MAAM,OAAO;GACrB,UAAU;GACV,MAAM;IAAE,QAAQ,EAAE,MAAM,OAAO;IAAI,GAAGO,EAAuBC,CAAS;GAAE;EAC1E,CACF;CACF,CAAC,GACH,CAACA,CAAS,CACZ;AACF"}
1
+ {"version":3,"file":"useRectTool.js","names":["RectIcon","useRectTool","options","useMemo","defineTool","cursorFor","createElement","insertBindingBehaviors","behaviors","INSERT_REPOSITION_BINDING"],"sources":["../../../../src/tools/builtin/rect/useRectTool.ts"],"sourcesContent":["import { useMemo, createElement } from 'react';\nimport { defineTool } from '../../overlayBinding';\nimport { RectIcon } from '../../../icons';\nimport type { Tool } from '../../overlayBinding';\nimport { INSERT_REPOSITION_BINDING } from 'interactions/actions/insert/repositionAction';\nimport { insertBindingBehaviors, type InsertToolOptions } from '../shared/insertToolOptions';\nimport { cursorFor } from '@weasel-js/cursor';\n\n/**\n * Drag-to-draw rectangle tool.\n *\n * The `drag` binding routes to `insertAction`, which owns the live preview\n * and commits via the `insert` dep on release. Consumers wanting a custom\n * node factory override the dep (`useDepSource('insert', …)`) rather than\n * the tool. Grid snapping comes from the `snap` dep.\n */\nexport function useRectTool(options: InsertToolOptions = {}): Tool {\n const { behaviors } = options;\n return useMemo(\n () =>\n defineTool({\n id: 'rect',\n keybinding: { key: 'R' },\n capabilities: ['creates-shapes'],\n hookName: 'useRectTool',\n cursor: cursorFor('crosshairRect', { fallback: 'crosshair' }),\n presentation: {\n label: 'Rectangle',\n icon: createElement(RectIcon),\n group: 'shape',\n },\n // Single binding: insertAction toggles corner ⇄ center on live Alt\n // state, so Alt can be engaged mid-drag.\n bindings: [\n {\n spec: { kind: 'drag' },\n actionId: 'insert',\n opts: { params: { kind: 'rect' } , ...insertBindingBehaviors(behaviors) },\n },\n INSERT_REPOSITION_BINDING,\n ],\n }),\n [behaviors],\n );\n}\n"],"mappings":";;;;;;;AAgBA,SAAgBC,EAAY,IAA6B,CAAC,GAAS;CACjE,IAAM,EAAE,iBAAcC;CACtB,OAAOC,QAEHC,EAAW;EACT,IAAI;EACJ,YAAY,EAAE,KAAK,IAAI;EACvB,cAAc,CAAC,gBAAgB;EAC/B,UAAU;EACV,QAAQC,EAAU,iBAAiB,EAAE,UAAU,YAAY,CAAC;EAC5D,cAAc;GACZ,OAAO;GACP,MAAMC,EAAcN,CAAQ;GAC5B,OAAO;EACT;EAGA,UAAU,CACR;GACE,MAAM,EAAE,MAAM,OAAO;GACrB,UAAU;GACV,MAAM;IAAE,QAAQ,EAAE,MAAM,OAAO;IAAI,GAAGO,EAAuBC,CAAS;GAAE;EAC1E,GACAC,CACF;CACF,CAAC,GACH,CAACD,CAAS,CACZ;AACF"}
@@ -0,0 +1,40 @@
1
+ import { toPlane as e } from "../../../core/viewport/parallax.js";
2
+ import { poseDescriptorForNode as t } from "../../../core/geometry/poseDescriptor.js";
3
+ import { shapeCoversPoint as n } from "../../../canvas/NodeShape.js";
4
+ import { ownClipOf as r } from "../../../canvas/pickWalk.js";
5
+ import { applyToPoint as i, boundsOfPath as a, meanScale as o, pathContainsPoint as s } from "@weasel-js/geom";
6
+ //#region src/tools/builtin/select/adapterPointQuery.ts
7
+ function c(c, l) {
8
+ let u = (d, f, p) => ({
9
+ hits: (e, i, o) => {
10
+ let u = o ? a(o) : t(c, e).getBounds(i);
11
+ if (e.kind !== "container") {
12
+ let t = l || o ? p : 0;
13
+ return d >= u.x - t && d <= u.x + u.width + t && f >= u.y - t && f <= u.y + u.height + t ? !l || n(e, i, d, f, {
14
+ tolerance: p,
15
+ derivedPath: o
16
+ }) : !1;
17
+ }
18
+ if (!(d >= u.x && d <= u.x + u.width && f >= u.y && f <= u.y + u.height)) return !1;
19
+ let m = r(e, i, o);
20
+ return m === null || s(m, d, f);
21
+ },
22
+ clipAdmits: (e) => s(e, d, f),
23
+ inPlane: (t) => {
24
+ let n = e(t, {
25
+ x: d,
26
+ y: f
27
+ });
28
+ return u(n.x, n.y, p * o(t.scale));
29
+ },
30
+ inCopy: (e) => {
31
+ let [t, n] = i(e, d, f);
32
+ return u(t, n, p * Math.sqrt(Math.abs(e[0] * e[3] - e[1] * e[2])));
33
+ }
34
+ });
35
+ return u;
36
+ }
37
+ //#endregion
38
+ export { c as adapterPointQuery };
39
+
40
+ //# sourceMappingURL=adapterPointQuery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapterPointQuery.js","names":["adapterPointQuery","pointQuery","b","derived","boundsOfPath","poseDescriptorForNode","d","node","pose","slop","preciseLeaves","t","px","py","shapeCoversPoint","own","ownClipOf","pathContainsPoint","clip","p","toPlane","m","meanScale","x","y","applyToPoint"],"sources":["../../../../src/tools/builtin/select/adapterPointQuery.ts"],"sourcesContent":["import { applyToPoint, boundsOfPath, meanScale, pathContainsPoint } from '@weasel-js/geom';\nimport { shapeCoversPoint } from 'canvas/NodeShape';\nimport { ownClipOf, type PickQuery } from 'canvas/pickWalk';\nimport { poseDescriptorForNode, type PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport type { Node } from 'core/scene/types';\nimport { toPlane } from 'core/viewport/parallax';\n\n/**\n * The point query `useSelectTool`'s default `pickEvery` asks of a bare adapter:\n * a point at (px, py) with `t` world units of slop. AABB first (cheap), then\n * the painter's ink when `preciseLeaves` asks for it and it is available. A\n * painter with no `silhouette` — or one that returns null, as `kit:text` does\n * for an empty node — keeps the AABB answer.\n *\n * The AABB pre-filter is grown by the slop: a shape's outline, and the slop\n * around it, reach outside the shape's own bounds.\n *\n * A node that derives its path is tested against that path's box: its own pose\n * is a placeholder, and the box of a straight route has no area to land in\n * without the slop.\n */\nexport function adapterPointQuery<TPose>(\n d: PoseDescriptor<TPose>,\n preciseLeaves: boolean,\n): (px: number, py: number, t: number) => PickQuery<TPose> {\n const pointQuery = (px: number, py: number, t: number): PickQuery<TPose> => ({\n hits: (node, pose, derived) => {\n const b = derived ? boundsOfPath(derived) : poseDescriptorForNode(d, node).getBounds(pose);\n if (node.kind !== 'container') {\n const slop = preciseLeaves || derived ? t : 0;\n if (!(px >= b.x - slop && px <= b.x + b.width + slop\n && py >= b.y - slop && py <= b.y + b.height + slop)) {\n return false;\n }\n if (!preciseLeaves) return true;\n return shapeCoversPoint(\n node as Node<unknown, string, TPose>, pose, px, py, { tolerance: t, derivedPath: derived },\n );\n }\n // A container's own clip *is* its hit shape — it is picked where it\n // paints, and it paints only inside its clip. Ancestor clips are the\n // walk's business; this one is not.\n const inAabb = px >= b.x && px <= b.x + b.width\n && py >= b.y && py <= b.y + b.height;\n if (!inAabb) return false;\n const own = ownClipOf(node, pose, derived);\n return own === null || pathContainsPoint(own, px, py);\n },\n clipAdmits: (clip) => pathContainsPoint(clip, px, py),\n inPlane: (m) => {\n const p = toPlane(m, { x: px, y: py });\n return pointQuery(p.x, p.y, t * meanScale(m.scale));\n },\n inCopy: (m) => {\n const [x, y] = applyToPoint(m, px, py);\n return pointQuery(x, y, t * Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])));\n },\n });\n return pointQuery;\n}\n"],"mappings":";;;;;;AAqBA,SAAgBA,EACd,GACA,GACyD;CACzD,IAAMC,KAAc,GAAY,GAAY,OAAiC;EAC3E,OAAO,GAAM,GAAM,MAAY;GAC7B,IAAMC,IAAIC,IAAUC,EAAaD,CAAO,IAAIE,EAAsBC,GAAGC,CAAI,CAAC,CAAC,UAAUC,CAAI;GACzF,IAAID,EAAK,SAAS,aAAa;IAC7B,IAAME,IAAOC,KAAiBP,IAAUQ,IAAI;IAM5C,OALMC,KAAMV,EAAE,IAAIO,KAAQG,KAAMV,EAAE,IAAIA,EAAE,QAAQO,KACvCI,KAAMX,EAAE,IAAIO,KAAQI,KAAMX,EAAE,IAAIA,EAAE,SAASO,IAGpD,CAAKC,KACEI,EACLP,GAAsCC,GAAMI,GAAIC,GAAI;KAAE,WAAWF;KAAG,aAAaR;IAAQ,CAC3F,IALS;GAMX;GAMA,IAAI,EAFWS,KAAMV,EAAE,KAAKU,KAAMV,EAAE,IAAIA,EAAE,SACrCW,KAAMX,EAAE,KAAKW,KAAMX,EAAE,IAAIA,EAAE,SACnB,OAAO;GACpB,IAAMa,IAAMC,EAAUT,GAAMC,GAAML,CAAO;GACzC,OAAOY,MAAQ,QAAQE,EAAkBF,GAAKH,GAAIC,CAAE;EACtD;EACA,aAAa,MAASI,EAAkBC,GAAMN,GAAIC,CAAE;EACpD,UAAU,MAAM;GACd,IAAMM,IAAIC,EAAQC,GAAG;IAAE,GAAGT;IAAI,GAAGC;GAAG,CAAC;GACrC,OAAOZ,EAAWkB,EAAE,GAAGA,EAAE,GAAGR,IAAIW,EAAUD,EAAE,KAAK,CAAC;EACpD;EACA,SAAS,MAAM;GACb,IAAM,CAACE,GAAGC,KAAKC,EAAaJ,GAAGT,GAAIC,CAAE;GACrC,OAAOZ,EAAWsB,GAAGC,GAAGb,IAAI,KAAK,KAAK,KAAK,IAAIU,EAAE,KAAKA,EAAE,KAAKA,EAAE,KAAKA,EAAE,EAAE,CAAC,CAAC;EAC5E;CACF;CACA,OAAOpB;AACT"}
@@ -1,5 +1,5 @@
1
1
  import { gestureLifecycleParams as e } from "../../../interactions/actions/gestureLifecycle.js";
2
- import { isAnchorOrControl as t, isResizeHandle as n, isRotateHandle as r } from "@weasel-js/routing";
2
+ import { isPathEditPart as t, isResizeHandle as n, isRotateHandle as r } from "@weasel-js/routing";
3
3
  import { hitPredicate as i } from "@weasel-js/gestures";
4
4
  //#region src/tools/builtin/select/selectionContributions.ts
5
5
  var a = "selection.move", o = "selection.transform", s = "selection.resize", c = "selection.rotate";
@@ -68,7 +68,7 @@ function d(t = {}) {
68
68
  n.pivot && (i.pivot = n.pivot);
69
69
  let a = {
70
70
  ...Object.keys(i).length > 0 ? { params: i } : {},
71
- ...n.behaviors?.length ? { behaviors: n.behaviors } : {}
71
+ ...n.behaviors === void 0 ? {} : { behaviors: n.behaviors }
72
72
  };
73
73
  return [{
74
74
  spec: {
@@ -110,8 +110,8 @@ function g(e = {}) {
110
110
  bindings: d(e)
111
111
  };
112
112
  }
113
- var _ = "selection.areaSelect", v = i((e, t) => e == null && t === "empty");
114
- function y() {
113
+ var _ = "selection.areaSelect", v = i((e, t) => e == null && t === "empty"), y = i((e, t) => e == null && t !== "empty");
114
+ function b() {
115
115
  return {
116
116
  id: _,
117
117
  eligibility: { always: !0 },
@@ -125,6 +125,6 @@ function y() {
125
125
  };
126
126
  }
127
127
  //#endregion
128
- export { _ as AREA_SELECT_ID, a as SELECTION_MOVE_ID, s as SELECTION_RESIZE_ID, c as SELECTION_ROTATE_ID, o as SELECTION_TRANSFORM_ID, y as areaSelectContribution, v as onEmptyCanvas, l as selectionMoveBindings, p as selectionMoveContribution, u as selectionResizeBindings, h as selectionResizeContribution, d as selectionRotateBindings, g as selectionRotateContribution, f as selectionTransformBindings, m as selectionTransformContribution };
128
+ export { _ as AREA_SELECT_ID, a as SELECTION_MOVE_ID, s as SELECTION_RESIZE_ID, c as SELECTION_ROTATE_ID, o as SELECTION_TRANSFORM_ID, b as areaSelectContribution, y as onBody, v as onEmptyCanvas, l as selectionMoveBindings, p as selectionMoveContribution, u as selectionResizeBindings, h as selectionResizeContribution, d as selectionRotateBindings, g as selectionRotateContribution, f as selectionTransformBindings, m as selectionTransformContribution };
129
129
 
130
130
  //# sourceMappingURL=selectionContributions.js.map