@weasel-js/core 1.9.4 → 1.10.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 (1092) hide show
  1. package/CHANGELOG.md +750 -0
  2. package/README.md +5 -3
  3. package/dist/WeaselProvider.js +5 -7
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +91 -83
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +3 -2
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +54 -100
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js.map +1 -1
  12. package/dist/affordances/rotationHandle.js +5 -4
  13. package/dist/affordances/rotationHandle.js.map +1 -1
  14. package/dist/animation/behaviors/coast.js +21 -0
  15. package/dist/animation/behaviors/coast.js.map +1 -0
  16. package/dist/animation/behaviors/coastByWrite.js +107 -0
  17. package/dist/animation/behaviors/coastByWrite.js.map +1 -0
  18. package/dist/animation/behaviors/coastOnTargets.js +94 -0
  19. package/dist/animation/behaviors/coastOnTargets.js.map +1 -0
  20. package/dist/animation/behaviors/momentum.js +48 -136
  21. package/dist/animation/behaviors/momentum.js.map +1 -1
  22. package/dist/animation/clipTargets.js +12 -0
  23. package/dist/animation/clipTargets.js.map +1 -0
  24. package/dist/animation/index.js +15 -20
  25. package/dist/animation/poseHelpers.js +112 -33
  26. package/dist/animation/poseHelpers.js.map +1 -1
  27. package/dist/animation/poseTarget.js +115 -0
  28. package/dist/animation/poseTarget.js.map +1 -0
  29. package/dist/animation/reflow.js +113 -83
  30. package/dist/animation/reflow.js.map +1 -1
  31. package/dist/animation/rewind.js +66 -0
  32. package/dist/animation/rewind.js.map +1 -0
  33. package/dist/animation/rig/bindRig.js +85 -53
  34. package/dist/animation/rig/bindRig.js.map +1 -1
  35. package/dist/animation/rig/rigNode.js +93 -0
  36. package/dist/animation/rig/rigNode.js.map +1 -0
  37. package/dist/animation/rig/rigSeat.js +26 -0
  38. package/dist/animation/rig/rigSeat.js.map +1 -0
  39. package/dist/animation/rig/skinBinding.js +56 -0
  40. package/dist/animation/rig/skinBinding.js.map +1 -0
  41. package/dist/animation/rig/useRig.js +31 -16
  42. package/dist/animation/rig/useRig.js.map +1 -1
  43. package/dist/animation/wrappers/animateLifecycle.js +8 -7
  44. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  45. package/dist/animation/wrappers/animateOnSetPose.js +31 -31
  46. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  47. package/dist/animation/wrappers/instantPose.js.map +1 -1
  48. package/dist/animation/writtenPoseTarget.js +33 -0
  49. package/dist/animation/writtenPoseTarget.js.map +1 -0
  50. package/dist/autoPoseDescriptor-DHg5KqaJ.d.ts +27 -0
  51. package/dist/barrel/canvas.js +31 -0
  52. package/dist/barrel/chrome.js +10 -10
  53. package/dist/barrel/input.js +16 -17
  54. package/dist/barrel/interactions.js +35 -39
  55. package/dist/barrel/paint.js +11 -18
  56. package/dist/barrel/paths.js +12 -19
  57. package/dist/barrel/renderer.js +14 -20
  58. package/dist/barrel/routing.js +42 -36
  59. package/dist/barrel/scene.js +37 -0
  60. package/dist/barrel/text.js +9 -18
  61. package/dist/barrel/viewport.js +41 -51
  62. package/dist/canvas/Canvas.js +281 -475
  63. package/dist/canvas/Canvas.js.map +1 -1
  64. package/dist/canvas/CanvasView.js +169 -188
  65. package/dist/canvas/CanvasView.js.map +1 -1
  66. package/dist/canvas/CursorCoordsHud.js +22 -23
  67. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  68. package/dist/canvas/DrawCanvas.js +39 -56
  69. package/dist/canvas/DrawCanvas.js.map +1 -1
  70. package/dist/canvas/ModalityHud.js.map +1 -1
  71. package/dist/canvas/NodeShape.js +28 -29
  72. package/dist/canvas/NodeShape.js.map +1 -1
  73. package/dist/canvas/PickHud.js.map +1 -1
  74. package/dist/canvas/SceneCanvas/DevHuds.js +40 -0
  75. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -0
  76. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +66 -107
  77. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -1
  78. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +27 -31
  79. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  80. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +51 -54
  81. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -1
  82. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +3 -3
  83. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -1
  84. package/dist/canvas/SceneCanvas/coordTrace.js +37 -1
  85. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  86. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +40 -29
  87. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  88. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +1 -1
  89. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  90. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  91. package/dist/canvas/SceneCanvas/features.js +73 -43
  92. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/isDev.js.map +1 -1
  94. package/dist/canvas/SceneCanvas/poseGeometry.js +33 -37
  95. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  96. package/dist/canvas/SceneCanvas/props.js +15 -14
  97. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  98. package/dist/canvas/SceneCanvas/toolRegistry.js +23 -0
  99. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -0
  100. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +6 -1
  101. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  102. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  103. package/dist/canvas/SceneCanvas/useBuiltinTools.js +21 -0
  104. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -0
  105. package/dist/canvas/SceneCanvas/useCanvasCamera.js +38 -0
  106. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -0
  107. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +20 -0
  108. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -0
  109. package/dist/canvas/SceneCanvas/useCanvasSelection.js +16 -0
  110. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -0
  111. package/dist/canvas/SceneCanvas/useCanvasTools.js +67 -0
  112. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -0
  113. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +29 -29
  114. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  115. package/dist/canvas/SceneCanvas/useHeldModifiers.js +20 -0
  116. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -0
  117. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +26 -0
  118. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -0
  119. package/dist/canvas/SceneCanvas/useNodeKinds.js +26 -0
  120. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -0
  121. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +39 -37
  122. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  123. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +47 -0
  124. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -0
  125. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +66 -0
  126. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -0
  127. package/dist/canvas/SceneCanvas/useSceneChrome.js +59 -0
  128. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -0
  129. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +23 -0
  130. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -0
  131. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +76 -80
  132. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  133. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +37 -0
  134. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -0
  135. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +38 -0
  136. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -0
  137. package/dist/canvas/SceneCanvas/useViewLayerGate.js +20 -0
  138. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +1 -0
  139. package/dist/canvas/SceneCanvas/useViewportActions.js +9 -1
  140. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  141. package/dist/canvas/SceneCanvas/worldPointAt.js +9 -0
  142. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -0
  143. package/dist/canvas/SceneCanvas.js +303 -707
  144. package/dist/canvas/SceneCanvas.js.map +1 -1
  145. package/dist/canvas/SceneViewCanvas.js +41 -47
  146. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  147. package/dist/canvas/adapterDerivedPath.js +26 -0
  148. package/dist/canvas/adapterDerivedPath.js.map +1 -0
  149. package/dist/canvas/affordanceAt.js +11 -1
  150. package/dist/canvas/affordanceAt.js.map +1 -1
  151. package/dist/canvas/buildSceneLayer.js +81 -61
  152. package/dist/canvas/buildSceneLayer.js.map +1 -1
  153. package/dist/canvas/buildSceneTree.js.map +1 -1
  154. package/dist/canvas/canvasRenderer.js +40 -44
  155. package/dist/canvas/canvasRenderer.js.map +1 -1
  156. package/dist/canvas/colorOverrides.js.map +1 -1
  157. package/dist/canvas/defaultDrawOne.js +12 -12
  158. package/dist/canvas/defaultDrawOne.js.map +1 -1
  159. package/dist/canvas/deps/areaSelect.js +4 -4
  160. package/dist/canvas/deps/areaSelect.js.map +1 -1
  161. package/dist/canvas/deps/debug.js.map +1 -1
  162. package/dist/canvas/deps/editAnchors.js +49 -68
  163. package/dist/canvas/deps/editAnchors.js.map +1 -1
  164. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  165. package/dist/canvas/deps/hitTestArea.js +31 -26
  166. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  167. package/dist/canvas/deps/insert.js +65 -54
  168. package/dist/canvas/deps/insert.js.map +1 -1
  169. package/dist/canvas/deps/lassoSelect.js +5 -5
  170. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  171. package/dist/canvas/deps/poseDescriptor.js +1 -1
  172. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  173. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  174. package/dist/canvas/deps/slice.js +44 -45
  175. package/dist/canvas/deps/slice.js.map +1 -1
  176. package/dist/canvas/deps/textEdit.js +8 -8
  177. package/dist/canvas/deps/textEdit.js.map +1 -1
  178. package/dist/canvas/deps/view.js.map +1 -1
  179. package/dist/canvas/derivedPath.js +43 -41
  180. package/dist/canvas/derivedPath.js.map +1 -1
  181. package/dist/canvas/drawEnvelope.js +8 -4
  182. package/dist/canvas/drawEnvelope.js.map +1 -1
  183. package/dist/canvas/getNodeAtPoint.js +2 -6
  184. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  185. package/dist/canvas/hud.module.js.map +1 -1
  186. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  187. package/dist/canvas/layerOrder.js.map +1 -1
  188. package/dist/canvas/layerSlots.js +6 -1
  189. package/dist/canvas/layerSlots.js.map +1 -1
  190. package/dist/canvas/nodeShapes/derivedPainter.js +12 -12
  191. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  192. package/dist/canvas/nodeShapes/imagePainter.js +10 -10
  193. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  194. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  195. package/dist/canvas/nodeShapes/nodePaint.js +34 -23
  196. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  197. package/dist/canvas/nodeShapes/pathPainter.js +23 -22
  198. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  199. package/dist/canvas/nodeShapes/poseBox.js +6 -6
  200. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  201. package/dist/canvas/nodeShapes/rectFallbackPainter.js +8 -8
  202. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  203. package/dist/canvas/nodeShapes/shapePainter.js +16 -16
  204. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  205. package/dist/canvas/nodeShapes/textPainter.js +1 -1
  206. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  207. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  208. package/dist/canvas/paintCull.js +6 -8
  209. package/dist/canvas/paintCull.js.map +1 -1
  210. package/dist/{features/cursor → canvas}/paintedCursorLayer.js +2 -2
  211. package/dist/canvas/paintedCursorLayer.js.map +1 -0
  212. package/dist/canvas/pickWalk.js +52 -50
  213. package/dist/canvas/pickWalk.js.map +1 -1
  214. package/dist/canvas/planeClips.js +18 -19
  215. package/dist/canvas/planeClips.js.map +1 -1
  216. package/dist/canvas/poseCascade.js +41 -0
  217. package/dist/canvas/poseCascade.js.map +1 -0
  218. package/dist/canvas/poseRotation.js +1 -3
  219. package/dist/canvas/poseRotation.js.map +1 -1
  220. package/dist/canvas/rasterReadback.js +22 -0
  221. package/dist/canvas/rasterReadback.js.map +1 -0
  222. package/dist/canvas/renderDebugSnapshot.js +12 -12
  223. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  224. package/dist/canvas/renderNeeds.js +3 -3
  225. package/dist/canvas/renderNeeds.js.map +1 -1
  226. package/dist/canvas/renderSceneToPixels.js +64 -83
  227. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  228. package/dist/canvas/sceneAdapter.js +68 -132
  229. package/dist/canvas/sceneAdapter.js.map +1 -1
  230. package/dist/canvas/sceneClipboard.js +1 -1
  231. package/dist/canvas/sceneClipboard.js.map +1 -1
  232. package/dist/canvas/sceneLayerPaint.js +4 -4
  233. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  234. package/dist/canvas/sceneSlotWiring.js +4 -4
  235. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  236. package/dist/canvas/sceneViewRender.js +36 -35
  237. package/dist/canvas/sceneViewRender.js.map +1 -1
  238. package/dist/canvas/slopsDebugLayer.js +4 -4
  239. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  240. package/dist/canvas/surface.module.js +6 -0
  241. package/dist/canvas/surface.module.js.map +1 -0
  242. package/dist/canvas/surfaceBox.js +16 -0
  243. package/dist/canvas/surfaceBox.js.map +1 -0
  244. package/dist/canvas/useCanvasRenderer.js +23 -11
  245. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  246. package/dist/canvas/useCanvasSurface.js +31 -0
  247. package/dist/canvas/useCanvasSurface.js.map +1 -0
  248. package/dist/canvas/useCanvasView.js +46 -37
  249. package/dist/canvas/useCanvasView.js.map +1 -1
  250. package/dist/canvas/useFrameLoop.js +11 -12
  251. package/dist/canvas/useFrameLoop.js.map +1 -1
  252. package/dist/canvas/useHostAnchor.js +35 -33
  253. package/dist/canvas/useHostAnchor.js.map +1 -1
  254. package/dist/canvas/useLateContentRedraw.js +8 -8
  255. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  256. package/dist/canvas/useSceneLayerList.js +4 -14
  257. package/dist/canvas/useSceneLayerList.js.map +1 -1
  258. package/dist/canvas/useSurfaceInput.js +42 -0
  259. package/dist/canvas/useSurfaceInput.js.map +1 -0
  260. package/dist/canvas/useToolCursor.js +29 -0
  261. package/dist/canvas/useToolCursor.js.map +1 -0
  262. package/dist/canvas/useViewHelpers.js +46 -85
  263. package/dist/canvas/useViewHelpers.js.map +1 -1
  264. package/dist/canvas/viewInputs.js.map +1 -1
  265. package/dist/canvas/viewRegistry.js +25 -27
  266. package/dist/canvas/viewRegistry.js.map +1 -1
  267. package/dist/canvas/watchElementMove.js +43 -0
  268. package/dist/canvas/watchElementMove.js.map +1 -0
  269. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  270. package/dist/clipboard.d.ts +7 -14
  271. package/dist/{types-B4iJRHC3.d.ts → clone-2a5hVbBd.d.ts} +122 -77
  272. package/dist/clone.d.ts +4 -8
  273. package/dist/clone.js +0 -2
  274. package/dist/core/device/targets.js.map +1 -1
  275. package/dist/core/device/useDeviceProfile.js +13 -13
  276. package/dist/core/device/useDeviceProfile.js.map +1 -1
  277. package/dist/{interactions/actions/resize → core/geometry}/autoPoseDescriptor.js +8 -7
  278. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -0
  279. package/dist/core/geometry/pathPoseDescriptor.js +88 -0
  280. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -0
  281. package/dist/core/geometry/poseDescriptor.js +61 -14
  282. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  283. package/dist/core/geometry/regionHit.js +35 -37
  284. package/dist/core/geometry/regionHit.js.map +1 -1
  285. package/dist/core/geometry/targetFrame.js +94 -0
  286. package/dist/core/geometry/targetFrame.js.map +1 -0
  287. package/dist/core/geometry/unionBounds.js +4 -5
  288. package/dist/core/geometry/unionBounds.js.map +1 -1
  289. package/dist/core/layers/backgroundFill.js +31 -0
  290. package/dist/core/layers/backgroundFill.js.map +1 -0
  291. package/dist/{features/groups → core/layers}/children.js +1 -1
  292. package/dist/core/layers/children.js.map +1 -0
  293. package/dist/{features/focus → core/layers}/gateLayer.js +2 -2
  294. package/dist/core/layers/gateLayer.js.map +1 -0
  295. package/dist/core/layers/layerGroup.js +40 -0
  296. package/dist/core/layers/layerGroup.js.map +1 -0
  297. package/dist/core/layers/render.js +50 -76
  298. package/dist/core/layers/render.js.map +1 -1
  299. package/dist/core/ops/createHistory.js +9 -9
  300. package/dist/core/ops/createHistory.js.map +1 -1
  301. package/dist/core/ops/delete.js.map +1 -1
  302. package/dist/core/paint/meshKind.js +16 -0
  303. package/dist/core/paint/meshKind.js.map +1 -0
  304. package/dist/{features/meshPaint/lazyKind.js → core/paint/meshKindLazy.js} +103 -92
  305. package/dist/core/paint/meshKindLazy.js.map +1 -0
  306. package/dist/core/paint/paintKindEntry.js +8 -0
  307. package/dist/core/paint/paintKindEntry.js.map +1 -0
  308. package/dist/core/paint/paintKinds.js +144 -0
  309. package/dist/core/paint/paintKinds.js.map +1 -0
  310. package/dist/core/paint/registerMesh.js +7 -0
  311. package/dist/core/paint/registerMesh.js.map +1 -0
  312. package/dist/core/scene/NodeProperties.js.map +1 -1
  313. package/dist/core/scene/NodeRouting.js.map +1 -1
  314. package/dist/core/scene/arrivalWindow.js +65 -64
  315. package/dist/core/scene/arrivalWindow.js.map +1 -1
  316. package/dist/core/scene/boundOps.js +40 -0
  317. package/dist/core/scene/boundOps.js.map +1 -0
  318. package/dist/core/scene/composeFrame.js +9 -6
  319. package/dist/core/scene/composeFrame.js.map +1 -1
  320. package/dist/{features/groups → core/scene}/composePose.js +18 -18
  321. package/dist/core/scene/composePose.js.map +1 -0
  322. package/dist/core/scene/depMemo.js +31 -6
  323. package/dist/core/scene/depMemo.js.map +1 -1
  324. package/dist/core/scene/derivedPath.js +19 -20
  325. package/dist/core/scene/derivedPath.js.map +1 -1
  326. package/dist/core/scene/editMode.js +26 -0
  327. package/dist/core/scene/editMode.js.map +1 -0
  328. package/dist/core/scene/effectivePose.js +38 -39
  329. package/dist/core/scene/effectivePose.js.map +1 -1
  330. package/dist/core/scene/fieldEdits.js +98 -0
  331. package/dist/core/scene/fieldEdits.js.map +1 -0
  332. package/dist/core/scene/historyFacade.js +116 -70
  333. package/dist/core/scene/historyFacade.js.map +1 -1
  334. package/dist/core/scene/historyForm.js +6 -0
  335. package/dist/core/scene/historyForm.js.map +1 -0
  336. package/dist/core/scene/kitOps.js +83 -71
  337. package/dist/core/scene/kitOps.js.map +1 -1
  338. package/dist/core/scene/kitRegistry.js.map +1 -1
  339. package/dist/core/scene/layerStack.js +105 -12
  340. package/dist/core/scene/layerStack.js.map +1 -1
  341. package/dist/core/scene/layoutPass.js +58 -59
  342. package/dist/core/scene/layoutPass.js.map +1 -1
  343. package/dist/{features/groups → core/scene}/nestedHit.js +3 -3
  344. package/dist/core/scene/nestedHit.js.map +1 -0
  345. package/dist/core/scene/nodeFnFields.js +9 -9
  346. package/dist/core/scene/nodeFnFields.js.map +1 -1
  347. package/dist/core/scene/nodeMemo.js.map +1 -1
  348. package/dist/core/scene/nodeStore.js +72 -71
  349. package/dist/core/scene/nodeStore.js.map +1 -1
  350. package/dist/core/scene/notifier.js +37 -0
  351. package/dist/core/scene/notifier.js.map +1 -0
  352. package/dist/core/scene/opTable.js +50 -0
  353. package/dist/core/scene/opTable.js.map +1 -0
  354. package/dist/core/scene/outerOps.js +66 -0
  355. package/dist/core/scene/outerOps.js.map +1 -0
  356. package/dist/core/scene/poseHold.js +39 -0
  357. package/dist/core/scene/poseHold.js.map +1 -0
  358. package/dist/core/scene/poseOverrides.js +44 -36
  359. package/dist/core/scene/poseOverrides.js.map +1 -1
  360. package/dist/core/scene/poseSnapshot.js.map +1 -1
  361. package/dist/core/scene/reconcileSpecs.js +3 -2
  362. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  363. package/dist/core/scene/recorder.js +86 -0
  364. package/dist/core/scene/recorder.js.map +1 -0
  365. package/dist/core/scene/renderOrder.js.map +1 -1
  366. package/dist/core/scene/scene.js +81 -690
  367. package/dist/core/scene/scene.js.map +1 -1
  368. package/dist/core/scene/sceneEdits.js +58 -0
  369. package/dist/core/scene/sceneEdits.js.map +1 -0
  370. package/dist/core/scene/sceneMutators.js +49 -0
  371. package/dist/core/scene/sceneMutators.js.map +1 -0
  372. package/dist/core/scene/scenePoseAdapter.js +16 -0
  373. package/dist/core/scene/scenePoseAdapter.js.map +1 -0
  374. package/dist/core/scene/sceneRecording.js +90 -0
  375. package/dist/core/scene/sceneRecording.js.map +1 -0
  376. package/dist/core/scene/sceneSelection.js +28 -0
  377. package/dist/core/scene/sceneSelection.js.map +1 -0
  378. package/dist/core/scene/sceneState.js +49 -0
  379. package/dist/core/scene/sceneState.js.map +1 -0
  380. package/dist/core/scene/serialization.js +8 -5
  381. package/dist/core/scene/serialization.js.map +1 -1
  382. package/dist/core/scene/staleReplay.js +51 -0
  383. package/dist/core/scene/staleReplay.js.map +1 -0
  384. package/dist/core/scene/statedFields.js +9 -0
  385. package/dist/core/scene/statedFields.js.map +1 -0
  386. package/dist/core/scene/treeEdits.js +127 -0
  387. package/dist/core/scene/treeEdits.js.map +1 -0
  388. package/dist/core/scene/treeReads.js +26 -0
  389. package/dist/core/scene/treeReads.js.map +1 -0
  390. package/dist/core/scene/types.js.map +1 -1
  391. package/dist/{features/groups → core/scene}/unionOfChildren.js +3 -3
  392. package/dist/core/scene/unionOfChildren.js.map +1 -0
  393. package/dist/core/scene/unitScopes.js +13 -0
  394. package/dist/core/scene/unitScopes.js.map +1 -0
  395. package/dist/core/scene/useScene.js.map +1 -1
  396. package/dist/core/selection/readOnlySelection.js +32 -0
  397. package/dist/core/selection/readOnlySelection.js.map +1 -0
  398. package/dist/core/selection/usePublishSceneSelection.js +26 -0
  399. package/dist/core/selection/usePublishSceneSelection.js.map +1 -0
  400. package/dist/core/selection/useSelection.js +34 -25
  401. package/dist/core/selection/useSelection.js.map +1 -1
  402. package/dist/core/shapeKinds.js.map +1 -1
  403. package/dist/core/stylus/stylus.js.map +1 -1
  404. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  405. package/dist/core/usePaintKinds.js +1 -1
  406. package/dist/core/usePaintKinds.js.map +1 -1
  407. package/dist/core/viewport/clientToWorld.js.map +1 -1
  408. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  409. package/dist/core/viewport/parallax.js.map +1 -1
  410. package/dist/core/viewport/screenSlop.js +11 -11
  411. package/dist/core/viewport/screenSlop.js.map +1 -1
  412. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  413. package/dist/core/viewport/useDecayLoop.js +8 -8
  414. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  415. package/dist/core/viewport/useNodeOverlayFrame.js +84 -0
  416. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -0
  417. package/dist/core/viewport/useViewAnimation.js +102 -43
  418. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  419. package/dist/core/viewport/view.js +7 -7
  420. package/dist/core/viewport/view.js.map +1 -1
  421. package/dist/core/viewport/wheelHandler.js.map +1 -1
  422. package/dist/{cornerHandles-CtCb8a3G.d.ts → cornerHandles-BEshc4z3.d.ts} +11 -24
  423. package/dist/debug/createDebugOverlayLayer.js +100 -100
  424. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  425. package/dist/debug/createDebugSink.js.map +1 -1
  426. package/dist/debug/frameStats.js.map +1 -1
  427. package/dist/debug/useDebugSink.js +52 -0
  428. package/dist/debug/useDebugSink.js.map +1 -0
  429. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  430. package/dist/features/chrome-caps/conditions.js.map +1 -1
  431. package/dist/features/chrome-caps/defaults.js.map +1 -1
  432. package/dist/features/chrome-caps/resolve.js.map +1 -1
  433. package/dist/features/chrome-caps/useChromeCaps.js +54 -0
  434. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -0
  435. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  436. package/dist/features/ingestion/contentHandlers.js +25 -19
  437. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  438. package/dist/features/ingestion/imageHandler.js +21 -24
  439. package/dist/features/ingestion/imageHandler.js.map +1 -1
  440. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  441. package/dist/features/ingestion/placement.js +16 -0
  442. package/dist/features/ingestion/placement.js.map +1 -0
  443. package/dist/features/ingestion/svgHandler.js +5 -0
  444. package/dist/features/ingestion/svgHandler.js.map +1 -1
  445. package/dist/features/ingestion/textHandler.js +28 -0
  446. package/dist/features/ingestion/textHandler.js.map +1 -0
  447. package/dist/features/ingestion/useCanvasIngestion.js +48 -0
  448. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -0
  449. package/dist/features/ingestion/weaselJsonHandler.js +5 -0
  450. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  451. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  452. package/dist/features/modes/modeLayers.js +7 -7
  453. package/dist/features/modes/modeLayers.js.map +1 -1
  454. package/dist/features/paths/editablePath.js +47 -0
  455. package/dist/features/paths/editablePath.js.map +1 -0
  456. package/dist/features/paths/index.js +9 -16
  457. package/dist/features/paths/pathEditState.js +41 -0
  458. package/dist/features/paths/pathEditState.js.map +1 -0
  459. package/dist/features/paths/pathEditingOverlayLayer.js +36 -38
  460. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  461. package/dist/features/paths/pathLayer.js +3 -2
  462. package/dist/features/paths/pathLayer.js.map +1 -1
  463. package/dist/features/paths/penPreviewLayer.js +86 -88
  464. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  465. package/dist/features/paths/usePathEdit.js +34 -0
  466. package/dist/features/paths/usePathEdit.js.map +1 -0
  467. package/dist/features/poseRun/usePoseRun.js +42 -55
  468. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  469. package/dist/features/selection/overlay.js +170 -178
  470. package/dist/features/selection/overlay.js.map +1 -1
  471. package/dist/features/text/index.js +6 -0
  472. package/dist/features/text/textLayer.js +1 -1
  473. package/dist/features/text/textLayer.js.map +1 -1
  474. package/dist/features/text/useSceneTextEdit.js +95 -82
  475. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  476. package/dist/features/viewports/viewportLayer.js +25 -36
  477. package/dist/features/viewports/viewportLayer.js.map +1 -1
  478. package/dist/index.d.ts +4507 -8459
  479. package/dist/index.js +275 -320
  480. package/dist/input/keyState.js +14 -14
  481. package/dist/interactions/actions/actionShortcuts.js.map +1 -1
  482. package/dist/interactions/actions/{defaults/align.js → align/action.js} +15 -16
  483. package/dist/interactions/actions/align/action.js.map +1 -0
  484. package/dist/interactions/actions/align/align.js +23 -23
  485. package/dist/interactions/actions/align/align.js.map +1 -1
  486. package/dist/interactions/actions/booleans/action.js +65 -0
  487. package/dist/interactions/actions/booleans/action.js.map +1 -0
  488. package/dist/interactions/actions/booleans/booleans.js +69 -78
  489. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  490. package/dist/interactions/actions/booleans/operands.js +40 -0
  491. package/dist/interactions/actions/booleans/operands.js.map +1 -0
  492. package/dist/interactions/actions/booleans/pieces.js +45 -0
  493. package/dist/interactions/actions/booleans/pieces.js.map +1 -0
  494. package/dist/interactions/actions/booleans/placement.js +24 -0
  495. package/dist/interactions/actions/booleans/placement.js.map +1 -0
  496. package/dist/interactions/actions/booleans/useBooleans.js +11 -9
  497. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  498. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  499. package/dist/interactions/actions/{defaults/clipboard.js → clipboard/action.js} +19 -19
  500. package/dist/interactions/actions/clipboard/action.js.map +1 -0
  501. package/dist/interactions/actions/clipboard/clipboardOps.js +15 -15
  502. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  503. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  504. package/dist/interactions/actions/clone/action.js +98 -0
  505. package/dist/interactions/actions/clone/action.js.map +1 -0
  506. package/dist/interactions/actions/clone/behaviors.js +52 -0
  507. package/dist/interactions/actions/clone/behaviors.js.map +1 -0
  508. package/dist/interactions/actions/defaultCommitAdapter.js +10 -37
  509. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  510. package/dist/interactions/actions/defaults/anchorEditing.js +41 -43
  511. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  512. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  513. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  514. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  515. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  516. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  517. package/dist/interactions/actions/defaults/duplicate.js +19 -19
  518. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  519. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  520. package/dist/interactions/actions/defaults/group.js +35 -40
  521. package/dist/interactions/actions/defaults/group.js.map +1 -1
  522. package/dist/interactions/actions/defaults/icons/booleanIcons.js +24 -1
  523. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -1
  524. package/dist/interactions/actions/defaults/icons/outlineIcons.js +39 -1
  525. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -1
  526. package/dist/interactions/actions/defaults/ingest.js +19 -15
  527. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  528. package/dist/interactions/actions/defaults/insertPathAnchor.js +14 -15
  529. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  530. package/dist/interactions/actions/defaults/nudge.js +30 -31
  531. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  532. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  533. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  534. package/dist/interactions/actions/defaults/setFill.js +9 -3
  535. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  536. package/dist/interactions/actions/defaults/setFillOpacity.js +4 -1
  537. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  538. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  539. package/dist/interactions/actions/defaults/sliceOps.js +20 -22
  540. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  541. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  542. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  543. package/dist/interactions/actions/defaults/viewportDragPan.js +1 -1
  544. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  545. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  546. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  547. package/dist/interactions/actions/{defaults/distribute.js → distribute/action.js} +18 -19
  548. package/dist/interactions/actions/distribute/action.js.map +1 -0
  549. package/dist/interactions/actions/distribute/distribute.js +11 -11
  550. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  551. package/dist/interactions/actions/{defaults/editAnchors.js → edit-anchors/action.js} +19 -21
  552. package/dist/interactions/actions/edit-anchors/action.js.map +1 -0
  553. package/dist/interactions/actions/edit-anchors/geometry.js +2 -4
  554. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  555. package/dist/interactions/actions/flip/action.js +124 -0
  556. package/dist/interactions/actions/flip/action.js.map +1 -0
  557. package/dist/interactions/actions/flip/helpers.js +1 -1
  558. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  559. package/dist/interactions/actions/gestureFrames.js +18 -0
  560. package/dist/interactions/actions/gestureFrames.js.map +1 -0
  561. package/dist/interactions/actions/gestureLifecycle.js +47 -20
  562. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  563. package/dist/interactions/actions/insert/action.js +72 -0
  564. package/dist/interactions/actions/insert/action.js.map +1 -0
  565. package/dist/interactions/actions/insert/commit.js +28 -0
  566. package/dist/interactions/actions/insert/commit.js.map +1 -0
  567. package/dist/interactions/actions/insert/extras.js +65 -0
  568. package/dist/interactions/actions/insert/extras.js.map +1 -0
  569. package/dist/interactions/actions/insert/frame.js +48 -0
  570. package/dist/interactions/actions/insert/frame.js.map +1 -0
  571. package/dist/interactions/actions/insert/geometry.js +35 -0
  572. package/dist/interactions/actions/insert/geometry.js.map +1 -0
  573. package/dist/interactions/actions/insert/rotateAction.js +21 -0
  574. package/dist/interactions/actions/insert/rotateAction.js.map +1 -0
  575. package/dist/interactions/actions/insert/session.js +59 -0
  576. package/dist/interactions/actions/insert/session.js.map +1 -0
  577. package/dist/interactions/actions/insert/shape.js +34 -0
  578. package/dist/interactions/actions/insert/shape.js.map +1 -0
  579. package/dist/interactions/actions/lasso-select/action.js +143 -0
  580. package/dist/interactions/actions/lasso-select/action.js.map +1 -0
  581. package/dist/interactions/actions/move/action.js +87 -0
  582. package/dist/interactions/actions/move/action.js.map +1 -0
  583. package/dist/interactions/actions/move/behaviors/layoutDrop.js +51 -0
  584. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -0
  585. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +15 -0
  586. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -0
  587. package/dist/interactions/actions/move/behaviors/snapToContainer.js +24 -23
  588. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  589. package/dist/interactions/actions/move/capture.js +99 -0
  590. package/dist/interactions/actions/move/capture.js.map +1 -0
  591. package/dist/interactions/actions/move/commit/index.js +41 -0
  592. package/dist/interactions/actions/move/commit/index.js.map +1 -0
  593. package/dist/interactions/actions/move/commit/layoutDrop.js +44 -0
  594. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -0
  595. package/dist/interactions/actions/move/commit/layoutRelease.js +100 -0
  596. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -0
  597. package/dist/interactions/actions/move/commit/rebase.js +18 -0
  598. package/dist/interactions/actions/move/commit/rebase.js.map +1 -0
  599. package/dist/interactions/actions/move/commit/reparent.js +65 -0
  600. package/dist/interactions/actions/move/commit/reparent.js.map +1 -0
  601. package/dist/interactions/actions/move/delta.js +51 -0
  602. package/dist/interactions/actions/move/delta.js.map +1 -0
  603. package/dist/interactions/actions/move/frame.js +59 -0
  604. package/dist/interactions/actions/move/frame.js.map +1 -0
  605. package/dist/interactions/actions/move/gestureAdapter.js +15 -40
  606. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  607. package/dist/interactions/actions/move/landedDescendants.js +8 -8
  608. package/dist/interactions/actions/move/layout/container.js +94 -0
  609. package/dist/interactions/actions/move/layout/container.js.map +1 -0
  610. package/dist/interactions/actions/move/layout/dragged.js +58 -0
  611. package/dist/interactions/actions/move/layout/dragged.js.map +1 -0
  612. package/dist/interactions/actions/move/layout/dropPass.js +122 -0
  613. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -0
  614. package/dist/interactions/actions/move/layout/exits.js +38 -0
  615. package/dist/interactions/actions/move/layout/exits.js.map +1 -0
  616. package/dist/interactions/actions/move/layout/glide.js +48 -0
  617. package/dist/interactions/actions/move/layout/glide.js.map +1 -0
  618. package/dist/interactions/actions/move/session.js +63 -0
  619. package/dist/interactions/actions/move/session.js.map +1 -0
  620. package/dist/interactions/actions/move/translate.js +61 -0
  621. package/dist/interactions/actions/move/translate.js.map +1 -0
  622. package/dist/interactions/actions/outlines/createOutlines.js +17 -64
  623. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  624. package/dist/interactions/actions/outlines/createOutlinesAction.js +51 -0
  625. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -0
  626. package/dist/interactions/actions/outlines/outlineStroke.js +72 -0
  627. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -0
  628. package/dist/interactions/actions/outlines/outlineStrokeAction.js +37 -0
  629. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -0
  630. package/dist/interactions/actions/outlines/replaceWithPaths.js +54 -0
  631. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -0
  632. package/dist/interactions/actions/outlines/strokeRegion.js +27 -0
  633. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -0
  634. package/dist/interactions/actions/planeInput.js.map +1 -1
  635. package/dist/interactions/actions/pointerState.js +12 -0
  636. package/dist/interactions/actions/pointerState.js.map +1 -0
  637. package/dist/interactions/actions/poseDescriptorDep.js +1 -1
  638. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  639. package/dist/interactions/actions/poseFrame.js +26 -26
  640. package/dist/interactions/actions/poseFrame.js.map +1 -1
  641. package/dist/interactions/actions/resize/action.js +55 -0
  642. package/dist/interactions/actions/resize/action.js.map +1 -0
  643. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -1
  644. package/dist/interactions/actions/resize/boxFrame.js +16 -0
  645. package/dist/interactions/actions/resize/boxFrame.js.map +1 -0
  646. package/dist/interactions/actions/resize/capture.js +85 -0
  647. package/dist/interactions/actions/resize/capture.js.map +1 -0
  648. package/dist/interactions/actions/resize/commit.js +69 -0
  649. package/dist/interactions/actions/resize/commit.js.map +1 -0
  650. package/dist/interactions/actions/resize/frame.js +74 -0
  651. package/dist/interactions/actions/resize/frame.js.map +1 -0
  652. package/dist/interactions/actions/resize/pointSnap.js +111 -0
  653. package/dist/interactions/actions/resize/pointSnap.js.map +1 -0
  654. package/dist/interactions/actions/resize/ruleBounds.js +9 -0
  655. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -0
  656. package/dist/interactions/actions/resize/session.js +49 -0
  657. package/dist/interactions/actions/resize/session.js.map +1 -0
  658. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  659. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  660. package/dist/interactions/actions/rotate/action.js +56 -0
  661. package/dist/interactions/actions/rotate/action.js.map +1 -0
  662. package/dist/interactions/actions/rotate/behaviors/index.js +7 -0
  663. package/dist/interactions/actions/rotate/behaviors/index.js.map +1 -0
  664. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +12 -0
  665. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +1 -0
  666. package/dist/interactions/actions/rotate/commit.js +40 -0
  667. package/dist/interactions/actions/rotate/commit.js.map +1 -0
  668. package/dist/interactions/actions/rotate/frame.js +65 -0
  669. package/dist/interactions/actions/rotate/frame.js.map +1 -0
  670. package/dist/interactions/actions/rotate/handle.js +12 -12
  671. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  672. package/dist/interactions/actions/rotate/session.js +92 -0
  673. package/dist/interactions/actions/rotate/session.js.map +1 -0
  674. package/dist/interactions/actions/spatialReference.js.map +1 -1
  675. package/dist/interactions/actions/useStandardActions.js +77 -72
  676. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  677. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +61 -42
  678. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  679. package/dist/interactions/gestures/shared/originProjection.js +1 -1
  680. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  681. package/dist/interactions/gestures/shared/screenTolerance.js +8 -2
  682. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  683. package/dist/interactions/gestures/shared/snap.js.map +1 -1
  684. package/dist/layout/arrivals.js +20 -23
  685. package/dist/layout/arrivals.js.map +1 -1
  686. package/dist/math-CYUjoyyU.d.ts +33 -0
  687. package/dist/math.d.ts +5 -2
  688. package/dist/math.js +6 -6
  689. package/dist/mesh.d.ts +4 -268
  690. package/dist/mesh.js +3 -7
  691. package/dist/move.d.ts +6 -4
  692. package/dist/{originProjection-gHnOup4e.d.ts → originProjection-PPT88jZv.d.ts} +1 -1
  693. package/dist/patterns-builtin.d.ts +1 -118
  694. package/dist/patterns-builtin.js +2 -3
  695. package/dist/poseDescriptor-Bqk-11Rl.d.ts +73 -0
  696. package/dist/renderer.d.ts +1 -92
  697. package/dist/renderer.js +2 -19
  698. package/dist/resize.d.ts +11 -22
  699. package/dist/resize.js +1 -1
  700. package/dist/style.css +1 -1
  701. package/dist/test-hook/install.js.map +1 -1
  702. package/dist/test-hook/useTestHook.js +22 -0
  703. package/dist/test-hook/useTestHook.js.map +1 -0
  704. package/dist/test-seams-D0pyV3pR.d.ts +149 -0
  705. package/dist/test-seams.d.ts +4 -4
  706. package/dist/test-seams.js +2 -2
  707. package/dist/tools/builtin/bone/boneActions.js +130 -0
  708. package/dist/tools/builtin/bone/boneActions.js.map +1 -0
  709. package/dist/tools/builtin/bone/boneOverlay.js +58 -0
  710. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -0
  711. package/dist/tools/builtin/bone/placedRig.js +24 -0
  712. package/dist/tools/builtin/bone/placedRig.js.map +1 -0
  713. package/dist/tools/builtin/bone/rigEditState.js +21 -0
  714. package/dist/tools/builtin/bone/rigEditState.js.map +1 -0
  715. package/dist/tools/builtin/bone/useBoneTool.js +98 -0
  716. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -0
  717. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  718. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  719. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  720. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  721. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  722. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  723. package/dist/tools/builtin/pen/usePenTool.js +161 -163
  724. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  725. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  726. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  727. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  728. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  729. package/dist/tools/builtin/select/adapterPointQuery.js +36 -0
  730. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -0
  731. package/dist/tools/builtin/select/selectionContributions.js +4 -4
  732. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  733. package/dist/tools/builtin/select/useSelectTool.js +43 -71
  734. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  735. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  736. package/dist/tools/builtin/slice/useSliceTool.js +67 -72
  737. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  738. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  739. package/dist/tools/builtin/text/useTextTool.js +8 -0
  740. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  741. package/dist/tools/builtin/weight/useWeightTool.js +77 -0
  742. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -0
  743. package/dist/tools/builtin/weight/weightActions.js +112 -0
  744. package/dist/tools/builtin/weight/weightActions.js.map +1 -0
  745. package/dist/tools/builtin/weight/weightOverlay.js +61 -0
  746. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -0
  747. package/dist/tools/overlayBinding.js.map +1 -1
  748. package/dist/tools/useKeybindings.js +20 -14
  749. package/dist/tools/useKeybindings.js.map +1 -1
  750. package/dist/{types-k-5Oqh-U.d.ts → types-CIKDwlsP.d.ts} +84 -164
  751. package/dist/util/paint.js +1 -1
  752. package/dist/util/paint.js.map +1 -1
  753. package/dist/version.js +1 -1
  754. package/package.json +26 -21
  755. package/dist/animation/colorHelpers.js +0 -135
  756. package/dist/animation/colorHelpers.js.map +0 -1
  757. package/dist/animation/colorRegistry.js +0 -37
  758. package/dist/animation/colorRegistry.js.map +0 -1
  759. package/dist/animation/engine/axes.js +0 -36
  760. package/dist/animation/engine/axes.js.map +0 -1
  761. package/dist/animation/engine/codec.js +0 -170
  762. package/dist/animation/engine/codec.js.map +0 -1
  763. package/dist/animation/engine/integrator.js +0 -12
  764. package/dist/animation/engine/integrator.js.map +0 -1
  765. package/dist/animation/loop.js +0 -60
  766. package/dist/animation/loop.js.map +0 -1
  767. package/dist/animation/observe.js +0 -23
  768. package/dist/animation/observe.js.map +0 -1
  769. package/dist/animation/rig/blendPoses.js +0 -43
  770. package/dist/animation/rig/blendPoses.js.map +0 -1
  771. package/dist/animation/rig/mirrorPose.js +0 -19
  772. package/dist/animation/rig/mirrorPose.js.map +0 -1
  773. package/dist/animation/rig/resolveSkeleton.js +0 -33
  774. package/dist/animation/rig/resolveSkeleton.js.map +0 -1
  775. package/dist/animation/rig/solveIk.js +0 -103
  776. package/dist/animation/rig/solveIk.js.map +0 -1
  777. package/dist/animation/rig/types.js +0 -12
  778. package/dist/animation/rig/types.js.map +0 -1
  779. package/dist/animation/slew.js +0 -27
  780. package/dist/animation/slew.js.map +0 -1
  781. package/dist/animation/stagger.js +0 -146
  782. package/dist/animation/stagger.js.map +0 -1
  783. package/dist/animation/timeline/booking.js +0 -114
  784. package/dist/animation/timeline/booking.js.map +0 -1
  785. package/dist/animation/timeline/createTimeline.js +0 -125
  786. package/dist/animation/timeline/createTimeline.js.map +0 -1
  787. package/dist/animation/timeline/sampleTrack.js +0 -79
  788. package/dist/animation/timeline/sampleTrack.js.map +0 -1
  789. package/dist/animation/useAnimator.js +0 -388
  790. package/dist/animation/useAnimator.js.map +0 -1
  791. package/dist/autoPoseDescriptor-Ct7yqivU.d.ts +0 -108
  792. package/dist/builtins-DPcdghtB.d.ts +0 -1223
  793. package/dist/canvas/MinimapCanvas.js +0 -140
  794. package/dist/canvas/MinimapCanvas.js.map +0 -1
  795. package/dist/canvas/deps/poseComposition.js +0 -11
  796. package/dist/canvas/deps/poseComposition.js.map +0 -1
  797. package/dist/canvas/minimapMath.js +0 -82
  798. package/dist/canvas/minimapMath.js.map +0 -1
  799. package/dist/canvas/toolPreview.js +0 -39
  800. package/dist/canvas/toolPreview.js.map +0 -1
  801. package/dist/core/adapters/arrayAdapter.js +0 -94
  802. package/dist/core/adapters/arrayAdapter.js.map +0 -1
  803. package/dist/core/adapters/useArrayAdapter.js +0 -13
  804. package/dist/core/adapters/useArrayAdapter.js.map +0 -1
  805. package/dist/core/fillInPoseFrame.js +0 -102
  806. package/dist/core/fillInPoseFrame.js.map +0 -1
  807. package/dist/core/geometry/poseFrame.js +0 -44
  808. package/dist/core/geometry/poseFrame.js.map +0 -1
  809. package/dist/core/geometry/poseRotation.js +0 -58
  810. package/dist/core/geometry/poseRotation.js.map +0 -1
  811. package/dist/core/gradient.js +0 -136
  812. package/dist/core/gradient.js.map +0 -1
  813. package/dist/core/markerInset.js +0 -24
  814. package/dist/core/markerInset.js.map +0 -1
  815. package/dist/core/mixed.js +0 -6
  816. package/dist/core/mixed.js.map +0 -1
  817. package/dist/core/paintKinds.js +0 -156
  818. package/dist/core/paintKinds.js.map +0 -1
  819. package/dist/core/scene/pickability.js +0 -6
  820. package/dist/core/scene/pickability.js.map +0 -1
  821. package/dist/core/strokeMarkerShapes.js +0 -139
  822. package/dist/core/strokeMarkerShapes.js.map +0 -1
  823. package/dist/core/strokeMarkers.js +0 -28
  824. package/dist/core/strokeMarkers.js.map +0 -1
  825. package/dist/core/viewport/meanScale.js +0 -8
  826. package/dist/core/viewport/meanScale.js.map +0 -1
  827. package/dist/core/viewport/pxExtent.js +0 -42
  828. package/dist/core/viewport/pxExtent.js.map +0 -1
  829. package/dist/features/cursor/paintedCursorLayer.js.map +0 -1
  830. package/dist/features/focus/gateLayer.js.map +0 -1
  831. package/dist/features/focus/useCanvasFocus.js +0 -29
  832. package/dist/features/focus/useCanvasFocus.js.map +0 -1
  833. package/dist/features/groups/children.js.map +0 -1
  834. package/dist/features/groups/composePose.js.map +0 -1
  835. package/dist/features/groups/nestedHit.js.map +0 -1
  836. package/dist/features/groups/unionOfChildren.js.map +0 -1
  837. package/dist/features/images/imageCache.js +0 -104
  838. package/dist/features/images/imageCache.js.map +0 -1
  839. package/dist/features/ingestion/index.js +0 -8
  840. package/dist/features/meshPaint/bake.js +0 -79
  841. package/dist/features/meshPaint/bake.js.map +0 -1
  842. package/dist/features/meshPaint/bakeCache.js +0 -59
  843. package/dist/features/meshPaint/bakeCache.js.map +0 -1
  844. package/dist/features/meshPaint/handles.js +0 -86
  845. package/dist/features/meshPaint/handles.js.map +0 -1
  846. package/dist/features/meshPaint/lazyKind.js.map +0 -1
  847. package/dist/features/meshPaint/meshPaint.js +0 -239
  848. package/dist/features/meshPaint/meshPaint.js.map +0 -1
  849. package/dist/features/meshPaint/meshShader.js +0 -6
  850. package/dist/features/meshPaint/meshShader.js.map +0 -1
  851. package/dist/features/meshPaint/register.js +0 -7
  852. package/dist/features/meshPaint/register.js.map +0 -1
  853. package/dist/features/meshPaint/surface.js +0 -110
  854. package/dist/features/meshPaint/surface.js.map +0 -1
  855. package/dist/features/minimap/actions.js +0 -53
  856. package/dist/features/minimap/actions.js.map +0 -1
  857. package/dist/features/minimap/createMinimapContribution.js +0 -96
  858. package/dist/features/minimap/createMinimapContribution.js.map +0 -1
  859. package/dist/features/minimap/layers.js +0 -85
  860. package/dist/features/minimap/layers.js.map +0 -1
  861. package/dist/features/overlays/useNodeOverlayFrame.js +0 -103
  862. package/dist/features/overlays/useNodeOverlayFrame.js.map +0 -1
  863. package/dist/features/parallax/createParallaxLayer.js +0 -26
  864. package/dist/features/parallax/createParallaxLayer.js.map +0 -1
  865. package/dist/features/parallax/createParallaxPlane.js +0 -22
  866. package/dist/features/parallax/createParallaxPlane.js.map +0 -1
  867. package/dist/features/paths/anchorEdits.js +0 -167
  868. package/dist/features/paths/anchorEdits.js.map +0 -1
  869. package/dist/features/paths/anchors.js +0 -159
  870. package/dist/features/paths/anchors.js.map +0 -1
  871. package/dist/features/paths/booleans.js +0 -2
  872. package/dist/features/paths/markerCommands.js +0 -149
  873. package/dist/features/paths/markerCommands.js.map +0 -1
  874. package/dist/features/paths/markerSites.js +0 -59
  875. package/dist/features/paths/markerSites.js.map +0 -1
  876. package/dist/features/paths/markers.js +0 -95
  877. package/dist/features/paths/markers.js.map +0 -1
  878. package/dist/features/paths/nearestAnchor.js +0 -36
  879. package/dist/features/paths/nearestAnchor.js.map +0 -1
  880. package/dist/features/paths/pathInWorld.js +0 -41
  881. package/dist/features/paths/pathInWorld.js.map +0 -1
  882. package/dist/features/paths/poseDescriptor.js +0 -39
  883. package/dist/features/paths/poseDescriptor.js.map +0 -1
  884. package/dist/features/paths/strokeToPath.js +0 -40
  885. package/dist/features/paths/strokeToPath.js.map +0 -1
  886. package/dist/features/paths/tessellate/dash.js +0 -52
  887. package/dist/features/paths/tessellate/dash.js.map +0 -1
  888. package/dist/features/paths/tessellate/insets.js +0 -32
  889. package/dist/features/paths/tessellate/insets.js.map +0 -1
  890. package/dist/features/paths/tessellate/metric.js +0 -72
  891. package/dist/features/paths/tessellate/metric.js.map +0 -1
  892. package/dist/features/paths/tessellate/stroke.js +0 -170
  893. package/dist/features/paths/tessellate/stroke.js.map +0 -1
  894. package/dist/features/paths/tessellate/vertexWidths.js +0 -32
  895. package/dist/features/paths/tessellate/vertexWidths.js.map +0 -1
  896. package/dist/features/patterns/commandPaint.js +0 -18
  897. package/dist/features/patterns/commandPaint.js.map +0 -1
  898. package/dist/features/patterns/index.js +0 -11
  899. package/dist/features/patterns/index.js.map +0 -1
  900. package/dist/features/patterns/patterns-builtin.js +0 -38
  901. package/dist/features/patterns/patterns-builtin.js.map +0 -1
  902. package/dist/features/patterns/rasterizeTile.js +0 -17
  903. package/dist/features/patterns/rasterizeTile.js.map +0 -1
  904. package/dist/features/patterns/resolveSpec.js +0 -65
  905. package/dist/features/patterns/resolveSpec.js.map +0 -1
  906. package/dist/features/patterns/tileGeometry.js +0 -158
  907. package/dist/features/patterns/tileGeometry.js.map +0 -1
  908. package/dist/features/pointer/PointerContext.js +0 -45
  909. package/dist/features/pointer/PointerContext.js.map +0 -1
  910. package/dist/features/selection/SelectionContext.js +0 -51
  911. package/dist/features/selection/SelectionContext.js.map +0 -1
  912. package/dist/features/simulation/createSimulation.js +0 -61
  913. package/dist/features/simulation/createSimulation.js.map +0 -1
  914. package/dist/features/simulation/types.js +0 -6
  915. package/dist/features/simulation/types.js.map +0 -1
  916. package/dist/features/simulation/useSimulation.js +0 -74
  917. package/dist/features/simulation/useSimulation.js.map +0 -1
  918. package/dist/features/text/domOffsets.js +0 -82
  919. package/dist/features/text/domOffsets.js.map +0 -1
  920. package/dist/features/text/domRuns.js +0 -230
  921. package/dist/features/text/domRuns.js.map +0 -1
  922. package/dist/features/text/fitTextPose.js +0 -38
  923. package/dist/features/text/fitTextPose.js.map +0 -1
  924. package/dist/features/text/hitTest.js +0 -48
  925. package/dist/features/text/hitTest.js.map +0 -1
  926. package/dist/features/text/isTextData.js +0 -8
  927. package/dist/features/text/isTextData.js.map +0 -1
  928. package/dist/features/text/overlayDirection.js +0 -15
  929. package/dist/features/text/overlayDirection.js.map +0 -1
  930. package/dist/features/text/renderLabel.js +0 -14
  931. package/dist/features/text/renderLabel.js.map +0 -1
  932. package/dist/features/text/runs/effectiveRangeStyle.js +0 -66
  933. package/dist/features/text/runs/effectiveRangeStyle.js.map +0 -1
  934. package/dist/features/text/runs/flagRange.js +0 -53
  935. package/dist/features/text/runs/flagRange.js.map +0 -1
  936. package/dist/features/text/runs/rangeStyle.js +0 -133
  937. package/dist/features/text/runs/rangeStyle.js.map +0 -1
  938. package/dist/features/text/textCommand.js +0 -60
  939. package/dist/features/text/textCommand.js.map +0 -1
  940. package/dist/features/text/textToPath.js +0 -181
  941. package/dist/features/text/textToPath.js.map +0 -1
  942. package/dist/features/text/useTextEdit.js +0 -491
  943. package/dist/features/text/useTextEdit.js.map +0 -1
  944. package/dist/features/tiling/createTiledLayer.js +0 -65
  945. package/dist/features/tiling/createTiledLayer.js.map +0 -1
  946. package/dist/features/tiling/tiledProject.js +0 -14
  947. package/dist/features/tiling/tiledProject.js.map +0 -1
  948. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +0 -26
  949. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +0 -1
  950. package/dist/interactions/actions/defaults/align.js.map +0 -1
  951. package/dist/interactions/actions/defaults/booleans.js +0 -52
  952. package/dist/interactions/actions/defaults/booleans.js.map +0 -1
  953. package/dist/interactions/actions/defaults/clipboard.js.map +0 -1
  954. package/dist/interactions/actions/defaults/clone.js +0 -91
  955. package/dist/interactions/actions/defaults/clone.js.map +0 -1
  956. package/dist/interactions/actions/defaults/createOutlines.js +0 -47
  957. package/dist/interactions/actions/defaults/createOutlines.js.map +0 -1
  958. package/dist/interactions/actions/defaults/distribute.js.map +0 -1
  959. package/dist/interactions/actions/defaults/editAnchors.js.map +0 -1
  960. package/dist/interactions/actions/defaults/flip.js +0 -125
  961. package/dist/interactions/actions/defaults/flip.js.map +0 -1
  962. package/dist/interactions/actions/defaults/insert.js +0 -287
  963. package/dist/interactions/actions/defaults/insert.js.map +0 -1
  964. package/dist/interactions/actions/defaults/lassoSelect.js +0 -153
  965. package/dist/interactions/actions/defaults/lassoSelect.js.map +0 -1
  966. package/dist/interactions/actions/defaults/move.js +0 -778
  967. package/dist/interactions/actions/defaults/move.js.map +0 -1
  968. package/dist/interactions/actions/defaults/resize.js +0 -341
  969. package/dist/interactions/actions/defaults/resize.js.map +0 -1
  970. package/dist/interactions/actions/defaults/rotate.js +0 -185
  971. package/dist/interactions/actions/defaults/rotate.js.map +0 -1
  972. package/dist/interactions/actions/previewOverrides.js +0 -25
  973. package/dist/interactions/actions/previewOverrides.js.map +0 -1
  974. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +0 -1
  975. package/dist/math-J-ACHyEg.d.ts +0 -159
  976. package/dist/registerProgram-T9S_PfAX.d.ts +0 -208
  977. package/dist/renderer/DrawCommand.js +0 -6
  978. package/dist/renderer/DrawCommand.js.map +0 -1
  979. package/dist/renderer/WeaselRenderer.js +0 -333
  980. package/dist/renderer/WeaselRenderer.js.map +0 -1
  981. package/dist/renderer/batchClip.js +0 -46
  982. package/dist/renderer/batchClip.js.map +0 -1
  983. package/dist/renderer/cache/GLImageCache.js +0 -74
  984. package/dist/renderer/cache/GLImageCache.js.map +0 -1
  985. package/dist/renderer/cache/GLMeshCache.js +0 -102
  986. package/dist/renderer/cache/GLMeshCache.js.map +0 -1
  987. package/dist/renderer/cache/GLTextureCache.js +0 -68
  988. package/dist/renderer/cache/GLTextureCache.js.map +0 -1
  989. package/dist/renderer/cache/GradientRampAtlas.js +0 -82
  990. package/dist/renderer/cache/GradientRampAtlas.js.map +0 -1
  991. package/dist/renderer/cache/cache.js +0 -13
  992. package/dist/renderer/cache/cache.js.map +0 -1
  993. package/dist/renderer/cache/markerCommandCache.js +0 -63
  994. package/dist/renderer/cache/markerCommandCache.js.map +0 -1
  995. package/dist/renderer/cache/outlineMeshCache.js +0 -15
  996. package/dist/renderer/cache/outlineMeshCache.js.map +0 -1
  997. package/dist/renderer/cache/outlineStrokeMeshCache.js +0 -36
  998. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +0 -1
  999. package/dist/renderer/cache/strokeMeshCache.js +0 -55
  1000. package/dist/renderer/cache/strokeMeshCache.js.map +0 -1
  1001. package/dist/renderer/cullDrawCommands.js +0 -90
  1002. package/dist/renderer/cullDrawCommands.js.map +0 -1
  1003. package/dist/renderer/draw/batch.js +0 -133
  1004. package/dist/renderer/draw/batch.js.map +0 -1
  1005. package/dist/renderer/draw/clip.js +0 -89
  1006. package/dist/renderer/draw/clip.js.map +0 -1
  1007. package/dist/renderer/draw/customShader.js +0 -230
  1008. package/dist/renderer/draw/customShader.js.map +0 -1
  1009. package/dist/renderer/draw/drawTriangles.js +0 -8
  1010. package/dist/renderer/draw/drawTriangles.js.map +0 -1
  1011. package/dist/renderer/draw/effects.js +0 -28
  1012. package/dist/renderer/draw/effects.js.map +0 -1
  1013. package/dist/renderer/draw/flushBatch.js +0 -35
  1014. package/dist/renderer/draw/flushBatch.js.map +0 -1
  1015. package/dist/renderer/draw/gradient.js +0 -90
  1016. package/dist/renderer/draw/gradient.js.map +0 -1
  1017. package/dist/renderer/draw/image.js +0 -38
  1018. package/dist/renderer/draw/image.js.map +0 -1
  1019. package/dist/renderer/draw/mesh.js +0 -16
  1020. package/dist/renderer/draw/mesh.js.map +0 -1
  1021. package/dist/renderer/draw/paintBind.js +0 -70
  1022. package/dist/renderer/draw/paintBind.js.map +0 -1
  1023. package/dist/renderer/draw/pathPaint.js +0 -142
  1024. package/dist/renderer/draw/pathPaint.js.map +0 -1
  1025. package/dist/renderer/draw/scratchPass.js +0 -83
  1026. package/dist/renderer/draw/scratchPass.js.map +0 -1
  1027. package/dist/renderer/draw/stencil.js +0 -28
  1028. package/dist/renderer/draw/stencil.js.map +0 -1
  1029. package/dist/renderer/draw/text.js +0 -167
  1030. package/dist/renderer/draw/text.js.map +0 -1
  1031. package/dist/renderer/draw/uniforms.js +0 -77
  1032. package/dist/renderer/draw/uniforms.js.map +0 -1
  1033. package/dist/renderer/draw.js +0 -79
  1034. package/dist/renderer/draw.js.map +0 -1
  1035. package/dist/renderer/drawBatch.js +0 -198
  1036. package/dist/renderer/drawBatch.js.map +0 -1
  1037. package/dist/renderer/effects/EffectTargets.js +0 -48
  1038. package/dist/renderer/effects/EffectTargets.js.map +0 -1
  1039. package/dist/renderer/effects/builtins.js +0 -31
  1040. package/dist/renderer/effects/builtins.js.map +0 -1
  1041. package/dist/renderer/effects/composite.js +0 -11
  1042. package/dist/renderer/effects/composite.js.map +0 -1
  1043. package/dist/renderer/effects/effectPrelude.js +0 -10
  1044. package/dist/renderer/effects/effectPrelude.js.map +0 -1
  1045. package/dist/renderer/effects/types.js +0 -10
  1046. package/dist/renderer/effects/types.js.map +0 -1
  1047. package/dist/renderer/glyphOutlineMesh.js +0 -67
  1048. package/dist/renderer/glyphOutlineMesh.js.map +0 -1
  1049. package/dist/renderer/index.js +0 -20
  1050. package/dist/renderer/math/color.js +0 -321
  1051. package/dist/renderer/math/color.js.map +0 -1
  1052. package/dist/renderer/math/mat3.js +0 -80
  1053. package/dist/renderer/math/mat3.js.map +0 -1
  1054. package/dist/renderer/math/patternSpace.js +0 -22
  1055. package/dist/renderer/math/patternSpace.js.map +0 -1
  1056. package/dist/renderer/math/viewToMat3.js +0 -19
  1057. package/dist/renderer/math/viewToMat3.js.map +0 -1
  1058. package/dist/renderer/paintResources.js +0 -18
  1059. package/dist/renderer/paintResources.js.map +0 -1
  1060. package/dist/renderer/paintScratch.js +0 -37
  1061. package/dist/renderer/paintScratch.js.map +0 -1
  1062. package/dist/renderer/shaders/ShaderProgram.js +0 -74
  1063. package/dist/renderer/shaders/ShaderProgram.js.map +0 -1
  1064. package/dist/renderer/shaders/batchFill.js +0 -119
  1065. package/dist/renderer/shaders/batchFill.js.map +0 -1
  1066. package/dist/renderer/shaders/customPrelude.js +0 -34
  1067. package/dist/renderer/shaders/customPrelude.js.map +0 -1
  1068. package/dist/renderer/shaders/extractUniformNames.js +0 -184
  1069. package/dist/renderer/shaders/extractUniformNames.js.map +0 -1
  1070. package/dist/renderer/shaders/glyphPaint.js +0 -61
  1071. package/dist/renderer/shaders/glyphPaint.js.map +0 -1
  1072. package/dist/renderer/shaders/gradFill.js +0 -31
  1073. package/dist/renderer/shaders/gradFill.js.map +0 -1
  1074. package/dist/renderer/shaders/pathFill.js +0 -14
  1075. package/dist/renderer/shaders/pathFill.js.map +0 -1
  1076. package/dist/renderer/shaders/patternFill.js +0 -25
  1077. package/dist/renderer/shaders/patternFill.js.map +0 -1
  1078. package/dist/renderer/shaders/registerProgram.js +0 -18
  1079. package/dist/renderer/shaders/registerProgram.js.map +0 -1
  1080. package/dist/renderer/spriteSheet.js +0 -14
  1081. package/dist/renderer/spriteSheet.js.map +0 -1
  1082. package/dist/renderer/state/GroupState.js +0 -77
  1083. package/dist/renderer/state/GroupState.js.map +0 -1
  1084. package/dist/renderer/strokeLengths.js +0 -50
  1085. package/dist/renderer/strokeLengths.js.map +0 -1
  1086. package/dist/renderer/syntheticItalic.js +0 -6
  1087. package/dist/renderer/syntheticItalic.js.map +0 -1
  1088. package/dist/renderer/textures/registerTexture.js +0 -34
  1089. package/dist/renderer/textures/registerTexture.js.map +0 -1
  1090. package/dist/scheduling/useVisibleRaf.js +0 -69
  1091. package/dist/scheduling/useVisibleRaf.js.map +0 -1
  1092. package/dist/test-seams-DM2B87-g.d.ts +0 -356
@@ -0,0 +1,26 @@
1
+ import { useMemo as e } from "react";
2
+ import { usePublishSelection as t } from "@weasel-js/routing/react";
3
+ //#region src/core/selection/usePublishSceneSelection.ts
4
+ function n(e) {
5
+ if (e.kind === "container") return "group";
6
+ let t = e.pose;
7
+ if (t && typeof t == "object" && "kind" in t && typeof t.kind == "string") return "path";
8
+ }
9
+ function r(e, t, r) {
10
+ if (t.length !== 0) return t.map((t) => {
11
+ let i = e.get(t);
12
+ if (i) return r ? r(i) : n(i);
13
+ });
14
+ }
15
+ function i(n, i, a) {
16
+ let o = e(() => r(n, i, a), [
17
+ n,
18
+ i,
19
+ a
20
+ ]);
21
+ t(i, o);
22
+ }
23
+ //#endregion
24
+ export { r as selectionKindLabels, i as usePublishSceneSelection };
25
+
26
+ //# sourceMappingURL=usePublishSceneSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePublishSceneSelection.js","names":["defaultKindLabel","node","pose","selectionKindLabels","ids","scene","id","describeKind","usePublishSceneSelection","kinds","useMemo"],"sources":["../../../src/core/selection/usePublishSceneSelection.ts"],"sourcesContent":["import { usePublishSelection } from '@weasel-js/routing/react';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport { useMemo } from 'react';\n\ntype KindLabel = string | undefined;\n\n// Not the routing kind: this reads the node and its pose where `NodeRouting.classify` reads\n// `data`, and the two disagree on most nodes (`SceneCanvas.selectionKinds.test.tsx`).\nfunction defaultKindLabel(node: Node<unknown, string, unknown>): KindLabel {\n if (node.kind === 'container') return 'group';\n const pose = node.pose as { kind?: unknown } | null;\n if (pose && typeof pose === 'object' && 'kind' in pose && typeof pose.kind === 'string') return 'path';\n return undefined;\n}\n\n/** The label published beside each selected id, parallel to `ids`; `undefined` when\n * nothing is selected. `describeKind` replaces the default for every node. */\nexport function selectionKindLabels<TData, TLayer extends string, TPose>(\n scene: Pick<Scene<TData, TLayer, TPose>, 'get'>,\n ids: readonly NodeId[],\n describeKind?: (node: Node<TData, TLayer, TPose>) => KindLabel,\n): readonly KindLabel[] | undefined {\n if (ids.length === 0) return undefined;\n return ids.map((id) => {\n const node = scene.get(id);\n if (!node) return undefined;\n return describeKind ? describeKind(node) : defaultKindLabel(node as Node<unknown, string, unknown>);\n });\n}\n\n/** Publishes a scene's selection, with a kind label per id, into any surrounding\n * `<SelectionContextProvider>`. A no-op without one. */\nexport function usePublishSceneSelection<TData, TLayer extends string, TPose>(\n scene: Pick<Scene<TData, TLayer, TPose>, 'get'>,\n ids: readonly NodeId[],\n describeKind?: (node: Node<TData, TLayer, TPose>) => KindLabel,\n): void {\n const kinds = useMemo(() => selectionKindLabels(scene, ids, describeKind), [scene, ids, describeKind]);\n usePublishSelection(ids, kinds);\n}\n"],"mappings":";;;AAQA,SAASA,EAAiB,GAAiD;CACzE,IAAIC,EAAK,SAAS,aAAa,OAAO;CACtC,IAAMC,IAAOD,EAAK;CAClB,IAAIC,KAAQ,OAAOA,KAAS,YAAY,UAAUA,KAAQ,OAAOA,EAAK,QAAS,UAAU,OAAO;AAElG;AAIA,SAAgBC,EACd,GACA,GACA,GACkC;CAClC,IAAIC,EAAI,WAAW,GACnB,OAAOA,EAAI,KAAK,MAAO;EACrB,IAAMH,IAAOI,EAAM,IAAIC,CAAE;EACzB,IAAKL,GACL,OAAOM,IAAeA,EAAaN,CAAI,IAAID,EAAiBC,CAAsC;CACpG,CAAC;AACH;AAIA,SAAgBO,EACd,GACA,GACA,GACM;CACN,IAAMC,IAAQC,QAAcP,EAAoBE,GAAOD,GAAKG,CAAY,GAAG;EAACF;EAAOD;EAAKG;CAAY,CAAC;CACrG,EAAoBH,GAAKK,CAAK;AAChC"}
@@ -3,25 +3,31 @@ import { useLayoutEffect as t, useMemo as n, useRef as r, useState as i, useSync
3
3
  import { useLatest as o } from "@weasel-js/react";
4
4
  import { createSelectionStore as s, intentOf as c, select as l } from "@weasel-js/select";
5
5
  //#region src/core/selection/useSelection.ts
6
- function u(u = {}) {
7
- let { mode: d = "single", extend: f = "shift", initial: p = [], lock: m = !1, scene: h } = u, [g] = i(() => s([...p])), _ = h ?? g, v = r(p);
8
- a(_.subscribe, () => _.getSelection());
9
- let y = r(!1);
6
+ function u(e) {
7
+ let { renderOrder: t } = e;
8
+ return typeof t == "function" ? () => t.call(e) : void 0;
9
+ }
10
+ function d(d = {}) {
11
+ let { mode: f = "single", extend: p = "shift", initial: m = [], lock: h = !1, scene: g, range: _, order: v } = d, [y] = i(() => s([...m])), b = g ?? y, x = r(m);
12
+ a(b.subscribe, () => b.getSelection());
13
+ let S = r(!1);
10
14
  t(() => {
11
- h && !y.current && (y.current = !0, v.current.length > 0 && h.getSelection().length === 0 && h.setSelection([...v.current]));
12
- }, [h]);
13
- let b = o({
14
- mode: d,
15
- extend: f,
16
- lock: m
17
- });
15
+ g && !S.current && (S.current = !0, x.current.length > 0 && g.getSelection().length === 0 && g.setSelection([...x.current]));
16
+ }, [g]);
17
+ let C = o({
18
+ mode: f,
19
+ extend: p,
20
+ lock: h,
21
+ range: _,
22
+ order: v
23
+ }), w = r(null);
18
24
  return n(() => {
19
- let t = () => _.getSelection(), n = (n) => {
20
- b.current.lock || (e("selection", "set", {
25
+ let t = () => b.getSelection(), n = (n) => {
26
+ C.current.lock || (e("selection", "set", {
21
27
  from: t().length,
22
28
  to: n.length,
23
29
  ids: n
24
- }), _.setSelection(n));
30
+ }), b.setSelection(n));
25
31
  }, r = (e) => t().filter((t) => t !== e);
26
32
  return {
27
33
  get current() {
@@ -30,36 +36,39 @@ function u(u = {}) {
30
36
  get: t,
31
37
  set: n,
32
38
  add(e) {
33
- b.current.mode === "single" ? n([e]) : t().includes(e) || n([...t(), e]);
39
+ C.current.mode === "single" ? n([e]) : t().includes(e) || n([...t(), e]);
34
40
  },
35
41
  remove(e) {
36
42
  t().includes(e) && n(r(e));
37
43
  },
38
44
  toggle(e) {
39
- t().includes(e) ? n(r(e)) : n(b.current.mode === "single" ? [e] : [...t(), e]);
45
+ t().includes(e) ? n(r(e)) : n(C.current.mode === "single" ? [e] : [...t(), e]);
40
46
  },
41
47
  clear() {
42
48
  n([]);
43
49
  },
44
50
  contains: (e) => t().includes(e),
45
51
  applyClick(e, r) {
46
- let { mode: i, extend: a } = b.current;
47
- n([...l({
48
- ids: t(),
49
- anchor: null
50
- }, e, c(r, {
52
+ let { mode: i, extend: a, range: o, order: s = u(b), lock: d } = C.current;
53
+ if (d) return;
54
+ let f = t(), p = w.current !== null && f.includes(w.current) ? w.current : f.at(-1) ?? null, m = c(r, {
51
55
  mode: i,
52
- toggle: a
53
- })).ids]);
56
+ toggle: a,
57
+ range: o
58
+ }), h = l({
59
+ ids: f,
60
+ anchor: p
61
+ }, e, m, m === "range" && s ? { order: [...s()] } : {});
62
+ w.current = h.anchor, n([...h.ids]);
54
63
  },
55
64
  adapterMethods: {
56
65
  getSelection: () => t(),
57
66
  setSelection: (e) => n(e)
58
67
  }
59
68
  };
60
- }, [_, b]);
69
+ }, [b, C]);
61
70
  }
62
71
  //#endregion
63
- export { u as useSelection };
72
+ export { d as useSelection };
64
73
 
65
74
  //# sourceMappingURL=useSelection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useSelection.js","names":["useSelection","opts","local","useState","createSelectionStore","initial","store","scene","initialRef","useRef","seeded","optsRef","useLatest","useMemo","get","set","dlog","ids","without","x","id","m","key","select","intentOf","modifiers"],"sources":["../../../src/core/selection/useSelection.ts"],"sourcesContent":["import { useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { createSelectionStore, intentOf, select, type SelectionStore as Store } from '@weasel-js/select';\nimport type { NodeId } from 'core/scene/types';\nimport { dlog } from 'debug/flag';\n\n/**\n * `SelectionApi`, `SelectionMode` and `SelectionExtendKey` are declared in\n * `@weasel-js/routing` — the `selection` dep and half the kit's actions are\n * typed in them. Re-exported here, beside the hook that returns one.\n */\nimport type { SelectionApi, SelectionMode, SelectionExtendKey } from '@weasel-js/routing';\nexport type { SelectionApi, SelectionMode, SelectionExtendKey };\n\n/** Somewhere selection can live outside this hook. `Scene` satisfies it;\n * so does any store with the same three methods. */\nexport type SelectionStore = Store<NodeId>;\n\n/** Options for {@link useSelection}. */\nexport interface UseSelectionOptions {\n /** Default `'single'`. */\n mode?: SelectionMode;\n /** Default `'shift'`. Ignored in single-mode. */\n extend?: SelectionExtendKey;\n /** Default `[]`. */\n initial?: readonly NodeId[];\n /** Keep the selection on this store rather than in the hook, so every\n * consumer of the same scene shares one selection and undo / redo can\n * restore it. `initial` then only seeds a store that has none yet.\n * Omit it and the hook owns a selection nobody else sees. */\n scene?: SelectionStore;\n /** When `true`, every mutator (`set`/`add`/`remove`/`toggle`/`clear`/\n * `applyClick`) is a no-op — selection stays at whatever `initial`\n * pinned it to. Useful for demos that exist to showcase a single\n * pre-selected node and don't want a\n * stray click to deselect. */\n lock?: boolean;\n}\n\n/**\n * Default implementation of the `getSelection` / `setSelection` adapter\n * contract every action hook (delete, duplicate, nudge, group, ...) requires.\n *\n * Owns selection state, exposes a click-policy helper (single vs multi with\n * an extend key), and pre-builds the two adapter methods consumers otherwise\n * hand-roll in every demo:\n *\n * ```tsx\n * const selection = useSelection({ mode: 'multi' });\n * const adapter = { ...arrayAdapter({...}), ...selection.adapterMethods };\n * ```\n *\n * Returns the same object for as long as `scene` is the same store, so it is\n * safe as a memo or effect dependency. The calling component re-renders when\n * the selection changes; key anything derived from the ids on\n * `selection.current`.\n */\nexport function useSelection(opts: UseSelectionOptions = {}): SelectionApi {\n const { mode = 'single', extend = 'shift', initial = [], lock = false, scene } = opts;\n // Without a `scene` the hook still keeps its ids in a store, so `get()` reads one store either\n // way and a write is visible before the re-render it causes.\n const [local] = useState(() => createSelectionStore<NodeId>([...initial]));\n const store = scene ?? local;\n const initialRef = useRef(initial);\n\n useSyncExternalStore(store.subscribe, () => store.getSelection());\n\n // A store that already holds a selection wins: the hook is joining it, not\n // resetting it. In an effect, not during render — the store has other\n // subscribers.\n const seeded = useRef(false);\n useLayoutEffect(() => {\n if (!scene || seeded.current) return;\n seeded.current = true;\n if (initialRef.current.length > 0 && scene.getSelection().length === 0) {\n scene.setSelection([...initialRef.current]);\n }\n }, [scene]);\n\n const optsRef = useLatest({ mode, extend, lock });\n\n return useMemo<SelectionApi>(() => {\n const get = (): NodeId[] => store.getSelection() as NodeId[];\n const set = (ids: NodeId[]): void => {\n if (optsRef.current.lock) return;\n dlog('selection', 'set', { from: get().length, to: ids.length, ids });\n store.setSelection(ids);\n };\n const without = (id: NodeId) => get().filter((x) => x !== id);\n return {\n get current() { return get(); },\n get,\n set,\n add(id) {\n if (optsRef.current.mode === 'single') set([id]);\n else if (!get().includes(id)) set([...get(), id]);\n },\n remove(id) {\n if (get().includes(id)) set(without(id));\n },\n toggle(id) {\n if (get().includes(id)) set(without(id));\n else set(optsRef.current.mode === 'single' ? [id] : [...get(), id]);\n },\n clear() { set([]); },\n contains: (id) => get().includes(id),\n applyClick(id, modifiers) {\n const { mode: m, extend: key } = optsRef.current;\n set([...select({ ids: get(), anchor: null }, id, intentOf(modifiers, { mode: m, toggle: key })).ids]);\n },\n adapterMethods: {\n getSelection: () => get(),\n setSelection: (ids: NodeId[]) => set(ids),\n },\n };\n }, [store, optsRef]);\n}\n"],"mappings":";;;;;AAyDA,SAAgBA,EAAa,IAA4B,CAAC,GAAiB;CACzE,IAAM,EAAE,UAAO,UAAU,YAAS,SAAS,aAAU,CAAC,GAAG,UAAO,IAAO,aAAUC,GAG3E,CAACC,KAASC,QAAeC,EAA6B,CAAC,GAAGC,CAAO,CAAC,CAAC,GACnEC,IAAQC,KAASL,GACjBM,IAAaC,EAAOJ,CAAO;CAEjC,EAAqBC,EAAM,iBAAiBA,EAAM,aAAa,CAAC;CAKhE,IAAMI,IAASD,EAAO,EAAK;CAC3B,QAAsB;EACpB,AAAKF,KAAS,GAAO,YACrB,EAAO,UAAU,IACbC,EAAW,QAAQ,SAAS,KAAKD,EAAM,aAAa,CAAC,CAAC,WAAW,KACnEA,EAAM,aAAa,CAAC,GAAGC,EAAW,OAAO,CAAC;CAE9C,GAAG,CAACD,CAAK,CAAC;CAEV,IAAMI,IAAUC,EAAU;EAAE;EAAM;EAAQ;CAAK,CAAC;CAEhD,OAAOC,QAA4B;EACjC,IAAMC,UAAsBR,EAAM,aAAa,GACzCS,KAAO,MAAwB;GACnC,AAAIJ,EAAQ,QAAQ,SACpBK,EAAK,aAAa,OAAO;IAAE,MAAMF,EAAI,CAAC,CAAC;IAAQ,IAAIG,EAAI;IAAQ;GAAI,CAAC,GACpEX,EAAM,aAAaW,CAAG;EACxB,GACMC,KAAW,MAAeJ,EAAI,CAAC,CAAC,QAAQ,MAAMK,MAAMC,CAAE;EAC5D,OAAO;GACL,IAAI,UAAU;IAAE,OAAON,EAAI;GAAG;GAC9B;GACA;GACA,IAAI,GAAI;IACN,AAAIH,EAAQ,QAAQ,SAAS,WAAUI,EAAI,CAACK,CAAE,CAAC,IACrCN,EAAI,CAAC,CAAC,SAASM,CAAE,KAAGL,EAAI,CAAC,GAAGD,EAAI,GAAGM,CAAE,CAAC;GAClD;GACA,OAAO,GAAI;IACT,AAAIN,EAAI,CAAC,CAAC,SAASM,CAAE,KAAGL,EAAIG,EAAQE,CAAE,CAAC;GACzC;GACA,OAAO,GAAI;IACT,AAAIN,EAAI,CAAC,CAAC,SAASM,CAAE,IAAGL,EAAIG,EAAQE,CAAE,CAAC,IAClCL,EAAIJ,EAAQ,QAAQ,SAAS,WAAW,CAACS,CAAE,IAAI,CAAC,GAAGN,EAAI,GAAGM,CAAE,CAAC;GACpE;GACA,QAAQ;IAAE,EAAI,CAAC,CAAC;GAAG;GACnB,WAAW,MAAON,EAAI,CAAC,CAAC,SAASM,CAAE;GACnC,WAAW,GAAI,GAAW;IACxB,IAAM,EAAE,MAAMC,GAAG,QAAQC,MAAQX,EAAQ;IACzC,EAAI,CAAC,GAAGY,EAAO;KAAE,KAAKT,EAAI;KAAG,QAAQ;IAAK,GAAGM,GAAII,EAASC,GAAW;KAAE,MAAMJ;KAAG,QAAQC;IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;GACtG;GACA,gBAAgB;IACd,oBAAoBR,EAAI;IACxB,eAAe,MAAkBC,EAAIE,CAAG;GAC1C;EACF;CACF,GAAG,CAACX,GAAOK,CAAO,CAAC;AACrB"}
1
+ {"version":3,"file":"useSelection.js","names":["paintOrderOf","store","renderOrder","useSelection","opts","local","useState","createSelectionStore","initial","scene","initialRef","useRef","seeded","optsRef","useLatest","anchorRef","useMemo","get","set","dlog","ids","without","x","id","m","key","rangeKey","walk","locked","anchor","intent","intentOf","modifiers","next","select"],"sources":["../../../src/core/selection/useSelection.ts"],"sourcesContent":["import { useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { createSelectionStore, intentOf, select, type SelectionStore as Store } from '@weasel-js/select';\nimport type { NodeId } from 'core/scene/types';\nimport { dlog } from 'debug/flag';\n\n/** Declared in `@weasel-js/routing`; re-exported here, beside the hook that returns one. */\nimport type { SelectionApi, SelectionMode, SelectionExtendKey } from '@weasel-js/routing';\nexport type { SelectionApi, SelectionMode, SelectionExtendKey };\n\n/** Somewhere selection can live outside this hook. `Scene` satisfies it;\n * so does any store with the same three methods. */\nexport type SelectionStore = Store<NodeId>;\n\n/** Options for {@link useSelection}. */\nexport interface UseSelectionOptions {\n /** Default `'single'`. */\n mode?: SelectionMode;\n /** Default `'shift'`. Ignored in single-mode. */\n extend?: SelectionExtendKey;\n /** The key that selects everything from the last pressed id to this one,\n * along `order`. Absent, nothing ranges. It beats `extend` when both name\n * one key, so give them different keys. Ignored in single-mode. */\n range?: SelectionExtendKey;\n /** The sequence a range walks: a layer panel's rows, a timeline's tracks.\n * Default is the order the `scene` paints in, back to front; with neither,\n * the range key replaces. */\n order?: () => Iterable<NodeId>;\n /** Default `[]`. */\n initial?: readonly NodeId[];\n /** Keep the selection on this store rather than in the hook, so every\n * consumer of the same scene shares one selection and undo / redo can\n * restore it. `initial` then only seeds a store that has none yet.\n * Omit it and the hook owns a selection nobody else sees. */\n scene?: SelectionStore;\n /** When `true`, every mutator (`set`/`add`/`remove`/`toggle`/`clear`/\n * `applyClick`) is a no-op — selection stays at whatever `initial`\n * pinned it to. */\n lock?: boolean;\n}\n\n/** The order a store paints its nodes in, when it is a scene and has one. */\nfunction paintOrderOf(store: SelectionStore): (() => Iterable<NodeId>) | undefined {\n const { renderOrder } = store as { renderOrder?: () => Iterable<NodeId> };\n return typeof renderOrder === 'function' ? () => renderOrder.call(store) : undefined;\n}\n\n/**\n * Owns selection state, exposes a click-policy helper (single vs multi with\n * an extend key), and pre-builds the `getSelection` / `setSelection` adapter\n * methods:\n *\n * ```tsx\n * const selection = useSelection({ mode: 'multi' });\n * const adapter = useSceneAdapter(scene, { selection: selection.adapterMethods });\n * ```\n *\n * Returns the same object for as long as `scene` is the same store, so it is\n * safe as a memo or effect dependency. The calling component re-renders when\n * the selection changes; key anything derived from the ids on\n * `selection.current`.\n */\nexport function useSelection(opts: UseSelectionOptions = {}): SelectionApi {\n const { mode = 'single', extend = 'shift', initial = [], lock = false, scene, range, order } = opts;\n // Without a `scene` the hook still keeps its ids in a store, so `get()` reads one store either\n // way and a write is visible before the re-render it causes.\n const [local] = useState(() => createSelectionStore<NodeId>([...initial]));\n const store = scene ?? local;\n const initialRef = useRef(initial);\n\n useSyncExternalStore(store.subscribe, () => store.getSelection());\n\n // A store that already holds a selection wins: the hook is joining it, not\n // resetting it. In an effect, not during render — the store has other\n // subscribers.\n const seeded = useRef(false);\n useLayoutEffect(() => {\n if (!scene || seeded.current) return;\n seeded.current = true;\n if (initialRef.current.length > 0 && scene.getSelection().length === 0) {\n scene.setSelection([...initialRef.current]);\n }\n }, [scene]);\n\n const optsRef = useLatest({ mode, extend, lock, range, order });\n const anchorRef = useRef<NodeId | null>(null);\n\n return useMemo<SelectionApi>(() => {\n const get = (): NodeId[] => store.getSelection() as NodeId[];\n const set = (ids: NodeId[]): void => {\n if (optsRef.current.lock) return;\n dlog('selection', 'set', { from: get().length, to: ids.length, ids });\n store.setSelection(ids);\n };\n const without = (id: NodeId) => get().filter((x) => x !== id);\n return {\n get current() { return get(); },\n get,\n set,\n add(id) {\n if (optsRef.current.mode === 'single') set([id]);\n else if (!get().includes(id)) set([...get(), id]);\n },\n remove(id) {\n if (get().includes(id)) set(without(id));\n },\n toggle(id) {\n if (get().includes(id)) set(without(id));\n else set(optsRef.current.mode === 'single' ? [id] : [...get(), id]);\n },\n clear() { set([]); },\n contains: (id) => get().includes(id),\n applyClick(id, modifiers) {\n const { mode: m, extend: key, range: rangeKey, order: walk = paintOrderOf(store), lock: locked } = optsRef.current;\n if (locked) return;\n const ids = get();\n // A selection something else set — a marquee, an undo — ranges from its last id.\n const anchor = anchorRef.current !== null && ids.includes(anchorRef.current)\n ? anchorRef.current\n : (ids.at(-1) ?? null);\n const intent = intentOf(modifiers, { mode: m, toggle: key, range: rangeKey });\n const next = select({ ids, anchor }, id, intent, intent === 'range' && walk ? { order: [...walk()] } : {});\n anchorRef.current = next.anchor;\n set([...next.ids]);\n },\n adapterMethods: {\n getSelection: () => get(),\n setSelection: (ids: NodeId[]) => set(ids),\n },\n };\n }, [store, optsRef]);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"shapeKinds.js","names":["SHAPE_KINDS","shapeKindsWhere","table","k","field","shapeKindInfo","kind","KIT_SHAPE_KINDS"],"sources":["../../src/core/shapeKinds.ts"],"sourcesContent":["/**\n * The kit's built-in shape kinds — one table, every other spelling derived.\n *\n * Lives in `core/` rather than beside the shape tools because both layers ask\n * questions of the same set: the interactions layer decides whether\n * `insertAction` can paint a live preview for a kind, and the canvas layer\n * decides which shape tools `useBuiltinShapeTools` mounts and what\n * `BUILTIN_TOOL_IDS` / `defaultNodeRouting` / `defaultNodeProperties` enumerate.\n *\n * This module imports nothing on purpose: `useBuiltinShapeTools` imports the\n * package barrel, so anything barrel-reachable that needs these lists at\n * module-evaluation time must not route through it.\n */\n\n/** What the kit knows about one built-in shape kind. */\nexport interface ShapeKindDescriptor {\n /** Mounted as a built-in shape tool by `useBuiltinShapeTools`, and so a\n * member of `BuiltinShapeToolId` / `KIT_SHAPE_KINDS`. `image` is false:\n * `useImageTool` needs a `src` and can't be auto-mounted. */\n readonly tool: boolean;\n /** `insertAction` emits an `insertPreview` overlay for this kind, and the\n * dispatcher overlay layer knows how to draw it. Kinds without one still\n * commit; they just have no live drag preview (`pen` and `lasso` don't\n * route through `insertAction` at all). */\n readonly insertPreview: boolean;\n}\n\n/**\n * Declaration order is the enumeration order of every derived list —\n * `KIT_SHAPE_KINDS`, and through it `defaultNodeRouting` /\n * `defaultNodeProperties` / `BUILTIN_TOOL_IDS`.\n */\nexport const SHAPE_KINDS = {\n rect: { tool: true, insertPreview: true },\n ellipse: { tool: true, insertPreview: true },\n line: { tool: true, insertPreview: true },\n polygon: { tool: true, insertPreview: true },\n star: { tool: true, insertPreview: true },\n pen: { tool: true, insertPreview: false },\n pencil: { tool: true, insertPreview: true },\n lasso: { tool: true, insertPreview: false },\n text: { tool: true, insertPreview: true },\n image: { tool: false, insertPreview: true },\n} as const satisfies Record<string, ShapeKindDescriptor>;\n\n/** Every kind in the table, tool or not. */\nexport type ShapeKind = keyof typeof SHAPE_KINDS;\n\n/** The keys of a shape-kind table whose descriptor sets `F` to `true`. */\nexport type ShapeKindsWhere<T, F extends keyof ShapeKindDescriptor> = {\n [K in keyof T]: T[K] extends Record<F, true> ? K : never;\n}[keyof T];\n\n/**\n * Built-in shape tool ids handled by `useBuiltinShapeTools`. Each maps to a\n * kit tool hook + a default `create` that produces a leaf node compatible\n * with `PATH_PAINTER`.\n */\nexport type BuiltinShapeToolId = ShapeKindsWhere<typeof SHAPE_KINDS, 'tool'>;\n\n/** The insert kinds the kit's dispatcher overlay layer knows how to render.\n * Consumer-defined kinds fall outside it: no live preview, commit unaffected. */\nexport type KitInsertShape = ShapeKindsWhere<typeof SHAPE_KINDS, 'insertPreview'>;\n\n/** Kinds in `table` whose descriptor sets `field`, in declaration order. */\nexport function shapeKindsWhere<T extends Record<string, ShapeKindDescriptor>>(\n table: T,\n field: keyof ShapeKindDescriptor,\n): (keyof T & string)[] {\n return (Object.keys(table) as (keyof T & string)[]).filter((k) => table[k][field]);\n}\n\n/** The descriptor for `kind`, or `undefined` for a kind the kit doesn't ship.\n * The one accessor: ask it rather than testing membership of a derived list. */\nexport function shapeKindInfo(kind: string): ShapeKindDescriptor | undefined {\n return (SHAPE_KINDS as Record<string, ShapeKindDescriptor>)[kind];\n}\n\n/** Runtime, iterable list of the shape-tool ids in `BuiltinShapeToolId`.\n * Surfaced so consumers (e.g. the Bundle Inspector) can enumerate the\n * builtin shape kinds without re-encoding the union. */\nexport const KIT_SHAPE_KINDS: readonly BuiltinShapeToolId[] =\n shapeKindsWhere(SHAPE_KINDS, 'tool') as BuiltinShapeToolId[];\n"],"mappings":";AAgCA,IAAaA,IAAc;CACzB,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,SAAS;EAAE,MAAM;EAAM,eAAe;CAAK;CAC3C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,SAAS;EAAE,MAAM;EAAM,eAAe;CAAK;CAC3C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,KAAK;EAAE,MAAM;EAAM,eAAe;CAAM;CACxC,QAAQ;EAAE,MAAM;EAAM,eAAe;CAAK;CAC1C,OAAO;EAAE,MAAM;EAAM,eAAe;CAAM;CAC1C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,OAAO;EAAE,MAAM;EAAO,eAAe;CAAK;AAC5C;AAsBA,SAAgBC,EACd,GACA,GACsB;CACtB,OAAQ,OAAO,KAAKC,CAAK,CAAC,CAA0B,QAAQ,MAAMA,EAAMC,EAAE,CAACC,EAAM;AACnF;AAIA,SAAgBC,EAAc,GAA+C;CAC3E,OAAQL,EAAoDM;AAC9D;AAKA,IAAaC,IACXN,EAAgBD,GAAa,MAAM"}
1
+ {"version":3,"file":"shapeKinds.js","names":["SHAPE_KINDS","shapeKindsWhere","table","k","field","shapeKindInfo","kind","KIT_SHAPE_KINDS"],"sources":["../../src/core/shapeKinds.ts"],"sourcesContent":["/**\n * The kit's built-in shape kinds — one table, every other spelling derived.\n *\n * This module imports nothing on purpose: `useBuiltinShapeTools` imports the\n * package barrel, so anything barrel-reachable that needs these lists at\n * module-evaluation time must not route through it.\n */\n\n/** What the kit knows about one built-in shape kind. */\nexport interface ShapeKindDescriptor {\n /** Mounted as a built-in shape tool by `useBuiltinShapeTools`, and so a\n * member of `BuiltinShapeToolId` / `KIT_SHAPE_KINDS`. `image` is false:\n * `useImageTool` needs a `src` and can't be auto-mounted. */\n readonly tool: boolean;\n /** `insertAction` emits an `insertPreview` overlay for this kind, and the\n * dispatcher overlay layer knows how to draw it. Kinds without one still\n * commit; they just have no live drag preview. */\n readonly insertPreview: boolean;\n}\n\n/**\n * Declaration order is the enumeration order of every derived list —\n * `KIT_SHAPE_KINDS`, and through it `defaultNodeRouting` /\n * `defaultNodeProperties` / `BUILTIN_TOOL_IDS`.\n */\nexport const SHAPE_KINDS = {\n rect: { tool: true, insertPreview: true },\n ellipse: { tool: true, insertPreview: true },\n line: { tool: true, insertPreview: true },\n polygon: { tool: true, insertPreview: true },\n star: { tool: true, insertPreview: true },\n pen: { tool: true, insertPreview: false },\n pencil: { tool: true, insertPreview: true },\n lasso: { tool: true, insertPreview: false },\n text: { tool: true, insertPreview: true },\n image: { tool: false, insertPreview: true },\n} as const satisfies Record<string, ShapeKindDescriptor>;\n\n/** Every kind in the table, tool or not. */\nexport type ShapeKind = keyof typeof SHAPE_KINDS;\n\n/** The keys of a shape-kind table whose descriptor sets `F` to `true`. */\nexport type ShapeKindsWhere<T, F extends keyof ShapeKindDescriptor> = {\n [K in keyof T]: T[K] extends Record<F, true> ? K : never;\n}[keyof T];\n\n/** Built-in shape tool ids handled by `useBuiltinShapeTools`. */\nexport type BuiltinShapeToolId = ShapeKindsWhere<typeof SHAPE_KINDS, 'tool'>;\n\n/** The insert kinds the kit's dispatcher overlay layer knows how to render.\n * Consumer-defined kinds fall outside it: no live preview, commit unaffected. */\nexport type KitInsertShape = ShapeKindsWhere<typeof SHAPE_KINDS, 'insertPreview'>;\n\n/** Kinds in `table` whose descriptor sets `field`, in declaration order. */\nexport function shapeKindsWhere<T extends Record<string, ShapeKindDescriptor>>(\n table: T,\n field: keyof ShapeKindDescriptor,\n): (keyof T & string)[] {\n return (Object.keys(table) as (keyof T & string)[]).filter((k) => table[k][field]);\n}\n\n/** The descriptor for `kind`, or `undefined` for a kind the kit doesn't ship.\n * The one accessor: ask it rather than testing membership of a derived list. */\nexport function shapeKindInfo(kind: string): ShapeKindDescriptor | undefined {\n return (SHAPE_KINDS as Record<string, ShapeKindDescriptor>)[kind];\n}\n\n/** Runtime, iterable list of the shape-tool ids in `BuiltinShapeToolId`. */\nexport const KIT_SHAPE_KINDS: readonly BuiltinShapeToolId[] =\n shapeKindsWhere(SHAPE_KINDS, 'tool') as BuiltinShapeToolId[];\n"],"mappings":";AAyBA,IAAaA,IAAc;CACzB,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,SAAS;EAAE,MAAM;EAAM,eAAe;CAAK;CAC3C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,SAAS;EAAE,MAAM;EAAM,eAAe;CAAK;CAC3C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,KAAK;EAAE,MAAM;EAAM,eAAe;CAAM;CACxC,QAAQ;EAAE,MAAM;EAAM,eAAe;CAAK;CAC1C,OAAO;EAAE,MAAM;EAAM,eAAe;CAAM;CAC1C,MAAM;EAAE,MAAM;EAAM,eAAe;CAAK;CACxC,OAAO;EAAE,MAAM;EAAO,eAAe;CAAK;AAC5C;AAkBA,SAAgBC,EACd,GACA,GACsB;CACtB,OAAQ,OAAO,KAAKC,CAAK,CAAC,CAA0B,QAAQ,MAAMA,EAAMC,EAAE,CAACC,EAAM;AACnF;AAIA,SAAgBC,EAAc,GAA+C;CAC3E,OAAQL,EAAoDM;AAC9D;AAGA,IAAaC,IACXN,EAAgBD,GAAa,MAAM"}
@@ -1 +1 @@
1
- {"version":3,"file":"stylus.js","names":["pressureToWidth","minWidth","options","maxWidth","gamma","shaped","pressure","getStylusData","ext","pointerType","forEachCoalesced","get","event","sub","list","e","screenX","screenY","ctx","worldX","worldY","clientToWorld"],"sources":["../../../src/core/stylus/stylus.ts"],"sourcesContent":["import { clientToWorld } from 'core/viewport/clientToWorld';\n/**\n * Stylus / Pencil pointer-event helpers.\n *\n * Most stylus information (pressure, tilt, altitude/azimuth) is already on\n * the standard `PointerEvent`. These helpers normalize the surface across\n * browsers, fill in sensible defaults for non-stylus inputs, and provide\n * a coalesced-event iterator so tools can opt into high-frequency samples\n * (Apple Pencil reports up to ~240Hz; most browsers coalesce those samples\n * into per-frame `pointermove` events whose intermediate states are only\n * accessible via `getCoalescedEvents()`).\n *\n * Apple-specific note: `pointerType: 'pen'` covers Apple Pencil on iPad\n * Safari. The barrel-double-tap (Pencil 2) and barrel-squeeze (Pencil\n * Pro) gestures are NOT exposed to web pages — they remain\n * UIKit-only via `UIPencilInteraction`.\n */\n\n/** Normalized snapshot of stylus state at a single pointer sample. */\nexport interface StylusData {\n /** 0..1. Mouse and ordinary touch report 0 when no button is held and 0.5\n * while a button is held (per the Pointer Events spec). Stylus inputs\n * report a true pressure curve. */\n pressure: number;\n /** Tilt of the pen in degrees from the surface normal, projected onto the\n * X axis. Range ±90. Zero for mouse/touch. */\n tiltX: number;\n /** Tilt projected onto the Y axis. Range ±90. Zero for mouse/touch. */\n tiltY: number;\n /** Newer (Pointer Events level 3) angle in radians between the surface\n * and the pen barrel. π/2 = perpendicular to the surface. Undefined on\n * browsers that haven't shipped the field yet. */\n altitudeAngle: number | undefined;\n /** Newer angle in radians around the Z axis. Undefined on browsers\n * without level-3 support. */\n azimuthAngle: number | undefined;\n /** Rotation of the pen barrel in degrees. Apple Pencil Pro reports this\n * natively but Safari does NOT yet surface it via PointerEvent.twist —\n * expect 0 there. Some Wacom stylus drivers do report it. */\n twist: number;\n /** Raw pointerType from the event ('mouse' | 'pen' | 'touch' | ''). */\n pointerType: string;\n /** Convenience: `pointerType === 'pen'`. */\n isStylus: boolean;\n}\n\n/** Options for `pressureToWidth`. */\nexport interface PressureToWidthOptions {\n /** Width returned at pressure 0. Default 0.5. */\n minWidth?: number;\n /** Width returned at pressure 1. Default 6. */\n maxWidth?: number;\n /** Response curve exponent applied to pressure before lerping\n * (`p ** gamma`). 1 = linear; >1 emphasizes light touches (sharper\n * thin → thick transition); <1 emphasizes heavy touches. Default 1.6,\n * a small bias toward heavy strokes that matches typical pencil feel\n * without crushing the dynamic range. */\n gamma?: number;\n}\n\n/**\n * Map a 0..1 pressure value to a stroke width.\n *\n * `width(p) = minWidth + (maxWidth - minWidth) × p^gamma`\n *\n * Mouse / non-stylus inputs report `pressure === 0` (no button) or `0.5`\n * (button held); callers that don't want uniform 0.5-pressure widths on\n * mouse input should gate on `pointerType === 'pen'` upstream and feed a\n * constant width on the non-stylus path.\n */\nexport function pressureToWidth(\n pressure: number,\n options: PressureToWidthOptions = {},\n): number {\n const minWidth = options.minWidth ?? 0.5;\n const maxWidth = options.maxWidth ?? 6;\n const gamma = options.gamma ?? 1.6;\n const p = Math.max(0, Math.min(1, pressure));\n const shaped = p ** gamma;\n return minWidth + (maxWidth - minWidth) * shaped;\n}\n\n/** Extract a normalized stylus snapshot from any PointerEvent. Pure. */\nexport function getStylusData(e: PointerEvent): StylusData {\n // `altitudeAngle` / `azimuthAngle` are Pointer Events level 3 — only\n // present in newer browsers. Read defensively so the helper degrades\n // gracefully on older runtimes.\n const ext = e as PointerEvent & {\n altitudeAngle?: number;\n azimuthAngle?: number;\n };\n const pointerType = e.pointerType ?? '';\n return {\n pressure: e.pressure,\n tiltX: e.tiltX ?? 0,\n tiltY: e.tiltY ?? 0,\n altitudeAngle: typeof ext.altitudeAngle === 'number' ? ext.altitudeAngle : undefined,\n azimuthAngle: typeof ext.azimuthAngle === 'number' ? ext.azimuthAngle : undefined,\n twist: e.twist ?? 0,\n pointerType,\n isStylus: pointerType === 'pen',\n };\n}\n\n/** One enriched sample, ready for tools that want world coords + stylus\n * data at every coalesced sub-frame. */\nexport interface PointerSample {\n /** Client coords (relative to viewport). */\n clientX: number;\n clientY: number;\n /** Canvas-relative CSS pixels. */\n screenX: number;\n screenY: number;\n /** World coords, derived from `screenX/Y` via the supplied view. */\n worldX: number;\n worldY: number;\n /** Stylus snapshot for this sample. */\n stylus: StylusData;\n /** Original event (may be the parent move or a coalesced sub-event). */\n event: PointerEvent;\n}\n\n/** Context for `forEachCoalesced` — the kit's `ToolCtx` satisfies this. */\nexport interface CoalescedCtx {\n canvasRect: { left: number; top: number };\n view: { x: number; y: number; scale: { x: number; y: number } };\n}\n\n/**\n * Iterate coalesced sub-events of a `pointermove`, yielding a\n * `PointerSample` per sub-event with world coords already derived.\n *\n * Browsers that batch high-frequency samples (Apple Pencil, drawing\n * tablets) expose them through `event.getCoalescedEvents()`. Pen / pencil\n * tools should iterate them for smooth strokes; mouse tools usually only\n * need the parent event and can ignore this.\n *\n * Fallback: when `getCoalescedEvents` is unavailable or returns an empty\n * list, the parent event itself is yielded once so callers don't drop\n * samples on older browsers.\n */\nexport function forEachCoalesced(\n event: PointerEvent,\n ctx: CoalescedCtx,\n cb: (sample: PointerSample) => void,\n): void {\n // Cast through unknown — older lib.dom.d.ts in some toolchains omits the\n // method even though every modern engine ships it.\n const get = (event as unknown as { getCoalescedEvents?: () => PointerEvent[] })\n .getCoalescedEvents;\n const sub = typeof get === 'function' ? get.call(event) : [];\n const list = sub.length > 0 ? sub : [event];\n for (const e of list) {\n const [screenX, screenY] = [e.clientX - ctx.canvasRect.left, e.clientY - ctx.canvasRect.top];\n const [worldX, worldY] = clientToWorld(e.clientX, e.clientY, ctx.canvasRect, ctx.view);\n cb({\n clientX: e.clientX,\n clientY: e.clientY,\n screenX,\n screenY,\n worldX,\n worldY,\n stylus: getStylusData(e),\n event: e,\n });\n }\n}\n"],"mappings":";;AAsEA,SAAgBA,EACd,GACA,IAAkC,CAAC,GAC3B;CACR,IAAMC,IAAWC,EAAQ,YAAY,IAC/BC,IAAWD,EAAQ,YAAY,GAC/BE,IAAQF,EAAQ,SAAS,KAEzBG,IADI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGC,CAAQ,CAC3B,KAAKF;CACpB,OAAOH,KAAYE,IAAWF,KAAYI;AAC5C;AAGA,SAAgBE,EAAc,GAA6B;CAIzD,IAAMC,IAAM,GAINC,IAAc,EAAE,eAAe;CACrC,OAAO;EACL,UAAU,EAAE;EACZ,OAAO,EAAE,SAAS;EAClB,OAAO,EAAE,SAAS;EAClB,eAAe,OAAOD,EAAI,iBAAkB,WAAWA,EAAI,gBAAgB,KAAA;EAC3E,cAAc,OAAOA,EAAI,gBAAiB,WAAWA,EAAI,eAAe,KAAA;EACxE,OAAO,EAAE,SAAS;EAClB;EACA,UAAUC,MAAgB;CAC5B;AACF;AAuCA,SAAgBC,EACd,GACA,GACA,GACM;CAGN,IAAMC,IAAOC,EACV,oBACGC,IAAM,OAAOF,KAAQ,aAAaA,EAAI,KAAKC,CAAK,IAAI,CAAC,GACrDE,IAAOD,EAAI,SAAS,IAAIA,IAAM,CAACD,CAAK;CAC1C,KAAK,IAAMG,KAAKD,GAAM;EACpB,IAAM,CAACE,GAASC,KAAW,CAACF,EAAE,UAAUG,EAAI,WAAW,MAAMH,EAAE,UAAUG,EAAI,WAAW,GAAG,GACrF,CAACC,GAAQC,KAAUC,EAAcN,EAAE,SAASA,EAAE,SAASG,EAAI,YAAYA,EAAI,IAAI;EACrF,EAAG;GACD,SAASH,EAAE;GACX,SAASA,EAAE;GACX;GACA;GACA;GACA;GACA,QAAQR,EAAcQ,CAAC;GACvB,OAAOA;EACT,CAAC;CACH;AACF"}
1
+ {"version":3,"file":"stylus.js","names":["pressureToWidth","minWidth","options","maxWidth","gamma","shaped","pressure","getStylusData","ext","pointerType","forEachCoalesced","get","event","sub","list","e","screenX","screenY","ctx","worldX","worldY","clientToWorld"],"sources":["../../../src/core/stylus/stylus.ts"],"sourcesContent":["import { clientToWorld } from 'core/viewport/clientToWorld';\n/**\n * Stylus / Pencil pointer-event helpers.\n *\n * These normalize the standard `PointerEvent` stylus fields across browsers,\n * fill in defaults for non-stylus inputs, and provide a coalesced-event\n * iterator for high-frequency samples.\n *\n * `pointerType: 'pen'` covers Apple Pencil on iPad Safari. The\n * barrel-double-tap (Pencil 2) and barrel-squeeze (Pencil Pro) gestures are\n * NOT exposed to web pages.\n */\n\n/** Normalized snapshot of stylus state at a single pointer sample. */\nexport interface StylusData {\n /** 0..1. Mouse and ordinary touch report 0 when no button is held and 0.5\n * while a button is held (per the Pointer Events spec). Stylus inputs\n * report a true pressure curve. */\n pressure: number;\n /** Tilt of the pen in degrees from the surface normal, projected onto the\n * X axis. Range ±90. Zero for mouse/touch. */\n tiltX: number;\n /** Tilt projected onto the Y axis. Range ±90. Zero for mouse/touch. */\n tiltY: number;\n /** Newer (Pointer Events level 3) angle in radians between the surface\n * and the pen barrel. π/2 = perpendicular to the surface. Undefined on\n * browsers that haven't shipped the field yet. */\n altitudeAngle: number | undefined;\n /** Newer angle in radians around the Z axis. Undefined on browsers\n * without level-3 support. */\n azimuthAngle: number | undefined;\n /** Rotation of the pen barrel in degrees. Apple Pencil Pro reports this\n * natively but Safari does NOT yet surface it via PointerEvent.twist —\n * expect 0 there. Some Wacom stylus drivers do report it. */\n twist: number;\n /** Raw pointerType from the event ('mouse' | 'pen' | 'touch' | ''). */\n pointerType: string;\n /** Convenience: `pointerType === 'pen'`. */\n isStylus: boolean;\n}\n\n/** Options for `pressureToWidth`. */\nexport interface PressureToWidthOptions {\n /** Width returned at pressure 0. Default 0.5. */\n minWidth?: number;\n /** Width returned at pressure 1. Default 6. */\n maxWidth?: number;\n /** Response curve exponent applied to pressure before lerping\n * (`p ** gamma`). 1 = linear. Default 1.6. */\n gamma?: number;\n}\n\n/**\n * Map a 0..1 pressure value to a stroke width.\n *\n * `width(p) = minWidth + (maxWidth - minWidth) × p^gamma`\n *\n * Mouse / non-stylus inputs report `pressure === 0` (no button) or `0.5`\n * (button held); gate on `pointerType === 'pen'` upstream to give them a\n * constant width instead.\n */\nexport function pressureToWidth(\n pressure: number,\n options: PressureToWidthOptions = {},\n): number {\n const minWidth = options.minWidth ?? 0.5;\n const maxWidth = options.maxWidth ?? 6;\n const gamma = options.gamma ?? 1.6;\n const p = Math.max(0, Math.min(1, pressure));\n const shaped = p ** gamma;\n return minWidth + (maxWidth - minWidth) * shaped;\n}\n\n/** Extract a normalized stylus snapshot from any PointerEvent. Pure. */\nexport function getStylusData(e: PointerEvent): StylusData {\n const ext = e as PointerEvent & {\n altitudeAngle?: number;\n azimuthAngle?: number;\n };\n const pointerType = e.pointerType ?? '';\n return {\n pressure: e.pressure,\n tiltX: e.tiltX ?? 0,\n tiltY: e.tiltY ?? 0,\n altitudeAngle: typeof ext.altitudeAngle === 'number' ? ext.altitudeAngle : undefined,\n azimuthAngle: typeof ext.azimuthAngle === 'number' ? ext.azimuthAngle : undefined,\n twist: e.twist ?? 0,\n pointerType,\n isStylus: pointerType === 'pen',\n };\n}\n\n/** One enriched sample, ready for tools that want world coords + stylus\n * data at every coalesced sub-frame. */\nexport interface PointerSample {\n /** Client coords (relative to viewport). */\n clientX: number;\n clientY: number;\n /** Canvas-relative CSS pixels. */\n screenX: number;\n screenY: number;\n /** World coords, derived from `screenX/Y` via the supplied view. */\n worldX: number;\n worldY: number;\n /** Stylus snapshot for this sample. */\n stylus: StylusData;\n /** Original event (may be the parent move or a coalesced sub-event). */\n event: PointerEvent;\n}\n\n/** Context for `forEachCoalesced`: the canvas's client rect and its view. */\nexport interface CoalescedCtx {\n canvasRect: { left: number; top: number };\n view: { x: number; y: number; scale: { x: number; y: number } };\n}\n\n/**\n * Iterate coalesced sub-events of a `pointermove`, yielding a\n * `PointerSample` per sub-event with world coords already derived. When\n * `getCoalescedEvents` is unavailable or returns an empty list, the parent\n * event itself is yielded once.\n */\nexport function forEachCoalesced(\n event: PointerEvent,\n ctx: CoalescedCtx,\n cb: (sample: PointerSample) => void,\n): void {\n // Cast through unknown — older lib.dom.d.ts in some toolchains omits the\n // method even though every modern engine ships it.\n const get = (event as unknown as { getCoalescedEvents?: () => PointerEvent[] })\n .getCoalescedEvents;\n const sub = typeof get === 'function' ? get.call(event) : [];\n const list = sub.length > 0 ? sub : [event];\n for (const e of list) {\n const [screenX, screenY] = [e.clientX - ctx.canvasRect.left, e.clientY - ctx.canvasRect.top];\n const [worldX, worldY] = clientToWorld(e.clientX, e.clientY, ctx.canvasRect, ctx.view);\n cb({\n clientX: e.clientX,\n clientY: e.clientY,\n screenX,\n screenY,\n worldX,\n worldY,\n stylus: getStylusData(e),\n event: e,\n });\n }\n}\n"],"mappings":";;AA6DA,SAAgBA,EACd,GACA,IAAkC,CAAC,GAC3B;CACR,IAAMC,IAAWC,EAAQ,YAAY,IAC/BC,IAAWD,EAAQ,YAAY,GAC/BE,IAAQF,EAAQ,SAAS,KAEzBG,IADI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGC,CAAQ,CAC3B,KAAKF;CACpB,OAAOH,KAAYE,IAAWF,KAAYI;AAC5C;AAGA,SAAgBE,EAAc,GAA6B;CACzD,IAAMC,IAAM,GAINC,IAAc,EAAE,eAAe;CACrC,OAAO;EACL,UAAU,EAAE;EACZ,OAAO,EAAE,SAAS;EAClB,OAAO,EAAE,SAAS;EAClB,eAAe,OAAOD,EAAI,iBAAkB,WAAWA,EAAI,gBAAgB,KAAA;EAC3E,cAAc,OAAOA,EAAI,gBAAiB,WAAWA,EAAI,eAAe,KAAA;EACxE,OAAO,EAAE,SAAS;EAClB;EACA,UAAUC,MAAgB;CAC5B;AACF;AAgCA,SAAgBC,EACd,GACA,GACA,GACM;CAGN,IAAMC,IAAOC,EACV,oBACGC,IAAM,OAAOF,KAAQ,aAAaA,EAAI,KAAKC,CAAK,IAAI,CAAC,GACrDE,IAAOD,EAAI,SAAS,IAAIA,IAAM,CAACD,CAAK;CAC1C,KAAK,IAAMG,KAAKD,GAAM;EACpB,IAAM,CAACE,GAASC,KAAW,CAACF,EAAE,UAAUG,EAAI,WAAW,MAAMH,EAAE,UAAUG,EAAI,WAAW,GAAG,GACrF,CAACC,GAAQC,KAAUC,EAAcN,EAAE,SAASA,EAAE,SAASG,EAAI,YAAYA,EAAI,IAAI;EACrF,EAAG;GACD,SAASH,EAAE;GACX,SAASA,EAAE;GACX;GACA;GACA;GACA;GACA,QAAQR,EAAcQ,CAAC;GACvB,OAAOA;EACT,CAAC;CACH;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"usePointerStylus.js","names":["IDLE","usePointerStylus","options","state","setState","useState","lastCommit","useRef","optsRef","useLatest","useEffect","el","target","onMove","e","raw","stylusOnly","now","minGap","maxFps","getStylusData","prev","onEnter","onLeave"],"sources":["../../../src/core/stylus/usePointerStylus.ts"],"sourcesContent":["import { useEffect, useRef, useState, type RefObject } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { getStylusData, type StylusData } from './stylus';\n\n/** State exposed by `usePointerStylus` — the most recent stylus snapshot\n * plus a `hovering` flag for the Pencil 2 / Pencil Pro \"near-surface but\n * not touching\" event stream. */\nexport interface PointerStylusState extends StylusData {\n /** True between `pointerenter` and `pointerleave` events on the target\n * element. iPad Safari fires these for Apple Pencil hover (on iPad Pro\n * / Pencil Pro), so this lights up when the pen is detected near the\n * glass without contact. */\n hovering: boolean;\n}\n\nconst IDLE: PointerStylusState = {\n pressure: 0,\n tiltX: 0,\n tiltY: 0,\n altitudeAngle: undefined,\n azimuthAngle: undefined,\n twist: 0,\n pointerType: '',\n isStylus: false,\n hovering: false,\n};\n\n/** Options for `usePointerStylus`. */\nexport interface UsePointerStylusOptions {\n /** Throttle re-renders to ≈this many state updates per second. The latest\n * sample is always kept; intermediates are dropped. Default 60. Set to\n * `Infinity` (or 0) to emit every move. */\n maxFps?: number;\n /** When true, only emit updates while `pointerType === 'pen'`. Useful\n * for stylus-only UI that should freeze when the user reaches for a\n * mouse. Default false. */\n stylusOnly?: boolean;\n}\n\n/**\n * Subscribe to pointer events on a target element (defaults to `window`)\n * and expose the most recent stylus snapshot.\n *\n * Reads pointer data via `pointermove` (button or no button) and tracks\n * `pointerenter` / `pointerleave` for the `hovering` flag. The hook does\n * NOT consume pointerdown / pointerup — leave gesture handling to the\n * Tool dispatcher.\n *\n * Re-renders are throttled by default to avoid storming the React scheduler\n * with 120–240Hz stylus updates. Consumers that need every sample (e.g.\n * recording for replay) should pass `maxFps: Infinity` and accept the\n * cost, or read a ref-backed snapshot in a `useFrame`-style loop instead.\n */\nexport function usePointerStylus(\n target?: RefObject<HTMLElement | null> | HTMLElement | null,\n options: UsePointerStylusOptions = {},\n): PointerStylusState {\n const { maxFps = 60, stylusOnly = false } = options;\n const [state, setState] = useState<PointerStylusState>(IDLE);\n // Track the last commit time to throttle. A ref avoids re-creating the\n // listener every render and avoids stale-closure read of an outer `let`.\n const lastCommit = useRef(-Infinity);\n const optsRef = useLatest({ maxFps, stylusOnly });\n\n useEffect(() => {\n const el: EventTarget =\n target == null\n ? window\n : target instanceof HTMLElement\n ? target\n : target.current ?? window;\n\n const onMove = (raw: Event) => {\n const e = raw as PointerEvent;\n const { maxFps, stylusOnly } = optsRef.current;\n if (stylusOnly && e.pointerType !== 'pen') return;\n const now = performance.now();\n const minGap = maxFps > 0 && Number.isFinite(maxFps) ? 1000 / maxFps : 0;\n if (minGap > 0 && now - lastCommit.current < minGap) return;\n lastCommit.current = now;\n setState((prev) => ({ ...getStylusData(e), hovering: prev.hovering }));\n };\n const onEnter = (raw: Event) => {\n const e = raw as PointerEvent;\n if (optsRef.current.stylusOnly && e.pointerType !== 'pen') return;\n setState((prev) => ({ ...prev, hovering: true }));\n };\n const onLeave = (raw: Event) => {\n const e = raw as PointerEvent;\n if (optsRef.current.stylusOnly && e.pointerType !== 'pen') return;\n setState((prev) => ({ ...prev, hovering: false }));\n };\n\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerenter', onEnter);\n el.addEventListener('pointerleave', onLeave);\n return () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerenter', onEnter);\n el.removeEventListener('pointerleave', onLeave);\n };\n }, [target, optsRef]);\n\n return state;\n}\n"],"mappings":";;;;AAeA,IAAMA,IAA2B;CAC/B,UAAU;CACV,OAAO;CACP,OAAO;CACP,eAAe,KAAA;CACf,cAAc,KAAA;CACd,OAAO;CACP,aAAa;CACb,UAAU;CACV,UAAU;AACZ;AA4BA,SAAgBC,EACd,GACA,IAAmC,CAAC,GAChB;CACpB,IAAM,EAAE,YAAS,IAAI,gBAAa,OAAUC,GACtC,CAACC,GAAOC,KAAYC,EAA6BL,CAAI,GAGrDM,IAAaC,EAAO,SAAS,GAC7BC,IAAUC,EAAU;EAAE;EAAQ;CAAW,CAAC;CAyChD,OAvCAC,QAAgB;EACd,IAAMC,IACJC,KAAU,OACN,SACAA,aAAkB,cAChBA,IACAA,EAAO,WAAW,QAEpBC,KAAU,MAAe;GAC7B,IAAMC,IAAIC,GACJ,EAAE,WAAQ,kBAAeP,EAAQ;GACvC,IAAIQ,KAAcF,EAAE,gBAAgB,OAAO;GAC3C,IAAMG,IAAM,YAAY,IAAI,GACtBC,IAASC,IAAS,KAAK,OAAO,SAASA,CAAM,IAAI,MAAOA,IAAS;GACvE,AAAID,IAAS,KAAKD,IAAMX,EAAW,UAAUY,MAC7C,EAAW,UAAUD,GACrBb,GAAU,OAAU;IAAE,GAAGgB,EAAcN,CAAC;IAAG,UAAUO,EAAK;GAAS,EAAE;EACvE,GACMC,KAAW,MAAe;GAC9B,IAAMR,IAAIC;GACV,AAAIP,EAAQ,QAAQ,cAAcM,EAAE,gBAAgB,SACpDV,GAAU,OAAU;IAAE,GAAGiB;IAAM,UAAU;GAAK,EAAE;EAClD,GACME,KAAW,MAAe;GAC9B,IAAMT,IAAIC;GACV,AAAIP,EAAQ,QAAQ,cAAcM,EAAE,gBAAgB,SACpDV,GAAU,OAAU;IAAE,GAAGiB;IAAM,UAAU;GAAM,EAAE;EACnD;EAKA,OAHAV,EAAG,iBAAiB,eAAeE,CAAM,GACzCF,EAAG,iBAAiB,gBAAgBW,CAAO,GAC3CX,EAAG,iBAAiB,gBAAgBY,CAAO,SAC9B;GAGX,AAFAZ,EAAG,oBAAoB,eAAeE,CAAM,GAC5CF,EAAG,oBAAoB,gBAAgBW,CAAO,GAC9CX,EAAG,oBAAoB,gBAAgBY,CAAO;EAChD;CACF,GAAG,CAACX,GAAQJ,CAAO,CAAC,GAEbL;AACT"}
1
+ {"version":3,"file":"usePointerStylus.js","names":["IDLE","usePointerStylus","options","state","setState","useState","lastCommit","useRef","optsRef","useLatest","useEffect","el","target","onMove","e","raw","stylusOnly","now","minGap","maxFps","getStylusData","prev","onEnter","onLeave"],"sources":["../../../src/core/stylus/usePointerStylus.ts"],"sourcesContent":["import { useEffect, useRef, useState, type RefObject } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { getStylusData, type StylusData } from './stylus';\n\n/** State exposed by `usePointerStylus` — the most recent stylus snapshot\n * plus a `hovering` flag. */\nexport interface PointerStylusState extends StylusData {\n /** True between `pointerenter` and `pointerleave` events on the target\n * element. iPad Safari fires these for Apple Pencil hover, so this is\n * true while the pen is near the glass without contact. */\n hovering: boolean;\n}\n\nconst IDLE: PointerStylusState = {\n pressure: 0,\n tiltX: 0,\n tiltY: 0,\n altitudeAngle: undefined,\n azimuthAngle: undefined,\n twist: 0,\n pointerType: '',\n isStylus: false,\n hovering: false,\n};\n\n/** Options for `usePointerStylus`. */\nexport interface UsePointerStylusOptions {\n /** Throttle re-renders to ≈this many state updates per second. The latest\n * sample is always kept; intermediates are dropped. Default 60. Set to\n * `Infinity` (or 0) to emit every move. */\n maxFps?: number;\n /** When true, only emit updates while `pointerType === 'pen'`. Default\n * false. */\n stylusOnly?: boolean;\n}\n\n/**\n * Subscribe to pointer events on a target element (defaults to `window`)\n * and expose the most recent stylus snapshot.\n *\n * The hook does NOT consume pointerdown / pointerup — leave gesture handling\n * to the dispatcher. Re-renders are throttled by default (`maxFps`); pass\n * `maxFps: Infinity` to get every sample.\n */\nexport function usePointerStylus(\n target?: RefObject<HTMLElement | null> | HTMLElement | null,\n options: UsePointerStylusOptions = {},\n): PointerStylusState {\n const { maxFps = 60, stylusOnly = false } = options;\n const [state, setState] = useState<PointerStylusState>(IDLE);\n // Track the last commit time to throttle. A ref avoids re-creating the\n // listener every render and avoids stale-closure read of an outer `let`.\n const lastCommit = useRef(-Infinity);\n const optsRef = useLatest({ maxFps, stylusOnly });\n\n useEffect(() => {\n const el: EventTarget =\n target == null\n ? window\n : target instanceof HTMLElement\n ? target\n : target.current ?? window;\n\n const onMove = (raw: Event) => {\n const e = raw as PointerEvent;\n const { maxFps, stylusOnly } = optsRef.current;\n if (stylusOnly && e.pointerType !== 'pen') return;\n const now = performance.now();\n const minGap = maxFps > 0 && Number.isFinite(maxFps) ? 1000 / maxFps : 0;\n if (minGap > 0 && now - lastCommit.current < minGap) return;\n lastCommit.current = now;\n setState((prev) => ({ ...getStylusData(e), hovering: prev.hovering }));\n };\n const onEnter = (raw: Event) => {\n const e = raw as PointerEvent;\n if (optsRef.current.stylusOnly && e.pointerType !== 'pen') return;\n setState((prev) => ({ ...prev, hovering: true }));\n };\n const onLeave = (raw: Event) => {\n const e = raw as PointerEvent;\n if (optsRef.current.stylusOnly && e.pointerType !== 'pen') return;\n setState((prev) => ({ ...prev, hovering: false }));\n };\n\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerenter', onEnter);\n el.addEventListener('pointerleave', onLeave);\n return () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerenter', onEnter);\n el.removeEventListener('pointerleave', onLeave);\n };\n }, [target, optsRef]);\n\n return state;\n}\n"],"mappings":";;;;AAaA,IAAMA,IAA2B;CAC/B,UAAU;CACV,OAAO;CACP,OAAO;CACP,eAAe,KAAA;CACf,cAAc,KAAA;CACd,OAAO;CACP,aAAa;CACb,UAAU;CACV,UAAU;AACZ;AAqBA,SAAgBC,EACd,GACA,IAAmC,CAAC,GAChB;CACpB,IAAM,EAAE,YAAS,IAAI,gBAAa,OAAUC,GACtC,CAACC,GAAOC,KAAYC,EAA6BL,CAAI,GAGrDM,IAAaC,EAAO,SAAS,GAC7BC,IAAUC,EAAU;EAAE;EAAQ;CAAW,CAAC;CAyChD,OAvCAC,QAAgB;EACd,IAAMC,IACJC,KAAU,OACN,SACAA,aAAkB,cAChBA,IACAA,EAAO,WAAW,QAEpBC,KAAU,MAAe;GAC7B,IAAMC,IAAIC,GACJ,EAAE,WAAQ,kBAAeP,EAAQ;GACvC,IAAIQ,KAAcF,EAAE,gBAAgB,OAAO;GAC3C,IAAMG,IAAM,YAAY,IAAI,GACtBC,IAASC,IAAS,KAAK,OAAO,SAASA,CAAM,IAAI,MAAOA,IAAS;GACvE,AAAID,IAAS,KAAKD,IAAMX,EAAW,UAAUY,MAC7C,EAAW,UAAUD,GACrBb,GAAU,OAAU;IAAE,GAAGgB,EAAcN,CAAC;IAAG,UAAUO,EAAK;GAAS,EAAE;EACvE,GACMC,KAAW,MAAe;GAC9B,IAAMR,IAAIC;GACV,AAAIP,EAAQ,QAAQ,cAAcM,EAAE,gBAAgB,SACpDV,GAAU,OAAU;IAAE,GAAGiB;IAAM,UAAU;GAAK,EAAE;EAClD,GACME,KAAW,MAAe;GAC9B,IAAMT,IAAIC;GACV,AAAIP,EAAQ,QAAQ,cAAcM,EAAE,gBAAgB,SACpDV,GAAU,OAAU;IAAE,GAAGiB;IAAM,UAAU;GAAM,EAAE;EACnD;EAKA,OAHAV,EAAG,iBAAiB,eAAeE,CAAM,GACzCF,EAAG,iBAAiB,gBAAgBW,CAAO,GAC3CX,EAAG,iBAAiB,gBAAgBY,CAAO,SAC9B;GAGX,AAFAZ,EAAG,oBAAoB,eAAeE,CAAM,GAC5CF,EAAG,oBAAoB,gBAAgBW,CAAO,GAC9CX,EAAG,oBAAoB,gBAAgBY,CAAO;EAChD;CACF,GAAG,CAACX,GAAQJ,CAAO,CAAC,GAEbL;AACT"}
@@ -1,4 +1,4 @@
1
- import { getPaintKind as e, listGradientKinds as t, listPaintKinds as n, paintKindRegistry as r } from "./paintKinds.js";
1
+ import { getPaintKind as e, listGradientKinds as t, listPaintKinds as n, paintKindRegistry as r } from "./paint/paintKinds.js";
2
2
  import { useCallback as i, useSyncExternalStore as a } from "react";
3
3
  //#region src/core/usePaintKinds.ts
4
4
  function o() {
@@ -1 +1 @@
1
- {"version":3,"file":"usePaintKinds.js","names":["usePaintKinds","useSyncExternalStore","paintKindRegistry","listPaintKinds","useGradientKinds","listGradientKinds","usePaintKind","read","useCallback","getPaintKind","kind"],"sources":["../../src/core/usePaintKinds.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react';\nimport {\n getPaintKind, listGradientKinds, listPaintKinds, paintKindRegistry, type PaintKindEntry,\n} from './paintKinds';\n\n/** Every registered paint kind, as {@link listPaintKinds} returns it,\n * re-rendering the caller whenever a kind is registered or removed. */\nexport function usePaintKinds(): readonly PaintKindEntry[] {\n return useSyncExternalStore(paintKindRegistry.subscribe, listPaintKinds, listPaintKinds);\n}\n\n/** Every registered gradient kind, as {@link listGradientKinds} returns it,\n * re-rendering the caller whenever a kind is registered or removed. */\nexport function useGradientKinds(): readonly PaintKindEntry[] {\n return useSyncExternalStore(paintKindRegistry.subscribe, listGradientKinds, listGradientKinds);\n}\n\n/**\n * The entry for `kind`, as {@link getPaintKind} returns it — `undefined` until\n * it is registered, and the new entry once it is. A kind with a loader starts\n * loading on the first read.\n */\nexport function usePaintKind(kind: string | undefined): PaintKindEntry | undefined {\n const read = useCallback(() => getPaintKind(kind), [kind]);\n return useSyncExternalStore(paintKindRegistry.subscribe, read, read);\n}\n"],"mappings":";;;AAOA,SAAgBA,IAA2C;CACzD,OAAOC,EAAqBC,EAAkB,WAAWC,GAAgBA,CAAc;AACzF;AAIA,SAAgBC,IAA8C;CAC5D,OAAOH,EAAqBC,EAAkB,WAAWG,GAAmBA,CAAiB;AAC/F;AAOA,SAAgBC,EAAa,GAAsD;CACjF,IAAMC,IAAOC,QAAkBC,EAAaC,CAAI,GAAG,CAACA,CAAI,CAAC;CACzD,OAAOT,EAAqBC,EAAkB,WAAWK,GAAMA,CAAI;AACrE"}
1
+ {"version":3,"file":"usePaintKinds.js","names":["usePaintKinds","useSyncExternalStore","paintKindRegistry","listPaintKinds","useGradientKinds","listGradientKinds","usePaintKind","read","useCallback","getPaintKind","kind"],"sources":["../../src/core/usePaintKinds.ts"],"sourcesContent":["import { useCallback, useSyncExternalStore } from 'react';\nimport {\n getPaintKind, listGradientKinds, listPaintKinds, paintKindRegistry,\n} from 'core/paint/paintKinds';\nimport type { PaintKindEntry } from 'core/paint/paintKindEntry';\n\n/** Every registered paint kind, as {@link listPaintKinds} returns it,\n * re-rendering the caller whenever a kind is registered or removed. */\nexport function usePaintKinds(): readonly PaintKindEntry[] {\n return useSyncExternalStore(paintKindRegistry.subscribe, listPaintKinds, listPaintKinds);\n}\n\n/** Every registered gradient kind, as {@link listGradientKinds} returns it,\n * re-rendering the caller whenever a kind is registered or removed. */\nexport function useGradientKinds(): readonly PaintKindEntry[] {\n return useSyncExternalStore(paintKindRegistry.subscribe, listGradientKinds, listGradientKinds);\n}\n\n/**\n * The entry for `kind`, as {@link getPaintKind} returns it — `undefined` until\n * it is registered, and the new entry once it is. A kind with a loader starts\n * loading on the first read.\n */\nexport function usePaintKind(kind: string | undefined): PaintKindEntry | undefined {\n const read = useCallback(() => getPaintKind(kind), [kind]);\n return useSyncExternalStore(paintKindRegistry.subscribe, read, read);\n}\n"],"mappings":";;;AAQA,SAAgBA,IAA2C;CACzD,OAAOC,EAAqBC,EAAkB,WAAWC,GAAgBA,CAAc;AACzF;AAIA,SAAgBC,IAA8C;CAC5D,OAAOH,EAAqBC,EAAkB,WAAWG,GAAmBA,CAAiB;AAC/F;AAOA,SAAgBC,EAAa,GAAsD;CACjF,IAAMC,IAAOC,QAAkBC,EAAaC,CAAI,GAAG,CAACA,CAAI,CAAC;CACzD,OAAOT,EAAqBC,EAAkB,WAAWK,GAAMA,CAAI;AACrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"clientToWorld.js","names":["clientToWorld","clientX","origin","view","clientY"],"sources":["../../../src/core/viewport/clientToWorld.ts"],"sourcesContent":["/**\n * Convert client coords directly to world coords by subtracting the canvas\n * rect origin and then applying the inverse view transform.\n *\n * This is the composition of `clientToCanvas` + the view-inverse half of\n * `screenToWorld`, but expressed against the `ViewLike` shape used by\n * `SceneCanvas` / `ToolCtx` (`{ scale: { x, y }, x, y }`) rather than the\n * `ViewTransform` shape used by `screenToWorld` (`{ panX, panY, zoom }`).\n */\nexport interface ViewLike {\n scale: { x: number; y: number };\n x: number;\n y: number;\n}\n\n/**\n * Map a browser client coord pair to world coords.\n *\n * @param clientX - `event.clientX`\n * @param clientY - `event.clientY`\n * @param origin - client-space origin of the surface `view` is a camera on.\n * For a whole canvas that is its bounding rect. For a viewport node it is\n * the canvas rect offset by the viewport's own rect, so the same call maps\n * into that viewport's inner world.\n * @param view - current viewport transform\n */\nexport function clientToWorld(\n clientX: number,\n clientY: number,\n origin: { left: number; top: number },\n view: ViewLike,\n): [number, number] {\n return [\n (clientX - origin.left) / view.scale.x + view.x,\n (clientY - origin.top) / view.scale.y + view.y,\n ];\n}\n"],"mappings":";AA0BA,SAAgBA,EACd,GACA,GACA,GACA,GACkB;CAClB,OAAO,EACJC,IAAUC,EAAO,QAAQC,EAAK,MAAM,IAAIA,EAAK,IAC7CC,IAAUF,EAAO,OAAOC,EAAK,MAAM,IAAIA,EAAK,CAC/C;AACF"}
1
+ {"version":3,"file":"clientToWorld.js","names":["clientToWorld","clientX","origin","view","clientY"],"sources":["../../../src/core/viewport/clientToWorld.ts"],"sourcesContent":["/**\n * Convert client coords directly to world coords by subtracting the canvas\n * rect origin and then applying the inverse view transform.\n *\n * This is the composition of `clientToCanvas` + the view-inverse half of\n * `screenToWorld`, but expressed against the `ViewLike` shape used by\n * `SceneCanvas` (`{ scale: { x, y }, x, y }`) rather than the\n * `ViewTransform` shape used by `screenToWorld` (`{ panX, panY, zoom }`).\n */\nexport interface ViewLike {\n scale: { x: number; y: number };\n x: number;\n y: number;\n}\n\n/**\n * Map a browser client coord pair to world coords.\n *\n * @param clientX - `event.clientX`\n * @param clientY - `event.clientY`\n * @param origin - client-space origin of the surface `view` is a camera on.\n * For a whole canvas that is its bounding rect. For a viewport node it is\n * the canvas rect offset by the viewport's own rect, so the same call maps\n * into that viewport's inner world.\n * @param view - current viewport transform\n */\nexport function clientToWorld(\n clientX: number,\n clientY: number,\n origin: { left: number; top: number },\n view: ViewLike,\n): [number, number] {\n return [\n (clientX - origin.left) / view.scale.x + view.x,\n (clientY - origin.top) / view.scale.y + view.y,\n ];\n}\n"],"mappings":";AA0BA,SAAgBA,EACd,GACA,GACA,GACA,GACkB;CAClB,OAAO,EACJC,IAAUC,EAAO,QAAQC,EAAK,MAAM,IAAIA,EAAK,IAC7CC,IAAUF,EAAO,OAAOC,EAAK,MAAM,IAAIA,EAAK,CAC/C;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"fitViewToBounds.js","names":["fitViewToBounds","DEFAULT_MAX_ZOOM","DEFAULT_MIN_ZOOM","opts","bounds","currentView","viewportDims","availW","padding","availH","sx","sy","rawX","rawY","u","scaleX","normalizeZoom","maxScale","minScale","scaleY","place","size","scale","avail","start","viewport"],"sources":["../../../src/core/viewport/fitViewToBounds.ts"],"sourcesContent":["import type { View } from './view';\nimport { DEFAULT_MIN_ZOOM, DEFAULT_MAX_ZOOM, normalizeZoom } from './zoomBounds';\n\n/** `Bounds` is declared in `@weasel-js/routing`, which is typed in it\n * throughout — every area-select, resize and preview surface names one.\n * Re-exported here, where core's call sites have always looked. */\nimport type { Bounds } from '@weasel-js/routing';\nexport type { Bounds };\n\n/** Pixel dimensions of the canvas viewport. */\nexport interface ViewportDims {\n width: number;\n height: number;\n}\n\n/** Options for {@link fitViewToBounds}. */\nexport interface FitViewToBoundsOptions {\n /** Inset (in CSS px) around the bounds. Default 16. */\n padding?: number;\n /**\n * Override the kit's system max scale. Defaults to the kit-wide max zoom\n * used by `computeWheelAction` (`DEFAULT_MAX_ZOOM`).\n */\n maxScale?: number;\n /**\n * Override the kit's system min scale. Defaults to the kit-wide min zoom\n * used by `computeWheelAction` (`DEFAULT_MIN_ZOOM`).\n */\n minScale?: number;\n /**\n * Fit mode:\n * - `'contain'` (default): uniform scale = `min(availW/w, availH/h)`. Bounds fit entirely; one axis has letterboxing.\n * - `'fill'`: uniform scale = `max(...)`. Bounds overflow viewport on one axis.\n * - `'stretch'`: per-axis scale. Bounds match viewport exactly; scale is non-uniform.\n */\n mode?: 'contain' | 'fill' | 'stretch';\n /**\n * Where bounds that overflow the viewport on an axis sit, which happens when\n * `minScale` stops the fit or `mode` is `'fill'`. `'center'` (default) shows\n * their middle; `'start'` shows their left or top edge, inset by `padding`.\n * An axis that fits is centered either way.\n */\n anchor?: 'center' | 'start';\n}\n\n/**\n * Compute the target {@link View} that fits `bounds` (world space) inside\n * `viewportDims` (CSS px). The bounds are centered in the viewport with\n * uniform padding on all sides; the resulting scale is clamped to the\n * configured min/max.\n *\n * View semantics: `view.x` / `view.y` is the world point currently drawn at\n * the canvas top-left, and `view.scale.{x,y}` is pixels per world unit on\n * each axis (see `view.ts`). So:\n * screenX = (worldX - view.x) * view.scale.x\n * screenY = (worldY - view.y) * view.scale.y\n *\n * Empty / zero-sized bounds or viewports cannot be fit — in that case this\n * returns `currentView` unchanged and logs a `console.warn`. Callers that\n * want to no-op silently can detect zero area themselves before calling.\n */\nexport function fitViewToBounds(\n bounds: Bounds,\n viewportDims: ViewportDims,\n currentView: View,\n opts: FitViewToBoundsOptions = {},\n): View {\n const { padding = 16, maxScale = DEFAULT_MAX_ZOOM, minScale = DEFAULT_MIN_ZOOM } = opts;\n\n if (bounds.width <= 0 || bounds.height <= 0) {\n console.warn('[weasel] fitViewToBounds: bounds has zero or negative area; returning currentView unchanged.', bounds);\n return currentView;\n }\n if (viewportDims.width <= 0 || viewportDims.height <= 0) {\n console.warn('[weasel] fitViewToBounds: viewport has zero or negative area; returning currentView unchanged.', viewportDims);\n return currentView;\n }\n\n const availW = Math.max(1, viewportDims.width - padding * 2);\n const availH = Math.max(1, viewportDims.height - padding * 2);\n const sx = availW / bounds.width;\n const sy = availH / bounds.height;\n\n let rawX: number;\n let rawY: number;\n switch (opts.mode ?? 'contain') {\n case 'fill': {\n const u = Math.max(sx, sy);\n rawX = u;\n rawY = u;\n break;\n }\n case 'stretch':\n rawX = sx;\n rawY = sy;\n break;\n case 'contain':\n default: {\n const u = Math.min(sx, sy);\n rawX = u;\n rawY = u;\n break;\n }\n }\n const scaleX = normalizeZoom(Math.min(maxScale, Math.max(minScale, rawX)));\n const scaleY = normalizeZoom(Math.min(maxScale, Math.max(minScale, rawY)));\n\n // Center bounds in the viewport. With view-as-camera semantics:\n // screenCenter = (worldCenter - view.x) * scale\n // view.x = worldCenter - viewportCenter / scale\n const place = (start: number, size: number, avail: number, viewport: number, scale: number) =>\n opts.anchor === 'start' && size * scale > avail + 1e-9\n ? start - padding / scale\n : start + size / 2 - viewport / (2 * scale);\n return {\n x: place(bounds.x, bounds.width, availW, viewportDims.width, scaleX),\n y: place(bounds.y, bounds.height, availH, viewportDims.height, scaleY),\n scale: { x: scaleX, y: scaleY },\n };\n}\n"],"mappings":";;AA6DA,SAAgBA,EACd,GACA,GACA,GACA,IAA+B,CAAC,GAC1B;CACN,IAAM,EAAE,aAAU,IAAI,cAAWC,GAAkB,cAAWC,MAAqBC;CAEnF,IAAIC,EAAO,SAAS,KAAKA,EAAO,UAAU,GAExC,OADA,QAAQ,KAAK,gGAAgGA,CAAM,GAC5GC;CAET,IAAIC,EAAa,SAAS,KAAKA,EAAa,UAAU,GAEpD,OADA,QAAQ,KAAK,kGAAkGA,CAAY,GACpHD;CAGT,IAAME,IAAS,KAAK,IAAI,GAAGD,EAAa,QAAQE,IAAU,CAAC,GACrDC,IAAS,KAAK,IAAI,GAAGH,EAAa,SAASE,IAAU,CAAC,GACtDE,IAAKH,IAASH,EAAO,OACrBO,IAAKF,IAASL,EAAO,QAEvBQ,GACAC;CACJ,QAAQV,EAAK,QAAQ,WAArB;EACE,KAAK,QAAQ;GACX,IAAMW,IAAI,KAAK,IAAIJ,GAAIC,CAAE;GAEzB,AADA,IAAOG,GACP,IAAOA;GACP;EACF;EACA,KAAK;GAEH,AADA,IAAOJ,GACP,IAAOC;GACP;EAEF,SAAS;GACP,IAAMG,IAAI,KAAK,IAAIJ,GAAIC,CAAE;GAEzB,AADA,IAAOG,GACP,IAAOA;GACP;EACF;CACF;CACA,IAAMC,IAASC,EAAc,KAAK,IAAIC,GAAU,KAAK,IAAIC,GAAUN,CAAI,CAAC,CAAC,GACnEO,IAASH,EAAc,KAAK,IAAIC,GAAU,KAAK,IAAIC,GAAUL,CAAI,CAAC,CAAC,GAKnEO,KAAS,GAAe,GAAc,GAAe,GAAkB,MAC3EjB,EAAK,WAAW,WAAWkB,IAAOC,IAAQC,IAAQ,OAC9CC,IAAQhB,IAAUc,IAClBE,IAAQH,IAAO,IAAII,KAAY,IAAIH;CACzC,OAAO;EACL,GAAGF,EAAMhB,EAAO,GAAGA,EAAO,OAAOG,GAAQD,EAAa,OAAOS,CAAM;EACnE,GAAGK,EAAMhB,EAAO,GAAGA,EAAO,QAAQK,GAAQH,EAAa,QAAQa,CAAM;EACrE,OAAO;GAAE,GAAGJ;GAAQ,GAAGI;EAAO;CAChC;AACF"}
1
+ {"version":3,"file":"fitViewToBounds.js","names":["fitViewToBounds","DEFAULT_MAX_ZOOM","DEFAULT_MIN_ZOOM","opts","bounds","currentView","viewportDims","availW","padding","availH","sx","sy","rawX","rawY","u","scaleX","normalizeZoom","maxScale","minScale","scaleY","place","size","scale","avail","start","viewport"],"sources":["../../../src/core/viewport/fitViewToBounds.ts"],"sourcesContent":["import type { View } from './view';\nimport { DEFAULT_MIN_ZOOM, DEFAULT_MAX_ZOOM, normalizeZoom } from './zoomBounds';\n\nimport type { Bounds } from '@weasel-js/routing';\nexport type { Bounds };\n\n/** Pixel dimensions of the canvas viewport. */\nexport interface ViewportDims {\n width: number;\n height: number;\n}\n\n/** Options for {@link fitViewToBounds}. */\nexport interface FitViewToBoundsOptions {\n /** Inset (in CSS px) around the bounds. Default 16. */\n padding?: number;\n /** Defaults to the kit-wide max zoom (`DEFAULT_MAX_ZOOM`). */\n maxScale?: number;\n /** Defaults to the kit-wide min zoom (`DEFAULT_MIN_ZOOM`). */\n minScale?: number;\n /**\n * Fit mode:\n * - `'contain'` (default): uniform scale = `min(availW/w, availH/h)`. Bounds fit entirely; one axis has letterboxing.\n * - `'fill'`: uniform scale = `max(...)`. Bounds overflow viewport on one axis.\n * - `'stretch'`: per-axis scale. Bounds match viewport exactly; scale is non-uniform.\n */\n mode?: 'contain' | 'fill' | 'stretch';\n /**\n * Where bounds that overflow the viewport on an axis sit, which happens when\n * `minScale` stops the fit or `mode` is `'fill'`. `'center'` (default) shows\n * their middle; `'start'` shows their left or top edge, inset by `padding`.\n * An axis that fits is centered either way.\n */\n anchor?: 'center' | 'start';\n}\n\n/**\n * Compute the target {@link View} that fits `bounds` (world space) inside\n * `viewportDims` (CSS px). The bounds are centered in the viewport with\n * uniform padding on all sides; the resulting scale is clamped to the\n * configured min/max.\n *\n * Empty / zero-sized bounds or viewports cannot be fit — in that case this\n * returns `currentView` unchanged and logs a `console.warn`.\n */\nexport function fitViewToBounds(\n bounds: Bounds,\n viewportDims: ViewportDims,\n currentView: View,\n opts: FitViewToBoundsOptions = {},\n): View {\n const { padding = 16, maxScale = DEFAULT_MAX_ZOOM, minScale = DEFAULT_MIN_ZOOM } = opts;\n\n if (bounds.width <= 0 || bounds.height <= 0) {\n console.warn('[weasel] fitViewToBounds: bounds has zero or negative area; returning currentView unchanged.', bounds);\n return currentView;\n }\n if (viewportDims.width <= 0 || viewportDims.height <= 0) {\n console.warn('[weasel] fitViewToBounds: viewport has zero or negative area; returning currentView unchanged.', viewportDims);\n return currentView;\n }\n\n const availW = Math.max(1, viewportDims.width - padding * 2);\n const availH = Math.max(1, viewportDims.height - padding * 2);\n const sx = availW / bounds.width;\n const sy = availH / bounds.height;\n\n let rawX: number;\n let rawY: number;\n switch (opts.mode ?? 'contain') {\n case 'fill': {\n const u = Math.max(sx, sy);\n rawX = u;\n rawY = u;\n break;\n }\n case 'stretch':\n rawX = sx;\n rawY = sy;\n break;\n case 'contain':\n default: {\n const u = Math.min(sx, sy);\n rawX = u;\n rawY = u;\n break;\n }\n }\n const scaleX = normalizeZoom(Math.min(maxScale, Math.max(minScale, rawX)));\n const scaleY = normalizeZoom(Math.min(maxScale, Math.max(minScale, rawY)));\n\n // screenCenter = (worldCenter - view.x) * scale, solved for view.x.\n const place = (start: number, size: number, avail: number, viewport: number, scale: number) =>\n opts.anchor === 'start' && size * scale > avail + 1e-9\n ? start - padding / scale\n : start + size / 2 - viewport / (2 * scale);\n return {\n x: place(bounds.x, bounds.width, availW, viewportDims.width, scaleX),\n y: place(bounds.y, bounds.height, availH, viewportDims.height, scaleY),\n scale: { x: scaleX, y: scaleY },\n };\n}\n"],"mappings":";;AA6CA,SAAgBA,EACd,GACA,GACA,GACA,IAA+B,CAAC,GAC1B;CACN,IAAM,EAAE,aAAU,IAAI,cAAWC,GAAkB,cAAWC,MAAqBC;CAEnF,IAAIC,EAAO,SAAS,KAAKA,EAAO,UAAU,GAExC,OADA,QAAQ,KAAK,gGAAgGA,CAAM,GAC5GC;CAET,IAAIC,EAAa,SAAS,KAAKA,EAAa,UAAU,GAEpD,OADA,QAAQ,KAAK,kGAAkGA,CAAY,GACpHD;CAGT,IAAME,IAAS,KAAK,IAAI,GAAGD,EAAa,QAAQE,IAAU,CAAC,GACrDC,IAAS,KAAK,IAAI,GAAGH,EAAa,SAASE,IAAU,CAAC,GACtDE,IAAKH,IAASH,EAAO,OACrBO,IAAKF,IAASL,EAAO,QAEvBQ,GACAC;CACJ,QAAQV,EAAK,QAAQ,WAArB;EACE,KAAK,QAAQ;GACX,IAAMW,IAAI,KAAK,IAAIJ,GAAIC,CAAE;GAEzB,AADA,IAAOG,GACP,IAAOA;GACP;EACF;EACA,KAAK;GAEH,AADA,IAAOJ,GACP,IAAOC;GACP;EAEF,SAAS;GACP,IAAMG,IAAI,KAAK,IAAIJ,GAAIC,CAAE;GAEzB,AADA,IAAOG,GACP,IAAOA;GACP;EACF;CACF;CACA,IAAMC,IAASC,EAAc,KAAK,IAAIC,GAAU,KAAK,IAAIC,GAAUN,CAAI,CAAC,CAAC,GACnEO,IAASH,EAAc,KAAK,IAAIC,GAAU,KAAK,IAAIC,GAAUL,CAAI,CAAC,CAAC,GAGnEO,KAAS,GAAe,GAAc,GAAe,GAAkB,MAC3EjB,EAAK,WAAW,WAAWkB,IAAOC,IAAQC,IAAQ,OAC9CC,IAAQhB,IAAUc,IAClBE,IAAQH,IAAO,IAAII,KAAY,IAAIH;CACzC,OAAO;EACL,GAAGF,EAAMhB,EAAO,GAAGA,EAAO,OAAOG,GAAQD,EAAa,OAAOS,CAAM;EACnE,GAAGK,EAAMhB,EAAO,GAAGA,EAAO,QAAQK,GAAQH,EAAa,QAAQa,CAAM;EACrE,OAAO;GAAE,GAAGJ;GAAQ,GAAGI;EAAO;CAChC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"parallax.js","names":["asXY","v","deriveParallaxView","p","opts","z","outer","planeMap","inner","kx","ky","toPlane","m","fromPlane","mapRect","a","map","r","b","rectToPlane","rectFromPlane","planeToPlane","from","to","f","IDENTITY_MAP","t","sx","sy","planeMatrix"],"sources":["../../../src/core/viewport/parallax.ts"],"sourcesContent":["import type { View } from './view';\n\n/** One value for both axes, or a separate value per axis. */\nexport type ScalarOrXY = number | { x: number; y: number };\n\n/** How a parallax plane tracks the camera: `pan` is the fraction of the\n * camera's translation it follows (1 = locked to the scene, 0 = fixed to the\n * screen), `zoom` the same for scale, and `anchor` the camera position\n * (`view.x` / `view.y`) the translation is measured from — every plane lines\n * up when the camera sits there. */\nexport interface ParallaxOpts {\n pan: ScalarOrXY;\n zoom?: ScalarOrXY;\n anchor?: { x: number; y: number };\n}\n\nfunction asXY(v: ScalarOrXY): { x: number; y: number } {\n return typeof v === 'number' ? { x: v, y: v } : v;\n}\n\n/**\n * Pure derivation of a parallax plane's inner `View` from the camera view\n * plus per-plane factors.\n *\n * `pan` controls how much the plane translates with the camera (1 = normal,\n * 0 = locked to `anchor`, >1 = leads). `zoom` controls how much it scales\n * with camera zoom (1 = normal, 0 = fixed at identity scale). `anchor`\n * (default origin) is the camera position at which all planes agree.\n *\n * Identity holds: `pan=1, zoom=1` returns a view equal to `outer`.\n */\nexport function deriveParallaxView(outer: View, opts: ParallaxOpts): View {\n const p = asXY(opts.pan);\n const z = asXY(opts.zoom ?? 1);\n const a = opts.anchor ?? { x: 0, y: 0 };\n return {\n x: a.x + (outer.x - a.x) * p.x,\n y: a.y + (outer.y - a.y) * p.y,\n scale: {\n x: 1 + (outer.scale.x - 1) * z.x,\n y: 1 + (outer.scale.y - 1) * z.y,\n },\n };\n}\n\n/** How a point of the camera's world lands in a plane's world, per axis:\n * `plane = world * scale + offset`. A plane draws its content through its\n * own view; this is what lets a pointer, a marquee or a selection box cross\n * between that view and the camera's. */\nexport interface PlaneMap {\n scale: { x: number; y: number };\n offset: { x: number; y: number };\n}\n\n/** The map from `outer`'s world into the world of a plane drawn through\n * `deriveParallaxView(outer, opts)` — the one that puts both points under the\n * same pixel. */\nexport function planeMap(outer: View, opts: ParallaxOpts): PlaneMap {\n const inner = deriveParallaxView(outer, opts);\n const kx = outer.scale.x / inner.scale.x;\n const ky = outer.scale.y / inner.scale.y;\n return {\n scale: { x: kx, y: ky },\n offset: { x: inner.x - kx * outer.x, y: inner.y - ky * outer.y },\n };\n}\n\n/** Map a point from the outer view's world into the plane's world. */\nexport function toPlane(m: PlaneMap, p: { x: number; y: number }): { x: number; y: number } {\n return { x: p.x * m.scale.x + m.offset.x, y: p.y * m.scale.y + m.offset.y };\n}\n\n/** Map a point from the plane's world back into the outer view's world. */\nexport function fromPlane(m: PlaneMap, p: { x: number; y: number }): { x: number; y: number } {\n return { x: (p.x - m.offset.x) / m.scale.x, y: (p.y - m.offset.y) / m.scale.y };\n}\n\ninterface Rect { x: number; y: number; width: number; height: number }\n\nfunction mapRect(r: Rect, map: (p: { x: number; y: number }) => { x: number; y: number }): Rect {\n const a = map({ x: r.x, y: r.y });\n const b = map({ x: r.x + r.width, y: r.y + r.height });\n return {\n x: Math.min(a.x, b.x),\n y: Math.min(a.y, b.y),\n width: Math.abs(b.x - a.x),\n height: Math.abs(b.y - a.y),\n };\n}\n\n/** A camera-world rect in the plane's world. The map is axis-aligned, so a\n * rect stays a rect; a flipped axis is normalized back to a positive size. */\nexport function rectToPlane<R extends Rect>(m: PlaneMap, r: R): R {\n return { ...r, ...mapRect(r, (p) => toPlane(m, p)) };\n}\n\n/** A plane-world rect in the camera's world — see {@link rectToPlane}. */\nexport function rectFromPlane<R extends Rect>(m: PlaneMap, r: R): R {\n return { ...r, ...mapRect(r, (p) => fromPlane(m, p)) };\n}\n\n/** The map from one world into another, where `null` is the camera's own:\n * `fromPlane(from)`, then `toPlane(to)`. Null when the two are the same\n * world, so a caller can skip the work. */\nexport function planeToPlane(from: PlaneMap | null, to: PlaneMap | null): PlaneMap | null {\n if (from === to) return null;\n const f = from ?? IDENTITY_MAP;\n const t = to ?? IDENTITY_MAP;\n const sx = t.scale.x / f.scale.x;\n const sy = t.scale.y / f.scale.y;\n const m = {\n scale: { x: sx, y: sy },\n offset: { x: t.offset.x - f.offset.x * sx, y: t.offset.y - f.offset.y * sy },\n };\n return m.scale.x === 1 && m.scale.y === 1 && m.offset.x === 0 && m.offset.y === 0 ? null : m;\n}\n\nconst IDENTITY_MAP: PlaneMap = { scale: { x: 1, y: 1 }, offset: { x: 0, y: 0 } };\n\n/** The map as an affine matrix in `@weasel-js/geom`'s `[a, b, c, d, e, f]`\n * order, for `transformPath` and friends. */\nexport function planeMatrix(m: PlaneMap): [number, number, number, number, number, number] {\n return [m.scale.x, 0, 0, m.scale.y, m.offset.x, m.offset.y];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parallax.js","names":["asXY","v","deriveParallaxView","p","opts","z","outer","planeMap","inner","kx","ky","toPlane","m","fromPlane","mapRect","a","map","r","b","rectToPlane","rectFromPlane","planeToPlane","from","to","f","IDENTITY_MAP","t","sx","sy","planeMatrix"],"sources":["../../../src/core/viewport/parallax.ts"],"sourcesContent":["import type { Rect } from '@weasel-js/geom';\nimport type { View } from './view';\n\n/** One value for both axes, or a separate value per axis. */\nexport type ScalarOrXY = number | { x: number; y: number };\n\n/** How a parallax plane tracks the camera: `pan` is the fraction of the\n * camera's translation it follows (1 = locked to the scene, 0 = fixed to the\n * screen), `zoom` the same for scale, and `anchor` the camera position\n * (`view.x` / `view.y`) the translation is measured from — every plane lines\n * up when the camera sits there. */\nexport interface ParallaxOpts {\n pan: ScalarOrXY;\n zoom?: ScalarOrXY;\n anchor?: { x: number; y: number };\n}\n\nfunction asXY(v: ScalarOrXY): { x: number; y: number } {\n return typeof v === 'number' ? { x: v, y: v } : v;\n}\n\n/**\n * Pure derivation of a parallax plane's inner `View` from the camera view\n * plus per-plane factors.\n *\n * `pan` controls how much the plane translates with the camera (1 = normal,\n * 0 = locked to `anchor`, >1 = leads). `zoom` controls how much it scales\n * with camera zoom (1 = normal, 0 = fixed at identity scale). `anchor`\n * (default origin) is the camera position at which all planes agree.\n *\n * Identity holds: `pan=1, zoom=1` returns a view equal to `outer`.\n */\nexport function deriveParallaxView(outer: View, opts: ParallaxOpts): View {\n const p = asXY(opts.pan);\n const z = asXY(opts.zoom ?? 1);\n const a = opts.anchor ?? { x: 0, y: 0 };\n return {\n x: a.x + (outer.x - a.x) * p.x,\n y: a.y + (outer.y - a.y) * p.y,\n scale: {\n x: 1 + (outer.scale.x - 1) * z.x,\n y: 1 + (outer.scale.y - 1) * z.y,\n },\n };\n}\n\n/** How a point of the camera's world lands in a plane's world, per axis:\n * `plane = world * scale + offset`. A plane draws its content through its\n * own view; this is what lets a pointer, a marquee or a selection box cross\n * between that view and the camera's. */\nexport interface PlaneMap {\n scale: { x: number; y: number };\n offset: { x: number; y: number };\n}\n\n/** The map from `outer`'s world into the world of a plane drawn through\n * `deriveParallaxView(outer, opts)` — the one that puts both points under the\n * same pixel. */\nexport function planeMap(outer: View, opts: ParallaxOpts): PlaneMap {\n const inner = deriveParallaxView(outer, opts);\n const kx = outer.scale.x / inner.scale.x;\n const ky = outer.scale.y / inner.scale.y;\n return {\n scale: { x: kx, y: ky },\n offset: { x: inner.x - kx * outer.x, y: inner.y - ky * outer.y },\n };\n}\n\n/** Map a point from the outer view's world into the plane's world. */\nexport function toPlane(m: PlaneMap, p: { x: number; y: number }): { x: number; y: number } {\n return { x: p.x * m.scale.x + m.offset.x, y: p.y * m.scale.y + m.offset.y };\n}\n\n/** Map a point from the plane's world back into the outer view's world. */\nexport function fromPlane(m: PlaneMap, p: { x: number; y: number }): { x: number; y: number } {\n return { x: (p.x - m.offset.x) / m.scale.x, y: (p.y - m.offset.y) / m.scale.y };\n}\n\nfunction mapRect(r: Rect, map: (p: { x: number; y: number }) => { x: number; y: number }): Rect {\n const a = map({ x: r.x, y: r.y });\n const b = map({ x: r.x + r.width, y: r.y + r.height });\n return {\n x: Math.min(a.x, b.x),\n y: Math.min(a.y, b.y),\n width: Math.abs(b.x - a.x),\n height: Math.abs(b.y - a.y),\n };\n}\n\n/** A camera-world rect in the plane's world. The map is axis-aligned, so a\n * rect stays a rect; a flipped axis is normalized back to a positive size. */\nexport function rectToPlane<R extends Rect>(m: PlaneMap, r: R): R {\n return { ...r, ...mapRect(r, (p) => toPlane(m, p)) };\n}\n\n/** A plane-world rect in the camera's world — see {@link rectToPlane}. */\nexport function rectFromPlane<R extends Rect>(m: PlaneMap, r: R): R {\n return { ...r, ...mapRect(r, (p) => fromPlane(m, p)) };\n}\n\n/** The map from one world into another, where `null` is the camera's own:\n * `fromPlane(from)`, then `toPlane(to)`. Null when the two are the same\n * world, so a caller can skip the work. */\nexport function planeToPlane(from: PlaneMap | null, to: PlaneMap | null): PlaneMap | null {\n if (from === to) return null;\n const f = from ?? IDENTITY_MAP;\n const t = to ?? IDENTITY_MAP;\n const sx = t.scale.x / f.scale.x;\n const sy = t.scale.y / f.scale.y;\n const m = {\n scale: { x: sx, y: sy },\n offset: { x: t.offset.x - f.offset.x * sx, y: t.offset.y - f.offset.y * sy },\n };\n return m.scale.x === 1 && m.scale.y === 1 && m.offset.x === 0 && m.offset.y === 0 ? null : m;\n}\n\nconst IDENTITY_MAP: PlaneMap = { scale: { x: 1, y: 1 }, offset: { x: 0, y: 0 } };\n\n/** The map as an affine matrix in `@weasel-js/geom`'s `[a, b, c, d, e, f]`\n * order, for `transformPath` and friends. */\nexport function planeMatrix(m: PlaneMap): [number, number, number, number, number, number] {\n return [m.scale.x, 0, 0, m.scale.y, m.offset.x, m.offset.y];\n}\n"],"mappings":"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"}
@@ -1,33 +1,33 @@
1
- import { multiply as e, rotate as t, scale as n } from "@weasel-js/geom";
1
+ import { multiply as e, scale as t } from "@weasel-js/geom";
2
2
  //#region src/core/viewport/screenSlop.ts
3
- function r(r, i = 0) {
4
- if (r === void 0) return {
3
+ function n(n, r) {
4
+ if (n === void 0) return {
5
5
  extra: 0,
6
6
  opts: {}
7
7
  };
8
- if (typeof r == "number") return {
9
- extra: r,
8
+ if (typeof n == "number") return {
9
+ extra: n,
10
10
  opts: {}
11
11
  };
12
- let a = n(r.scale.x, r.scale.y);
12
+ let i = t(n.scale.x, n.scale.y);
13
13
  return {
14
14
  extra: 0,
15
15
  opts: { slop: {
16
- px: r.px,
17
- transform: i ? e(a, t(i)) : a
16
+ px: n.px,
17
+ transform: r ? e(i, r) : i
18
18
  } }
19
19
  };
20
20
  }
21
- function i(e, t, n = 1) {
21
+ function r(e, t, n = 1) {
22
22
  return t > 0 ? typeof e == "object" ? {
23
23
  ...e,
24
24
  px: e.px + t
25
25
  } : (e ?? 0) + t / (n > 0 ? n : 1) : e;
26
26
  }
27
- function a(e) {
27
+ function i(e) {
28
28
  return e === void 0 ? !1 : typeof e == "number" ? e > 0 : e.px > 0;
29
29
  }
30
30
  //#endregion
31
- export { a as hasSlop, r as slopForStrokeHit, i as widenSlop };
31
+ export { i as hasSlop, n as slopForStrokeHit, r as widenSlop };
32
32
 
33
33
  //# sourceMappingURL=screenSlop.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"screenSlop.js","names":["scaleMat","slopForStrokeHit","slop","s","scale","rotation","multiply","rotate","widenSlop","px","hasSlop"],"sources":["../../../src/core/viewport/screenSlop.ts"],"sourcesContent":["/**\n * Pointer forgiveness measured on screen.\n *\n * A pick slop is a screen distance: \"within 4px of the outline\". Converting it\n * to a world distance — per axis or as one scalar — is exact only when the\n * frame the geometry lives in reaches the screen by a similarity. A rotated\n * node under non-uniform zoom does not: a screen circle pulled back into its\n * frame is a tilted ellipse, so the test is run against the geometry's screen\n * image instead (`strokeHitTest`'s `slop`).\n */\nimport { multiply, rotate, scale as scaleMat, type Mat3 } from '@weasel-js/geom';\nimport type { Scale2 } from './pxExtent';\n\n/** `px` screen pixels under a view whose per-axis scale is `scale`. */\nexport interface ScreenSlop {\n px: number;\n scale: Scale2;\n}\n\n/** A slop in world units (a number, the view-less form) or on screen. */\nexport type PickSlop = number | ScreenSlop;\n\n/**\n * How `strokeHitTest` should apply a slop to geometry in a frame turned by\n * `rotation` from world: a world slop adds to the threshold, a screen slop is\n * handed over with the frame's map to the screen.\n */\nexport function slopForStrokeHit(\n slop: PickSlop | undefined,\n rotation = 0,\n): { extra: number; opts: { slop?: { px: number; transform: Mat3 } } } {\n if (slop === undefined) return { extra: 0, opts: {} };\n if (typeof slop === 'number') return { extra: slop, opts: {} };\n const s = scaleMat(slop.scale.x, slop.scale.y);\n return {\n extra: 0,\n opts: { slop: { px: slop.px, transform: rotation ? multiply(s, rotate(rotation)) : s } },\n };\n}\n\n/** `slop` widened by `px` screen pixels — kept on screen when it is measured\n * there, and read at `scale` when it is a world distance. */\nexport function widenSlop(slop: PickSlop | undefined, px: number, scale = 1): PickSlop | undefined {\n if (!(px > 0)) return slop;\n if (typeof slop === 'object') return { ...slop, px: slop.px + px };\n return (slop ?? 0) + px / (scale > 0 ? scale : 1);\n}\n\n/** Is any slop set at all? A zero reach plus a zero slop hits nothing. */\nexport function hasSlop(slop: PickSlop | undefined): boolean {\n if (slop === undefined) return false;\n return typeof slop === 'number' ? slop > 0 : slop.px > 0;\n}\n"],"mappings":";;AA2BA,SAAgBC,EACd,GACA,IAAW,GAC0D;CACrE,IAAIC,MAAS,KAAA,GAAW,OAAO;EAAE,OAAO;EAAG,MAAM,CAAC;CAAE;CACpD,IAAI,OAAOA,KAAS,UAAU,OAAO;EAAE,OAAOA;EAAM,MAAM,CAAC;CAAE;CAC7D,IAAMC,IAAIH,EAASE,EAAK,MAAM,GAAGA,EAAK,MAAM,CAAC;CAC7C,OAAO;EACL,OAAO;EACP,MAAM,EAAE,MAAM;GAAE,IAAIA,EAAK;GAAI,WAAWG,IAAWC,EAASH,GAAGI,EAAOF,CAAQ,CAAC,IAAIF;EAAE,EAAE;CACzF;AACF;AAIA,SAAgBK,EAAU,GAA4B,GAAY,IAAQ,GAAyB;CAGjG,OAFMC,IAAK,IACP,OAAOP,KAAS,WAAiB;EAAE,GAAGA;EAAM,IAAIA,EAAK,KAAKO;CAAG,KACzDP,KAAQ,KAAKO,KAAML,IAAQ,IAAIA,IAAQ,KAFzBF;AAGxB;AAGA,SAAgBQ,EAAQ,GAAqC;CAE3D,OADIR,MAAS,KAAA,IAAkB,KACxB,OAAOA,KAAS,WAAWA,IAAO,IAAIA,EAAK,KAAK;AACzD"}
1
+ {"version":3,"file":"screenSlop.js","names":["scaleMat","slopForStrokeHit","slop","s","scale","frame","multiply","widenSlop","px","hasSlop"],"sources":["../../../src/core/viewport/screenSlop.ts"],"sourcesContent":["/**\n * Pointer forgiveness measured on screen.\n *\n * A pick slop is a screen distance: \"within 4px of the outline\". Converting it\n * to a world distance — per axis or as one scalar — is exact only when the\n * frame the geometry lives in reaches the screen by a similarity. A rotated\n * node under non-uniform zoom does not: a screen circle pulled back into its\n * frame is a tilted ellipse, so the test is run against the geometry's screen\n * image instead (`strokeHitTest`'s `slop`).\n */\nimport { multiply, scale as scaleMat, type Mat3 } from '@weasel-js/geom';\nimport type { Scale2 } from '@weasel-js/geom';\n\n/** `px` screen pixels under a view whose per-axis scale is `scale`. */\nexport interface ScreenSlop {\n px: number;\n scale: Scale2;\n}\n\n/** A slop in world units (a number, the view-less form) or on screen. */\nexport type PickSlop = number | ScreenSlop;\n\n/**\n * How `strokeHitTest` should apply a slop to geometry in a frame that\n * reaches world by `frame` (`poseFrameOf`; only its linear part is read): a\n * world slop adds to the threshold, a screen slop is handed over with the\n * frame's map to the screen.\n */\nexport function slopForStrokeHit(\n slop: PickSlop | undefined,\n frame?: Mat3 | null,\n): { extra: number; opts: { slop?: { px: number; transform: Mat3 } } } {\n if (slop === undefined) return { extra: 0, opts: {} };\n if (typeof slop === 'number') return { extra: slop, opts: {} };\n const s = scaleMat(slop.scale.x, slop.scale.y);\n return {\n extra: 0,\n opts: { slop: { px: slop.px, transform: frame ? multiply(s, frame) : s } },\n };\n}\n\n/** `slop` widened by `px` screen pixels — kept on screen when it is measured\n * there, and read at `scale` when it is a world distance. */\nexport function widenSlop(slop: PickSlop | undefined, px: number, scale = 1): PickSlop | undefined {\n if (!(px > 0)) return slop;\n if (typeof slop === 'object') return { ...slop, px: slop.px + px };\n return (slop ?? 0) + px / (scale > 0 ? scale : 1);\n}\n\n/** Is any slop set at all? A zero reach plus a zero slop hits nothing. */\nexport function hasSlop(slop: PickSlop | undefined): boolean {\n if (slop === undefined) return false;\n return typeof slop === 'number' ? slop > 0 : slop.px > 0;\n}\n"],"mappings":";;AA4BA,SAAgBC,EACd,GACA,GACqE;CACrE,IAAIC,MAAS,KAAA,GAAW,OAAO;EAAE,OAAO;EAAG,MAAM,CAAC;CAAE;CACpD,IAAI,OAAOA,KAAS,UAAU,OAAO;EAAE,OAAOA;EAAM,MAAM,CAAC;CAAE;CAC7D,IAAMC,IAAIH,EAASE,EAAK,MAAM,GAAGA,EAAK,MAAM,CAAC;CAC7C,OAAO;EACL,OAAO;EACP,MAAM,EAAE,MAAM;GAAE,IAAIA,EAAK;GAAI,WAAWG,IAAQC,EAASH,GAAGE,CAAK,IAAIF;EAAE,EAAE;CAC3E;AACF;AAIA,SAAgBI,EAAU,GAA4B,GAAY,IAAQ,GAAyB;CAGjG,OAFMC,IAAK,IACP,OAAON,KAAS,WAAiB;EAAE,GAAGA;EAAM,IAAIA,EAAK,KAAKM;CAAG,KACzDN,KAAQ,KAAKM,KAAMJ,IAAQ,IAAIA,IAAQ,KAFzBF;AAGxB;AAGA,SAAgBO,EAAQ,GAAqC;CAE3D,OADIP,MAAS,KAAA,IAAkB,KACxB,OAAOA,KAAS,WAAWA,IAAO,IAAIA,EAAK,KAAK;AACzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"useCanvasSize.js","names":["useCanvasSize","useDeviceProfile","size","setSize","useState","measure","useCallback","containerRef","rect","prev","useEffect","observer"],"sources":["../../../src/core/viewport/useCanvasSize.ts"],"sourcesContent":["import { type RefObject, useCallback, useEffect, useState } from 'react';\nimport type { CanvasSize } from './clampView';\nimport { useDeviceProfile } from '../device/useDeviceProfile';\n\n/** Size snapshot returned by `useCanvasSize` — the kit-wide `CanvasSize`\n * (width × height in CSS pixels) plus the current devicePixelRatio. */\nexport interface CanvasSizeSnapshot extends CanvasSize {\n dpr: number;\n}\n\n/** Track a container's content-rect size via `ResizeObserver`, and density via\n * the ambient `DeviceProfile`.\n *\n * This hook is the screen path's designated ambient-density source —\n * rendering code should take density as a parameter (cf.\n * `renderSceneToPixels`, `renderSceneToCanvas`'s `dpr`) rather than reading\n * `window.devicePixelRatio` inline.\n *\n * Density deliberately does NOT come from a `window.devicePixelRatio` read\n * inside the resize callback: that only refreshes when the element resizes,\n * so dragging a window to a different-density display without resizing it\n * left the snapshot stale. The profile watches a re-armed resolution media\n * query instead. */\nexport function useCanvasSize(containerRef: RefObject<HTMLElement | null>): CanvasSizeSnapshot {\n const { dpr } = useDeviceProfile();\n const [size, setSize] = useState<CanvasSize>({ width: 0, height: 0 });\n\n const measure = useCallback(() => {\n if (!containerRef.current) return;\n const rect = containerRef.current.getBoundingClientRect();\n setSize((prev) =>\n prev.width === rect.width && prev.height === rect.height\n ? prev\n : { width: rect.width, height: rect.height },\n );\n }, [containerRef]);\n\n useEffect(() => {\n measure();\n const observer = new ResizeObserver(measure);\n if (containerRef.current) {\n observer.observe(containerRef.current);\n }\n return () => observer.disconnect();\n }, [measure, containerRef]);\n\n return { width: size.width, height: size.height, dpr };\n}\n"],"mappings":";;;AAuBA,SAAgBA,EAAc,GAAiE;CAC7F,IAAM,EAAE,WAAQC,EAAiB,GAC3B,CAACC,GAAMC,KAAWC,EAAqB;EAAE,OAAO;EAAG,QAAQ;CAAE,CAAC,GAE9DC,IAAUC,QAAkB;EAChC,IAAI,CAACC,EAAa,SAAS;EAC3B,IAAMC,IAAOD,EAAa,QAAQ,sBAAsB;EACxD,GAAS,MACPE,EAAK,UAAUD,EAAK,SAASC,EAAK,WAAWD,EAAK,SAC9CC,IACA;GAAE,OAAOD,EAAK;GAAO,QAAQA,EAAK;EAAO,CAC/C;CACF,GAAG,CAACD,CAAY,CAAC;CAWjB,OATAG,QAAgB;EACd,EAAQ;EACR,IAAMC,IAAW,IAAI,eAAeN,CAAO;EAI3C,OAHIE,EAAa,WACfI,EAAS,QAAQJ,EAAa,OAAO,SAE1BI,EAAS,WAAW;CACnC,GAAG,CAACN,GAASE,CAAY,CAAC,GAEnB;EAAE,OAAOL,EAAK;EAAO,QAAQA,EAAK;EAAQ;CAAI;AACvD"}
1
+ {"version":3,"file":"useCanvasSize.js","names":["useCanvasSize","useDeviceProfile","size","setSize","useState","measure","useCallback","containerRef","rect","prev","useEffect","observer"],"sources":["../../../src/core/viewport/useCanvasSize.ts"],"sourcesContent":["import { type RefObject, useCallback, useEffect, useState } from 'react';\nimport type { CanvasSize } from './clampView';\nimport { useDeviceProfile } from '../device/useDeviceProfile';\n\n/** Size snapshot returned by `useCanvasSize` — the kit-wide `CanvasSize`\n * (width × height in CSS pixels) plus the current devicePixelRatio. */\nexport interface CanvasSizeSnapshot extends CanvasSize {\n dpr: number;\n}\n\n/** Track a container's content-rect size via `ResizeObserver`, and density via\n * the ambient `DeviceProfile`.\n *\n * Density deliberately does NOT come from a `window.devicePixelRatio` read\n * inside the resize callback: that only refreshes when the element resizes,\n * so dragging a window to a different-density display without resizing it\n * leaves the snapshot stale. */\nexport function useCanvasSize(containerRef: RefObject<HTMLElement | null>): CanvasSizeSnapshot {\n const { dpr } = useDeviceProfile();\n const [size, setSize] = useState<CanvasSize>({ width: 0, height: 0 });\n\n const measure = useCallback(() => {\n if (!containerRef.current) return;\n const rect = containerRef.current.getBoundingClientRect();\n setSize((prev) =>\n prev.width === rect.width && prev.height === rect.height\n ? prev\n : { width: rect.width, height: rect.height },\n );\n }, [containerRef]);\n\n useEffect(() => {\n measure();\n const observer = new ResizeObserver(measure);\n if (containerRef.current) {\n observer.observe(containerRef.current);\n }\n return () => observer.disconnect();\n }, [measure, containerRef]);\n\n return { width: size.width, height: size.height, dpr };\n}\n"],"mappings":";;;AAiBA,SAAgBA,EAAc,GAAiE;CAC7F,IAAM,EAAE,WAAQC,EAAiB,GAC3B,CAACC,GAAMC,KAAWC,EAAqB;EAAE,OAAO;EAAG,QAAQ;CAAE,CAAC,GAE9DC,IAAUC,QAAkB;EAChC,IAAI,CAACC,EAAa,SAAS;EAC3B,IAAMC,IAAOD,EAAa,QAAQ,sBAAsB;EACxD,GAAS,MACPE,EAAK,UAAUD,EAAK,SAASC,EAAK,WAAWD,EAAK,SAC9CC,IACA;GAAE,OAAOD,EAAK;GAAO,QAAQA,EAAK;EAAO,CAC/C;CACF,GAAG,CAACD,CAAY,CAAC;CAWjB,OATAG,QAAgB;EACd,EAAQ;EACR,IAAMC,IAAW,IAAI,eAAeN,CAAO;EAI3C,OAHIE,EAAa,WACfI,EAAS,QAAQJ,EAAa,OAAO,SAE1BI,EAAS,WAAW;CACnC,GAAG,CAACN,GAASE,CAAY,CAAC,GAEnB;EAAE,OAAOL,EAAK;EAAO,QAAQA,EAAK;EAAQ;CAAI;AACvD"}
@@ -1,15 +1,15 @@
1
- import { useVisibleRaf as e } from "../../scheduling/useVisibleRaf.js";
2
- import { useCallback as t, useEffect as n, useRef as r } from "react";
1
+ import { useCallback as e, useEffect as t, useRef as n } from "react";
2
+ import { useVisibleRaf as r } from "@weasel-js/react";
3
3
  //#region src/core/viewport/useDecayLoop.ts
4
4
  var i = .5;
5
5
  function a() {
6
- let a = r(null), o = e((e) => {
6
+ let a = n(null), o = r((e) => {
7
7
  c(e);
8
- }, { onResume: t(() => {
8
+ }, { onResume: e(() => {
9
9
  a.current && (a.current.lastTime = null);
10
- }, []) }), s = t(() => {
10
+ }, []) }), s = e(() => {
11
11
  o.cancel(), a.current = null;
12
- }, [o]), c = t((e) => {
12
+ }, [o]), c = e((e) => {
13
13
  let t = a.current;
14
14
  if (!t) return;
15
15
  if (t.lastTime === null) {
@@ -29,7 +29,7 @@ function a() {
29
29
  t.boundary === "stop" ? (e !== void 0 && o < e ? (s = e - t.posX, t.vx = 0) : n !== void 0 && o > n && (s = n - t.posX, t.vx = 0), r !== void 0 && l < r ? (c = r - t.posY, t.vy = 0) : a !== void 0 && l > a && (c = a - t.posY, t.vy = 0)) : t.boundary === "spring" ? (e !== void 0 && o < e ? (s = e - t.posX, t.vx = Math.abs(t.vx) * i) : n !== void 0 && o > n && (s = n - t.posX, t.vx = -Math.abs(t.vx) * i), r !== void 0 && l < r ? (c = r - t.posY, t.vy = Math.abs(t.vy) * i) : a !== void 0 && l > a && (c = a - t.posY, t.vy = -Math.abs(t.vy) * i)) : (e !== void 0 && o < e ? (s = e - t.posX, t.vx = Math.abs(t.vx)) : n !== void 0 && o > n && (s = n - t.posX, t.vx = -Math.abs(t.vx)), r !== void 0 && l < r ? (c = r - t.posY, t.vy = Math.abs(t.vy)) : a !== void 0 && l > a && (c = a - t.posY, t.vy = -Math.abs(t.vy))), t.posX += s, t.posY += c;
30
30
  }
31
31
  t.onTick(s, c), o.request();
32
- }, [o]), l = t((e) => {
32
+ }, [o]), l = e((e) => {
33
33
  s();
34
34
  let { velocity: t, friction: n = .92, minSpeed: r = .01, viewBounds: i, boundary: c, initialPosition: l, onTick: u, onEnd: d } = e;
35
35
  if (Math.sqrt(t.vx ** 2 + t.vy ** 2) < r) {
@@ -50,7 +50,7 @@ function a() {
50
50
  onEnd: d
51
51
  }, o.request();
52
52
  }, [s, o]);
53
- return n(() => () => {
53
+ return t(() => () => {
54
54
  s();
55
55
  }, [s]), {
56
56
  start: l,
@@ -1 +1 @@
1
- {"version":3,"file":"useDecayLoop.js","names":["SPRING_DAMPING","useDecayLoop","stateRef","useRef","frameLoop","useVisibleRaf","now","useCallback","cancel","tick","s","dt","f","dx","dy","newX","newY","minX","maxX","minY","maxY","start","config","velocity","minSpeed","initialPosition","useEffect"],"sources":["../../../src/core/viewport/useDecayLoop.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useVisibleRaf } from '../../scheduling/useVisibleRaf';\n\n/** Per-axis limits on a view's position. Any side may be left open. */\nexport interface PanBounds {\n minX?: number;\n maxX?: number;\n minY?: number;\n maxY?: number;\n}\n\n/** Momentum settings for a pan: how quickly a flung view slows, when it stops,\n * and what happens at the pan limits. The `DecayLoopConfig` fields a caller\n * chooses up front, without the per-gesture `velocity` / `onTick`. */\nexport interface InertiaConfig {\n friction?: number;\n minSpeed?: number;\n /** What to do when inertial pan reaches `bounds`. Default: no clamping. */\n boundary?: 'stop' | 'bounce' | 'spring';\n /** View-coordinate limits for boundary clamping. Requires `boundary` to take effect. */\n bounds?: PanBounds;\n}\n\n/** How a decay should run: its starting velocity, how fast it slows, and what\n * happens if it reaches the pan limits. */\nexport interface DecayLoopConfig {\n velocity: { vx: number; vy: number };\n friction?: number;\n minSpeed?: number;\n /** Bounds for boundary clamping. Requires `boundary` to take effect. */\n viewBounds?: PanBounds;\n /**\n * What to do when the accumulated position hits `viewBounds`. Default: no clamping.\n * - `'stop'`: clamp at boundary, kill velocity component.\n * - `'bounce'`: linear reflection — flip velocity sign, magnitude preserved.\n * - `'spring'`: damped reflection — flip velocity sign and shrink magnitude\n * by `SPRING_DAMPING` per bounce so the motion settles naturally.\n */\n boundary?: 'stop' | 'bounce' | 'spring';\n /** Starting position for internal boundary tracking. Required when `viewBounds` is set. */\n initialPosition?: { x: number; y: number };\n onTick: (dx: number, dy: number) => void;\n onEnd?: () => void;\n}\n\n/**\n * Fraction of velocity preserved per `'spring'` bounce. 0.5 means each bounce\n * loses half its energy, giving a quick visible settle (typically 2–4 bounces\n * before `minSpeed` cuts the loop). Fixed for v1; a future `bounceDamping`\n * config option could expose this if a consumer needs control.\n */\nconst SPRING_DAMPING = 0.5;\n\n/** A rAF loop that coasts a value to a stop under friction, reporting the\n * per-frame delta. What turns a released pan drag into momentum scrolling. */\nexport function useDecayLoop() {\n const stateRef = useRef<{\n vx: number; vy: number;\n friction: number; minSpeed: number;\n lastTime: number | null;\n posX: number; posY: number;\n viewBounds: PanBounds | undefined;\n boundary: 'stop' | 'bounce' | 'spring' | undefined;\n onTick: (dx: number, dy: number) => void;\n onEnd?: () => void;\n } | null>(null);\n\n const frameLoop = useVisibleRaf(\n (now: number) => { tick(now); },\n {\n // Coasting does not continue while suspended: dropping `lastTime` makes\n // the resuming frame seed a fresh interval instead of applying an hour of\n // friction at once, which would end the decay before it was seen.\n onResume: useCallback(() => {\n if (stateRef.current) stateRef.current.lastTime = null;\n }, []),\n },\n );\n\n const cancel = useCallback(() => {\n frameLoop.cancel();\n stateRef.current = null;\n }, [frameLoop]);\n\n const tick = useCallback((now: number) => {\n const s = stateRef.current;\n if (!s) return;\n if (s.lastTime === null) {\n s.lastTime = now;\n frameLoop.request();\n return;\n }\n const dt = Math.min(now - s.lastTime, 64); // cap at 64ms to avoid huge jumps\n s.lastTime = now;\n // Time-normalize friction to 60fps baseline\n const f = Math.pow(s.friction, dt / 16.67);\n s.vx *= f;\n s.vy *= f;\n const speed = Math.sqrt(s.vx * s.vx + s.vy * s.vy);\n if (speed < s.minSpeed) {\n stateRef.current = null;\n frameLoop.cancel();\n s.onEnd?.();\n return;\n }\n let dx = s.vx * dt;\n let dy = s.vy * dt;\n if (s.viewBounds && s.boundary) {\n const { minX, maxX, minY, maxY } = s.viewBounds;\n const newX = s.posX + dx;\n const newY = s.posY + dy;\n if (s.boundary === 'stop') {\n if (minX !== undefined && newX < minX) { dx = minX - s.posX; s.vx = 0; }\n else if (maxX !== undefined && newX > maxX) { dx = maxX - s.posX; s.vx = 0; }\n if (minY !== undefined && newY < minY) { dy = minY - s.posY; s.vy = 0; }\n else if (maxY !== undefined && newY > maxY) { dy = maxY - s.posY; s.vy = 0; }\n } else if (s.boundary === 'spring') {\n // Damped reflection: flip sign AND scale magnitude by SPRING_DAMPING so\n // each bounce loses energy. Once |v| < minSpeed the outer loop ends.\n if (minX !== undefined && newX < minX) { dx = minX - s.posX; s.vx = Math.abs(s.vx) * SPRING_DAMPING; }\n else if (maxX !== undefined && newX > maxX) { dx = maxX - s.posX; s.vx = -Math.abs(s.vx) * SPRING_DAMPING; }\n if (minY !== undefined && newY < minY) { dy = minY - s.posY; s.vy = Math.abs(s.vy) * SPRING_DAMPING; }\n else if (maxY !== undefined && newY > maxY) { dy = maxY - s.posY; s.vy = -Math.abs(s.vy) * SPRING_DAMPING; }\n } else {\n if (minX !== undefined && newX < minX) { dx = minX - s.posX; s.vx = Math.abs(s.vx); }\n else if (maxX !== undefined && newX > maxX) { dx = maxX - s.posX; s.vx = -Math.abs(s.vx); }\n if (minY !== undefined && newY < minY) { dy = minY - s.posY; s.vy = Math.abs(s.vy); }\n else if (maxY !== undefined && newY > maxY) { dy = maxY - s.posY; s.vy = -Math.abs(s.vy); }\n }\n s.posX += dx;\n s.posY += dy;\n }\n s.onTick(dx, dy);\n frameLoop.request();\n }, [frameLoop]);\n\n const start = useCallback((config: DecayLoopConfig) => {\n cancel();\n const { velocity, friction = 0.92, minSpeed = 0.01, viewBounds, boundary, initialPosition, onTick, onEnd } = config;\n const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);\n if (speed < minSpeed) { onEnd?.(); return; }\n stateRef.current = {\n vx: velocity.vx, vy: velocity.vy, friction, minSpeed, lastTime: null,\n posX: initialPosition?.x ?? 0, posY: initialPosition?.y ?? 0,\n viewBounds, boundary,\n onTick, onEnd,\n };\n frameLoop.request();\n }, [cancel, frameLoop]);\n\n useEffect(() => () => { cancel(); }, [cancel]);\n\n return { start, cancel };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useDecayLoop.js","names":["SPRING_DAMPING","useDecayLoop","stateRef","useRef","frameLoop","useVisibleRaf","now","useCallback","cancel","tick","s","dt","f","dx","dy","newX","newY","minX","maxX","minY","maxY","start","config","velocity","minSpeed","initialPosition","useEffect"],"sources":["../../../src/core/viewport/useDecayLoop.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useVisibleRaf } from '@weasel-js/react';\n\n/** Per-axis limits on a view's position. Any side may be left open. */\nexport interface PanBounds {\n minX?: number;\n maxX?: number;\n minY?: number;\n maxY?: number;\n}\n\n/** Momentum settings for a pan: how quickly a flung view slows, when it stops,\n * and what happens at the pan limits. The `DecayLoopConfig` fields a caller\n * chooses up front, without the per-gesture `velocity` / `onTick`. */\nexport interface InertiaConfig {\n friction?: number;\n minSpeed?: number;\n /** What to do when inertial pan reaches `bounds`. Default: no clamping. */\n boundary?: 'stop' | 'bounce' | 'spring';\n /** View-coordinate limits for boundary clamping. Requires `boundary` to take effect. */\n bounds?: PanBounds;\n}\n\n/** How a decay should run: its starting velocity, how fast it slows, and what\n * happens if it reaches the pan limits. */\nexport interface DecayLoopConfig {\n velocity: { vx: number; vy: number };\n friction?: number;\n minSpeed?: number;\n /** Bounds for boundary clamping. Requires `boundary` to take effect. */\n viewBounds?: PanBounds;\n /**\n * What to do when the accumulated position hits `viewBounds`. Default: no clamping.\n * - `'stop'`: clamp at boundary, kill velocity component.\n * - `'bounce'`: linear reflection — flip velocity sign, magnitude preserved.\n * - `'spring'`: damped reflection — flip velocity sign and shrink magnitude\n * by `SPRING_DAMPING` per bounce so the motion settles naturally.\n */\n boundary?: 'stop' | 'bounce' | 'spring';\n /** Starting position for internal boundary tracking. Required when `viewBounds` is set. */\n initialPosition?: { x: number; y: number };\n onTick: (dx: number, dy: number) => void;\n onEnd?: () => void;\n}\n\n/**\n * Fraction of velocity preserved per `'spring'` bounce. 0.5 means each bounce\n * loses half its energy, giving a quick visible settle (typically 2–4 bounces\n * before `minSpeed` cuts the loop). Fixed for v1; a future `bounceDamping`\n * config option could expose this if a consumer needs control.\n */\nconst SPRING_DAMPING = 0.5;\n\n/** A rAF loop that coasts a value to a stop under friction, reporting the\n * per-frame delta. What turns a released pan drag into momentum scrolling. */\nexport function useDecayLoop() {\n const stateRef = useRef<{\n vx: number; vy: number;\n friction: number; minSpeed: number;\n lastTime: number | null;\n posX: number; posY: number;\n viewBounds: PanBounds | undefined;\n boundary: 'stop' | 'bounce' | 'spring' | undefined;\n onTick: (dx: number, dy: number) => void;\n onEnd?: () => void;\n } | null>(null);\n\n const frameLoop = useVisibleRaf(\n (now: number) => { tick(now); },\n {\n // Coasting does not continue while suspended: dropping `lastTime` makes\n // the resuming frame seed a fresh interval instead of applying an hour of\n // friction at once, which would end the decay before it was seen.\n onResume: useCallback(() => {\n if (stateRef.current) stateRef.current.lastTime = null;\n }, []),\n },\n );\n\n const cancel = useCallback(() => {\n frameLoop.cancel();\n stateRef.current = null;\n }, [frameLoop]);\n\n const tick = useCallback((now: number) => {\n const s = stateRef.current;\n if (!s) return;\n if (s.lastTime === null) {\n s.lastTime = now;\n frameLoop.request();\n return;\n }\n const dt = Math.min(now - s.lastTime, 64); // cap at 64ms to avoid huge jumps\n s.lastTime = now;\n // Time-normalize friction to 60fps baseline\n const f = Math.pow(s.friction, dt / 16.67);\n s.vx *= f;\n s.vy *= f;\n const speed = Math.sqrt(s.vx * s.vx + s.vy * s.vy);\n if (speed < s.minSpeed) {\n stateRef.current = null;\n frameLoop.cancel();\n s.onEnd?.();\n return;\n }\n let dx = s.vx * dt;\n let dy = s.vy * dt;\n if (s.viewBounds && s.boundary) {\n const { minX, maxX, minY, maxY } = s.viewBounds;\n const newX = s.posX + dx;\n const newY = s.posY + dy;\n if (s.boundary === 'stop') {\n if (minX !== undefined && newX < minX) { dx = minX - s.posX; s.vx = 0; }\n else if (maxX !== undefined && newX > maxX) { dx = maxX - s.posX; s.vx = 0; }\n if (minY !== undefined && newY < minY) { dy = minY - s.posY; s.vy = 0; }\n else if (maxY !== undefined && newY > maxY) { dy = maxY - s.posY; s.vy = 0; }\n } else if (s.boundary === 'spring') {\n // Damped reflection: flip sign AND scale magnitude by SPRING_DAMPING so\n // each bounce loses energy. Once |v| < minSpeed the outer loop ends.\n if (minX !== undefined && newX < minX) { dx = minX - s.posX; s.vx = Math.abs(s.vx) * SPRING_DAMPING; }\n else if (maxX !== undefined && newX > maxX) { dx = maxX - s.posX; s.vx = -Math.abs(s.vx) * SPRING_DAMPING; }\n if (minY !== undefined && newY < minY) { dy = minY - s.posY; s.vy = Math.abs(s.vy) * SPRING_DAMPING; }\n else if (maxY !== undefined && newY > maxY) { dy = maxY - s.posY; s.vy = -Math.abs(s.vy) * SPRING_DAMPING; }\n } else {\n if (minX !== undefined && newX < minX) { dx = minX - s.posX; s.vx = Math.abs(s.vx); }\n else if (maxX !== undefined && newX > maxX) { dx = maxX - s.posX; s.vx = -Math.abs(s.vx); }\n if (minY !== undefined && newY < minY) { dy = minY - s.posY; s.vy = Math.abs(s.vy); }\n else if (maxY !== undefined && newY > maxY) { dy = maxY - s.posY; s.vy = -Math.abs(s.vy); }\n }\n s.posX += dx;\n s.posY += dy;\n }\n s.onTick(dx, dy);\n frameLoop.request();\n }, [frameLoop]);\n\n const start = useCallback((config: DecayLoopConfig) => {\n cancel();\n const { velocity, friction = 0.92, minSpeed = 0.01, viewBounds, boundary, initialPosition, onTick, onEnd } = config;\n const speed = Math.sqrt(velocity.vx ** 2 + velocity.vy ** 2);\n if (speed < minSpeed) { onEnd?.(); return; }\n stateRef.current = {\n vx: velocity.vx, vy: velocity.vy, friction, minSpeed, lastTime: null,\n posX: initialPosition?.x ?? 0, posY: initialPosition?.y ?? 0,\n viewBounds, boundary,\n onTick, onEnd,\n };\n frameLoop.request();\n }, [cancel, frameLoop]);\n\n useEffect(() => () => { cancel(); }, [cancel]);\n\n return { start, cancel };\n}\n"],"mappings":"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"}