@weasel-js/core 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1431) hide show
  1. package/CHANGELOG.md +587 -0
  2. package/README.md +16 -15
  3. package/dist/WeaselProvider.js +25 -9
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +217 -140
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +92 -50
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +147 -84
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js +140 -65
  12. package/dist/affordances/pathAnchors.js.map +1 -1
  13. package/dist/affordances/rotateCursor.js +10 -4
  14. package/dist/affordances/rotateCursor.js.map +1 -1
  15. package/dist/affordances/rotationHandle.js +83 -60
  16. package/dist/affordances/rotationHandle.js.map +1 -1
  17. package/dist/animation/behaviors/coast.js +20 -14
  18. package/dist/animation/behaviors/coast.js.map +1 -1
  19. package/dist/animation/behaviors/coastByWrite.js +98 -70
  20. package/dist/animation/behaviors/coastByWrite.js.map +1 -1
  21. package/dist/animation/behaviors/coastOnTargets.js +115 -67
  22. package/dist/animation/behaviors/coastOnTargets.js.map +1 -1
  23. package/dist/animation/behaviors/momentum.js +88 -53
  24. package/dist/animation/behaviors/momentum.js.map +1 -1
  25. package/dist/animation/clipTargets.js +14 -7
  26. package/dist/animation/clipTargets.js.map +1 -1
  27. package/dist/animation/departures.js +116 -0
  28. package/dist/animation/departures.js.map +1 -0
  29. package/dist/animation/index.js +18 -15
  30. package/dist/animation/poseHelpers.js +147 -107
  31. package/dist/animation/poseHelpers.js.map +1 -1
  32. package/dist/animation/poseTarget.js +158 -85
  33. package/dist/animation/poseTarget.js.map +1 -1
  34. package/dist/animation/poseTransition.js +64 -0
  35. package/dist/animation/poseTransition.js.map +1 -0
  36. package/dist/animation/reflow.js +208 -120
  37. package/dist/animation/reflow.js.map +1 -1
  38. package/dist/animation/rewind.js +76 -45
  39. package/dist/animation/rewind.js.map +1 -1
  40. package/dist/animation/rig/bindRig.js +135 -82
  41. package/dist/animation/rig/bindRig.js.map +1 -1
  42. package/dist/animation/rig/rigNode.js +120 -75
  43. package/dist/animation/rig/rigNode.js.map +1 -1
  44. package/dist/animation/rig/rigSeat.js +61 -41
  45. package/dist/animation/rig/rigSeat.js.map +1 -1
  46. package/dist/animation/rig/skinBinding.js +57 -45
  47. package/dist/animation/rig/skinBinding.js.map +1 -1
  48. package/dist/animation/rig/useRig.js +44 -30
  49. package/dist/animation/rig/useRig.js.map +1 -1
  50. package/dist/animation/wrappers/animateLifecycle.js +51 -35
  51. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  52. package/dist/animation/wrappers/animateOnSetPose.js +55 -32
  53. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  54. package/dist/animation/wrappers/instantPose.js +13 -8
  55. package/dist/animation/wrappers/instantPose.js.map +1 -1
  56. package/dist/animation/writtenPoseTarget.js +44 -22
  57. package/dist/animation/writtenPoseTarget.js.map +1 -1
  58. package/dist/{autoPoseDescriptor-DHg5KqaJ.d.ts → autoPoseDescriptor-CZ1eXbzY.d.ts} +1 -1
  59. package/dist/barrel/canvas.js +41 -32
  60. package/dist/barrel/chrome.js +19 -16
  61. package/dist/barrel/icons.js +6 -0
  62. package/dist/barrel/input.js +19 -18
  63. package/dist/barrel/interactions.js +40 -39
  64. package/dist/barrel/paint.js +12 -11
  65. package/dist/barrel/paths.js +39 -13
  66. package/dist/barrel/renderer.js +24 -14
  67. package/dist/barrel/routing.js +69 -58
  68. package/dist/barrel/scene.js +48 -37
  69. package/dist/barrel/text.js +10 -9
  70. package/dist/barrel/viewport.js +47 -45
  71. package/dist/canvas/Canvas.js +189 -306
  72. package/dist/canvas/Canvas.js.map +1 -1
  73. package/dist/canvas/CanvasView.js +273 -199
  74. package/dist/canvas/CanvasView.js.map +1 -1
  75. package/dist/canvas/CursorCoordsHud.js +103 -64
  76. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  77. package/dist/canvas/DrawCanvas.js +68 -41
  78. package/dist/canvas/DrawCanvas.js.map +1 -1
  79. package/dist/canvas/LeanSceneCanvas.js +23 -0
  80. package/dist/canvas/LeanSceneCanvas.js.map +1 -0
  81. package/dist/canvas/ModalityHud.js +58 -43
  82. package/dist/canvas/ModalityHud.js.map +1 -1
  83. package/dist/canvas/NodeShape.js +137 -60
  84. package/dist/canvas/NodeShape.js.map +1 -1
  85. package/dist/canvas/PickHud.js +77 -59
  86. package/dist/canvas/PickHud.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +9 -6
  88. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js.map +1 -1
  89. package/dist/canvas/SceneCanvas/CanvasKitProviders.js +25 -0
  90. package/dist/canvas/SceneCanvas/CanvasKitProviders.js.map +1 -0
  91. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +10 -6
  92. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/DevHuds.js +47 -32
  94. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -1
  95. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +72 -37
  96. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  97. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +110 -0
  98. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -0
  99. package/dist/canvas/SceneCanvas/brushOverlay.js +36 -0
  100. package/dist/canvas/SceneCanvas/brushOverlay.js.map +1 -0
  101. package/dist/canvas/SceneCanvas/canvasPassThrough.js +72 -0
  102. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -0
  103. package/dist/canvas/SceneCanvas/contributionFrameHooks.js +54 -32
  104. package/dist/canvas/SceneCanvas/contributionFrameHooks.js.map +1 -1
  105. package/dist/canvas/SceneCanvas/coordTrace.js +36 -29
  106. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  107. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +318 -159
  108. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  109. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +39 -13
  110. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  111. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js +83 -47
  112. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  113. package/dist/canvas/SceneCanvas/features.js +83 -106
  114. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  115. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +80 -62
  116. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -1
  117. package/dist/canvas/SceneCanvas/mergeLayers.js +43 -0
  118. package/dist/canvas/SceneCanvas/mergeLayers.js.map +1 -0
  119. package/dist/canvas/SceneCanvas/namedPresets.js +56 -0
  120. package/dist/canvas/SceneCanvas/namedPresets.js.map +1 -0
  121. package/dist/canvas/SceneCanvas/poseGeometry.js +66 -31
  122. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  123. package/dist/canvas/SceneCanvas/poseRegistrars.js +18 -8
  124. package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -1
  125. package/dist/canvas/SceneCanvas/presets/arrange.js +27 -0
  126. package/dist/canvas/SceneCanvas/presets/arrange.js.map +1 -0
  127. package/dist/canvas/SceneCanvas/presets/chrome.js +14 -0
  128. package/dist/canvas/SceneCanvas/presets/chrome.js.map +1 -0
  129. package/dist/canvas/SceneCanvas/presets/edit.js +59 -0
  130. package/dist/canvas/SceneCanvas/presets/edit.js.map +1 -0
  131. package/dist/canvas/SceneCanvas/presets/ingest.js +13 -0
  132. package/dist/canvas/SceneCanvas/presets/ingest.js.map +1 -0
  133. package/dist/canvas/SceneCanvas/presets/paths.js +67 -0
  134. package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -0
  135. package/dist/canvas/SceneCanvas/presets/select.js +19 -0
  136. package/dist/canvas/SceneCanvas/presets/select.js.map +1 -0
  137. package/dist/canvas/SceneCanvas/presets/toolDriven.js +20 -0
  138. package/dist/canvas/SceneCanvas/presets/toolDriven.js.map +1 -0
  139. package/dist/canvas/SceneCanvas/presets/transform.js +41 -0
  140. package/dist/canvas/SceneCanvas/presets/transform.js.map +1 -0
  141. package/dist/canvas/SceneCanvas/presets/view.js +14 -0
  142. package/dist/canvas/SceneCanvas/presets/view.js.map +1 -0
  143. package/dist/canvas/SceneCanvas/props.js +19 -35
  144. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  145. package/dist/canvas/SceneCanvas/scenePointQuery.js +43 -35
  146. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
  147. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +22 -15
  148. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -1
  149. package/dist/canvas/SceneCanvas/toolRegistry.js +30 -15
  150. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
  151. package/dist/canvas/SceneCanvas/useActionTunings.js +14 -11
  152. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
  153. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +68 -35
  154. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  155. package/dist/canvas/SceneCanvas/useBakedScene.js +17 -0
  156. package/dist/canvas/SceneCanvas/useBakedScene.js.map +1 -0
  157. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +65 -0
  158. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +1 -0
  159. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +47 -23
  160. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  161. package/dist/canvas/SceneCanvas/useBuiltinTools.js +29 -14
  162. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
  163. package/dist/canvas/SceneCanvas/useCanvasCamera.js +53 -38
  164. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -1
  165. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +24 -14
  166. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -1
  167. package/dist/canvas/SceneCanvas/useCanvasSelection.js +30 -12
  168. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
  169. package/dist/canvas/SceneCanvas/useCanvasTools.js +112 -53
  170. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  171. package/dist/canvas/SceneCanvas/useChromeAffordances.js +31 -0
  172. package/dist/canvas/SceneCanvas/useChromeAffordances.js.map +1 -0
  173. package/dist/canvas/SceneCanvas/useContributionRoles.js +107 -56
  174. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
  175. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js +64 -0
  176. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js.map +1 -0
  177. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +104 -71
  178. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  179. package/dist/canvas/SceneCanvas/useHeldModifiers.js +21 -14
  180. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -1
  181. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +21 -19
  182. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -1
  183. package/dist/canvas/SceneCanvas/useNodeKinds.js +28 -19
  184. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
  185. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +91 -59
  186. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  187. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +62 -35
  188. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
  189. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +110 -50
  190. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  191. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js +30 -0
  192. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js.map +1 -0
  193. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +40 -0
  194. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -0
  195. package/dist/canvas/SceneCanvas/useSceneChrome.js +100 -44
  196. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
  197. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +163 -0
  198. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -0
  199. package/dist/canvas/SceneCanvas/useScenePicking.js +69 -0
  200. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -0
  201. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +28 -17
  202. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -1
  203. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +159 -80
  204. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  205. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +38 -26
  206. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -1
  207. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +108 -0
  208. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -0
  209. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +40 -27
  210. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -1
  211. package/dist/canvas/SceneCanvas/useSurfaceRouting.js +29 -0
  212. package/dist/canvas/SceneCanvas/useSurfaceRouting.js.map +1 -0
  213. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js +44 -0
  214. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js.map +1 -0
  215. package/dist/canvas/SceneCanvas/useToolKeybindings.js +28 -0
  216. package/dist/canvas/SceneCanvas/useToolKeybindings.js.map +1 -0
  217. package/dist/canvas/SceneCanvas/useViewportActions.js +52 -28
  218. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  219. package/dist/canvas/SceneCanvas/worldPointAt.js +10 -4
  220. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
  221. package/dist/canvas/SceneCanvas.js +274 -312
  222. package/dist/canvas/SceneCanvas.js.map +1 -1
  223. package/dist/canvas/SceneViewCanvas.js +68 -42
  224. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  225. package/dist/canvas/SurfaceCanvas.js +53 -31
  226. package/dist/canvas/SurfaceCanvas.js.map +1 -1
  227. package/dist/canvas/accentColor.js +8 -5
  228. package/dist/canvas/accentColor.js.map +1 -1
  229. package/dist/canvas/adapterDerivedPath.js +33 -18
  230. package/dist/canvas/adapterDerivedPath.js.map +1 -1
  231. package/dist/canvas/adapterPickSource.js +49 -23
  232. package/dist/canvas/adapterPickSource.js.map +1 -1
  233. package/dist/canvas/affordanceAt.js +106 -50
  234. package/dist/canvas/affordanceAt.js.map +1 -1
  235. package/dist/canvas/buildSceneLayer.js +111 -80
  236. package/dist/canvas/buildSceneLayer.js.map +1 -1
  237. package/dist/canvas/buildSceneTree.js +101 -59
  238. package/dist/canvas/buildSceneTree.js.map +1 -1
  239. package/dist/canvas/canvasRenderer.js +156 -71
  240. package/dist/canvas/canvasRenderer.js.map +1 -1
  241. package/dist/canvas/colorOverrides.js +18 -10
  242. package/dist/canvas/colorOverrides.js.map +1 -1
  243. package/dist/canvas/copiesAbove.js +24 -14
  244. package/dist/canvas/copiesAbove.js.map +1 -1
  245. package/dist/canvas/defaultDrawOne.js +55 -31
  246. package/dist/canvas/defaultDrawOne.js.map +1 -1
  247. package/dist/canvas/deps/areaSelect.js +30 -12
  248. package/dist/canvas/deps/areaSelect.js.map +1 -1
  249. package/dist/canvas/deps/booleans.js +104 -0
  250. package/dist/canvas/deps/booleans.js.map +1 -0
  251. package/dist/canvas/deps/changes.js +17 -9
  252. package/dist/canvas/deps/changes.js.map +1 -1
  253. package/dist/canvas/deps/debug.js +12 -5
  254. package/dist/canvas/deps/debug.js.map +1 -1
  255. package/dist/canvas/deps/dispatchSources.js +27 -0
  256. package/dist/canvas/deps/dispatchSources.js.map +1 -0
  257. package/dist/canvas/deps/dispatcher.js +18 -7
  258. package/dist/canvas/deps/dispatcher.js.map +1 -1
  259. package/dist/canvas/deps/editAnchors.js +253 -63
  260. package/dist/canvas/deps/editAnchors.js.map +1 -1
  261. package/dist/canvas/deps/geometryProjection.js +13 -7
  262. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  263. package/dist/canvas/deps/hitTestArea.js +78 -53
  264. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  265. package/dist/canvas/deps/ingestion.js +18 -13
  266. package/dist/canvas/deps/ingestion.js.map +1 -1
  267. package/dist/canvas/deps/insert.js +176 -116
  268. package/dist/canvas/deps/insert.js.map +1 -1
  269. package/dist/canvas/deps/kitSettings.js +16 -0
  270. package/dist/canvas/deps/kitSettings.js.map +1 -0
  271. package/dist/canvas/deps/lassoSelect.js +25 -13
  272. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  273. package/dist/canvas/deps/layout.js +32 -20
  274. package/dist/canvas/deps/layout.js.map +1 -1
  275. package/dist/canvas/deps/nodeAtPoint.js +28 -14
  276. package/dist/canvas/deps/nodeAtPoint.js.map +1 -1
  277. package/dist/canvas/deps/pathLeaf.js +66 -0
  278. package/dist/canvas/deps/pathLeaf.js.map +1 -0
  279. package/dist/canvas/deps/pathLeafDeps.js +13 -0
  280. package/dist/canvas/deps/pathLeafDeps.js.map +1 -0
  281. package/dist/canvas/deps/poseDescriptor.js +10 -8
  282. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  283. package/dist/canvas/deps/previewPaths.js +44 -0
  284. package/dist/canvas/deps/previewPaths.js.map +1 -0
  285. package/dist/canvas/deps/resizePolicy.js +32 -25
  286. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  287. package/dist/canvas/deps/slice.js +73 -87
  288. package/dist/canvas/deps/slice.js.map +1 -1
  289. package/dist/canvas/deps/snap.js +58 -7
  290. package/dist/canvas/deps/snap.js.map +1 -1
  291. package/dist/canvas/deps/surface.js +30 -0
  292. package/dist/canvas/deps/surface.js.map +1 -0
  293. package/dist/canvas/deps/textEdit.js +21 -13
  294. package/dist/canvas/deps/textEdit.js.map +1 -1
  295. package/dist/canvas/deps/view.js +46 -34
  296. package/dist/canvas/deps/view.js.map +1 -1
  297. package/dist/canvas/derivedPath.js +154 -70
  298. package/dist/canvas/derivedPath.js.map +1 -1
  299. package/dist/canvas/doubleClickTarget.js +20 -0
  300. package/dist/canvas/doubleClickTarget.js.map +1 -0
  301. package/dist/canvas/drawEnvelope.js +26 -17
  302. package/dist/canvas/drawEnvelope.js.map +1 -1
  303. package/dist/canvas/drawnBounds.js +116 -0
  304. package/dist/canvas/drawnBounds.js.map +1 -0
  305. package/dist/canvas/getNodeAtPoint.js +11 -8
  306. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  307. package/dist/canvas/hostAnchor.js +35 -18
  308. package/dist/canvas/hostAnchor.js.map +1 -1
  309. package/dist/canvas/hud.module.js +25 -14
  310. package/dist/canvas/hud.module.js.map +1 -1
  311. package/dist/canvas/insertPreviewExtent.js +82 -61
  312. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  313. package/dist/canvas/kitRequirements.js +154 -115
  314. package/dist/canvas/kitRequirements.js.map +1 -1
  315. package/dist/canvas/layerHover.js +28 -0
  316. package/dist/canvas/layerHover.js.map +1 -0
  317. package/dist/canvas/layerOrder.js +107 -57
  318. package/dist/canvas/layerOrder.js.map +1 -1
  319. package/dist/canvas/layerSlots.js +16 -9
  320. package/dist/canvas/layerSlots.js.map +1 -1
  321. package/dist/canvas/mountedCanvases.js +23 -13
  322. package/dist/canvas/mountedCanvases.js.map +1 -1
  323. package/dist/canvas/nodeShapes/derivedPainter.js +65 -25
  324. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  325. package/dist/canvas/nodeShapes/imagePainter.js +69 -53
  326. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  327. package/dist/canvas/nodeShapes/measurePainter.js +58 -0
  328. package/dist/canvas/nodeShapes/measurePainter.js.map +1 -0
  329. package/dist/canvas/nodeShapes/memo.js +16 -5
  330. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  331. package/dist/canvas/nodeShapes/nodePaint.js +125 -46
  332. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  333. package/dist/canvas/nodeShapes/pathPainter.js +41 -27
  334. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  335. package/dist/canvas/nodeShapes/poseBox.js +20 -13
  336. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  337. package/dist/canvas/nodeShapes/rectFallbackPainter.js +26 -22
  338. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  339. package/dist/canvas/nodeShapes/shapePainter.js +67 -46
  340. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  341. package/dist/canvas/nodeShapes/strokedBounds.js +177 -0
  342. package/dist/canvas/nodeShapes/strokedBounds.js.map +1 -0
  343. package/dist/canvas/nodeShapes/textPainter.js +170 -37
  344. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  345. package/dist/canvas/overChildren.js +29 -18
  346. package/dist/canvas/overChildren.js.map +1 -1
  347. package/dist/canvas/overlayRoleStrokes.js +20 -3
  348. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  349. package/dist/canvas/paintCull.js +24 -12
  350. package/dist/canvas/paintCull.js.map +1 -1
  351. package/dist/canvas/paintedCursorLayer.js +59 -35
  352. package/dist/canvas/paintedCursorLayer.js.map +1 -1
  353. package/dist/canvas/pathOverlay.js +63 -0
  354. package/dist/canvas/pathOverlay.js.map +1 -0
  355. package/dist/canvas/pickReach.js +34 -17
  356. package/dist/canvas/pickReach.js.map +1 -1
  357. package/dist/canvas/pickWalk.js +151 -102
  358. package/dist/canvas/pickWalk.js.map +1 -1
  359. package/dist/canvas/planeClips.js +39 -22
  360. package/dist/canvas/planeClips.js.map +1 -1
  361. package/dist/canvas/poseCascade.js +51 -27
  362. package/dist/canvas/poseCascade.js.map +1 -1
  363. package/dist/canvas/poseRotation.js +24 -14
  364. package/dist/canvas/poseRotation.js.map +1 -1
  365. package/dist/canvas/rasterReadback.js +23 -15
  366. package/dist/canvas/rasterReadback.js.map +1 -1
  367. package/dist/canvas/rasterToPng.js +21 -15
  368. package/dist/canvas/rasterToPng.js.map +1 -1
  369. package/dist/canvas/renderDebugSnapshot.js +36 -19
  370. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  371. package/dist/canvas/renderNeeds.js +33 -18
  372. package/dist/canvas/renderNeeds.js.map +1 -1
  373. package/dist/canvas/renderSceneToPixels.js +202 -87
  374. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  375. package/dist/canvas/sceneAdapter.js +96 -75
  376. package/dist/canvas/sceneAdapter.js.map +1 -1
  377. package/dist/canvas/sceneClipboard.js +141 -92
  378. package/dist/canvas/sceneClipboard.js.map +1 -1
  379. package/dist/canvas/sceneLayerPaint.js +56 -27
  380. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  381. package/dist/canvas/sceneSlotWiring.js +24 -14
  382. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  383. package/dist/canvas/sceneViewRender.js +85 -49
  384. package/dist/canvas/sceneViewRender.js.map +1 -1
  385. package/dist/canvas/slopsDebugLayer.js +58 -49
  386. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  387. package/dist/canvas/surfaceContribution.js +22 -10
  388. package/dist/canvas/surfaceContribution.js.map +1 -1
  389. package/dist/canvas/useCanvasElements.js +31 -0
  390. package/dist/canvas/useCanvasElements.js.map +1 -0
  391. package/dist/canvas/useCanvasHandle.js +69 -0
  392. package/dist/canvas/useCanvasHandle.js.map +1 -0
  393. package/dist/canvas/useCanvasPaint.js +91 -0
  394. package/dist/canvas/useCanvasPaint.js.map +1 -0
  395. package/dist/canvas/useCanvasRenderer.js +45 -23
  396. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  397. package/dist/canvas/useCanvasSurface.js +41 -23
  398. package/dist/canvas/useCanvasSurface.js.map +1 -1
  399. package/dist/canvas/useCanvasView.js +80 -48
  400. package/dist/canvas/useCanvasView.js.map +1 -1
  401. package/dist/canvas/useClientToWorld.js +27 -0
  402. package/dist/canvas/useClientToWorld.js.map +1 -0
  403. package/dist/canvas/useExtraLayers.js +45 -0
  404. package/dist/canvas/useExtraLayers.js.map +1 -0
  405. package/dist/canvas/useFrameLoop.js +109 -49
  406. package/dist/canvas/useFrameLoop.js.map +1 -1
  407. package/dist/canvas/useHitObserver.js +22 -15
  408. package/dist/canvas/useHitObserver.js.map +1 -1
  409. package/dist/canvas/useHostAnchor.js +83 -53
  410. package/dist/canvas/useHostAnchor.js.map +1 -1
  411. package/dist/canvas/useLateContentRedraw.js +21 -14
  412. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  413. package/dist/canvas/useLayerStack.js +72 -0
  414. package/dist/canvas/useLayerStack.js.map +1 -0
  415. package/dist/canvas/usePaintedCursor.js +28 -0
  416. package/dist/canvas/usePaintedCursor.js.map +1 -0
  417. package/dist/canvas/useRedrawOn.js +24 -14
  418. package/dist/canvas/useRedrawOn.js.map +1 -1
  419. package/dist/canvas/useSceneAdapter.js +21 -16
  420. package/dist/canvas/useSceneAdapter.js.map +1 -1
  421. package/dist/canvas/useSceneLayerList.js +15 -7
  422. package/dist/canvas/useSceneLayerList.js.map +1 -1
  423. package/dist/canvas/useSurfaceInput.js +46 -27
  424. package/dist/canvas/useSurfaceInput.js.map +1 -1
  425. package/dist/canvas/useSurfaceSize.js +43 -0
  426. package/dist/canvas/useSurfaceSize.js.map +1 -0
  427. package/dist/canvas/useToolCursor.js +30 -21
  428. package/dist/canvas/useToolCursor.js.map +1 -1
  429. package/dist/canvas/useViewHelpers.js +112 -61
  430. package/dist/canvas/useViewHelpers.js.map +1 -1
  431. package/dist/canvas/useViewLayerGate.js +29 -0
  432. package/dist/canvas/useViewLayerGate.js.map +1 -0
  433. package/dist/canvas/useViewNesting.js +104 -0
  434. package/dist/canvas/useViewNesting.js.map +1 -0
  435. package/dist/canvas/useViewRegistrySurface.js +44 -0
  436. package/dist/canvas/useViewRegistrySurface.js.map +1 -0
  437. package/dist/canvas/viewInputs.js +14 -11
  438. package/dist/canvas/viewInputs.js.map +1 -1
  439. package/dist/canvas/viewRegistry.js +140 -42
  440. package/dist/canvas/viewRegistry.js.map +1 -1
  441. package/dist/canvas/watchElementMove.js +71 -33
  442. package/dist/canvas/watchElementMove.js.map +1 -1
  443. package/dist/canvas/wrapNodeOutput.js +20 -13
  444. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  445. package/dist/clipboard.d.ts +7 -3
  446. package/dist/clipboard.js +4 -3
  447. package/dist/{clone-C0eADtS0.d.ts → clone-DZDrfIlU.d.ts} +20 -53
  448. package/dist/clone.d.ts +5 -4
  449. package/dist/core/adapters/testing/rootsTree.js +17 -0
  450. package/dist/core/adapters/testing/rootsTree.js.map +1 -0
  451. package/dist/core/applyOps.js +23 -7
  452. package/dist/core/applyOps.js.map +1 -1
  453. package/dist/core/device/index.js +6 -5
  454. package/dist/core/device/targets.js +29 -8
  455. package/dist/core/device/targets.js.map +1 -1
  456. package/dist/core/device/useDeviceProfile.js +86 -52
  457. package/dist/core/device/useDeviceProfile.js.map +1 -1
  458. package/dist/core/device/useTargetBasePx.js +23 -0
  459. package/dist/core/device/useTargetBasePx.js.map +1 -0
  460. package/dist/core/device/watchDevicePixelRatio.js +27 -10
  461. package/dist/core/device/watchDevicePixelRatio.js.map +1 -1
  462. package/dist/core/geometry/autoPoseDescriptor.js +38 -24
  463. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -1
  464. package/dist/core/geometry/inkExtents.js +60 -0
  465. package/dist/core/geometry/inkExtents.js.map +1 -0
  466. package/dist/core/geometry/pathPoseDescriptor.js +101 -76
  467. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -1
  468. package/dist/core/geometry/poseDescriptor.js +199 -136
  469. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  470. package/dist/core/geometry/regionHit.js +127 -79
  471. package/dist/core/geometry/regionHit.js.map +1 -1
  472. package/dist/core/geometry/targetFrame.js +84 -60
  473. package/dist/core/geometry/targetFrame.js.map +1 -1
  474. package/dist/core/geometry/unionBounds.js +103 -48
  475. package/dist/core/geometry/unionBounds.js.map +1 -1
  476. package/dist/core/isPlainObject.js +3 -2
  477. package/dist/core/layers/backgroundFill.js +23 -15
  478. package/dist/core/layers/backgroundFill.js.map +1 -1
  479. package/dist/core/layers/children.js +16 -13
  480. package/dist/core/layers/children.js.map +1 -1
  481. package/dist/core/layers/gateLayer.js +24 -9
  482. package/dist/core/layers/gateLayer.js.map +1 -1
  483. package/dist/core/layers/layerGroup.js +42 -29
  484. package/dist/core/layers/layerGroup.js.map +1 -1
  485. package/dist/core/layers/redrawSource.js +15 -0
  486. package/dist/core/layers/redrawSource.js.map +1 -0
  487. package/dist/core/layers/render.js +183 -93
  488. package/dist/core/layers/render.js.map +1 -1
  489. package/dist/core/layers/retain.js +38 -0
  490. package/dist/core/layers/retain.js.map +1 -0
  491. package/dist/core/ops/arrange.js +30 -19
  492. package/dist/core/ops/arrange.js.map +1 -1
  493. package/dist/core/ops/create.js +32 -23
  494. package/dist/core/ops/create.js.map +1 -1
  495. package/dist/core/ops/createHistory.js +23 -14
  496. package/dist/core/ops/createHistory.js.map +1 -1
  497. package/dist/core/ops/delete.js +80 -53
  498. package/dist/core/ops/delete.js.map +1 -1
  499. package/dist/core/ops/nodeFlags.js +44 -0
  500. package/dist/core/ops/nodeFlags.js.map +1 -0
  501. package/dist/core/ops/registry.js +26 -11
  502. package/dist/core/ops/registry.js.map +1 -1
  503. package/dist/core/ops/reorder/algorithms.js +62 -38
  504. package/dist/core/ops/reorder/algorithms.js.map +1 -1
  505. package/dist/core/ops/reorder/index.js +124 -84
  506. package/dist/core/ops/reorder/index.js.map +1 -1
  507. package/dist/core/ops/reorder/setChildOrder.js +32 -23
  508. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  509. package/dist/core/ops/reparent.js +63 -37
  510. package/dist/core/ops/reparent.js.map +1 -1
  511. package/dist/core/ops/select.js +23 -20
  512. package/dist/core/ops/select.js.map +1 -1
  513. package/dist/core/ops/setData.js +23 -21
  514. package/dist/core/ops/setData.js.map +1 -1
  515. package/dist/core/ops/setLayer.js +26 -21
  516. package/dist/core/ops/setLayer.js.map +1 -1
  517. package/dist/core/ops/setLayout.js +27 -18
  518. package/dist/core/ops/setLayout.js.map +1 -1
  519. package/dist/core/ops/setPath.js +60 -41
  520. package/dist/core/ops/setPath.js.map +1 -1
  521. package/dist/core/ops/setText.js +26 -21
  522. package/dist/core/ops/setText.js.map +1 -1
  523. package/dist/core/ops/slot.js +36 -22
  524. package/dist/core/ops/slot.js.map +1 -1
  525. package/dist/core/ops/transform.js +35 -28
  526. package/dist/core/ops/transform.js.map +1 -1
  527. package/dist/core/pages/fitViewToPage.js +13 -11
  528. package/dist/core/pages/fitViewToPage.js.map +1 -1
  529. package/dist/core/pages/pages.js +73 -42
  530. package/dist/core/pages/pages.js.map +1 -1
  531. package/dist/core/pages/pagesLayer.js +19 -13
  532. package/dist/core/pages/pagesLayer.js.map +1 -1
  533. package/dist/core/paint/meshKind.js +16 -11
  534. package/dist/core/paint/meshKind.js.map +1 -1
  535. package/dist/core/paint/meshKindLazy.js +1 -1
  536. package/dist/core/paint/meshKindLazy.js.map +1 -1
  537. package/dist/core/paint/paintKindEntry.js +13 -4
  538. package/dist/core/paint/paintKindEntry.js.map +1 -1
  539. package/dist/core/paint/paintKinds.js +149 -88
  540. package/dist/core/paint/paintKinds.js.map +1 -1
  541. package/dist/core/paint/registerMesh.js +6 -4
  542. package/dist/core/paint/registerMesh.js.map +1 -1
  543. package/dist/core/scene/NodeProperties.js +15 -10
  544. package/dist/core/scene/NodeProperties.js.map +1 -1
  545. package/dist/core/scene/NodeRouting.js +16 -12
  546. package/dist/core/scene/NodeRouting.js.map +1 -1
  547. package/dist/core/scene/annotation.js +28 -0
  548. package/dist/core/scene/annotation.js.map +1 -0
  549. package/dist/core/scene/appliedLog.js +31 -23
  550. package/dist/core/scene/appliedLog.js.map +1 -1
  551. package/dist/core/scene/arrivalWindow.js +120 -75
  552. package/dist/core/scene/arrivalWindow.js.map +1 -1
  553. package/dist/core/scene/arrivals.js +17 -6
  554. package/dist/core/scene/arrivals.js.map +1 -1
  555. package/dist/core/scene/boundOps.js +42 -23
  556. package/dist/core/scene/boundOps.js.map +1 -1
  557. package/dist/core/scene/composeFrame.js +51 -21
  558. package/dist/core/scene/composeFrame.js.map +1 -1
  559. package/dist/core/scene/composePose.js +114 -62
  560. package/dist/core/scene/composePose.js.map +1 -1
  561. package/dist/core/scene/depFrame.js +94 -0
  562. package/dist/core/scene/depFrame.js.map +1 -0
  563. package/dist/core/scene/depMemo.js +44 -19
  564. package/dist/core/scene/depMemo.js.map +1 -1
  565. package/dist/core/scene/dependents.js +73 -45
  566. package/dist/core/scene/dependents.js.map +1 -1
  567. package/dist/core/scene/derivedParts.js +58 -0
  568. package/dist/core/scene/derivedParts.js.map +1 -0
  569. package/dist/core/scene/derivedPath.js +52 -22
  570. package/dist/core/scene/derivedPath.js.map +1 -1
  571. package/dist/core/scene/editMode.js +11 -11
  572. package/dist/core/scene/editMode.js.map +1 -1
  573. package/dist/core/scene/effectivePose.js +167 -51
  574. package/dist/core/scene/effectivePose.js.map +1 -1
  575. package/dist/core/scene/fieldEdits.js +95 -75
  576. package/dist/core/scene/fieldEdits.js.map +1 -1
  577. package/dist/core/scene/historyFacade.js +126 -87
  578. package/dist/core/scene/historyFacade.js.map +1 -1
  579. package/dist/core/scene/historyForm.js +7 -3
  580. package/dist/core/scene/historyForm.js.map +1 -1
  581. package/dist/core/scene/kitOps.js +203 -131
  582. package/dist/core/scene/kitOps.js.map +1 -1
  583. package/dist/core/scene/kitRegistry.js +49 -22
  584. package/dist/core/scene/kitRegistry.js.map +1 -1
  585. package/dist/core/scene/layerStack.js +123 -92
  586. package/dist/core/scene/layerStack.js.map +1 -1
  587. package/dist/core/scene/layoutPass.js +118 -72
  588. package/dist/core/scene/layoutPass.js.map +1 -1
  589. package/dist/core/scene/lockGuard.js +32 -24
  590. package/dist/core/scene/lockGuard.js.map +1 -1
  591. package/dist/core/scene/minSize.js +17 -0
  592. package/dist/core/scene/minSize.js.map +1 -0
  593. package/dist/core/scene/nestedHit.js +45 -31
  594. package/dist/core/scene/nestedHit.js.map +1 -1
  595. package/dist/core/scene/nodeFlags.js +43 -0
  596. package/dist/core/scene/nodeFlags.js.map +1 -0
  597. package/dist/core/scene/nodeFnFields.js +58 -41
  598. package/dist/core/scene/nodeFnFields.js.map +1 -1
  599. package/dist/core/scene/nodeGates.js +58 -0
  600. package/dist/core/scene/nodeGates.js.map +1 -0
  601. package/dist/core/scene/nodeMemo.js +92 -40
  602. package/dist/core/scene/nodeMemo.js.map +1 -1
  603. package/dist/core/scene/nodeStore.js +179 -99
  604. package/dist/core/scene/nodeStore.js.map +1 -1
  605. package/dist/core/scene/notifier.js +30 -19
  606. package/dist/core/scene/notifier.js.map +1 -1
  607. package/dist/core/scene/opTable.js +42 -36
  608. package/dist/core/scene/opTable.js.map +1 -1
  609. package/dist/core/scene/outerOps.js +49 -43
  610. package/dist/core/scene/outerOps.js.map +1 -1
  611. package/dist/core/scene/pathEffects/blend.js +80 -0
  612. package/dist/core/scene/pathEffects/blend.js.map +1 -0
  613. package/dist/core/scene/pathEffects/derive.js +112 -0
  614. package/dist/core/scene/pathEffects/derive.js.map +1 -0
  615. package/dist/core/scene/pathEffects/effects.js +40 -0
  616. package/dist/core/scene/pathEffects/effects.js.map +1 -0
  617. package/dist/core/scene/poseFeed.js +95 -60
  618. package/dist/core/scene/poseFeed.js.map +1 -1
  619. package/dist/core/scene/poseHold.js +33 -24
  620. package/dist/core/scene/poseHold.js.map +1 -1
  621. package/dist/core/scene/poseOverrides.js +86 -49
  622. package/dist/core/scene/poseOverrides.js.map +1 -1
  623. package/dist/core/scene/poseRemovals.js +58 -0
  624. package/dist/core/scene/poseRemovals.js.map +1 -0
  625. package/dist/core/scene/poseSnapshot.js +62 -41
  626. package/dist/core/scene/poseSnapshot.js.map +1 -1
  627. package/dist/core/scene/poseWrites.js +151 -0
  628. package/dist/core/scene/poseWrites.js.map +1 -0
  629. package/dist/core/scene/reconcileSpecs.js +63 -34
  630. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  631. package/dist/core/scene/recorder.js +90 -57
  632. package/dist/core/scene/recorder.js.map +1 -1
  633. package/dist/core/scene/renderOrder.js +105 -59
  634. package/dist/core/scene/renderOrder.js.map +1 -1
  635. package/dist/core/scene/scene.js +133 -80
  636. package/dist/core/scene/scene.js.map +1 -1
  637. package/dist/core/scene/sceneEdits.js +62 -49
  638. package/dist/core/scene/sceneEdits.js.map +1 -1
  639. package/dist/core/scene/sceneMutators.js +44 -36
  640. package/dist/core/scene/sceneMutators.js.map +1 -1
  641. package/dist/core/scene/scenePoseAdapter.js +13 -9
  642. package/dist/core/scene/scenePoseAdapter.js.map +1 -1
  643. package/dist/core/scene/sceneRecording.js +89 -73
  644. package/dist/core/scene/sceneRecording.js.map +1 -1
  645. package/dist/core/scene/sceneSelection.js +23 -16
  646. package/dist/core/scene/sceneSelection.js.map +1 -1
  647. package/dist/core/scene/sceneState.js +54 -36
  648. package/dist/core/scene/sceneState.js.map +1 -1
  649. package/dist/core/scene/serialization.js +87 -50
  650. package/dist/core/scene/serialization.js.map +1 -1
  651. package/dist/core/scene/staleReplay.js +35 -26
  652. package/dist/core/scene/staleReplay.js.map +1 -1
  653. package/dist/core/scene/statedFields.js +10 -5
  654. package/dist/core/scene/statedFields.js.map +1 -1
  655. package/dist/core/scene/treeEdits.js +129 -98
  656. package/dist/core/scene/treeEdits.js.map +1 -1
  657. package/dist/core/scene/treeOrder.js +13 -8
  658. package/dist/core/scene/treeOrder.js.map +1 -1
  659. package/dist/core/scene/treeReads.js +25 -16
  660. package/dist/core/scene/treeReads.js.map +1 -1
  661. package/dist/core/scene/types.js +4 -3
  662. package/dist/core/scene/types.js.map +1 -1
  663. package/dist/core/scene/unionOfChildren.js +20 -10
  664. package/dist/core/scene/unionOfChildren.js.map +1 -1
  665. package/dist/core/scene/unitScopes.js +15 -8
  666. package/dist/core/scene/unitScopes.js.map +1 -1
  667. package/dist/core/scene/useScene.js +32 -24
  668. package/dist/core/scene/useScene.js.map +1 -1
  669. package/dist/core/selection/chromeState.js +41 -17
  670. package/dist/core/selection/chromeState.js.map +1 -1
  671. package/dist/core/selection/readOnlySelection.js +39 -24
  672. package/dist/core/selection/readOnlySelection.js.map +1 -1
  673. package/dist/core/selection/selectionTarget.js +14 -3
  674. package/dist/core/selection/selectionTarget.js.map +1 -1
  675. package/dist/core/selection/usePublishSceneSelection.js +25 -18
  676. package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
  677. package/dist/core/selection/useSelection.js +90 -57
  678. package/dist/core/selection/useSelection.js.map +1 -1
  679. package/dist/core/shapeKinds.js +43 -28
  680. package/dist/core/shapeKinds.js.map +1 -1
  681. package/dist/core/stableStringify.js +5 -4
  682. package/dist/core/stableStringify.js.map +1 -1
  683. package/dist/core/stylus/stylus.js +49 -25
  684. package/dist/core/stylus/stylus.js.map +1 -1
  685. package/dist/core/stylus/usePointerStylus.js +61 -34
  686. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  687. package/dist/core/usePaintKinds.js +21 -11
  688. package/dist/core/usePaintKinds.js.map +1 -1
  689. package/dist/core/viewport/clampView.js +31 -15
  690. package/dist/core/viewport/clampView.js.map +1 -1
  691. package/dist/core/viewport/clientToWorld.js +15 -4
  692. package/dist/core/viewport/clientToWorld.js.map +1 -1
  693. package/dist/core/viewport/createVelocityTracker.js +23 -19
  694. package/dist/core/viewport/createVelocityTracker.js.map +1 -1
  695. package/dist/core/viewport/fitToBounds.js +28 -11
  696. package/dist/core/viewport/fitToBounds.js.map +1 -1
  697. package/dist/core/viewport/fitViewToBounds.js +45 -19
  698. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  699. package/dist/core/viewport/interpolateView.js +40 -20
  700. package/dist/core/viewport/interpolateView.js.map +1 -1
  701. package/dist/core/viewport/parallax.js +89 -56
  702. package/dist/core/viewport/parallax.js.map +1 -1
  703. package/dist/core/viewport/sceneNodeClientRect.js +21 -12
  704. package/dist/core/viewport/sceneNodeClientRect.js.map +1 -1
  705. package/dist/core/viewport/screenSlop.js +40 -17
  706. package/dist/core/viewport/screenSlop.js.map +1 -1
  707. package/dist/core/viewport/useAutoCenter.js +36 -22
  708. package/dist/core/viewport/useAutoCenter.js.map +1 -1
  709. package/dist/core/viewport/useCanvasSize.js +43 -22
  710. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  711. package/dist/core/viewport/useDecayLoop.js +120 -48
  712. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  713. package/dist/core/viewport/useNodeOverlayFrame.js +93 -58
  714. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -1
  715. package/dist/core/viewport/useVelocityTracker.js +9 -6
  716. package/dist/core/viewport/useVelocityTracker.js.map +1 -1
  717. package/dist/core/viewport/useViewAnimation.js +143 -84
  718. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  719. package/dist/core/viewport/view.js +48 -24
  720. package/dist/core/viewport/view.js.map +1 -1
  721. package/dist/core/viewport/viewTransform.js +8 -6
  722. package/dist/core/viewport/viewTransform.js.map +1 -1
  723. package/dist/core/viewport/viewportWorldRect.js +15 -7
  724. package/dist/core/viewport/viewportWorldRect.js.map +1 -1
  725. package/dist/core/viewport/wheelHandler.js +31 -20
  726. package/dist/core/viewport/wheelHandler.js.map +1 -1
  727. package/dist/core/viewport/zoomAt.js +47 -19
  728. package/dist/core/viewport/zoomAt.js.map +1 -1
  729. package/dist/core/viewport/zoomBounds.js +33 -17
  730. package/dist/core/viewport/zoomBounds.js.map +1 -1
  731. package/dist/cornerHandles-Camw_yeu.d.ts +169 -0
  732. package/dist/debug/createDebugOverlayLayer.js +303 -215
  733. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  734. package/dist/debug/createDebugSink.js +68 -47
  735. package/dist/debug/createDebugSink.js.map +1 -1
  736. package/dist/debug/defaultTheme.js +16 -4
  737. package/dist/debug/defaultTheme.js.map +1 -1
  738. package/dist/debug/flag.js +3 -2
  739. package/dist/debug/frameStats.js +11 -9
  740. package/dist/debug/frameStats.js.map +1 -1
  741. package/dist/debug/parseDebugFlags.js +25 -17
  742. package/dist/debug/parseDebugFlags.js.map +1 -1
  743. package/dist/debug/useDebugSink.js +52 -33
  744. package/dist/debug/useDebugSink.js.map +1 -1
  745. package/dist/depSchema-Cgfu_G9s.d.ts +3581 -0
  746. package/dist/features/chrome-caps/buildChromeCtx.js +12 -10
  747. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  748. package/dist/features/chrome-caps/conditions.js +103 -25
  749. package/dist/features/chrome-caps/conditions.js.map +1 -1
  750. package/dist/features/chrome-caps/defaults.js +18 -10
  751. package/dist/features/chrome-caps/defaults.js.map +1 -1
  752. package/dist/features/chrome-caps/index.js +8 -7
  753. package/dist/features/chrome-caps/resolve.js +28 -16
  754. package/dist/features/chrome-caps/resolve.js.map +1 -1
  755. package/dist/features/chrome-caps/useChromeCaps.js +52 -44
  756. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -1
  757. package/dist/features/chrome-caps/useHoverTracking.js +52 -26
  758. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  759. package/dist/features/ingestion/contentHandlers.js +80 -34
  760. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  761. package/dist/features/ingestion/imageHandler.js +49 -29
  762. package/dist/features/ingestion/imageHandler.js.map +1 -1
  763. package/dist/features/ingestion/openFilePicker.js +27 -9
  764. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  765. package/dist/features/ingestion/placement.js +20 -11
  766. package/dist/features/ingestion/placement.js.map +1 -1
  767. package/dist/features/ingestion/registerKitHandlers.js +35 -18
  768. package/dist/features/ingestion/registerKitHandlers.js.map +1 -1
  769. package/dist/features/ingestion/svgHandler.js +60 -34
  770. package/dist/features/ingestion/svgHandler.js.map +1 -1
  771. package/dist/features/ingestion/textHandler.js +37 -16
  772. package/dist/features/ingestion/textHandler.js.map +1 -1
  773. package/dist/features/ingestion/useCanvasIngestion.js +57 -39
  774. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -1
  775. package/dist/features/ingestion/weaselJsonHandler.js +38 -28
  776. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  777. package/dist/features/longPress/longPressFeedback.js +110 -81
  778. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  779. package/dist/features/measure/actionIds.js +22 -0
  780. package/dist/features/measure/actionIds.js.map +1 -0
  781. package/dist/features/measure/measureCommands.js +178 -0
  782. package/dist/features/measure/measureCommands.js.map +1 -0
  783. package/dist/features/measure/measureContribution.js +57 -0
  784. package/dist/features/measure/measureContribution.js.map +1 -0
  785. package/dist/features/measure/measureEdits.js +82 -0
  786. package/dist/features/measure/measureEdits.js.map +1 -0
  787. package/dist/features/measure/measureGestures.js +185 -0
  788. package/dist/features/measure/measureGestures.js.map +1 -0
  789. package/dist/features/measure/measureHit.js +80 -0
  790. package/dist/features/measure/measureHit.js.map +1 -0
  791. package/dist/features/measure/measureLayer.js +86 -0
  792. package/dist/features/measure/measureLayer.js.map +1 -0
  793. package/dist/features/measure/measurement.js +79 -0
  794. package/dist/features/measure/measurement.js.map +1 -0
  795. package/dist/features/measure/measurements.js +41 -0
  796. package/dist/features/measure/measurements.js.map +1 -0
  797. package/dist/features/modes/modeLayers.js +81 -55
  798. package/dist/features/modes/modeLayers.js.map +1 -1
  799. package/dist/features/modes/modeTriggers.js +66 -0
  800. package/dist/features/modes/modeTriggers.js.map +1 -0
  801. package/dist/features/pathEffects/index.js +35 -0
  802. package/dist/features/pathEffects/index.js.map +1 -0
  803. package/dist/features/pathEffects/readSource.js +46 -0
  804. package/dist/features/pathEffects/readSource.js.map +1 -0
  805. package/dist/features/paths/anchorData.js +65 -0
  806. package/dist/features/paths/anchorData.js.map +1 -0
  807. package/dist/features/paths/anchorMarkers.js +137 -0
  808. package/dist/features/paths/anchorMarkers.js.map +1 -0
  809. package/dist/features/paths/editablePath.js +149 -46
  810. package/dist/features/paths/editablePath.js.map +1 -1
  811. package/dist/features/paths/index.js +12 -9
  812. package/dist/features/paths/originProjection.js +16 -9
  813. package/dist/features/paths/originProjection.js.map +1 -1
  814. package/dist/features/paths/pathEditExtension.js +26 -0
  815. package/dist/features/paths/pathEditExtension.js.map +1 -0
  816. package/dist/features/paths/pathEditState.js +107 -26
  817. package/dist/features/paths/pathEditState.js.map +1 -1
  818. package/dist/features/paths/pathEditingOverlayLayer.js +58 -110
  819. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  820. package/dist/features/paths/pathLayer.js +79 -29
  821. package/dist/features/paths/pathLayer.js.map +1 -1
  822. package/dist/features/paths/pathRepresentation.js +27 -0
  823. package/dist/features/paths/pathRepresentation.js.map +1 -0
  824. package/dist/features/paths/pathSnap/glyphs.js +39 -0
  825. package/dist/features/paths/pathSnap/glyphs.js.map +1 -0
  826. package/dist/features/paths/pathSnap/pathSnapSource.js +82 -0
  827. package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -0
  828. package/dist/features/paths/pathSnap/sceneIndex.js +78 -0
  829. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -0
  830. package/dist/features/paths/pathSnap/snapGeometry.js +47 -0
  831. package/dist/features/paths/pathSnap/snapGeometry.js.map +1 -0
  832. package/dist/features/paths/penPreviewLayer.js +135 -102
  833. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  834. package/dist/features/paths/shapeGenerator.js +112 -60
  835. package/dist/features/paths/shapeGenerator.js.map +1 -1
  836. package/dist/features/paths/strokeOutline.js +15 -0
  837. package/dist/features/paths/strokeOutline.js.map +1 -0
  838. package/dist/features/paths/useAnchorFields.js +35 -0
  839. package/dist/features/paths/useAnchorFields.js.map +1 -0
  840. package/dist/features/paths/usePathEdit.js +58 -28
  841. package/dist/features/paths/usePathEdit.js.map +1 -1
  842. package/dist/features/poseRun/usePoseRun.js +110 -43
  843. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  844. package/dist/features/selection/handleCommands.js +116 -0
  845. package/dist/features/selection/handleCommands.js.map +1 -0
  846. package/dist/features/selection/overlay.js +288 -328
  847. package/dist/features/selection/overlay.js.map +1 -1
  848. package/dist/features/selection/selectionPose.js +109 -0
  849. package/dist/features/selection/selectionPose.js.map +1 -0
  850. package/dist/features/snap/angle2d.js +158 -0
  851. package/dist/features/snap/angle2d.js.map +1 -0
  852. package/dist/features/snap/debugCandidates.js +27 -0
  853. package/dist/features/snap/debugCandidates.js.map +1 -0
  854. package/dist/features/snap/gather.js +71 -0
  855. package/dist/features/snap/gather.js.map +1 -0
  856. package/dist/features/snap/inputSubspace.js +46 -0
  857. package/dist/features/snap/inputSubspace.js.map +1 -0
  858. package/dist/features/snap/marks.js +29 -0
  859. package/dist/features/snap/marks.js.map +1 -0
  860. package/dist/features/snap/outcomeStore.js +25 -0
  861. package/dist/features/snap/outcomeStore.js.map +1 -0
  862. package/dist/features/snap/pointSnap.js +48 -0
  863. package/dist/features/snap/pointSnap.js.map +1 -0
  864. package/dist/features/snap/probes2d.js +91 -0
  865. package/dist/features/snap/probes2d.js.map +1 -0
  866. package/dist/features/snap/readoutDraw.js +93 -0
  867. package/dist/features/snap/readoutDraw.js.map +1 -0
  868. package/dist/features/snap/readoutLayer.js +49 -0
  869. package/dist/features/snap/readoutLayer.js.map +1 -0
  870. package/dist/features/snap/registry.js +27 -0
  871. package/dist/features/snap/registry.js.map +1 -0
  872. package/dist/features/snap/resizeBox.js +137 -0
  873. package/dist/features/snap/resizeBox.js.map +1 -0
  874. package/dist/features/snap/roles.js +31 -0
  875. package/dist/features/snap/roles.js.map +1 -0
  876. package/dist/features/snap/rotationSource.js +30 -0
  877. package/dist/features/snap/rotationSource.js.map +1 -0
  878. package/dist/features/snap/sceneReads.js +45 -0
  879. package/dist/features/snap/sceneReads.js.map +1 -0
  880. package/dist/features/snap/sceneSession2d.js +79 -0
  881. package/dist/features/snap/sceneSession2d.js.map +1 -0
  882. package/dist/features/snap/screen.js +23 -0
  883. package/dist/features/snap/screen.js.map +1 -0
  884. package/dist/features/snap/session2d.js +129 -0
  885. package/dist/features/snap/session2d.js.map +1 -0
  886. package/dist/features/snap/spanSnap.js +77 -0
  887. package/dist/features/snap/spanSnap.js.map +1 -0
  888. package/dist/features/snap/stepAngles.js +15 -0
  889. package/dist/features/snap/stepAngles.js.map +1 -0
  890. package/dist/features/text/editingDrawOne.js +32 -0
  891. package/dist/features/text/editingDrawOne.js.map +1 -0
  892. package/dist/features/text/index.js +7 -6
  893. package/dist/features/text/textHitAt.js +51 -0
  894. package/dist/features/text/textHitAt.js.map +1 -0
  895. package/dist/features/text/textLayer.js +21 -27
  896. package/dist/features/text/textLayer.js.map +1 -1
  897. package/dist/features/text/useSceneTextEdit.js +190 -128
  898. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  899. package/dist/features/viewports/viewResolver.js +48 -39
  900. package/dist/features/viewports/viewResolver.js.map +1 -1
  901. package/dist/features/viewports/viewportLayer.js +60 -29
  902. package/dist/features/viewports/viewportLayer.js.map +1 -1
  903. package/dist/iconRegistry/IconRegistryProvider.js +73 -0
  904. package/dist/iconRegistry/IconRegistryProvider.js.map +1 -0
  905. package/dist/iconRegistry/useIconGlyph.js +14 -0
  906. package/dist/iconRegistry/useIconGlyph.js.map +1 -0
  907. package/dist/iconRegistry/useIconVariant.js +29 -0
  908. package/dist/iconRegistry/useIconVariant.js.map +1 -0
  909. package/dist/icons.d.ts +6 -0
  910. package/dist/icons.js +3 -0
  911. package/dist/icons.table.js +13 -0
  912. package/dist/icons.table.js.map +1 -0
  913. package/dist/icons.table.json +556 -0
  914. package/dist/icons2.table.js +9 -0
  915. package/dist/icons2.table.js.map +1 -0
  916. package/dist/index.d.ts +4259 -5074
  917. package/dist/index.js +340 -285
  918. package/dist/input/keyState.js +118 -54
  919. package/dist/input/keyState.js.map +1 -1
  920. package/dist/input/useKeyModifiers.js +13 -7
  921. package/dist/input/useKeyModifiers.js.map +1 -1
  922. package/dist/input/useKeyState.js +23 -16
  923. package/dist/input/useKeyState.js.map +1 -1
  924. package/dist/interactions/actions/align/action.js +76 -45
  925. package/dist/interactions/actions/align/action.js.map +1 -1
  926. package/dist/interactions/actions/align/align.js +86 -48
  927. package/dist/interactions/actions/align/align.js.map +1 -1
  928. package/dist/interactions/actions/booleans/action.js +67 -33
  929. package/dist/interactions/actions/booleans/action.js.map +1 -1
  930. package/dist/interactions/actions/booleans/booleans.js +77 -70
  931. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  932. package/dist/interactions/actions/booleans/commit.js +49 -0
  933. package/dist/interactions/actions/booleans/commit.js.map +1 -0
  934. package/dist/interactions/actions/booleans/custom.js +48 -0
  935. package/dist/interactions/actions/booleans/custom.js.map +1 -0
  936. package/dist/interactions/actions/booleans/operands.js +43 -32
  937. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  938. package/dist/interactions/actions/booleans/pieces.js +29 -23
  939. package/dist/interactions/actions/booleans/pieces.js.map +1 -1
  940. package/dist/interactions/actions/booleans/placement.js +30 -17
  941. package/dist/interactions/actions/booleans/placement.js.map +1 -1
  942. package/dist/interactions/actions/booleans/useBooleans.js +30 -17
  943. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  944. package/dist/interactions/actions/booleans/useBooleansAdapter.js +8 -5
  945. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  946. package/dist/interactions/actions/clipboard/action.js +81 -40
  947. package/dist/interactions/actions/clipboard/action.js.map +1 -1
  948. package/dist/interactions/actions/clipboard/clipboardOps.js +100 -72
  949. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  950. package/dist/interactions/actions/clipboard/materializePaste.js +38 -19
  951. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  952. package/dist/interactions/actions/clipboard/wireFormat.js +66 -28
  953. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  954. package/dist/interactions/actions/clone/action.js +102 -70
  955. package/dist/interactions/actions/clone/action.js.map +1 -1
  956. package/dist/interactions/actions/clone/behaviors.js +55 -38
  957. package/dist/interactions/actions/clone/behaviors.js.map +1 -1
  958. package/dist/interactions/actions/defaultCommitAdapter.js +32 -10
  959. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  960. package/dist/interactions/actions/defaults/anchorEditing.js +252 -111
  961. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  962. package/dist/interactions/actions/defaults/anchorFields.js +54 -0
  963. package/dist/interactions/actions/defaults/anchorFields.js.map +1 -0
  964. package/dist/interactions/actions/defaults/anchorHandles.js +31 -27
  965. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -1
  966. package/dist/interactions/actions/defaults/anchorJoin.js +55 -37
  967. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
  968. package/dist/interactions/actions/defaults/areaSelect.js +56 -40
  969. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  970. package/dist/interactions/actions/defaults/bendSegment.js +67 -31
  971. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
  972. package/dist/interactions/actions/defaults/cancelGesture.js +12 -5
  973. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  974. package/dist/interactions/actions/defaults/clearSelection.js +22 -7
  975. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  976. package/dist/interactions/actions/defaults/contextMenu.js +149 -0
  977. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -0
  978. package/dist/interactions/actions/defaults/copySubtree.js +43 -29
  979. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  980. package/dist/interactions/actions/defaults/createPaintAction.js +79 -54
  981. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  982. package/dist/interactions/actions/defaults/delete.js +61 -33
  983. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  984. package/dist/interactions/actions/defaults/duplicate.js +60 -32
  985. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  986. package/dist/interactions/actions/defaults/enterPathEdit.js +22 -18
  987. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  988. package/dist/interactions/actions/defaults/enterTextEdit.js +20 -8
  989. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  990. package/dist/interactions/actions/defaults/escape.js +16 -7
  991. package/dist/interactions/actions/defaults/escape.js.map +1 -1
  992. package/dist/interactions/actions/defaults/exitPathEdit.js +6 -6
  993. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
  994. package/dist/interactions/actions/defaults/group.js +122 -73
  995. package/dist/interactions/actions/defaults/group.js.map +1 -1
  996. package/dist/interactions/actions/defaults/ingest.js +52 -35
  997. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  998. package/dist/interactions/actions/defaults/insertPathAnchor.js +43 -22
  999. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  1000. package/dist/interactions/actions/defaults/nudge.js +79 -52
  1001. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  1002. package/dist/interactions/actions/defaults/nudgeSteps.js +17 -12
  1003. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -1
  1004. package/dist/interactions/actions/defaults/pathEditMarks.js +60 -0
  1005. package/dist/interactions/actions/defaults/pathEditMarks.js.map +1 -0
  1006. package/dist/interactions/actions/defaults/pathEditTools.js +57 -0
  1007. package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -0
  1008. package/dist/interactions/actions/defaults/pinchZoom.js +55 -39
  1009. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  1010. package/dist/interactions/actions/defaults/reorder.js +71 -40
  1011. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  1012. package/dist/interactions/actions/defaults/requiresSelection.js +13 -6
  1013. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  1014. package/dist/interactions/actions/defaults/segmentUnder.js +24 -16
  1015. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -1
  1016. package/dist/interactions/actions/defaults/selectAll.js +21 -7
  1017. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  1018. package/dist/interactions/actions/defaults/setFill.js +37 -21
  1019. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  1020. package/dist/interactions/actions/defaults/setFillOpacity.js +19 -10
  1021. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  1022. package/dist/interactions/actions/defaults/setStroke.js +46 -25
  1023. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  1024. package/dist/interactions/actions/defaults/setStrokeOpacity.js +19 -11
  1025. package/dist/interactions/actions/defaults/setStrokeOpacity.js.map +1 -1
  1026. package/dist/interactions/actions/defaults/slice.js +42 -17
  1027. package/dist/interactions/actions/defaults/slice.js.map +1 -1
  1028. package/dist/interactions/actions/defaults/sliceOps.js +63 -42
  1029. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  1030. package/dist/interactions/actions/defaults/toolActivate.js +34 -16
  1031. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  1032. package/dist/interactions/actions/defaults/toolResetToDefault.js +29 -10
  1033. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  1034. package/dist/interactions/actions/defaults/undoRedo.js +26 -20
  1035. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
  1036. package/dist/interactions/actions/defaults/viewportDragPan.js +91 -58
  1037. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  1038. package/dist/interactions/actions/defaults/viewportWheelPan.js +42 -23
  1039. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  1040. package/dist/interactions/actions/defaults/viewportZoom.js +107 -59
  1041. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  1042. package/dist/interactions/actions/distribute/action.js +62 -39
  1043. package/dist/interactions/actions/distribute/action.js.map +1 -1
  1044. package/dist/interactions/actions/distribute/distribute.js +53 -34
  1045. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  1046. package/dist/interactions/actions/distribute/plan.js +40 -22
  1047. package/dist/interactions/actions/distribute/plan.js.map +1 -1
  1048. package/dist/interactions/actions/drawnBoxes.js +31 -0
  1049. package/dist/interactions/actions/drawnBoxes.js.map +1 -0
  1050. package/dist/interactions/actions/edit-anchors/action.js +248 -72
  1051. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  1052. package/dist/interactions/actions/edit-anchors/extensionDrags.js +50 -0
  1053. package/dist/interactions/actions/edit-anchors/extensionDrags.js.map +1 -0
  1054. package/dist/interactions/actions/edit-anchors/geometry.js +74 -47
  1055. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  1056. package/dist/interactions/actions/edit-anchors/handleDrag.js +101 -0
  1057. package/dist/interactions/actions/edit-anchors/handleDrag.js.map +1 -0
  1058. package/dist/interactions/actions/edit-anchors/handles.js +41 -27
  1059. package/dist/interactions/actions/edit-anchors/handles.js.map +1 -1
  1060. package/dist/interactions/actions/edit-anchors/params.js +12 -0
  1061. package/dist/interactions/actions/edit-anchors/params.js.map +1 -0
  1062. package/dist/interactions/actions/edit-anchors/preview.js +61 -19
  1063. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
  1064. package/dist/interactions/actions/edit-anchors/symmetry.js +12 -7
  1065. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -1
  1066. package/dist/interactions/actions/flip/action.js +119 -61
  1067. package/dist/interactions/actions/flip/action.js.map +1 -1
  1068. package/dist/interactions/actions/flip/helpers.js +69 -36
  1069. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  1070. package/dist/interactions/actions/geometryProjection.js +17 -12
  1071. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  1072. package/dist/interactions/actions/gestureFrames.js +20 -11
  1073. package/dist/interactions/actions/gestureFrames.js.map +1 -1
  1074. package/dist/interactions/actions/gestureLifecycle.js +93 -48
  1075. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  1076. package/dist/interactions/actions/hitSelection.js +6 -4
  1077. package/dist/interactions/actions/hitSelection.js.map +1 -1
  1078. package/dist/interactions/actions/insert/action.js +71 -42
  1079. package/dist/interactions/actions/insert/action.js.map +1 -1
  1080. package/dist/interactions/actions/insert/commit.js +44 -22
  1081. package/dist/interactions/actions/insert/commit.js.map +1 -1
  1082. package/dist/interactions/actions/insert/extras.js +60 -38
  1083. package/dist/interactions/actions/insert/extras.js.map +1 -1
  1084. package/dist/interactions/actions/insert/frame.js +58 -39
  1085. package/dist/interactions/actions/insert/frame.js.map +1 -1
  1086. package/dist/interactions/actions/insert/geometry.js +29 -25
  1087. package/dist/interactions/actions/insert/geometry.js.map +1 -1
  1088. package/dist/interactions/actions/insert/placeAction.js +108 -0
  1089. package/dist/interactions/actions/insert/placeAction.js.map +1 -0
  1090. package/dist/interactions/actions/insert/repositionAction.js +26 -11
  1091. package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
  1092. package/dist/interactions/actions/insert/rotateAction.js +19 -8
  1093. package/dist/interactions/actions/insert/rotateAction.js.map +1 -1
  1094. package/dist/interactions/actions/insert/session.js +57 -41
  1095. package/dist/interactions/actions/insert/session.js.map +1 -1
  1096. package/dist/interactions/actions/insert/shape.js +83 -25
  1097. package/dist/interactions/actions/insert/shape.js.map +1 -1
  1098. package/dist/interactions/actions/lasso-select/action.js +160 -100
  1099. package/dist/interactions/actions/lasso-select/action.js.map +1 -1
  1100. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +44 -25
  1101. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
  1102. package/dist/interactions/actions/move/action.js +87 -52
  1103. package/dist/interactions/actions/move/action.js.map +1 -1
  1104. package/dist/interactions/actions/move/behaviors/layoutDrop.js +56 -36
  1105. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
  1106. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +20 -10
  1107. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -1
  1108. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +40 -24
  1109. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
  1110. package/dist/interactions/actions/move/behaviors/snapToContainer.js +102 -64
  1111. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  1112. package/dist/interactions/actions/move/capture.js +103 -78
  1113. package/dist/interactions/actions/move/capture.js.map +1 -1
  1114. package/dist/interactions/actions/move/commit/index.js +43 -34
  1115. package/dist/interactions/actions/move/commit/index.js.map +1 -1
  1116. package/dist/interactions/actions/move/commit/layoutDrop.js +43 -32
  1117. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -1
  1118. package/dist/interactions/actions/move/commit/layoutRelease.js +97 -77
  1119. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -1
  1120. package/dist/interactions/actions/move/commit/rebase.js +16 -13
  1121. package/dist/interactions/actions/move/commit/rebase.js.map +1 -1
  1122. package/dist/interactions/actions/move/commit/reparent.js +83 -57
  1123. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  1124. package/dist/interactions/actions/move/delta.js +58 -36
  1125. package/dist/interactions/actions/move/delta.js.map +1 -1
  1126. package/dist/interactions/actions/move/frame.js +72 -35
  1127. package/dist/interactions/actions/move/frame.js.map +1 -1
  1128. package/dist/interactions/actions/move/gestureAdapter.js +30 -20
  1129. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  1130. package/dist/interactions/actions/move/landedDescendants.js +40 -25
  1131. package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
  1132. package/dist/interactions/actions/move/layout/container.js +92 -72
  1133. package/dist/interactions/actions/move/layout/container.js.map +1 -1
  1134. package/dist/interactions/actions/move/layout/dragged.js +61 -39
  1135. package/dist/interactions/actions/move/layout/dragged.js.map +1 -1
  1136. package/dist/interactions/actions/move/layout/dropPass.js +136 -94
  1137. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
  1138. package/dist/interactions/actions/move/layout/exits.js +58 -30
  1139. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  1140. package/dist/interactions/actions/move/layout/glide.js +55 -34
  1141. package/dist/interactions/actions/move/layout/glide.js.map +1 -1
  1142. package/dist/interactions/actions/move/session.js +85 -56
  1143. package/dist/interactions/actions/move/session.js.map +1 -1
  1144. package/dist/interactions/actions/move/translate.js +58 -43
  1145. package/dist/interactions/actions/move/translate.js.map +1 -1
  1146. package/dist/interactions/actions/outlines/createOutlines.js +28 -20
  1147. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  1148. package/dist/interactions/actions/outlines/createOutlinesAction.js +43 -31
  1149. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
  1150. package/dist/interactions/actions/outlines/outlineStroke.js +68 -45
  1151. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
  1152. package/dist/interactions/actions/outlines/outlineStrokeAction.js +24 -19
  1153. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -1
  1154. package/dist/interactions/actions/outlines/replaceWithPaths.js +57 -42
  1155. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -1
  1156. package/dist/interactions/actions/outlines/strokeRegion.js +37 -22
  1157. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -1
  1158. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js +8 -5
  1159. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js.map +1 -1
  1160. package/dist/interactions/actions/pathCommands/cutJoin.js +119 -72
  1161. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
  1162. package/dist/interactions/actions/pathCommands/livePathEdit.js +74 -40
  1163. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -1
  1164. package/dist/interactions/actions/pathCommands/pathNodes.js +91 -82
  1165. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -1
  1166. package/dist/interactions/actions/pathCommands/simplifyOffset.js +52 -28
  1167. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -1
  1168. package/dist/interactions/actions/pathGestureTags.js +29 -0
  1169. package/dist/interactions/actions/pathGestureTags.js.map +1 -0
  1170. package/dist/interactions/actions/planeInput.js +198 -123
  1171. package/dist/interactions/actions/planeInput.js.map +1 -1
  1172. package/dist/interactions/actions/pointerState.js +12 -7
  1173. package/dist/interactions/actions/pointerState.js.map +1 -1
  1174. package/dist/interactions/actions/poseDescriptorDep.js +24 -14
  1175. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  1176. package/dist/interactions/actions/poseFrame.js +45 -28
  1177. package/dist/interactions/actions/poseFrame.js.map +1 -1
  1178. package/dist/interactions/actions/resize/action.js +68 -39
  1179. package/dist/interactions/actions/resize/action.js.map +1 -1
  1180. package/dist/interactions/actions/resize/aspect.js +44 -0
  1181. package/dist/interactions/actions/resize/aspect.js.map +1 -0
  1182. package/dist/interactions/actions/resize/behaviors/clampMinSize.js +38 -13
  1183. package/dist/interactions/actions/resize/behaviors/clampMinSize.js.map +1 -1
  1184. package/dist/interactions/actions/resize/boxFrame.js +15 -11
  1185. package/dist/interactions/actions/resize/boxFrame.js.map +1 -1
  1186. package/dist/interactions/actions/resize/capture.js +105 -62
  1187. package/dist/interactions/actions/resize/capture.js.map +1 -1
  1188. package/dist/interactions/actions/resize/commit.js +75 -56
  1189. package/dist/interactions/actions/resize/commit.js.map +1 -1
  1190. package/dist/interactions/actions/resize/cornerHandles.js +154 -17
  1191. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
  1192. package/dist/interactions/actions/resize/frame.js +133 -66
  1193. package/dist/interactions/actions/resize/frame.js.map +1 -1
  1194. package/dist/interactions/actions/resize/minimum.js +35 -0
  1195. package/dist/interactions/actions/resize/minimum.js.map +1 -0
  1196. package/dist/interactions/actions/resize/replay.js +40 -30
  1197. package/dist/interactions/actions/resize/replay.js.map +1 -1
  1198. package/dist/interactions/actions/resize/ruleBounds.js +8 -5
  1199. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -1
  1200. package/dist/interactions/actions/resize/session.js +95 -50
  1201. package/dist/interactions/actions/resize/session.js.map +1 -1
  1202. package/dist/interactions/actions/resolveOverlays.js +48 -33
  1203. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  1204. package/dist/interactions/actions/resolvePreviews.js +63 -46
  1205. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  1206. package/dist/interactions/actions/rotate/action.js +68 -42
  1207. package/dist/interactions/actions/rotate/action.js.map +1 -1
  1208. package/dist/interactions/actions/rotate/commit.js +39 -31
  1209. package/dist/interactions/actions/rotate/commit.js.map +1 -1
  1210. package/dist/interactions/actions/rotate/frame.js +75 -47
  1211. package/dist/interactions/actions/rotate/frame.js.map +1 -1
  1212. package/dist/interactions/actions/rotate/geometry.js +36 -24
  1213. package/dist/interactions/actions/rotate/geometry.js.map +1 -1
  1214. package/dist/interactions/actions/rotate/handle.js +28 -15
  1215. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  1216. package/dist/interactions/actions/rotate/replay.js +22 -18
  1217. package/dist/interactions/actions/rotate/replay.js.map +1 -1
  1218. package/dist/interactions/actions/rotate/session.js +115 -76
  1219. package/dist/interactions/actions/rotate/session.js.map +1 -1
  1220. package/dist/interactions/actions/selectionSubtree.js +124 -53
  1221. package/dist/interactions/actions/selectionSubtree.js.map +1 -1
  1222. package/dist/interactions/actions/spatialReference.js +33 -26
  1223. package/dist/interactions/actions/spatialReference.js.map +1 -1
  1224. package/dist/interactions/actions/testUtils.js +53 -0
  1225. package/dist/interactions/actions/testUtils.js.map +1 -0
  1226. package/dist/interactions/actions/transform-again/action.js +50 -35
  1227. package/dist/interactions/actions/transform-again/action.js.map +1 -1
  1228. package/dist/interactions/actions/transform-again/memory.js +32 -21
  1229. package/dist/interactions/actions/transform-again/memory.js.map +1 -1
  1230. package/dist/interactions/actions/useActionSet.js +83 -0
  1231. package/dist/interactions/actions/useActionSet.js.map +1 -0
  1232. package/dist/interactions/actions/useStandardActions.js +23 -165
  1233. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  1234. package/dist/interactions/gestures/dragGesture/dragGesture.js +109 -68
  1235. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
  1236. package/dist/interactions/gestures/dragGesture/dragPointOf.js +17 -10
  1237. package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -1
  1238. package/dist/interactions/gestures/dragRadial/dragRadial.js +129 -93
  1239. package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -1
  1240. package/dist/interactions/gestures/dragRect/dragRect.js +155 -111
  1241. package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -1
  1242. package/dist/interactions/gestures/handleDrag/handleDrag.js +52 -30
  1243. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
  1244. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +168 -97
  1245. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  1246. package/dist/interactions/gestures/shared/originProjection.js +32 -25
  1247. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  1248. package/dist/interactions/gestures/shared/screenTolerance.js +26 -17
  1249. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  1250. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +39 -21
  1251. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  1252. package/dist/kitSettingsSchema.js +80 -0
  1253. package/dist/kitSettingsSchema.js.map +1 -0
  1254. package/dist/{math-CYUjoyyU.d.ts → math-CrJULaZI.d.ts} +5 -6
  1255. package/dist/math.d.ts +4 -5
  1256. package/dist/math.js +7 -6
  1257. package/dist/mesh.js +3 -2
  1258. package/dist/move.d.ts +7 -6
  1259. package/dist/move.js +4 -3
  1260. package/dist/{originProjection-CoNVpITV.d.ts → options-p9GZMXbY.d.ts} +4 -27
  1261. package/dist/originProjection-gY0jb4Wb.d.ts +24 -0
  1262. package/dist/patterns-builtin.js +3 -2
  1263. package/dist/{poseDescriptor-Bqk-11Rl.d.ts → poseDescriptor-DN2yfnq_.d.ts} +7 -7
  1264. package/dist/renderer.d.ts +1 -1
  1265. package/dist/renderer.js +3 -2
  1266. package/dist/resize.d.ts +10 -28
  1267. package/dist/resize.js +6 -7
  1268. package/dist/routing.js +3 -2
  1269. package/dist/style.css +88 -1
  1270. package/dist/test-hook/createTestHook.js +23 -20
  1271. package/dist/test-hook/createTestHook.js.map +1 -1
  1272. package/dist/test-hook/install.js +32 -13
  1273. package/dist/test-hook/install.js.map +1 -1
  1274. package/dist/test-hook/useTestHook.js +22 -16
  1275. package/dist/test-hook/useTestHook.js.map +1 -1
  1276. package/dist/test-seams.d.ts +164 -1
  1277. package/dist/test-seams.js +8 -3
  1278. package/dist/tools/builtin/bone/boneActions.js +96 -70
  1279. package/dist/tools/builtin/bone/boneActions.js.map +1 -1
  1280. package/dist/tools/builtin/bone/boneOverlay.js +49 -36
  1281. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -1
  1282. package/dist/tools/builtin/bone/placedRig.js +18 -14
  1283. package/dist/tools/builtin/bone/placedRig.js.map +1 -1
  1284. package/dist/tools/builtin/bone/rigEditState.js +22 -13
  1285. package/dist/tools/builtin/bone/rigEditState.js.map +1 -1
  1286. package/dist/tools/builtin/bone/useBoneTool.js +68 -41
  1287. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -1
  1288. package/dist/tools/builtin/ellipse/useEllipseTool.js +22 -17
  1289. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  1290. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +44 -28
  1291. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  1292. package/dist/tools/builtin/hand/dragPanContribution.js +12 -7
  1293. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
  1294. package/dist/tools/builtin/hand/useHandTool.js +21 -13
  1295. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  1296. package/dist/tools/builtin/image/useImageTool.js +28 -19
  1297. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  1298. package/dist/tools/builtin/lasso/useLassoTool.js +48 -36
  1299. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  1300. package/dist/tools/builtin/line/useLineTool.js +24 -17
  1301. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  1302. package/dist/tools/builtin/measure/useMeasureTool.js +84 -0
  1303. package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -0
  1304. package/dist/tools/builtin/pen/penHandle.js +60 -0
  1305. package/dist/tools/builtin/pen/penHandle.js.map +1 -0
  1306. package/dist/tools/builtin/pen/usePenTool.js +461 -303
  1307. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  1308. package/dist/tools/builtin/pencil/usePencilTool.js +20 -15
  1309. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  1310. package/dist/tools/builtin/pickTopMostHit.js +51 -31
  1311. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  1312. package/dist/tools/builtin/polygon/usePolygonTool.js +45 -28
  1313. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  1314. package/dist/tools/builtin/rect/useRectTool.js +24 -16
  1315. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  1316. package/dist/tools/builtin/select/adapterPointQuery.js +47 -30
  1317. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  1318. package/dist/tools/builtin/select/selectionContributions.js +94 -56
  1319. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  1320. package/dist/tools/builtin/select/useSelectTool.js +155 -108
  1321. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  1322. package/dist/tools/builtin/shared/insertToolOptions.js +5 -4
  1323. package/dist/tools/builtin/shared/insertToolOptions.js.map +1 -1
  1324. package/dist/tools/builtin/shared/pointerFollower.js +15 -8
  1325. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  1326. package/dist/tools/builtin/slice/useSliceTool.js +148 -101
  1327. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  1328. package/dist/tools/builtin/star/useStarTool.js +48 -31
  1329. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  1330. package/dist/tools/builtin/sticky/stickyNode.js +49 -0
  1331. package/dist/tools/builtin/sticky/stickyNode.js.map +1 -0
  1332. package/dist/tools/builtin/sticky/useStickyTool.js +86 -0
  1333. package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -0
  1334. package/dist/tools/builtin/text/useTextTool.js +59 -34
  1335. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  1336. package/dist/tools/builtin/weight/useWeightTool.js +66 -42
  1337. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -1
  1338. package/dist/tools/builtin/weight/weightActions.js +93 -65
  1339. package/dist/tools/builtin/weight/weightActions.js.map +1 -1
  1340. package/dist/tools/builtin/weight/weightOverlay.js +47 -30
  1341. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -1
  1342. package/dist/tools/overlayBinding.js +7 -5
  1343. package/dist/tools/overlayBinding.js.map +1 -1
  1344. package/dist/tools/useKeybindings.js +62 -46
  1345. package/dist/tools/useKeybindings.js.map +1 -1
  1346. package/dist/{types-DBbbCy0i.d.ts → types-CHVXGfYm.d.ts} +5 -5
  1347. package/dist/util/color.js +39 -18
  1348. package/dist/util/color.js.map +1 -1
  1349. package/dist/util/paint.js +93 -38
  1350. package/dist/util/paint.js.map +1 -1
  1351. package/dist/version.js +11 -3
  1352. package/dist/version.js.map +1 -1
  1353. package/package.json +35 -23
  1354. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +0 -126
  1355. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +0 -1
  1356. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +0 -55
  1357. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +0 -1
  1358. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +0 -16
  1359. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +0 -1
  1360. package/dist/canvas/SceneCanvas/isDev.js +0 -12
  1361. package/dist/canvas/SceneCanvas/isDev.js.map +0 -1
  1362. package/dist/canvas/SceneCanvas/useViewLayerGate.js +0 -20
  1363. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +0 -1
  1364. package/dist/cornerHandles-BSKbyuvQ.d.ts +0 -104
  1365. package/dist/icons/ArrowIcon.js +0 -23
  1366. package/dist/icons/ArrowIcon.js.map +0 -1
  1367. package/dist/icons/EllipseIcon.js +0 -21
  1368. package/dist/icons/EllipseIcon.js.map +0 -1
  1369. package/dist/icons/EyedropperIcon.js +0 -49
  1370. package/dist/icons/EyedropperIcon.js.map +0 -1
  1371. package/dist/icons/HandIcon.js +0 -59
  1372. package/dist/icons/HandIcon.js.map +0 -1
  1373. package/dist/icons/ImageIcon.js +0 -34
  1374. package/dist/icons/ImageIcon.js.map +0 -1
  1375. package/dist/icons/LassoIcon.js +0 -22
  1376. package/dist/icons/LassoIcon.js.map +0 -1
  1377. package/dist/icons/LineIcon.js +0 -22
  1378. package/dist/icons/LineIcon.js.map +0 -1
  1379. package/dist/icons/PenIcon.js +0 -36
  1380. package/dist/icons/PenIcon.js.map +0 -1
  1381. package/dist/icons/PencilIcon.js +0 -25
  1382. package/dist/icons/PencilIcon.js.map +0 -1
  1383. package/dist/icons/PolygonIcon.js +0 -19
  1384. package/dist/icons/PolygonIcon.js.map +0 -1
  1385. package/dist/icons/RectIcon.js +0 -37
  1386. package/dist/icons/RectIcon.js.map +0 -1
  1387. package/dist/icons/SelectIcon.js +0 -20
  1388. package/dist/icons/SelectIcon.js.map +0 -1
  1389. package/dist/icons/SliceIcon.js +0 -24
  1390. package/dist/icons/SliceIcon.js.map +0 -1
  1391. package/dist/icons/StarIcon.js +0 -19
  1392. package/dist/icons/StarIcon.js.map +0 -1
  1393. package/dist/icons/TextIcon.js +0 -19
  1394. package/dist/icons/TextIcon.js.map +0 -1
  1395. package/dist/icons/UnknownIcon.js +0 -33
  1396. package/dist/icons/UnknownIcon.js.map +0 -1
  1397. package/dist/icons/_base.js +0 -12
  1398. package/dist/icons/_base.js.map +0 -1
  1399. package/dist/interactions/actions/actionShortcuts.js +0 -32
  1400. package/dist/interactions/actions/actionShortcuts.js.map +0 -1
  1401. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js +0 -40
  1402. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js.map +0 -1
  1403. package/dist/interactions/actions/defaults/icons/actionGlyphs.js +0 -10
  1404. package/dist/interactions/actions/defaults/icons/actionGlyphs.js.map +0 -1
  1405. package/dist/interactions/actions/defaults/icons/alignIcons.js +0 -173
  1406. package/dist/interactions/actions/defaults/icons/alignIcons.js.map +0 -1
  1407. package/dist/interactions/actions/defaults/icons/anchorIcons.js +0 -75
  1408. package/dist/interactions/actions/defaults/icons/anchorIcons.js.map +0 -1
  1409. package/dist/interactions/actions/defaults/icons/booleanIcons.js +0 -194
  1410. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +0 -1
  1411. package/dist/interactions/actions/defaults/icons/distributeIcons.js +0 -63
  1412. package/dist/interactions/actions/defaults/icons/distributeIcons.js.map +0 -1
  1413. package/dist/interactions/actions/defaults/icons/editIcons.js +0 -307
  1414. package/dist/interactions/actions/defaults/icons/editIcons.js.map +0 -1
  1415. package/dist/interactions/actions/defaults/icons/outlineIcons.js +0 -91
  1416. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +0 -1
  1417. package/dist/interactions/actions/resize/behaviors/index.js +0 -8
  1418. package/dist/interactions/actions/resize/behaviors/index.js.map +0 -1
  1419. package/dist/interactions/actions/resize/behaviors/lockAspect.js +0 -24
  1420. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +0 -1
  1421. package/dist/interactions/actions/resize/pointSnap.js +0 -111
  1422. package/dist/interactions/actions/resize/pointSnap.js.map +0 -1
  1423. package/dist/interactions/actions/rotate/behaviors/index.js +0 -7
  1424. package/dist/interactions/actions/rotate/behaviors/index.js.map +0 -1
  1425. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +0 -12
  1426. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +0 -1
  1427. package/dist/interactions/gestures/shared/snap.js +0 -24
  1428. package/dist/interactions/gestures/shared/snap.js.map +0 -1
  1429. package/dist/test-seams-D0pyV3pR.d.ts +0 -149
  1430. package/dist/util/constrainTo45.js +0 -17
  1431. package/dist/util/constrainTo45.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.js","names":["projectBounds","t","viewToTransform","view","sx","sy","worldToScreen","b","leavesOf","isContainer","id","out","visit","kids","getChildren","nid","k","composeSelectionPose","opts","d","AUTO_POSE_DESCRIPTOR","selectionLeaves","resolveLeaf","moved","moveOverlay","resizeOverlay","getStoredPose","leaves","containerResizeLeafPoses","leafBounds","leafId","visualBoundsViaDescriptor","overlayLeaf","u","unionAABB","makeContainerAwareBoundsResolver","oriented","framedBounds","p","getPose","DEFAULT_OUTLINE","DEFAULT_HANDLE_FILL","DEFAULT_HANDLE_OUTLINE","DEFAULT_HANDLE_SIZE","HANDLE_BASE_PX","defaultHandlesOf","resolveOutlineStroke","resolveHandles","rotateAroundMat3","c","theta","s","tx","cx","cy","ty","rectPathFor","outlineCommandsFor","align","stroke","width","resolveStrokeWidth","ids","worldB","resolveBounds","padded","pad","xf","targetTransformOf","r","alignedStrokeRect","q","screenCorners","PATH_M","PATH_L","PATH_Z","targetCorners","x","y","w","ccx","ccy","normal","nx","a","ny","l","mx","my","n1","i","n2","handleCommandsFor","half","handles","handleAlign","handleWidth","angle","screenAngleOf","angleOf","hLocal","handlesOf","hWorld","localToWorld","hsx","hsy","center","baseRect","sr","fillCmd","strokeCmd","rotationHandleCommands","rotationHandle","distance","rotation","scx","scy","size","arcRadius","ARC_HALF_ANGLE","arcWidth","cmds","xs","ys","arcCoords","arcPath","headLen","headWidth","arrowHead","len","ux","uy","px","py","tipX","endX","tipY","endY","baseLeftX","baseLeftY","baseRightX","baseRightY","angleA","endAX","endAY","tangentAX","tangentAY","angleB","endBX","endBY","tangentBX","tangentBY","headA","headB","transform","mat3","rot","buildSelectionLayer","passes","poseBounds","rotationHandleDistance","rotationBadgeOf","chromeState","asChromeState","data","allIds","chromeSelectionIds","suppressed","isVisible","asIsVisible","showOutline","showHandles","showRotation","resolveTargetBounds","MULTI_RESIZE_TARGET_ID","outlineIdsRaw","outlineIds","cmd","DEFAULT_ROTATION_HANDLE_DISTANCE","createSelectionOutlineLayer","createSelectionHandlesLayer","createSelectionOverlayLayer","maybe","state"],"sources":["../../../src/features/selection/overlay.ts"],"sourcesContent":["/**\n * Selection overlay primitives — render layers for drawing selection\n * outlines and corner resize handles.\n *\n * **Pose shape:** TPose is generic; callers pass `poseDescriptor` for poses\n * `AUTO_POSE_DESCRIPTOR` can't read. Container ids reduce via `unionAABB`\n * over the projected AABBs.\n */\n\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport { mat3, type GlMat3 } from '@weasel-js/renderer';\nimport type { NodeId } from 'core/scene/types';\nimport type { RenderLayer } from 'core/layers/render';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport {\n framedBounds,\n visualBoundsViaDescriptor,\n type PoseDescriptor,\n} from 'core/geometry/poseDescriptor';\nimport { angleOf, localToWorld, targetCorners, targetTransformOf, type TargetTransform } from 'core/geometry/targetFrame';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport { alignedStrokeRect, type CommandStroke, type CommandFill } from '@weasel-js/paint';\nimport { resolveStrokeWidth } from '@weasel-js/stroke';\nimport {\n rotationHandle,\n DEFAULT_ROTATION_HANDLE_DISTANCE,\n} from 'interactions/actions/rotate/handle';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport type { ChromeState } from 'core/selection/chromeState';\nimport { MULTI_RESIZE_TARGET_ID } from 'core/selection/selectionTarget';\nimport type { View } from 'core/viewport/view';\nimport { viewToTransform } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\nimport { screenAngleOf } from '@weasel-js/geom';\nimport { PATH_L, PATH_M, PATH_Z, type PolygonPath } from '@weasel-js/geom';\nimport { HANDLE_BASE_PX } from 'core/device/targets';\n\n/** Project world AABB into screen-space AABB using the active view. */\nfunction projectBounds<B extends Bounds>(b: B, view: View): B {\n const t = viewToTransform(view);\n const [sx, sy] = worldToScreen(b.x, b.y, t);\n return { ...b, x: sx, y: sy, width: b.width * view.scale.x, height: b.height * view.scale.y };\n}\n\n\n/**\n * Transitive leaf ids under `id`. A childless node is a leaf only if it is not\n * itself a container: an empty container contributes no bounds, and its own\n * stored pose is at its most stale when no children are left to have moved it.\n */\nfunction leavesOf(\n id: string,\n getChildren: (id: string) => readonly string[],\n isContainer: (id: string) => boolean,\n): string[] {\n if (!isContainer(id)) return [id];\n const out: string[] = [];\n const visit = (nid: string) => {\n const kids = getChildren(nid);\n if (kids.length === 0) { if (!isContainer(nid)) out.push(nid); return; }\n for (const k of kids) visit(k);\n };\n visit(id);\n return out;\n}\n\n/** Options for `composeSelectionPose`. */\nexport interface ComposeSelectionPoseOpts<TPose> {\n /** Move overlay; when present its `poses` map wins over everything else. */\n moveOverlay?: { poses: Map<string, TPose> } | null;\n /**\n * Resize overlay; consulted only when move overlay does not own the id.\n * For container resize, `leafPoses` (when present) maps each leaf id under\n * the container to its overlay pose. If absent the container falls back to\n * stored leaf poses.\n */\n resizeOverlay?: {\n id: string;\n currentPose: TPose;\n leafPoses?: Map<string, TPose>;\n } | null;\n /** Fallback pose lookup (typically the stored/committed pose). */\n getStoredPose: (id: string) => TPose;\n /** How to read poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Walk a container's direct children (e.g. `scene.childrenOf`). With\n * `isContainer`, a selected container resolves to the union AABB of its\n * transitive leaf poses instead of its own stored pose. */\n getChildren?: (id: string) => readonly string[];\n /** True when `id` is a structural container. */\n isContainer?: (id: string) => boolean;\n}\n\n/**\n * Build a pose resolver for a selection. Precedence per id:\n * move overlay > resize overlay > stored. When `getChildren`/`isContainer`\n * are supplied and the id resolves to a container, the resolver returns the\n * union AABB of all transitive leaf poses (each leaf still subject to the\n * precedence rules). Containers with no leaves resolve to `null`.\n */\nexport function composeSelectionPose<TPose>(\n opts: ComposeSelectionPoseOpts<TPose>,\n): (id: string) => TPose | null {\n const { moveOverlay, resizeOverlay, getStoredPose, getChildren, isContainer } = opts;\n const d = (opts.poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n\n const selectionLeaves = (id: string): string[] =>\n getChildren && isContainer ? leavesOf(id, getChildren, isContainer) : [id];\n\n const resolveLeaf = (id: string): TPose => {\n const moved = moveOverlay?.poses.get(id);\n if (moved !== undefined) return moved;\n if (resizeOverlay && resizeOverlay.id === id) return resizeOverlay.currentPose;\n return getStoredPose(id);\n };\n\n return (id: string): TPose | null => {\n if (isContainer?.(id)) {\n const leaves = selectionLeaves(id);\n if (leaves.length === 0) return null;\n const containerResizeLeafPoses =\n resizeOverlay && resizeOverlay.id === id ? resizeOverlay.leafPoses : undefined;\n const leafBounds: Bounds[] = [];\n for (const leafId of leaves) {\n const moved = moveOverlay?.poses.get(leafId);\n if (moved !== undefined) {\n leafBounds.push(visualBoundsViaDescriptor(moved, d));\n continue;\n }\n const overlayLeaf = containerResizeLeafPoses?.get(leafId);\n if (overlayLeaf !== undefined) {\n leafBounds.push(visualBoundsViaDescriptor(overlayLeaf, d));\n continue;\n }\n leafBounds.push(visualBoundsViaDescriptor(getStoredPose(leafId), d));\n }\n const u = unionAABB(leafBounds);\n if (u === null) return null;\n return d.fromBounds(u, getStoredPose(leaves[0]!));\n }\n return resolveLeaf(id);\n };\n}\n\n/**\n * Build a pose resolver that handles container ids by computing the union\n * AABB of every leaf's bounds. Non-container ids pass through directly. When\n * `getChildren`/`isContainer` are omitted, every id is treated as a leaf.\n */\nfunction makeContainerAwareBoundsResolver<TPose>(\n getPose: (id: string) => TPose | null,\n d: PoseDescriptor<TPose>,\n getChildren?: (id: string) => readonly string[],\n isContainer?: (id: string) => boolean,\n): (id: string) => Bounds | null {\n const oriented = (p: TPose): Bounds => framedBounds(p, d);\n if (getChildren === undefined || isContainer === undefined) {\n return (id: string) => {\n const p = getPose(id);\n return p === null ? null : oriented(p);\n };\n }\n return (id: string): Bounds | null => {\n if (!isContainer(id)) {\n const p = getPose(id);\n return p === null ? null : oriented(p);\n }\n const leaves = leavesOf(id, getChildren, isContainer);\n if (leaves.length === 0) return null;\n const leafBounds: Bounds[] = [];\n for (const leafId of leaves) {\n const p = getPose(leafId);\n if (p !== null) leafBounds.push(visualBoundsViaDescriptor(p, d));\n }\n if (leafBounds.length === 0) return null;\n return unionAABB(leafBounds);\n };\n}\n\n/** Options every selection layer shares. `getSelection` and `getPose` are\n * declared on {@link SelectionOverlayLayerOpts}, which makes both optional —\n * omitted, they come off the draw envelope. */\ninterface SelectionLayerCommon<TPose> {\n /** How to read poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Walk a container's direct children (e.g. `scene.childrenOf`). When\n * supplied with `isContainer`, any id that resolves to a container is\n * rendered using the union bounds of all its transitive leaves. */\n getChildren?: (id: string) => readonly string[];\n /** True when `id` is a structural container. */\n isContainer?: (id: string) => boolean;\n}\n\n/** Options for `createSelectionOutlineLayer`. The overlay layer's options\n * minus the handle visuals — the two run the same body. */\nexport type SelectionOutlineLayerOpts<TPose> =\n Omit<SelectionOverlayLayerOpts<TPose>, 'handles' | 'handlesOf' | 'rotationHandle'>;\n\n/** Options for `createSelectionHandlesLayer`. The overlay layer's options\n * minus the outline stroke — the two run the same body. */\nexport type SelectionHandlesLayerOpts<TPose> =\n Omit<SelectionOverlayLayerOpts<TPose>, 'outline'>;\n\n/** Options for `createSelectionOverlayLayer`. */\nexport interface SelectionOverlayLayerOpts<TPose>\n extends SelectionLayerCommon<TPose> {\n /**\n * Which ids to draw chrome for. Omit to take them from the `ChromeState` on\n * the draw envelope, which is what makes one canvas's several views each\n * outline their own selection — the layer is shared, the envelope is not.\n */\n getSelection?: () => readonly NodeId[];\n /**\n * Resolve an id to the pose to draw chrome around. Return null to skip an\n * id. Omit to take bounds from the same envelope `getSelection` omitted\n * takes ids from.\n *\n * Takes `string` rather than `NodeId` because the container-aware resolver\n * walks expanded leaf ids via `getChildren`, which is generic over strings.\n */\n getPose?: (id: string) => TPose | null;\n outline?: CommandStroke & { pad?: number };\n /** Pass `false` to render outlines only. */\n handles?: SelectionHandleStyle | false;\n handlesOf?: (bounds: Bounds) => { x: number; y: number }[];\n /** Draw a rotate badge above the selection's top edge. `true` places it at\n * the default offset; `distance` sets the offset in screen pixels. Off by\n * default. */\n rotationHandle?:\n | boolean\n | {\n distance?: number;\n };\n /** Optional separate id list for the per-item outline pass, for a\n * multi-selection whose handle pass works against a synthetic union id\n * (e.g. `MULTI_RESIZE_TARGET_ID`) while each real member is outlined.\n * When omitted, the outline pass uses the handle pass's ids. */\n getOutlineIds?: () => readonly NodeId[];\n /** Optional set of ids to suppress entirely — both outline and handles\n * are skipped. */\n getSuppressedIds?: () => ReadonlySet<string>;\n}\n\nconst DEFAULT_OUTLINE: Required<Pick<CommandStroke, 'paint' | 'width'>> & { pad: number } = {\n paint: { kind: 'solid', color: '#f0e0a8' },\n width: 2,\n pad: 1,\n};\nconst DEFAULT_HANDLE_FILL: CommandFill = { paint: { kind: 'solid', color: '#d4c4a8' } };\nconst DEFAULT_HANDLE_OUTLINE: CommandStroke = {\n paint: { kind: 'solid', color: '#1a130d' },\n width: 1,\n};\nconst DEFAULT_HANDLE_SIZE = HANDLE_BASE_PX;\n\nfunction defaultHandlesOf(b: Bounds): { x: number; y: number }[] {\n return [\n { x: b.x, y: b.y },\n { x: b.x + b.width, y: b.y },\n { x: b.x, y: b.y + b.height },\n { x: b.x + b.width, y: b.y + b.height },\n ];\n}\n\nfunction resolveOutlineStroke(opts?: CommandStroke & { pad?: number }): {\n stroke: CommandStroke;\n pad: number;\n} {\n if (!opts) {\n return {\n stroke: { paint: DEFAULT_OUTLINE.paint, width: DEFAULT_OUTLINE.width },\n pad: DEFAULT_OUTLINE.pad,\n };\n }\n return {\n stroke: {\n paint: opts.paint,\n width: opts.width ?? DEFAULT_OUTLINE.width,\n dash: opts.dash,\n cap: opts.cap,\n join: opts.join,\n align: opts.align,\n },\n pad: opts.pad ?? DEFAULT_OUTLINE.pad,\n };\n}\n\n/** Handle visuals, as a consumer supplies them. */\nexport interface SelectionHandleStyle {\n size?: number;\n fill?: CommandFill;\n outline?: CommandStroke;\n}\n\ninterface ResolvedHandles {\n size: number;\n fill: CommandFill;\n outline: CommandStroke;\n}\n\nfunction resolveHandles(opts?: SelectionHandleStyle): ResolvedHandles {\n return {\n size: opts?.size ?? DEFAULT_HANDLE_SIZE,\n fill: opts?.fill ?? DEFAULT_HANDLE_FILL,\n outline: opts?.outline ?? DEFAULT_HANDLE_OUTLINE,\n };\n}\n\n/**\n * GL helper: build the matrix `translate(cx, cy) * rotate(θ) * translate(-cx, -cy)`\n * used to wrap rotated outline / handle commands.\n */\nfunction rotateAroundMat3(cx: number, cy: number, theta: number): GlMat3 {\n const c = Math.cos(theta);\n const s = Math.sin(theta);\n // Composed in column-major (matches mat3 helpers): T(cx,cy) · R(θ) · T(-cx,-cy).\n // After expansion: a=c, b=s, c'=-s, d=c, tx=cx - c*cx + s*cy, ty=cy - s*cx - c*cy.\n const tx = cx - c * cx + s * cy;\n const ty = cy - s * cx - c * cy;\n return new Float32Array([\n c, s, 0,\n -s, c, 0,\n tx, ty, 1,\n ]) as GlMat3;\n}\n\n/** GL helper: emit a closed rect path (kind:'rect'). */\nfunction rectPathFor(x: number, y: number, width: number, height: number): { kind: 'rect'; x: number; y: number; width: number; height: number } {\n return { kind: 'rect', x, y, width, height };\n}\n\n/** GL helper: emit an outline command for one bounds entry. */\nfunction outlineCommandsFor(\n ids: readonly string[],\n resolveBounds: (id: string) => Bounds | null,\n stroke: CommandStroke,\n pad: number,\n view: View,\n): DrawCommand[] {\n const out: DrawCommand[] = [];\n const align = stroke.align ?? 'center';\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n for (const id of ids) {\n const worldB = resolveBounds(id);\n if (!worldB) continue;\n const b = projectBounds(worldB, view);\n const padded = {\n x: b.x - pad,\n y: b.y - pad,\n width: b.width + pad * 2,\n height: b.height + pad * 2,\n };\n const xf = targetTransformOf(worldB);\n if (xf.identity) {\n const r = alignedStrokeRect(padded, align, width);\n out.push({ kind: 'path', path: rectPathFor(r.x, r.y, r.width, r.height), stroke });\n continue;\n }\n // Turned or skewed, the target lands on screen as a parallelogram, so the\n // outline is traced through its projected corners. `alignedStrokeRect`'s\n // shift is folded into the offset so the ribbon lands where it would.\n const shift = align === 'outer' ? width / 2 : align === 'inner' ? -width / 2 : 0;\n const q = screenCorners(worldB, xf, view, pad + shift);\n out.push({\n kind: 'path',\n path: {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]),\n coords: new Float32Array([q[0].x, q[0].y, q[1].x, q[1].y, q[2].x, q[2].y, q[3].x, q[3].y]),\n fillRule: 'nonzero',\n },\n stroke: { ...stroke, align: 'center' },\n });\n }\n return out;\n}\n\n/**\n * A framed target's corners on screen, TL/TR/BR/BL, each pushed `pad` screen\n * pixels out from both edges that meet there.\n */\nfunction screenCorners(\n worldB: Bounds,\n xf: TargetTransform,\n view: View,\n pad: number,\n): { x: number; y: number }[] {\n const t = viewToTransform(view);\n const q = targetCorners(worldB, xf).map((w) => {\n const [x, y] = worldToScreen(w.x, w.y, t);\n return { x, y };\n });\n if (pad === 0) return q;\n const [ccx, ccy] = worldToScreen(worldB.x + worldB.width / 2, worldB.y + worldB.height / 2, t);\n const normal = (a: { x: number; y: number }, b: { x: number; y: number }) => {\n let nx = -(b.y - a.y), ny = b.x - a.x;\n const l = Math.hypot(nx, ny) || 1;\n nx /= l; ny /= l;\n const mx = (a.x + b.x) / 2 - ccx, my = (a.y + b.y) / 2 - ccy;\n return nx * mx + ny * my < 0 ? { x: -nx, y: -ny } : { x: nx, y: ny };\n };\n return q.map((c, i) => {\n const n1 = normal(q[(i + 3) % 4], c);\n const n2 = normal(c, q[(i + 1) % 4]);\n // The point `pad` off both edge lines.\n const k = pad / (1 + n1.x * n2.x + n1.y * n2.y);\n return { x: c.x + (n1.x + n2.x) * k, y: c.y + (n1.y + n2.y) * k };\n });\n}\n\n/** GL helper: emit handle fill+stroke commands for one bounds entry. */\nfunction handleCommandsFor(\n ids: readonly string[],\n resolveBounds: (id: string) => Bounds | null,\n handles: ResolvedHandles,\n handlesOf: (b: Bounds) => { x: number; y: number }[],\n view: View,\n): DrawCommand[] {\n const out: DrawCommand[] = [];\n const half = handles.size / 2;\n const handleAlign = handles.outline.align ?? 'center';\n const handleWidth = resolveStrokeWidth(handles.outline.width ?? 1, 1);\n for (const id of ids) {\n const worldB = resolveBounds(id);\n if (!worldB) continue;\n // Framed in world, then projected: turning the projected point instead\n // lands somewhere else under non-uniform zoom.\n const xf = targetTransformOf(worldB);\n const t = viewToTransform(view);\n const angle = screenAngleOf(angleOf(xf), view.scale);\n for (const hLocal of handlesOf(worldB)) {\n const hWorld = localToWorld(xf, hLocal.x, hLocal.y);\n const [hsx, hsy] = worldToScreen(hWorld.x, hWorld.y, t);\n const center = { x: hsx, y: hsy };\n const baseRect = {\n x: center.x - half,\n y: center.y - half,\n width: handles.size,\n height: handles.size,\n };\n const sr = alignedStrokeRect(baseRect, handleAlign, handleWidth);\n const fillCmd: DrawCommand = {\n kind: 'path',\n path: rectPathFor(baseRect.x, baseRect.y, baseRect.width, baseRect.height),\n fill: handles.fill,\n };\n const strokeCmd: DrawCommand = {\n kind: 'path',\n path: rectPathFor(sr.x, sr.y, sr.width, sr.height),\n stroke: handles.outline,\n };\n if (angle === 0) {\n out.push(fillCmd, strokeCmd);\n } else {\n out.push({\n kind: 'group',\n transform: rotateAroundMat3(center.x, center.y, angle),\n children: [fillCmd, strokeCmd],\n });\n }\n }\n }\n return out;\n}\n\n/** GL helper: emit a curved double-headed arrow, the rotate badge above the\n * rect. The arc opens *toward* the object (apex on top, mouth pointing\n * down), with an arrowhead at each endpoint pointing along the tangent. */\nfunction rotationHandleCommands(\n worldB: Bounds,\n handles: ResolvedHandles,\n distance: number,\n view: View,\n): DrawCommand[] {\n const hWorld = rotationHandle(worldB, distance, view.scale);\n const rotation = hWorld.angle;\n const t = viewToTransform(view);\n const [scx, scy] = worldToScreen(hWorld.cx, hWorld.cy, t);\n const size = handles.size;\n const arcRadius = size;\n const ARC_HALF_ANGLE = (Math.PI * 240) / 360 / 2; // 120°\n const N_SEGS = 18;\n const arcWidth = resolveStrokeWidth(handles.outline.width ?? 1, 1) * 1.5;\n const stroke: CommandStroke = {\n paint: handles.fill.paint,\n width: arcWidth,\n cap: 'round',\n join: 'round',\n };\n // The arc as a polyline in handle-local coords, centered on the handle\n // anchor: apex at -y, endpoints at +y near the rect side.\n const cmds: number[] = [PATH_M];\n const xs: number[] = [];\n const ys: number[] = [];\n for (let i = 0; i <= N_SEGS; i++) {\n const t = i / N_SEGS;\n const angle = ARC_HALF_ANGLE - t * ARC_HALF_ANGLE * 2;\n xs.push(arcRadius * Math.sin(angle));\n ys.push(-arcRadius * Math.cos(angle));\n if (i > 0) cmds.push(PATH_L);\n }\n const arcCoords: number[] = [];\n for (let i = 0; i < xs.length; i++) {\n arcCoords.push(xs[i], ys[i]);\n }\n const arcPath: PolygonPath = {\n kind: 'polygon',\n commands: new Uint8Array(cmds),\n coords: new Float32Array(arcCoords),\n fillRule: 'nonzero',\n };\n // Arrowheads: small filled triangles at each endpoint, pointing along\n // the tangent (away from the arc body).\n const headLen = size * 0.6;\n const headWidth = size * 0.4;\n const arrowHead = (endX: number, endY: number, tx: number, ty: number): PolygonPath => {\n // Normalize tangent.\n const len = Math.hypot(tx, ty) || 1;\n const ux = tx / len;\n const uy = ty / len;\n // Perpendicular (rotate tangent 90° CCW).\n const px = -uy;\n const py = ux;\n // Triangle: tip is endX+ux*headLen, base is endX (with +/- headWidth/2 along p).\n const tipX = endX + ux * headLen;\n const tipY = endY + uy * headLen;\n const baseLeftX = endX + px * (headWidth / 2);\n const baseLeftY = endY + py * (headWidth / 2);\n const baseRightX = endX - px * (headWidth / 2);\n const baseRightY = endY - py * (headWidth / 2);\n return {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L]),\n coords: new Float32Array([tipX, tipY, baseLeftX, baseLeftY, baseRightX, baseRightY, tipX, tipY]),\n fillRule: 'nonzero',\n };\n };\n // Endpoint A (right side, angle = +ARC_HALF_ANGLE). Arc point:\n // (sin(a)·R, -cos(a)·R). Tangent (d/da) = (cos(a)·R, sin(a)·R).\n const angleA = ARC_HALF_ANGLE;\n const endAX = arcRadius * Math.sin(angleA);\n const endAY = -arcRadius * Math.cos(angleA);\n const tangentAX = Math.cos(angleA);\n const tangentAY = Math.sin(angleA);\n // Endpoint B (left side, angle = -ARC_HALF_ANGLE): tangent in the\n // outward direction is the negation of the above.\n const angleB = -ARC_HALF_ANGLE;\n const endBX = arcRadius * Math.sin(angleB);\n const endBY = -arcRadius * Math.cos(angleB);\n const tangentBX = -Math.cos(angleB);\n const tangentBY = -Math.sin(angleB);\n const headA = arrowHead(endAX, endAY, tangentAX, tangentAY);\n const headB = arrowHead(endBX, endBY, tangentBX, tangentBY);\n // Build transform: translate(scx, scy) [* rotate(rotation)].\n let transform = mat3.translated(mat3.identity(), scx, scy);\n if (rotation !== 0) {\n const c = Math.cos(rotation);\n const s = Math.sin(rotation);\n const rot = new Float32Array([c, s, 0, -s, c, 0, 0, 0, 1]) as GlMat3;\n transform = mat3.multiply(transform, rot);\n }\n return [\n {\n kind: 'group',\n transform,\n children: [\n { kind: 'path', path: arcPath, stroke },\n { kind: 'path', path: headA, fill: handles.fill },\n { kind: 'path', path: headB, fill: handles.fill },\n ],\n },\n ];\n}\n\n/** Which passes a selection layer runs. The three exported factories differ\n * only in this — everything else they do is shared, so a fix to one is a fix\n * to all three. */\ninterface SelectionPasses {\n readonly id: string;\n readonly label: string;\n readonly outline: boolean;\n readonly handles: boolean;\n}\n\nfunction buildSelectionLayer<TPose>(\n opts: SelectionOverlayLayerOpts<TPose>,\n passes: SelectionPasses,\n): RenderLayer<unknown> {\n const { stroke, pad } = resolveOutlineStroke(opts.outline);\n const handlesEnabled = passes.handles && opts.handles !== false;\n const handles = handlesEnabled ? resolveHandles(opts.handles || undefined) : null;\n const handlesOf = opts.handlesOf ?? defaultHandlesOf;\n const d = (opts.poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n const getPose = opts.getPose;\n const poseBounds = getPose\n ? makeContainerAwareBoundsResolver(getPose, d, opts.getChildren, opts.isContainer)\n : null;\n const rotationHandleDistance = passes.handles\n ? rotationBadgeOf(opts)?.distancePx ?? null\n : null;\n\n return {\n id: passes.id,\n label: passes.label,\n space: 'screen',\n draw: (data, view) => {\n // The synthetic multi-resize id resolves to `ChromeState.unionBounds`,\n // the same value the affordance hit-tester reads, so painted chrome\n // and its hit region stay in agreement. With no chromeState on the\n // draw envelope, fall through to the supplied resolver.\n const chromeState = asChromeState(data);\n const allIds = opts.getSelection\n ? opts.getSelection()\n : chromeSelectionIds(chromeState);\n if (allIds.length === 0) return [];\n const suppressed = opts.getSuppressedIds?.();\n const ids = suppressed && suppressed.size > 0\n ? allIds.filter((id) => !suppressed.has(id as unknown as string))\n : allIds;\n if (ids.length === 0) return [];\n // Chrome-caps: gate each pass on its canonical id. When no\n // `getIsVisible` is wired, every pass runs.\n const isVisible = asIsVisible(data);\n const showOutline = passes.outline && (isVisible ? isVisible('selection.outline') : true);\n const showHandles = isVisible ? isVisible('selection.resize-handles') : true;\n const showRotation = isVisible ? isVisible('selection.rotation-handle') : true;\n\n const resolveBounds = poseBounds ?? ((id: string) => chromeState?.boundsOf(id) ?? null);\n const resolveTargetBounds = (id: string): Bounds | null => {\n if (id === MULTI_RESIZE_TARGET_ID && chromeState?.unionBounds != null) {\n return chromeState.unionBounds;\n }\n return resolveBounds(id);\n };\n\n const out: DrawCommand[] = [];\n if (showOutline) {\n const outlineIdsRaw = opts.getOutlineIds\n ? opts.getOutlineIds()\n : (opts.getSelection ? ids : (chromeState?.selection ?? ids));\n const outlineIds = suppressed && suppressed.size > 0\n ? outlineIdsRaw.filter((id) => !suppressed.has(id as unknown as string))\n : outlineIdsRaw;\n for (const cmd of outlineCommandsFor(outlineIds, resolveTargetBounds, stroke, pad, view)) out.push(cmd);\n }\n if (!handles) return out;\n if (showHandles) {\n for (const cmd of handleCommandsFor(ids, resolveTargetBounds, handles, handlesOf, view)) out.push(cmd);\n }\n if (showRotation && rotationHandleDistance !== null) {\n for (const id of ids) {\n const b = resolveTargetBounds(id);\n if (!b) continue;\n for (const cmd of rotationHandleCommands(b, handles, rotationHandleDistance, view)) {\n out.push(cmd);\n }\n }\n }\n return out;\n },\n };\n}\n\n/** Where the overlay paints its rotate badge and how big it is, in screen\n * pixels, or `null` when it paints none. The badge's grab region and its\n * slops halo read this too, so all three agree on it. */\nexport function rotationBadgeOf(\n opts: Pick<SelectionOverlayLayerOpts<unknown>, 'handles' | 'rotationHandle'>,\n): { distancePx: number; sizePx: number } | null {\n const r = opts.rotationHandle;\n if (!r || opts.handles === false) return null;\n return {\n distancePx: r === true ? DEFAULT_ROTATION_HANDLE_DISTANCE : r.distance ?? DEFAULT_ROTATION_HANDLE_DISTANCE,\n sizePx: resolveHandles(opts.handles || undefined).size,\n };\n}\n/**\n * `RenderLayer` that draws selection outlines only. Stack alongside\n * `createSelectionHandlesLayer` (or use `createSelectionOverlayLayer`, which\n * runs both passes in one layer) when both are wanted.\n */\nexport function createSelectionOutlineLayer<TPose>(\n opts: SelectionOutlineLayerOpts<TPose>,\n): RenderLayer<unknown> {\n return buildSelectionLayer(opts, {\n id: 'selection-outline',\n label: 'Selection outline',\n outline: true,\n handles: false,\n });\n}\n\n/**\n * `RenderLayer` that draws selection handles only. Stack on top of\n * `createSelectionOutlineLayer` (handles render on top of the outline).\n */\nexport function createSelectionHandlesLayer<TPose>(\n opts: SelectionHandlesLayerOpts<TPose>,\n): RenderLayer<unknown> {\n return buildSelectionLayer(opts, {\n id: 'selection-handles',\n label: 'Selection handles',\n outline: false,\n handles: true,\n });\n}\n\n/**\n * Draws outlines then handles in a single layer. Exactly equivalent to\n * stacking `createSelectionOutlineLayer` and `createSelectionHandlesLayer` —\n * all three run the same body. Pass `handles: false` to render outlines only.\n */\nexport function createSelectionOverlayLayer<TPose>(\n opts: SelectionOverlayLayerOpts<TPose>,\n): RenderLayer<unknown> {\n return buildSelectionLayer(opts, {\n id: 'selection-overlay',\n label: 'Selection',\n outline: true,\n handles: true,\n });\n}\n\n/** Pull a chrome-caps visibility predicate off the draw `data` envelope.\n * Returns `null` when the caller passed bare data (no `getIsVisible`\n * thunk) — the layer then renders unconditionally. */\nfunction asIsVisible(data: unknown): ((id: string) => boolean) | null {\n const maybe = data as { getIsVisible?: () => (id: string) => boolean };\n if (typeof maybe?.getIsVisible === 'function') return maybe.getIsVisible();\n return null;\n}\n\n/** The ids the handle pass works against when the layer takes its selection\n * from the envelope: the synthetic union id for a multi-selection, the\n * selection itself otherwise. */\nfunction chromeSelectionIds(state: ChromeState | null): readonly NodeId[] {\n if (!state) return [];\n if (state.multiActive) return [MULTI_RESIZE_TARGET_ID as NodeId];\n return state.selection;\n}\n\n/** Pull live `ChromeState` off the draw `data` envelope. Returns `null` for\n * callers that pass plain data with no `getChromeState` thunk — the layer\n * then resolves the multi-union via the supplied `getPose` resolver. */\nfunction asChromeState(data: unknown): ChromeState | null {\n const maybe = data as { getChromeState?: () => ChromeState };\n if (typeof maybe?.getChromeState === 'function') return maybe.getChromeState();\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"overlay.js","names":[],"sources":["../../../src/features/selection/overlay.ts"],"sourcesContent":["/**\n * Selection overlay primitives — render layers for drawing selection\n * outlines and resize handles.\n *\n * **Pose shape:** TPose is generic; callers pass `poseDescriptor` for poses\n * `AUTO_POSE_DESCRIPTOR` can't read. Container ids reduce via `unionAABB`\n * over the projected AABBs.\n */\n\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport { mat3, type GlMat3 } from '@weasel-js/renderer';\nimport type { NodeId } from 'core/scene/types';\nimport type { RenderLayer } from 'core/layers/render';\nimport type { PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport type { DrawnBoundsScene } from 'canvas/drawnBounds';\nimport { containerAwareBoundsResolver } from './selectionPose';\nimport { targetCorners, targetTransformOf, type TargetTransform } from 'core/geometry/targetFrame';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport { alignedStrokeRect, type CommandStroke } from '@weasel-js/paint';\nimport { resolveStrokeWidth } from '@weasel-js/stroke';\nimport {\n rotationHandle,\n DEFAULT_ROTATION_HANDLE_DISTANCE,\n} from 'interactions/actions/rotate/handle';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport type { ChromeState } from 'core/selection/chromeState';\nimport { MULTI_RESIZE_TARGET_ID } from 'core/selection/selectionTarget';\nimport type { View } from 'core/viewport/view';\nimport { viewToTransform } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\nimport { PATH_L, PATH_M, PATH_Z, type PolygonPath } from '@weasel-js/geom';\nimport {\n handleCommandsFor, rectPathFor, resolveHandles, type ResizeHandleLayout, type ResolvedHandles, type SelectionHandleStyle,\n} from './handleCommands';\n\nexport type { SelectionHandleStyle };\n\nexport { composeSelectionPose, type ComposeSelectionPoseOpts } from './selectionPose';\n\n/** Project world AABB into screen-space AABB using the active view. */\nfunction projectBounds<B extends Bounds>(b: B, view: View): B {\n const t = viewToTransform(view);\n const [sx, sy] = worldToScreen(b.x, b.y, t);\n return { ...b, x: sx, y: sy, width: b.width * view.scale.x, height: b.height * view.scale.y };\n}\n\n\n/** Options every selection layer shares. `getSelection` and `getPose` are\n * declared on {@link SelectionOverlayLayerOpts}, which makes both optional —\n * omitted, they come off the draw envelope. */\ninterface SelectionLayerCommon<TPose> {\n /** How to read poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Walk a container's direct children (e.g. `scene.childrenOf`). When\n * supplied with `isContainer`, any id that resolves to a container is\n * rendered using the union bounds of all its transitive leaves. */\n getChildren?: (id: string) => readonly string[];\n /** True when `id` is a structural container. */\n isContainer?: (id: string) => boolean;\n /** The nodes behind the ids `getPose` answers for. With it, a stroked\n * node's chrome sits on its stroke (`drawnBoundsOf`); without, on its\n * pose box. Ignored when bounds come off the draw envelope. */\n scene?: DrawnBoundsScene;\n}\n\n/** Options for `createSelectionOutlineLayer`. The overlay layer's options\n * minus the handle visuals — the two run the same body. */\nexport type SelectionOutlineLayerOpts<TPose> =\n Omit<SelectionOverlayLayerOpts<TPose>, 'handles' | 'handlesOf' | 'resizeHandles' | 'rotationHandle'>;\n\n/** Options for `createSelectionHandlesLayer`. The overlay layer's options\n * minus the outline stroke — the two run the same body. */\nexport type SelectionHandlesLayerOpts<TPose> =\n Omit<SelectionOverlayLayerOpts<TPose>, 'outline'>;\n\n/** Options for `createSelectionOverlayLayer`. */\nexport interface SelectionOverlayLayerOpts<TPose>\n extends SelectionLayerCommon<TPose> {\n /**\n * Which ids to draw chrome for. Omit to take them from the `ChromeState` on\n * the draw envelope, which is what makes one canvas's several views each\n * outline their own selection — the layer is shared, the envelope is not.\n */\n getSelection?: () => readonly NodeId[];\n /**\n * Resolve an id to the pose to draw chrome around. Return null to skip an\n * id. Omit to take bounds from the same envelope `getSelection` omitted\n * takes ids from.\n *\n * Takes `string` rather than `NodeId` because the container-aware resolver\n * walks expanded leaf ids via `getChildren`, which is generic over strings.\n */\n getPose?: (id: string) => TPose | null;\n outline?: CommandStroke & { pad?: number };\n /** Pass `false` to render outlines only. */\n handles?: SelectionHandleStyle | false;\n /** Where to paint handles, in the bounds' own frame. Replaces the kit's\n * layout, `resizeHandles` included. */\n handlesOf?: (bounds: Bounds) => { x: number; y: number }[];\n /** The layout the resize affordance hits by: its `hitRadiusPx`, never\n * `handles.size`, decides which edge handles are painted. Default: edges on,\n * at the kit's default hit radius. */\n resizeHandles?: Partial<ResizeHandleLayout>;\n /** Draw a rotate badge above the selection's top edge. `true` places it at\n * the default offset; `distance` sets the offset in screen pixels. Off by\n * default. */\n rotationHandle?:\n | boolean\n | {\n distance?: number;\n };\n /** Optional separate id list for the per-item outline pass, for a\n * multi-selection whose handle pass works against a synthetic union id\n * (e.g. `MULTI_RESIZE_TARGET_ID`) while each real member is outlined.\n * When omitted, the outline pass uses the handle pass's ids. */\n getOutlineIds?: () => readonly NodeId[];\n /** Optional set of ids to suppress entirely — both outline and handles\n * are skipped. */\n getSuppressedIds?: () => ReadonlySet<string>;\n}\n\nconst DEFAULT_OUTLINE: Required<Pick<CommandStroke, 'paint' | 'width'>> & { pad: number } = {\n paint: { kind: 'solid', color: '#f0e0a8' },\n width: 2,\n pad: 1,\n};\nfunction resolveOutlineStroke(opts?: CommandStroke & { pad?: number }): {\n stroke: CommandStroke;\n pad: number;\n} {\n if (!opts) {\n return {\n stroke: { paint: DEFAULT_OUTLINE.paint, width: DEFAULT_OUTLINE.width },\n pad: DEFAULT_OUTLINE.pad,\n };\n }\n return {\n stroke: {\n paint: opts.paint,\n width: opts.width ?? DEFAULT_OUTLINE.width,\n dash: opts.dash,\n cap: opts.cap,\n join: opts.join,\n align: opts.align,\n },\n pad: opts.pad ?? DEFAULT_OUTLINE.pad,\n };\n}\n\n/** GL helper: emit an outline command for one bounds entry. */\nfunction outlineCommandsFor(\n ids: readonly string[],\n resolveBounds: (id: string) => Bounds | null,\n stroke: CommandStroke,\n pad: number,\n view: View,\n): DrawCommand[] {\n const out: DrawCommand[] = [];\n const align = stroke.align ?? 'center';\n const width = resolveStrokeWidth(stroke.width ?? 1, 1);\n for (const id of ids) {\n const worldB = resolveBounds(id);\n if (!worldB) continue;\n const b = projectBounds(worldB, view);\n const padded = {\n x: b.x - pad,\n y: b.y - pad,\n width: b.width + pad * 2,\n height: b.height + pad * 2,\n };\n const xf = targetTransformOf(worldB);\n if (xf.identity) {\n const r = alignedStrokeRect(padded, align, width);\n out.push({ kind: 'path', path: rectPathFor(r.x, r.y, r.width, r.height), stroke });\n continue;\n }\n // Turned or skewed, the target lands on screen as a parallelogram, so the\n // outline is traced through its projected corners. `alignedStrokeRect`'s\n // shift is folded into the offset so the ribbon lands where it would.\n const shift = align === 'outer' ? width / 2 : align === 'inner' ? -width / 2 : 0;\n const q = screenCorners(worldB, xf, view, pad + shift);\n out.push({\n kind: 'path',\n path: {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L, PATH_Z]),\n coords: new Float32Array([q[0].x, q[0].y, q[1].x, q[1].y, q[2].x, q[2].y, q[3].x, q[3].y]),\n fillRule: 'nonzero',\n },\n stroke: { ...stroke, align: 'center' },\n });\n }\n return out;\n}\n\n/**\n * A framed target's corners on screen, TL/TR/BR/BL, each pushed `pad` screen\n * pixels out from both edges that meet there.\n */\nfunction screenCorners(\n worldB: Bounds,\n xf: TargetTransform,\n view: View,\n pad: number,\n): { x: number; y: number }[] {\n const t = viewToTransform(view);\n const q = targetCorners(worldB, xf).map((w) => {\n const [x, y] = worldToScreen(w.x, w.y, t);\n return { x, y };\n });\n if (pad === 0) return q;\n const [ccx, ccy] = worldToScreen(worldB.x + worldB.width / 2, worldB.y + worldB.height / 2, t);\n const normal = (a: { x: number; y: number }, b: { x: number; y: number }) => {\n let nx = -(b.y - a.y), ny = b.x - a.x;\n const l = Math.hypot(nx, ny) || 1;\n nx /= l; ny /= l;\n const mx = (a.x + b.x) / 2 - ccx, my = (a.y + b.y) / 2 - ccy;\n return nx * mx + ny * my < 0 ? { x: -nx, y: -ny } : { x: nx, y: ny };\n };\n return q.map((c, i) => {\n const n1 = normal(q[(i + 3) % 4], c);\n const n2 = normal(c, q[(i + 1) % 4]);\n // The point `pad` off both edge lines.\n const k = pad / (1 + n1.x * n2.x + n1.y * n2.y);\n return { x: c.x + (n1.x + n2.x) * k, y: c.y + (n1.y + n2.y) * k };\n });\n}\n\n/** GL helper: emit a curved double-headed arrow, the rotate badge above the\n * rect. The arc opens *toward* the object (apex on top, mouth pointing\n * down), with an arrowhead at each endpoint pointing along the tangent. */\nfunction rotationHandleCommands(\n worldB: Bounds,\n handles: ResolvedHandles,\n distance: number,\n view: View,\n): DrawCommand[] {\n const hWorld = rotationHandle(worldB, distance, view.scale);\n const rotation = hWorld.angle;\n const t = viewToTransform(view);\n const [scx, scy] = worldToScreen(hWorld.cx, hWorld.cy, t);\n const size = handles.size;\n const arcRadius = size;\n const ARC_HALF_ANGLE = (Math.PI * 240) / 360 / 2; // 120°\n const N_SEGS = 18;\n const arcWidth = resolveStrokeWidth(handles.outline.width ?? 1, 1) * 1.5;\n const stroke: CommandStroke = {\n paint: handles.fill.paint,\n width: arcWidth,\n cap: 'round',\n join: 'round',\n };\n // The arc as a polyline in handle-local coords, centered on the handle\n // anchor: apex at -y, endpoints at +y near the rect side.\n const cmds: number[] = [PATH_M];\n const xs: number[] = [];\n const ys: number[] = [];\n for (let i = 0; i <= N_SEGS; i++) {\n const t = i / N_SEGS;\n const angle = ARC_HALF_ANGLE - t * ARC_HALF_ANGLE * 2;\n xs.push(arcRadius * Math.sin(angle));\n ys.push(-arcRadius * Math.cos(angle));\n if (i > 0) cmds.push(PATH_L);\n }\n const arcCoords: number[] = [];\n for (let i = 0; i < xs.length; i++) {\n arcCoords.push(xs[i], ys[i]);\n }\n const arcPath: PolygonPath = {\n kind: 'polygon',\n commands: new Uint8Array(cmds),\n coords: new Float32Array(arcCoords),\n fillRule: 'nonzero',\n };\n // Arrowheads: small filled triangles at each endpoint, pointing along\n // the tangent (away from the arc body).\n const headLen = size * 0.6;\n const headWidth = size * 0.4;\n const arrowHead = (endX: number, endY: number, tx: number, ty: number): PolygonPath => {\n // Normalize tangent.\n const len = Math.hypot(tx, ty) || 1;\n const ux = tx / len;\n const uy = ty / len;\n // Perpendicular (rotate tangent 90° CCW).\n const px = -uy;\n const py = ux;\n // Triangle: tip is endX+ux*headLen, base is endX (with +/- headWidth/2 along p).\n const tipX = endX + ux * headLen;\n const tipY = endY + uy * headLen;\n const baseLeftX = endX + px * (headWidth / 2);\n const baseLeftY = endY + py * (headWidth / 2);\n const baseRightX = endX - px * (headWidth / 2);\n const baseRightY = endY - py * (headWidth / 2);\n return {\n kind: 'polygon',\n commands: new Uint8Array([PATH_M, PATH_L, PATH_L, PATH_L]),\n coords: new Float32Array([tipX, tipY, baseLeftX, baseLeftY, baseRightX, baseRightY, tipX, tipY]),\n fillRule: 'nonzero',\n };\n };\n // Endpoint A (right side, angle = +ARC_HALF_ANGLE). Arc point:\n // (sin(a)·R, -cos(a)·R). Tangent (d/da) = (cos(a)·R, sin(a)·R).\n const angleA = ARC_HALF_ANGLE;\n const endAX = arcRadius * Math.sin(angleA);\n const endAY = -arcRadius * Math.cos(angleA);\n const tangentAX = Math.cos(angleA);\n const tangentAY = Math.sin(angleA);\n // Endpoint B (left side, angle = -ARC_HALF_ANGLE): tangent in the\n // outward direction is the negation of the above.\n const angleB = -ARC_HALF_ANGLE;\n const endBX = arcRadius * Math.sin(angleB);\n const endBY = -arcRadius * Math.cos(angleB);\n const tangentBX = -Math.cos(angleB);\n const tangentBY = -Math.sin(angleB);\n const headA = arrowHead(endAX, endAY, tangentAX, tangentAY);\n const headB = arrowHead(endBX, endBY, tangentBX, tangentBY);\n // Build transform: translate(scx, scy) [* rotate(rotation)].\n let transform = mat3.translated(mat3.identity(), scx, scy);\n if (rotation !== 0) {\n const c = Math.cos(rotation);\n const s = Math.sin(rotation);\n const rot = new Float32Array([c, s, 0, -s, c, 0, 0, 0, 1]) as GlMat3;\n transform = mat3.multiply(transform, rot);\n }\n return [\n {\n kind: 'group',\n transform,\n children: [\n { kind: 'path', path: arcPath, stroke },\n { kind: 'path', path: headA, fill: handles.fill },\n { kind: 'path', path: headB, fill: handles.fill },\n ],\n },\n ];\n}\n\n/** Which passes a selection layer runs. The three exported factories differ\n * only in this — everything else they do is shared, so a fix to one is a fix\n * to all three. */\ninterface SelectionPasses {\n readonly id: string;\n readonly label: string;\n readonly outline: boolean;\n readonly handles: boolean;\n}\n\nfunction buildSelectionLayer<TPose>(\n opts: SelectionOverlayLayerOpts<TPose>,\n passes: SelectionPasses,\n): RenderLayer<unknown> {\n const { stroke, pad } = resolveOutlineStroke(opts.outline);\n const handlesEnabled = passes.handles && opts.handles !== false;\n const handles = handlesEnabled ? resolveHandles(opts.handles || undefined) : null;\n const { handlesOf, resizeHandles } = opts;\n const d = (opts.poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n const getPose = opts.getPose;\n const poseBounds = getPose\n ? containerAwareBoundsResolver(getPose, d, opts.getChildren, opts.isContainer, opts.scene)\n : null;\n const rotationHandleDistance = passes.handles\n ? rotationBadgeOf(opts)?.distancePx ?? null\n : null;\n\n return {\n id: passes.id,\n label: passes.label,\n space: 'screen',\n draw: (data, view) => {\n // The synthetic multi-resize id resolves to `ChromeState.unionBounds`,\n // the same value the affordance hit-tester reads, so painted chrome\n // and its hit region stay in agreement. With no chromeState on the\n // draw envelope, fall through to the supplied resolver.\n const chromeState = asChromeState(data);\n const allIds = opts.getSelection\n ? opts.getSelection()\n : chromeSelectionIds(chromeState);\n if (allIds.length === 0) return [];\n const suppressed = opts.getSuppressedIds?.();\n const ids = suppressed && suppressed.size > 0\n ? allIds.filter((id) => !suppressed.has(id as unknown as string))\n : allIds;\n if (ids.length === 0) return [];\n // Chrome-caps: gate each pass on its canonical id. When no\n // `getIsVisible` is wired, every pass runs.\n const isVisible = asIsVisible(data);\n const showOutline = passes.outline && (isVisible ? isVisible('selection.outline') : true);\n const showHandles = isVisible ? isVisible('selection.resize-handles') : true;\n const showRotation = isVisible ? isVisible('selection.rotation-handle') : true;\n\n const resolveBounds = poseBounds\n ? (id: string) => poseBounds(id, view.scale)\n : (id: string) => chromeState?.boundsOf(id) ?? null;\n const resolveTargetBounds = (id: string): Bounds | null => {\n if (id === MULTI_RESIZE_TARGET_ID && chromeState?.unionBounds != null) {\n return chromeState.unionBounds;\n }\n return resolveBounds(id);\n };\n\n const out: DrawCommand[] = [];\n if (showOutline) {\n const outlineIdsRaw = opts.getOutlineIds\n ? opts.getOutlineIds()\n : (opts.getSelection ? ids : (chromeState?.selection ?? ids));\n const outlineIds = suppressed && suppressed.size > 0\n ? outlineIdsRaw.filter((id) => !suppressed.has(id as unknown as string))\n : outlineIdsRaw;\n for (const cmd of outlineCommandsFor(outlineIds, resolveTargetBounds, stroke, pad, view)) out.push(cmd);\n }\n if (!handles) return out;\n if (showHandles) {\n for (const cmd of handleCommandsFor(ids, resolveTargetBounds, handles, handlesOf, resizeHandles, view)) out.push(cmd);\n }\n if (showRotation && rotationHandleDistance !== null) {\n for (const id of ids) {\n const b = resolveTargetBounds(id);\n if (!b) continue;\n for (const cmd of rotationHandleCommands(b, handles, rotationHandleDistance, view)) {\n out.push(cmd);\n }\n }\n }\n return out;\n },\n };\n}\n\n/** Where the overlay paints its rotate badge and how big it is, in screen\n * pixels, or `null` when it paints none. The badge's grab region and its\n * slops halo read this too, so all three agree on it. */\nexport function rotationBadgeOf(\n opts: Pick<SelectionOverlayLayerOpts<unknown>, 'handles' | 'rotationHandle'>,\n): { distancePx: number; sizePx: number } | null {\n const r = opts.rotationHandle;\n if (!r || opts.handles === false) return null;\n return {\n distancePx: r === true ? DEFAULT_ROTATION_HANDLE_DISTANCE : r.distance ?? DEFAULT_ROTATION_HANDLE_DISTANCE,\n sizePx: resolveHandles(opts.handles || undefined).size,\n };\n}\n/**\n * `RenderLayer` that draws selection outlines only. Stack alongside\n * `createSelectionHandlesLayer` (or use `createSelectionOverlayLayer`, which\n * runs both passes in one layer) when both are wanted.\n */\nexport function createSelectionOutlineLayer<TPose>(\n opts: SelectionOutlineLayerOpts<TPose>,\n): RenderLayer<unknown> {\n return buildSelectionLayer(opts, {\n id: 'selection-outline',\n label: 'Selection outline',\n outline: true,\n handles: false,\n });\n}\n\n/**\n * `RenderLayer` that draws selection handles only. Stack on top of\n * `createSelectionOutlineLayer` (handles render on top of the outline).\n */\nexport function createSelectionHandlesLayer<TPose>(\n opts: SelectionHandlesLayerOpts<TPose>,\n): RenderLayer<unknown> {\n return buildSelectionLayer(opts, {\n id: 'selection-handles',\n label: 'Selection handles',\n outline: false,\n handles: true,\n });\n}\n\n/**\n * Draws outlines then handles in a single layer. Exactly equivalent to\n * stacking `createSelectionOutlineLayer` and `createSelectionHandlesLayer` —\n * all three run the same body. Pass `handles: false` to render outlines only.\n */\nexport function createSelectionOverlayLayer<TPose>(\n opts: SelectionOverlayLayerOpts<TPose>,\n): RenderLayer<unknown> {\n return buildSelectionLayer(opts, {\n id: 'selection-overlay',\n label: 'Selection',\n outline: true,\n handles: true,\n });\n}\n\n/** Pull a chrome-caps visibility predicate off the draw `data` envelope.\n * Returns `null` when the caller passed bare data (no `getIsVisible`\n * thunk) — the layer then renders unconditionally. */\nfunction asIsVisible(data: unknown): ((id: string) => boolean) | null {\n const maybe = data as { getIsVisible?: () => (id: string) => boolean };\n if (typeof maybe?.getIsVisible === 'function') return maybe.getIsVisible();\n return null;\n}\n\n/** The ids the handle pass works against when the layer takes its selection\n * from the envelope: the synthetic union id for a multi-selection, the\n * selection itself otherwise. */\nfunction chromeSelectionIds(state: ChromeState | null): readonly NodeId[] {\n if (!state) return [];\n if (state.multiActive) return [MULTI_RESIZE_TARGET_ID as NodeId];\n return state.selection;\n}\n\n/** Pull live `ChromeState` off the draw `data` envelope. Returns `null` for\n * callers that pass plain data with no `getChromeState` thunk — the layer\n * then resolves the multi-union via the supplied `getPose` resolver. */\nfunction asChromeState(data: unknown): ChromeState | null {\n const maybe = data as { getChromeState?: () => ChromeState };\n if (typeof maybe?.getChromeState === 'function') return maybe.getChromeState();\n return null;\n}\n"],"mappings":"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"}
@@ -0,0 +1,109 @@
1
+ import { unionAABB } from "../../core/geometry/unionBounds.js";
2
+ import { framedBounds, visualBoundsViaDescriptor } from "../../core/geometry/poseDescriptor.js";
3
+ import { AUTO_POSE_DESCRIPTOR } from "../../core/geometry/autoPoseDescriptor.js";
4
+ import { drawnAABBOf, drawnBoundsOf } from "../../canvas/drawnBounds.js";
5
+
6
+ //#region src/features/selection/selectionPose.ts
7
+ /**
8
+ * Transitive leaf ids under `id`. A childless node is a leaf only if it is not
9
+ * itself a container: an empty container contributes no bounds, and its own
10
+ * stored pose is at its most stale when no children are left to have moved it.
11
+ */
12
+ function leavesOf(id, getChildren, isContainer) {
13
+ if (!isContainer(id)) return [id];
14
+ const out = [];
15
+ const visit = (nid) => {
16
+ const kids = getChildren(nid);
17
+ if (kids.length === 0) {
18
+ if (!isContainer(nid)) out.push(nid);
19
+ return;
20
+ }
21
+ for (const k of kids) visit(k);
22
+ };
23
+ visit(id);
24
+ return out;
25
+ }
26
+ /** How one id's pose becomes a box: the pose box, or with a scene the box the
27
+ * node is drawn with. Each id is read as a leaf — the pose already says where
28
+ * a container is, so its members' stored poses are not consulted again. */
29
+ function boxReader(d, scene) {
30
+ if (!scene) return {
31
+ framed: (_id, pose) => framedBounds(pose, d),
32
+ aabb: (_id, pose) => visualBoundsViaDescriptor(pose, d)
33
+ };
34
+ const leaves = { get: (id) => scene.get(id) };
35
+ const opts = (scale) => ({
36
+ descriptor: d,
37
+ ...scale !== void 0 ? { scale } : {}
38
+ });
39
+ return {
40
+ framed: (id, pose, scale) => drawnBoundsOf(leaves, id, pose, opts(scale)),
41
+ aabb: (id, pose, scale) => drawnAABBOf(leaves, id, pose, opts(scale))
42
+ };
43
+ }
44
+ /**
45
+ * Build a pose resolver for a selection. Precedence per id:
46
+ * move overlay > resize overlay > stored. When `getChildren`/`isContainer`
47
+ * are supplied and the id resolves to a container, the resolver returns the
48
+ * union AABB of all transitive leaf poses (each leaf still subject to the
49
+ * precedence rules). Containers with no leaves resolve to `null`.
50
+ */
51
+ function composeSelectionPose(opts) {
52
+ const { moveOverlay, resizeOverlay, getStoredPose, getChildren, isContainer } = opts;
53
+ const d = opts.poseDescriptor ?? AUTO_POSE_DESCRIPTOR;
54
+ const boxes = boxReader(d, opts.scene);
55
+ const selectionLeaves = (id) => getChildren && isContainer ? leavesOf(id, getChildren, isContainer) : [id];
56
+ const resolveLeaf = (id) => {
57
+ const moved = moveOverlay?.poses.get(id);
58
+ if (moved !== void 0) return moved;
59
+ if (resizeOverlay && resizeOverlay.id === id) return resizeOverlay.currentPose;
60
+ return getStoredPose(id);
61
+ };
62
+ return (id) => {
63
+ if (isContainer?.(id)) {
64
+ const leaves = selectionLeaves(id);
65
+ if (leaves.length === 0) return null;
66
+ const containerResizeLeafPoses = resizeOverlay && resizeOverlay.id === id ? resizeOverlay.leafPoses : void 0;
67
+ const scale = opts.viewScale?.();
68
+ const leafBounds = [];
69
+ for (const leafId of leaves) {
70
+ const pose = moveOverlay?.poses.get(leafId) ?? containerResizeLeafPoses?.get(leafId) ?? getStoredPose(leafId);
71
+ leafBounds.push(boxes.aabb(leafId, pose, scale));
72
+ }
73
+ const u = unionAABB(leafBounds);
74
+ if (u === null) return null;
75
+ return d.fromBounds(u, getStoredPose(leaves[0]));
76
+ }
77
+ return resolveLeaf(id);
78
+ };
79
+ }
80
+ /**
81
+ * Build a bounds resolver that handles container ids by computing the union
82
+ * AABB of every leaf's bounds. Non-container ids pass through directly. When
83
+ * `getChildren`/`isContainer` are omitted, every id is treated as a leaf.
84
+ * With a scene, each leaf is boxed as drawn at the view's scale.
85
+ */
86
+ function containerAwareBoundsResolver(getPose, d, getChildren, isContainer, scene) {
87
+ const boxes = boxReader(d, scene);
88
+ const leaf = (id, scale) => {
89
+ const p = getPose(id);
90
+ return p === null ? null : boxes.framed(id, p, scale);
91
+ };
92
+ if (getChildren === void 0 || isContainer === void 0) return leaf;
93
+ return (id, scale) => {
94
+ if (!isContainer(id)) return leaf(id, scale);
95
+ const leaves = leavesOf(id, getChildren, isContainer);
96
+ if (leaves.length === 0) return null;
97
+ const leafBounds = [];
98
+ for (const leafId of leaves) {
99
+ const p = getPose(leafId);
100
+ if (p !== null) leafBounds.push(boxes.aabb(leafId, p, scale));
101
+ }
102
+ if (leafBounds.length === 0) return null;
103
+ return unionAABB(leafBounds);
104
+ };
105
+ }
106
+
107
+ //#endregion
108
+ export { composeSelectionPose, containerAwareBoundsResolver };
109
+ //# sourceMappingURL=selectionPose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectionPose.js","names":[],"sources":["../../../src/features/selection/selectionPose.ts"],"sourcesContent":["/**\n * The pose and box a selection's chrome is drawn around: precedence between\n * the in-flight overlays and the stored pose, a container's union over its\n * leaves, and the drawn box a scene supplies.\n */\nimport type { Scale2 } from '@weasel-js/geom';\nimport { drawnAABBOf, drawnBoundsOf, type DrawnBoundsScene } from 'canvas/drawnBounds';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport { framedBounds, visualBoundsViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport type { NodeId } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\n\n/**\n * Transitive leaf ids under `id`. A childless node is a leaf only if it is not\n * itself a container: an empty container contributes no bounds, and its own\n * stored pose is at its most stale when no children are left to have moved it.\n */\nfunction leavesOf(\n id: string,\n getChildren: (id: string) => readonly string[],\n isContainer: (id: string) => boolean,\n): string[] {\n if (!isContainer(id)) return [id];\n const out: string[] = [];\n const visit = (nid: string) => {\n const kids = getChildren(nid);\n if (kids.length === 0) { if (!isContainer(nid)) out.push(nid); return; }\n for (const k of kids) visit(k);\n };\n visit(id);\n return out;\n}\n\n/** How one id's pose becomes a box: the pose box, or with a scene the box the\n * node is drawn with. Each id is read as a leaf — the pose already says where\n * a container is, so its members' stored poses are not consulted again. */\nfunction boxReader<TPose>(\n d: PoseDescriptor<TPose>,\n scene: DrawnBoundsScene | undefined,\n): { framed(id: string, pose: TPose, scale?: number | Scale2): Bounds; aabb(id: string, pose: TPose, scale?: number | Scale2): Bounds } {\n if (!scene) {\n return {\n framed: (_id, pose) => framedBounds(pose, d),\n aabb: (_id, pose) => visualBoundsViaDescriptor(pose, d),\n };\n }\n const leaves: DrawnBoundsScene = { get: (id) => scene.get(id) };\n const opts = (scale: number | Scale2 | undefined) => ({\n descriptor: d as PoseDescriptor<unknown>,\n ...(scale !== undefined ? { scale } : {}),\n });\n return {\n framed: (id, pose, scale) => drawnBoundsOf(leaves, id as NodeId, pose, opts(scale)),\n aabb: (id, pose, scale) => drawnAABBOf(leaves, id as NodeId, pose, opts(scale)),\n };\n}\n\n/** Options for `composeSelectionPose`. */\nexport interface ComposeSelectionPoseOpts<TPose> {\n /** Move overlay; when present its `poses` map wins over everything else. */\n moveOverlay?: { poses: Map<string, TPose> } | null;\n /**\n * Resize overlay; consulted only when move overlay does not own the id.\n * For container resize, `leafPoses` (when present) maps each leaf id under\n * the container to its overlay pose. If absent the container falls back to\n * stored leaf poses.\n */\n resizeOverlay?: {\n id: string;\n currentPose: TPose;\n leafPoses?: Map<string, TPose>;\n } | null;\n /** Fallback pose lookup (typically the stored/committed pose). */\n getStoredPose: (id: string) => TPose;\n /** How to read poses. Default `AUTO_POSE_DESCRIPTOR`. */\n poseDescriptor?: PoseDescriptor<TPose>;\n /** Walk a container's direct children (e.g. `scene.childrenOf`). With\n * `isContainer`, a selected container resolves to the union AABB of its\n * transitive leaf poses instead of its own stored pose. */\n getChildren?: (id: string) => readonly string[];\n /** True when `id` is a structural container. */\n isContainer?: (id: string) => boolean;\n /** The nodes behind the ids. With it, a container's union takes each leaf\n * as drawn, stroke included (`drawnBoundsOf`); without, its pose box. */\n scene?: DrawnBoundsScene;\n /** View scale a screen-pixel stroke is resolved at. Default 1. */\n viewScale?: () => number | Scale2;\n}\n\n/**\n * Build a pose resolver for a selection. Precedence per id:\n * move overlay > resize overlay > stored. When `getChildren`/`isContainer`\n * are supplied and the id resolves to a container, the resolver returns the\n * union AABB of all transitive leaf poses (each leaf still subject to the\n * precedence rules). Containers with no leaves resolve to `null`.\n */\nexport function composeSelectionPose<TPose>(\n opts: ComposeSelectionPoseOpts<TPose>,\n): (id: string) => TPose | null {\n const { moveOverlay, resizeOverlay, getStoredPose, getChildren, isContainer } = opts;\n const d = (opts.poseDescriptor ?? AUTO_POSE_DESCRIPTOR) as PoseDescriptor<TPose>;\n const boxes = boxReader(d, opts.scene);\n\n const selectionLeaves = (id: string): string[] =>\n getChildren && isContainer ? leavesOf(id, getChildren, isContainer) : [id];\n\n const resolveLeaf = (id: string): TPose => {\n const moved = moveOverlay?.poses.get(id);\n if (moved !== undefined) return moved;\n if (resizeOverlay && resizeOverlay.id === id) return resizeOverlay.currentPose;\n return getStoredPose(id);\n };\n\n return (id: string): TPose | null => {\n if (isContainer?.(id)) {\n const leaves = selectionLeaves(id);\n if (leaves.length === 0) return null;\n const containerResizeLeafPoses =\n resizeOverlay && resizeOverlay.id === id ? resizeOverlay.leafPoses : undefined;\n const scale = opts.viewScale?.();\n const leafBounds: Bounds[] = [];\n for (const leafId of leaves) {\n const pose = moveOverlay?.poses.get(leafId)\n ?? containerResizeLeafPoses?.get(leafId)\n ?? getStoredPose(leafId);\n leafBounds.push(boxes.aabb(leafId, pose, scale));\n }\n const u = unionAABB(leafBounds);\n if (u === null) return null;\n return d.fromBounds(u, getStoredPose(leaves[0]!));\n }\n return resolveLeaf(id);\n };\n}\n\n/**\n * Build a bounds resolver that handles container ids by computing the union\n * AABB of every leaf's bounds. Non-container ids pass through directly. When\n * `getChildren`/`isContainer` are omitted, every id is treated as a leaf.\n * With a scene, each leaf is boxed as drawn at the view's scale.\n */\nexport function containerAwareBoundsResolver<TPose>(\n getPose: (id: string) => TPose | null,\n d: PoseDescriptor<TPose>,\n getChildren: ((id: string) => readonly string[]) | undefined,\n isContainer: ((id: string) => boolean) | undefined,\n scene: DrawnBoundsScene | undefined,\n): (id: string, scale: Scale2) => Bounds | null {\n const boxes = boxReader(d, scene);\n const leaf = (id: string, scale: Scale2): Bounds | null => {\n const p = getPose(id);\n return p === null ? null : boxes.framed(id, p, scale);\n };\n if (getChildren === undefined || isContainer === undefined) return leaf;\n return (id, scale) => {\n if (!isContainer(id)) return leaf(id, scale);\n const leaves = leavesOf(id, getChildren, isContainer);\n if (leaves.length === 0) return null;\n const leafBounds: Bounds[] = [];\n for (const leafId of leaves) {\n const p = getPose(leafId);\n if (p !== null) leafBounds.push(boxes.aabb(leafId, p, scale));\n }\n if (leafBounds.length === 0) return null;\n return unionAABB(leafBounds);\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ import { distinct, markFromPlane } from "./marks.js";
2
+ import { screenOf } from "./screen.js";
3
+ import { stepAngles } from "./stepAngles.js";
4
+ import { resolveSnap } from "@weasel-js/geom/nd";
5
+
6
+ //#region src/features/snap/angle2d.ts
7
+ /** A snap session's one-dimensional path: an angle about a pivot, snapped by
8
+ * the same resolver as a point, with reach carried through the radius. */
9
+ var TURN = Math.PI * 2;
10
+ var PROBE = "angle";
11
+ /** A press near the pivot turns px reach into a wide angle; it reaches no
12
+ * further than this. */
13
+ var MAX_REACH_RAD = Math.PI / 6;
14
+ /** Where `theta` lands, and what it met. Writes the marks to the store. */
15
+ function angleAt(inputs, sources, theta, mods) {
16
+ const { req, store } = inputs;
17
+ const scale = req.reachRad !== void 0 ? 1 : pressRadiusPx(inputs);
18
+ const reachOf = (s) => req.reachRad ?? Math.min(s.reachPx ?? inputs.reachPx, MAX_REACH_RAD * scale);
19
+ const candidates = collectAngles(inputs, sources, theta, mods, reachOf);
20
+ if (candidates.length === 0) {
21
+ store.set([]);
22
+ return {
23
+ theta,
24
+ marks: []
25
+ };
26
+ }
27
+ const res = resolveSnap({
28
+ probes: [{
29
+ id: PROBE,
30
+ at: [0],
31
+ role: "pointer"
32
+ }],
33
+ input: {
34
+ at: [0],
35
+ dirs: [[1]]
36
+ },
37
+ delta0: [theta],
38
+ candidates,
39
+ toScreen: ([t]) => [scale > 0 ? t * scale : NaN]
40
+ });
41
+ const out = res.delta[0];
42
+ const marks = distinct(res.satisfied.flatMap((c) => {
43
+ const m = c.mark ?? rayMarks(inputs, out);
44
+ return "kind" in m ? [m] : m;
45
+ }));
46
+ const plane = req.plane?.() ?? null;
47
+ store.set(plane ? marks.map((m) => markFromPlane(m, plane)) : marks);
48
+ return {
49
+ theta: out,
50
+ marks
51
+ };
52
+ }
53
+ function collectAngles(inputs, sources, theta, mods, reachOf) {
54
+ const { req } = inputs;
55
+ const out = [];
56
+ const c = req.constrain;
57
+ if (mods.constrain && typeof c === "object" && c.step > 0) for (const at of stepAngles(theta, c.step)) out.push({
58
+ probe: PROBE,
59
+ locus: {
60
+ at: [at],
61
+ dirs: []
62
+ },
63
+ source: "constrain",
64
+ order: -1,
65
+ tier: "target",
66
+ reachPx: 0,
67
+ required: true
68
+ });
69
+ const theta0 = req.theta0 ?? 0;
70
+ if (mods.hold) {
71
+ const at = theta0 + TURN * Math.round((theta - theta0) / TURN);
72
+ out.push({
73
+ probe: PROBE,
74
+ locus: {
75
+ at: [at],
76
+ dirs: []
77
+ },
78
+ source: "hold",
79
+ order: -1,
80
+ tier: "target",
81
+ reachPx: 0,
82
+ required: true,
83
+ mark: []
84
+ });
85
+ }
86
+ if (mods.suspend) return out;
87
+ const q = {
88
+ pivot: req.pivot ?? req.press,
89
+ press: req.press,
90
+ theta0,
91
+ theta,
92
+ ids: req.ids ?? [],
93
+ exclude: inputs.exclude ?? req.ids ?? [],
94
+ mods,
95
+ ...req.also ? { also: req.also } : {},
96
+ ...inputs.scene ? { scene: inputs.scene } : {},
97
+ ...inputs.rotationOf ? { rotationOf: inputs.rotationOf } : {}
98
+ };
99
+ let order = 0;
100
+ sources.forEach((source) => {
101
+ if (!source.angles) return;
102
+ const reachPx = reachOf(source);
103
+ for (const a of source.angles(q)) {
104
+ const at = a.angle + TURN * Math.round((theta - a.angle) / TURN);
105
+ out.push({
106
+ probe: PROBE,
107
+ locus: {
108
+ at: [at],
109
+ dirs: []
110
+ },
111
+ source: source.id,
112
+ order: order++,
113
+ tier: source.tier ?? "target",
114
+ reachPx,
115
+ ...a.required ? { required: true } : {},
116
+ ...a.mark ? { mark: a.mark } : {}
117
+ });
118
+ }
119
+ });
120
+ return out;
121
+ }
122
+ /** The screen distance from the pivot to the press: what turns reach in px
123
+ * into radians. */
124
+ function pressRadiusPx(inputs) {
125
+ const { req } = inputs;
126
+ const pivot = req.pivot ?? req.press;
127
+ const toScreen = screenOf(inputs.view(), req.plane?.() ?? null);
128
+ const [ax, ay] = toScreen([pivot.x, pivot.y]);
129
+ const [bx, by] = toScreen([req.press.x, req.press.y]);
130
+ return Math.hypot(bx - ax, by - ay);
131
+ }
132
+ /** A ray from the pivot out to the press radius, along where the pointer
133
+ * lands at `theta`, labeled with `theta` in degrees. */
134
+ function rayMarks(inputs, theta) {
135
+ const { req } = inputs;
136
+ const pivot = req.pivot ?? req.press;
137
+ const r = Math.hypot(req.press.x - pivot.x, req.press.y - pivot.y);
138
+ const dir = Math.atan2(req.press.y - pivot.y, req.press.x - pivot.x) + theta - (req.theta0 ?? 0);
139
+ const end = {
140
+ x: pivot.x + r * Math.cos(dir),
141
+ y: pivot.y + r * Math.sin(dir)
142
+ };
143
+ const deg = (Math.round(theta * 180 / Math.PI) % 360 + 360) % 360;
144
+ return [{
145
+ kind: "line",
146
+ from: pivot,
147
+ to: end
148
+ }, {
149
+ kind: "point",
150
+ at: end,
151
+ glyph: "quadrant",
152
+ label: `${deg}°`
153
+ }];
154
+ }
155
+
156
+ //#endregion
157
+ export { angleAt };
158
+ //# sourceMappingURL=angle2d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"angle2d.js","names":[],"sources":["../../../src/features/snap/angle2d.ts"],"sourcesContent":["/** A snap session's one-dimensional path: an angle about a pivot, snapped by\n * the same resolver as a point, with reach carried through the radius. */\nimport { resolveSnap, type SnapCandidate } from '@weasel-js/geom/nd';\nimport type { SnapMods } from 'interactions/actions/snapDep';\nimport { distinct, markFromPlane } from './marks';\nimport { screenOf } from './screen';\nimport { stepAngles } from './stepAngles';\nimport type { Session2dInputs } from './session2d';\nimport type { AngleCollect, SnapMark, SnapMarks, SnapSource } from './types';\n\nconst TURN = Math.PI * 2;\nconst PROBE = 'angle';\n/** A press near the pivot turns px reach into a wide angle; it reaches no\n * further than this. */\nconst MAX_REACH_RAD = Math.PI / 6;\n\n/** Where `theta` lands, and what it met. Writes the marks to the store. */\nexport function angleAt(\n inputs: Session2dInputs, sources: readonly SnapSource[], theta: number, mods: SnapMods,\n): { theta: number; marks: readonly SnapMark[] } {\n const { req, store } = inputs;\n // Screen px per radian, or 1 when the gesture gives its reach in radians.\n const scale = req.reachRad !== undefined ? 1 : pressRadiusPx(inputs);\n const reachOf = (s: SnapSource) => req.reachRad\n ?? Math.min(s.reachPx ?? inputs.reachPx, MAX_REACH_RAD * scale);\n const candidates = collectAngles(inputs, sources, theta, mods, reachOf);\n if (candidates.length === 0) {\n store.set([]);\n return { theta, marks: [] };\n }\n const res = resolveSnap({\n probes: [{ id: PROBE, at: [0], role: 'pointer' }],\n input: { at: [0], dirs: [[1]] },\n delta0: [theta],\n candidates,\n // No radius, no reach: only a required angle can win.\n toScreen: ([t]) => [scale > 0 ? t * scale : NaN],\n });\n const out = res.delta[0];\n const marks = distinct(res.satisfied.flatMap((c) => {\n const m = c.mark ?? rayMarks(inputs, out);\n return 'kind' in m ? [m] : m;\n }));\n const plane = req.plane?.() ?? null;\n store.set(plane ? marks.map((m) => markFromPlane(m, plane)) : marks);\n return { theta: out, marks };\n}\n\nfunction collectAngles(\n inputs: Session2dInputs, sources: readonly SnapSource[], theta: number, mods: SnapMods,\n reachOf: (s: SnapSource) => number,\n): SnapCandidate<SnapMarks>[] {\n const { req } = inputs;\n const out: SnapCandidate<SnapMarks>[] = [];\n const c = req.constrain;\n if (mods.constrain && typeof c === 'object' && c.step > 0) {\n for (const at of stepAngles(theta, c.step)) {\n out.push({ probe: PROBE, locus: { at: [at], dirs: [] }, source: 'constrain', order: -1, tier: 'target', reachPx: 0, required: true });\n }\n }\n const theta0 = req.theta0 ?? 0;\n if (mods.hold) {\n const at = theta0 + TURN * Math.round((theta - theta0) / TURN);\n out.push({ probe: PROBE, locus: { at: [at], dirs: [] }, source: 'hold', order: -1, tier: 'target', reachPx: 0, required: true, mark: [] });\n }\n if (mods.suspend) return out;\n const q: AngleCollect = {\n pivot: req.pivot ?? req.press,\n press: req.press,\n theta0,\n theta,\n ids: req.ids ?? [],\n exclude: inputs.exclude ?? req.ids ?? [],\n mods,\n ...(req.also ? { also: req.also } : {}),\n ...(inputs.scene ? { scene: inputs.scene } : {}),\n ...(inputs.rotationOf ? { rotationOf: inputs.rotationOf } : {}),\n };\n // Runs across sources and their yields: an earlier source, then an earlier\n // yield, wins a tie.\n let order = 0;\n sources.forEach((source) => {\n if (!source.angles) return;\n const reachPx = reachOf(source);\n for (const a of source.angles(q)) {\n // The whole turn of the angle nearest `theta`: 0 catches 359°.\n const at = a.angle + TURN * Math.round((theta - a.angle) / TURN);\n out.push({\n probe: PROBE, locus: { at: [at], dirs: [] }, source: source.id, order: order++, tier: source.tier ?? 'target', reachPx,\n ...(a.required ? { required: true } : {}),\n ...(a.mark ? { mark: a.mark } : {}),\n });\n }\n });\n return out;\n}\n\n/** The screen distance from the pivot to the press: what turns reach in px\n * into radians. */\nfunction pressRadiusPx(inputs: Session2dInputs): number {\n const { req } = inputs;\n const pivot = req.pivot ?? req.press;\n const toScreen = screenOf(inputs.view(), req.plane?.() ?? null);\n const [ax, ay] = toScreen([pivot.x, pivot.y]);\n const [bx, by] = toScreen([req.press.x, req.press.y]);\n return Math.hypot(bx - ax, by - ay);\n}\n\n/** A ray from the pivot out to the press radius, along where the pointer\n * lands at `theta`, labeled with `theta` in degrees. */\nfunction rayMarks(inputs: Session2dInputs, theta: number): SnapMark[] {\n const { req } = inputs;\n const pivot = req.pivot ?? req.press;\n const r = Math.hypot(req.press.x - pivot.x, req.press.y - pivot.y);\n const dir = Math.atan2(req.press.y - pivot.y, req.press.x - pivot.x) + theta - (req.theta0 ?? 0);\n const end = { x: pivot.x + r * Math.cos(dir), y: pivot.y + r * Math.sin(dir) };\n const deg = ((Math.round(theta * 180 / Math.PI) % 360) + 360) % 360;\n return [\n { kind: 'line', from: pivot, to: end },\n { kind: 'point', at: end, glyph: 'quadrant', label: `${deg}°` },\n ];\n}\n"],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { fromPlane } from "../../core/viewport/parallax.js";
2
+ import { closestOnFlat } from "@weasel-js/geom/nd";
3
+
4
+ //#region src/features/snap/debugCandidates.ts
5
+ /** Replaces the sink's snap records with one frame's candidates: where each
6
+ * would put its probe, accepted when the result meets it. Camera world. */
7
+ function recordSnapCandidates(debug, candidates, satisfied, probes, delta0, plane) {
8
+ debug.clearSnap();
9
+ const met = new Set(satisfied);
10
+ const at = new Map(probes.map((q) => [q.id, [q.at.x + delta0.x, q.at.y + delta0.y]]));
11
+ for (const c of candidates) {
12
+ const p = at.get(c.probe);
13
+ if (!p) continue;
14
+ const [x, y] = closestOnFlat(c.locus, p);
15
+ debug.recordSnapCandidate(plane ? fromPlane(plane, {
16
+ x,
17
+ y
18
+ }) : {
19
+ x,
20
+ y
21
+ }, met.has(c));
22
+ }
23
+ }
24
+
25
+ //#endregion
26
+ export { recordSnapCandidates };
27
+ //# sourceMappingURL=debugCandidates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugCandidates.js","names":[],"sources":["../../../src/features/snap/debugCandidates.ts"],"sourcesContent":["import { closestOnFlat, type SnapCandidate } from '@weasel-js/geom/nd';\nimport type { DebugSink } from '@weasel-js/routing';\nimport { fromPlane, type PlaneMap } from 'core/viewport/parallax';\nimport type { SnapProbeAt } from './types';\n\ntype Point = { x: number; y: number };\n\n/** Replaces the sink's snap records with one frame's candidates: where each\n * would put its probe, accepted when the result meets it. Camera world. */\nexport function recordSnapCandidates(\n debug: DebugSink,\n candidates: readonly SnapCandidate<unknown>[],\n satisfied: readonly SnapCandidate<unknown>[],\n probes: readonly SnapProbeAt[],\n delta0: Point,\n plane: PlaneMap | null,\n): void {\n debug.clearSnap();\n const met = new Set(satisfied);\n const at = new Map(probes.map((q) => [q.id, [q.at.x + delta0.x, q.at.y + delta0.y]]));\n for (const c of candidates) {\n const p = at.get(c.probe);\n if (!p) continue;\n const [x, y] = closestOnFlat(c.locus, p);\n debug.recordSnapCandidate(plane ? fromPlane(plane, { x, y }) : { x, y }, met.has(c));\n }\n}\n"],"mappings":";;;;;;AASA,SAAgB,qBACd,OACA,YACA,WACA,QACA,QACA,OACM;CACN,MAAM,UAAU;CAChB,MAAM,MAAM,IAAI,IAAI,SAAS;CAC7B,MAAM,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,IAAI,OAAO,GAAG,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;CACpF,KAAK,MAAM,KAAK,YAAY;EAC1B,MAAM,IAAI,GAAG,IAAI,EAAE,KAAK;EACxB,IAAI,CAAC,GAAG;EACR,MAAM,CAAC,GAAG,KAAK,cAAc,EAAE,OAAO,CAAC;EACvC,MAAM,oBAAoB,QAAQ,UAAU,OAAO;GAAE;GAAG;EAAE,CAAC,IAAI;GAAE;GAAG;EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;CACrF;AACF"}
@@ -0,0 +1,71 @@
1
+ import { distinct } from "./marks.js";
2
+
3
+ //#region src/features/snap/gather.ts
4
+ var DEFAULT_GESTURES = [
5
+ "point",
6
+ "move",
7
+ "resize"
8
+ ];
9
+ /** The sources that answer `gesture`: those naming it, and, for one naming none, point, move and resize. */
10
+ function snapSourcesFor(sources, gesture) {
11
+ return sources.filter((s) => (s.gestures ?? DEFAULT_GESTURES).includes(gesture));
12
+ }
13
+ /** How near `origin` a point target counts as on it, relative to its magnitude. */
14
+ var ORIGIN_EPS = 1e-9;
15
+ /**
16
+ * One frame's resolver candidates: each source is asked, through `ask`, about
17
+ * the probes whose role it matches and the reach that applies to it (its
18
+ * own `reachPx`, else `opts.reachPx`), and what it answers for a probe it was
19
+ * not offered, or a point on `origin`, is dropped. Sources run in order, and
20
+ * an earlier source, then an earlier yield, wins a full tie. The building
21
+ * block of a host's own snap session over `resolveSnap`.
22
+ */
23
+ function gatherSnapCandidates(sources, probes, ask, opts) {
24
+ const origin = opts.origin === void 0 ? null : opts.toVec(opts.origin);
25
+ const out = [];
26
+ let order = 0;
27
+ for (const source of sources) {
28
+ const offered = probes.filter((q) => source.roles.includes(q.role));
29
+ if (offered.length === 0) continue;
30
+ const ids = new Set(offered.map((q) => q.id));
31
+ const reachPx = source.reachPx ?? opts.reachPx;
32
+ for (const c of source.collect(ask(source, offered, reachPx))) {
33
+ if (!ids.has(c.probe)) continue;
34
+ const at = opts.toVec(c.locus.at);
35
+ if (origin && c.locus.dirs.length === 0 && same(at, origin)) continue;
36
+ out.push({
37
+ probe: c.probe,
38
+ locus: {
39
+ at,
40
+ dirs: c.locus.dirs.map(opts.toVec)
41
+ },
42
+ ...c.locus.span ? { span: c.locus.span } : {},
43
+ source: source.id,
44
+ order: order++,
45
+ tier: source.tier ?? "target",
46
+ reachPx,
47
+ ...c.required ? { required: true } : {},
48
+ ...c.mark ? { mark: c.mark } : {}
49
+ });
50
+ }
51
+ }
52
+ return out;
53
+ }
54
+ function same(a, b) {
55
+ const eps = ORIGIN_EPS * Math.max(1, ...b.map(Math.abs));
56
+ return a.every((v, i) => Math.abs(v - b[i]) <= eps);
57
+ }
58
+ /** The marks of the candidates a result meets, with `delta` the resolved
59
+ * move, and repeats dropped so a target several probes meet is drawn once. */
60
+ function resolvedSnapMarks(satisfied, delta) {
61
+ return distinct(satisfied.flatMap((c) => marksOf(c.mark, delta)));
62
+ }
63
+ function marksOf(mark, delta) {
64
+ if (!mark) return [];
65
+ const m = typeof mark === "function" ? mark(delta) : mark;
66
+ return "kind" in m ? [m] : m;
67
+ }
68
+
69
+ //#endregion
70
+ export { gatherSnapCandidates, resolvedSnapMarks, snapSourcesFor };
71
+ //# sourceMappingURL=gather.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gather.js","names":[],"sources":["../../../src/features/snap/gather.ts"],"sourcesContent":["import type { SnapCandidate, Vec } from '@weasel-js/geom/nd';\nimport { distinct } from './marks';\nimport type { SnapCollect, SnapGesture, SnapMark, SnapProbeAt, SnapSource, SourceCandidate } from './types';\n\nconst DEFAULT_GESTURES: readonly SnapGesture[] = ['point', 'move', 'resize'];\n\n/** The sources that answer `gesture`: those naming it, and, for one naming none, point, move and resize. */\nexport function snapSourcesFor<S extends Pick<SnapSource<unknown>, 'gestures'>>(sources: readonly S[], gesture: SnapGesture): S[] {\n return sources.filter((s) => (s.gestures ?? DEFAULT_GESTURES).includes(gesture));\n}\n\n/** What a candidate draws when the result meets it. */\nexport type SnapCandidateMark<P> = NonNullable<SourceCandidate<P>['mark']>;\n\n/** How near `origin` a point target counts as on it, relative to its magnitude. */\nconst ORIGIN_EPS = 1e-9;\n\n/** How `gatherSnapCandidates` reads a host's points. */\nexport interface GatherSnapOptions<P> {\n /** `p` as a resolver tuple. */\n toVec(p: P): Vec;\n /** The reach of a source that sets none, in screen px. */\n reachPx: number;\n /** Where the geometry being drawn starts: no point target on it is offered. */\n origin?: P;\n}\n\n/**\n * One frame's resolver candidates: each source is asked, through `ask`, about\n * the probes whose role it matches and the reach that applies to it (its\n * own `reachPx`, else `opts.reachPx`), and what it answers for a probe it was\n * not offered, or a point on `origin`, is dropped. Sources run in order, and\n * an earlier source, then an earlier yield, wins a full tie. The building\n * block of a host's own snap session over `resolveSnap`.\n */\nexport function gatherSnapCandidates<P>(\n sources: readonly SnapSource<P>[],\n probes: readonly SnapProbeAt<P>[],\n ask: (source: SnapSource<P>, offered: SnapProbeAt<P>[], reachPx: number) => SnapCollect<P>,\n opts: GatherSnapOptions<P>,\n): SnapCandidate<SnapCandidateMark<P>>[] {\n const origin = opts.origin === undefined ? null : opts.toVec(opts.origin);\n const out: SnapCandidate<SnapCandidateMark<P>>[] = [];\n let order = 0;\n for (const source of sources) {\n const offered = probes.filter((q) => source.roles.includes(q.role));\n if (offered.length === 0) continue;\n const ids = new Set(offered.map((q) => q.id));\n const reachPx = source.reachPx ?? opts.reachPx;\n for (const c of source.collect(ask(source, offered, reachPx))) {\n if (!ids.has(c.probe)) continue;\n const at = opts.toVec(c.locus.at);\n if (origin && c.locus.dirs.length === 0 && same(at, origin)) continue;\n out.push({\n probe: c.probe, locus: { at, dirs: c.locus.dirs.map(opts.toVec) },\n ...(c.locus.span ? { span: c.locus.span } : {}),\n source: source.id, order: order++, tier: source.tier ?? 'target', reachPx,\n ...(c.required ? { required: true } : {}),\n ...(c.mark ? { mark: c.mark } : {}),\n });\n }\n }\n return out;\n}\n\nfunction same(a: Vec, b: Vec): boolean {\n const eps = ORIGIN_EPS * Math.max(1, ...b.map(Math.abs));\n return a.every((v, i) => Math.abs(v - b[i]) <= eps);\n}\n\n/** The marks of the candidates a result meets, with `delta` the resolved\n * move, and repeats dropped so a target several probes meet is drawn once. */\nexport function resolvedSnapMarks<P>(\n satisfied: readonly { mark?: SnapCandidateMark<P> }[], delta: P,\n): SnapMark<P>[] {\n return distinct(satisfied.flatMap((c) => marksOf(c.mark, delta)));\n}\n\nfunction marksOf<P>(mark: SnapCandidateMark<P> | undefined, delta: P): readonly SnapMark<P>[] {\n if (!mark) return [];\n const m = typeof mark === 'function' ? mark(delta) : mark;\n return 'kind' in m ? [m as SnapMark<P>] : (m as readonly SnapMark<P>[]);\n}\n"],"mappings":";;;AAIA,IAAM,mBAA2C;CAAC;CAAS;CAAQ;AAAQ;;AAG3E,SAAgB,eAAgE,SAAuB,SAA2B;CAChI,OAAO,QAAQ,QAAQ,OAAO,EAAE,YAAY,iBAAA,CAAkB,SAAS,OAAO,CAAC;AACjF;;AAMA,IAAM,aAAa;;;;;;;;;AAoBnB,SAAgB,qBACd,SACA,QACA,KACA,MACuC;CACvC,MAAM,SAAS,KAAK,WAAW,SAAY,OAAO,KAAK,MAAM,KAAK,MAAM;CACxE,MAAM,MAA6C,CAAC;CACpD,IAAI,QAAQ;CACZ,KAAK,MAAM,UAAU,SAAS;EAC5B,MAAM,UAAU,OAAO,QAAQ,MAAM,OAAO,MAAM,SAAS,EAAE,IAAI,CAAC;EAClE,IAAI,QAAQ,WAAW,GAAG;EAC1B,MAAM,MAAM,IAAI,IAAI,QAAQ,KAAK,MAAM,EAAE,EAAE,CAAC;EAC5C,MAAM,UAAU,OAAO,WAAW,KAAK;EACvC,KAAK,MAAM,KAAK,OAAO,QAAQ,IAAI,QAAQ,SAAS,OAAO,CAAC,GAAG;GAC7D,IAAI,CAAC,IAAI,IAAI,EAAE,KAAK,GAAG;GACvB,MAAM,KAAK,KAAK,MAAM,EAAE,MAAM,EAAE;GAChC,IAAI,UAAU,EAAE,MAAM,KAAK,WAAW,KAAK,KAAK,IAAI,MAAM,GAAG;GAC7D,IAAI,KAAK;IACP,OAAO,EAAE;IAAO,OAAO;KAAE;KAAI,MAAM,EAAE,MAAM,KAAK,IAAI,KAAK,KAAK;IAAE;IAChE,GAAI,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,QAAQ,OAAO;IAAI,OAAO;IAAS,MAAM,OAAO,QAAQ;IAAU;IAClE,GAAI,EAAE,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;GACnC,CAAC;EACH;CACF;CACA,OAAO;AACT;AAEA,SAAS,KAAK,GAAQ,GAAiB;CACrC,MAAM,MAAM,aAAa,KAAK,IAAI,GAAG,GAAG,EAAE,IAAI,KAAK,GAAG,CAAC;CACvD,OAAO,EAAE,OAAO,GAAG,MAAM,KAAK,IAAI,IAAI,EAAE,EAAE,KAAK,GAAG;AACpD;;;AAIA,SAAgB,kBACd,WAAuD,OACxC;CACf,OAAO,SAAS,UAAU,SAAS,MAAM,QAAQ,EAAE,MAAM,KAAK,CAAC,CAAC;AAClE;AAEA,SAAS,QAAW,MAAwC,OAAkC;CAC5F,IAAI,CAAC,MAAM,OAAO,CAAC;CACnB,MAAM,IAAI,OAAO,SAAS,aAAa,KAAK,KAAK,IAAI;CACrD,OAAO,UAAU,IAAI,CAAC,CAAgB,IAAK;AAC7C"}