@weasel-js/core 1.10.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/CHANGELOG.md +168 -0
  2. package/README.md +33 -0
  3. package/dist/affordances/composeAffordanceLayer.js +21 -21
  4. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  5. package/dist/affordances/hitAffordanceRegions.js +48 -32
  6. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  7. package/dist/affordances/pathAnchors.js +50 -28
  8. package/dist/affordances/pathAnchors.js.map +1 -1
  9. package/dist/affordances/rotateCursor.js +12 -0
  10. package/dist/affordances/rotateCursor.js.map +1 -0
  11. package/dist/affordances/rotationHandle.js +40 -43
  12. package/dist/affordances/rotationHandle.js.map +1 -1
  13. package/dist/animation/rig/rigNode.js +9 -3
  14. package/dist/animation/rig/rigNode.js.map +1 -1
  15. package/dist/animation/rig/rigSeat.js +46 -13
  16. package/dist/animation/rig/rigSeat.js.map +1 -1
  17. package/dist/animation/rig/skinBinding.js +22 -14
  18. package/dist/animation/rig/skinBinding.js.map +1 -1
  19. package/dist/barrel/canvas.js +29 -28
  20. package/dist/barrel/interactions.js +33 -32
  21. package/dist/barrel/paths.js +11 -10
  22. package/dist/barrel/routing.js +49 -48
  23. package/dist/barrel/scene.js +10 -10
  24. package/dist/barrel/viewport.js +24 -21
  25. package/dist/canvas/Canvas.js +6 -17
  26. package/dist/canvas/Canvas.js.map +1 -1
  27. package/dist/canvas/CanvasView.js +34 -37
  28. package/dist/canvas/CanvasView.js.map +1 -1
  29. package/dist/canvas/CursorCoordsHud.js +3 -3
  30. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  31. package/dist/canvas/DrawCanvas.js +3 -3
  32. package/dist/canvas/DrawCanvas.js.map +1 -1
  33. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +24 -23
  34. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  35. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +40 -49
  36. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -1
  37. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +297 -259
  38. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  39. package/dist/canvas/SceneCanvas/features.js +3 -24
  40. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  41. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +97 -0
  42. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -0
  43. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  44. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  45. package/dist/canvas/SceneCanvas/scenePointQuery.js +50 -0
  46. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -0
  47. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +52 -0
  48. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -0
  49. package/dist/canvas/SceneCanvas/useActionTunings.js +17 -0
  50. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -0
  51. package/dist/canvas/SceneCanvas/useCanvasCamera.js +37 -29
  52. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -1
  53. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +11 -11
  54. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -1
  55. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +45 -109
  56. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  57. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +49 -41
  58. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +64 -96
  60. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  61. package/dist/canvas/SceneCanvas/worldPointAt.js +3 -4
  62. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
  63. package/dist/canvas/SceneCanvas.js +77 -80
  64. package/dist/canvas/SceneCanvas.js.map +1 -1
  65. package/dist/canvas/SceneViewCanvas.js +3 -3
  66. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  67. package/dist/canvas/SurfaceCanvas.js +40 -0
  68. package/dist/canvas/SurfaceCanvas.js.map +1 -0
  69. package/dist/canvas/adapterDerivedPath.js +13 -13
  70. package/dist/canvas/adapterDerivedPath.js.map +1 -1
  71. package/dist/canvas/adapterPickSource.js +34 -0
  72. package/dist/canvas/adapterPickSource.js.map +1 -0
  73. package/dist/canvas/affordanceAt.js +1 -1
  74. package/dist/canvas/affordanceAt.js.map +1 -1
  75. package/dist/canvas/buildSceneLayer.js.map +1 -1
  76. package/dist/canvas/buildSceneTree.js +56 -34
  77. package/dist/canvas/buildSceneTree.js.map +1 -1
  78. package/dist/canvas/copiesAbove.js +27 -0
  79. package/dist/canvas/copiesAbove.js.map +1 -0
  80. package/dist/canvas/defaultDrawOne.js +24 -23
  81. package/dist/canvas/defaultDrawOne.js.map +1 -1
  82. package/dist/canvas/deps/editAnchors.js +45 -50
  83. package/dist/canvas/deps/editAnchors.js.map +1 -1
  84. package/dist/canvas/deps/hitTestArea.js +30 -15
  85. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  86. package/dist/canvas/deps/insert.js +134 -100
  87. package/dist/canvas/deps/insert.js.map +1 -1
  88. package/dist/canvas/deps/layout.js +9 -15
  89. package/dist/canvas/deps/layout.js.map +1 -1
  90. package/dist/canvas/derivedPath.js +53 -29
  91. package/dist/canvas/derivedPath.js.map +1 -1
  92. package/dist/canvas/insertPreviewExtent.js +33 -31
  93. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  94. package/dist/canvas/overChildren.js +29 -0
  95. package/dist/canvas/overChildren.js.map +1 -0
  96. package/dist/canvas/paintedCursorLayer.js.map +1 -1
  97. package/dist/canvas/pickReach.js +23 -0
  98. package/dist/canvas/pickReach.js.map +1 -0
  99. package/dist/canvas/pickWalk.js +51 -80
  100. package/dist/canvas/pickWalk.js.map +1 -1
  101. package/dist/canvas/sceneAdapter.js +14 -35
  102. package/dist/canvas/sceneAdapter.js.map +1 -1
  103. package/dist/canvas/sceneSlotWiring.js +11 -10
  104. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  105. package/dist/canvas/sceneViewRender.js +38 -44
  106. package/dist/canvas/sceneViewRender.js.map +1 -1
  107. package/dist/canvas/useCanvasView.js +42 -44
  108. package/dist/canvas/useCanvasView.js.map +1 -1
  109. package/dist/canvas/useSceneAdapter.js +22 -0
  110. package/dist/canvas/useSceneAdapter.js.map +1 -0
  111. package/dist/canvas/useSurfaceInput.js +13 -16
  112. package/dist/canvas/useSurfaceInput.js.map +1 -1
  113. package/dist/canvas/viewRegistry.js +31 -23
  114. package/dist/canvas/viewRegistry.js.map +1 -1
  115. package/dist/canvas/wrapNodeOutput.js +7 -2
  116. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  117. package/dist/clipboard.d.ts +1 -1
  118. package/dist/{clone-2a5hVbBd.d.ts → clone-C0eADtS0.d.ts} +13 -13
  119. package/dist/clone.d.ts +2 -2
  120. package/dist/core/geometry/poseDescriptor.js +49 -23
  121. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  122. package/dist/core/geometry/regionHit.js +2 -2
  123. package/dist/core/geometry/regionHit.js.map +1 -1
  124. package/dist/core/geometry/targetFrame.js.map +1 -1
  125. package/dist/core/layers/children.js +1 -3
  126. package/dist/core/layers/children.js.map +1 -1
  127. package/dist/core/ops/create.js +2 -2
  128. package/dist/core/ops/create.js.map +1 -1
  129. package/dist/core/ops/delete.js +19 -23
  130. package/dist/core/ops/delete.js.map +1 -1
  131. package/dist/core/ops/reorder/index.js +3 -7
  132. package/dist/core/ops/reorder/index.js.map +1 -1
  133. package/dist/core/ops/reorder/setChildOrder.js +2 -4
  134. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  135. package/dist/core/ops/reparent.js +0 -1
  136. package/dist/core/ops/reparent.js.map +1 -1
  137. package/dist/core/ops/slot.js +3 -6
  138. package/dist/core/ops/slot.js.map +1 -1
  139. package/dist/core/pages/fitViewToPage.js +15 -0
  140. package/dist/core/pages/fitViewToPage.js.map +1 -0
  141. package/dist/core/pages/pages.js +65 -0
  142. package/dist/core/pages/pages.js.map +1 -0
  143. package/dist/core/pages/pagesLayer.js +27 -0
  144. package/dist/core/pages/pagesLayer.js.map +1 -0
  145. package/dist/core/paint/meshKindLazy.js +2 -2
  146. package/dist/core/paint/meshKindLazy.js.map +1 -1
  147. package/dist/core/scene/NodeProperties.js.map +1 -1
  148. package/dist/core/scene/composeFrame.js.map +1 -1
  149. package/dist/core/scene/composePose.js +58 -20
  150. package/dist/core/scene/composePose.js.map +1 -1
  151. package/dist/core/scene/effectivePose.js +5 -1
  152. package/dist/core/scene/effectivePose.js.map +1 -1
  153. package/dist/core/scene/historyFacade.js +19 -13
  154. package/dist/core/scene/historyFacade.js.map +1 -1
  155. package/dist/core/scene/nodeFnFields.js +7 -0
  156. package/dist/core/scene/nodeFnFields.js.map +1 -1
  157. package/dist/core/scene/outerOps.js +2 -1
  158. package/dist/core/scene/outerOps.js.map +1 -1
  159. package/dist/core/scene/reconcileSpecs.js +1 -1
  160. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  161. package/dist/core/scene/sceneRecording.js +2 -1
  162. package/dist/core/scene/sceneRecording.js.map +1 -1
  163. package/dist/core/scene/types.js.map +1 -1
  164. package/dist/core/viewport/screenSlop.js.map +1 -1
  165. package/dist/core/viewport/useDecayLoop.js +28 -30
  166. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  167. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -1
  168. package/dist/core/viewport/useViewAnimation.js +70 -69
  169. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  170. package/dist/core/viewport/view.js +8 -5
  171. package/dist/core/viewport/view.js.map +1 -1
  172. package/dist/core/viewport/zoomAt.js +11 -2
  173. package/dist/core/viewport/zoomAt.js.map +1 -1
  174. package/dist/{cornerHandles-BEshc4z3.d.ts → cornerHandles-BSKbyuvQ.d.ts} +1 -1
  175. package/dist/features/paths/editablePath.js +24 -8
  176. package/dist/features/paths/editablePath.js.map +1 -1
  177. package/dist/features/paths/index.js +4 -4
  178. package/dist/features/paths/shapeGenerator.js +89 -0
  179. package/dist/features/paths/shapeGenerator.js.map +1 -0
  180. package/dist/features/paths/usePathEdit.js +13 -13
  181. package/dist/features/poseRun/usePoseRun.js +25 -25
  182. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  183. package/dist/features/text/useSceneTextEdit.js +82 -64
  184. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  185. package/dist/features/viewports/viewResolver.js +28 -24
  186. package/dist/features/viewports/viewResolver.js.map +1 -1
  187. package/dist/icons/SliceIcon.js +24 -0
  188. package/dist/icons/SliceIcon.js.map +1 -0
  189. package/dist/index.d.ts +956 -581
  190. package/dist/index.js +260 -251
  191. package/dist/interactions/actions/align/align.js +9 -9
  192. package/dist/interactions/actions/align/align.js.map +1 -1
  193. package/dist/interactions/actions/booleans/booleans.js +18 -18
  194. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  195. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  196. package/dist/interactions/actions/clone/action.js +35 -30
  197. package/dist/interactions/actions/clone/action.js.map +1 -1
  198. package/dist/interactions/actions/defaults/anchorEditing.js +56 -59
  199. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  200. package/dist/interactions/actions/defaults/anchorHandles.js +42 -0
  201. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -0
  202. package/dist/interactions/actions/defaults/anchorJoin.js +92 -0
  203. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -0
  204. package/dist/interactions/actions/defaults/bendSegment.js +46 -0
  205. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -0
  206. package/dist/interactions/actions/defaults/copySubtree.js +1 -1
  207. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  208. package/dist/interactions/actions/defaults/duplicate.js +32 -17
  209. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  210. package/dist/interactions/actions/defaults/enterPathEdit.js +19 -7
  211. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  212. package/dist/interactions/actions/defaults/icons/anchorIcons.js +75 -0
  213. package/dist/interactions/actions/defaults/icons/anchorIcons.js.map +1 -0
  214. package/dist/interactions/actions/defaults/icons/editIcons.js +35 -8
  215. package/dist/interactions/actions/defaults/icons/editIcons.js.map +1 -1
  216. package/dist/interactions/actions/defaults/insertPathAnchor.js +16 -31
  217. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  218. package/dist/interactions/actions/defaults/nudge.js +28 -23
  219. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  220. package/dist/interactions/actions/defaults/pinchZoom.js +29 -29
  221. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  222. package/dist/interactions/actions/defaults/segmentUnder.js +22 -0
  223. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -0
  224. package/dist/interactions/actions/defaults/viewportZoom.js +82 -79
  225. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  226. package/dist/interactions/actions/distribute/distribute.js +8 -8
  227. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  228. package/dist/interactions/actions/edit-anchors/action.js +58 -55
  229. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  230. package/dist/interactions/actions/edit-anchors/preview.js +26 -0
  231. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -0
  232. package/dist/interactions/actions/edit-anchors/symmetry.js +11 -0
  233. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -0
  234. package/dist/interactions/actions/flip/action.js.map +1 -1
  235. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  236. package/dist/interactions/actions/insert/action.js +37 -30
  237. package/dist/interactions/actions/insert/action.js.map +1 -1
  238. package/dist/interactions/actions/insert/frame.js +9 -2
  239. package/dist/interactions/actions/insert/frame.js.map +1 -1
  240. package/dist/interactions/actions/insert/repositionAction.js +31 -0
  241. package/dist/interactions/actions/insert/repositionAction.js.map +1 -0
  242. package/dist/interactions/actions/lasso-select/action.js +32 -32
  243. package/dist/interactions/actions/move/action.js +29 -25
  244. package/dist/interactions/actions/move/action.js.map +1 -1
  245. package/dist/interactions/actions/move/behaviors/snapToContainer.js +12 -6
  246. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  247. package/dist/interactions/actions/move/capture.js +32 -23
  248. package/dist/interactions/actions/move/capture.js.map +1 -1
  249. package/dist/interactions/actions/move/frame.js +2 -14
  250. package/dist/interactions/actions/move/frame.js.map +1 -1
  251. package/dist/interactions/actions/move/session.js +1 -1
  252. package/dist/interactions/actions/move/session.js.map +1 -1
  253. package/dist/interactions/actions/move/translate.js.map +1 -1
  254. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  255. package/dist/interactions/actions/outlines/replaceWithPaths.js +13 -13
  256. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -1
  257. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -1
  258. package/dist/interactions/actions/pathCommands/cutJoin.js +102 -0
  259. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -0
  260. package/dist/interactions/actions/pathCommands/livePathEdit.js +64 -0
  261. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -0
  262. package/dist/interactions/actions/pathCommands/pathNodes.js +99 -0
  263. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -0
  264. package/dist/interactions/actions/pathCommands/simplifyOffset.js +42 -0
  265. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -0
  266. package/dist/interactions/actions/resize/action.js +31 -20
  267. package/dist/interactions/actions/resize/action.js.map +1 -1
  268. package/dist/interactions/actions/resize/commit.js.map +1 -1
  269. package/dist/interactions/actions/resize/frame.js +29 -15
  270. package/dist/interactions/actions/resize/frame.js.map +1 -1
  271. package/dist/interactions/actions/resize/replay.js +47 -0
  272. package/dist/interactions/actions/resize/replay.js.map +1 -0
  273. package/dist/interactions/actions/resize/session.js +49 -35
  274. package/dist/interactions/actions/resize/session.js.map +1 -1
  275. package/dist/interactions/actions/resolveOverlays.js +2 -1
  276. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  277. package/dist/interactions/actions/rotate/action.js +40 -25
  278. package/dist/interactions/actions/rotate/action.js.map +1 -1
  279. package/dist/interactions/actions/rotate/frame.js +1 -1
  280. package/dist/interactions/actions/rotate/frame.js.map +1 -1
  281. package/dist/interactions/actions/rotate/replay.js +22 -0
  282. package/dist/interactions/actions/rotate/replay.js.map +1 -0
  283. package/dist/interactions/actions/rotate/session.js +42 -32
  284. package/dist/interactions/actions/rotate/session.js.map +1 -1
  285. package/dist/interactions/actions/transform-again/action.js +63 -0
  286. package/dist/interactions/actions/transform-again/action.js.map +1 -0
  287. package/dist/interactions/actions/transform-again/memory.js +35 -0
  288. package/dist/interactions/actions/transform-again/memory.js.map +1 -0
  289. package/dist/interactions/actions/useStandardActions.js +101 -83
  290. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  291. package/dist/move.d.ts +4 -4
  292. package/dist/{originProjection-PPT88jZv.d.ts → originProjection-CoNVpITV.d.ts} +1 -1
  293. package/dist/resize.d.ts +3 -3
  294. package/dist/style.css +1 -1
  295. package/dist/tools/builtin/ellipse/useEllipseTool.js +16 -15
  296. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  297. package/dist/tools/builtin/line/useLineTool.js +16 -15
  298. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  299. package/dist/tools/builtin/pen/usePenTool.js +111 -111
  300. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  301. package/dist/tools/builtin/pickTopMostHit.js +11 -14
  302. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  303. package/dist/tools/builtin/polygon/usePolygonTool.js +17 -15
  304. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  305. package/dist/tools/builtin/rect/useRectTool.js +15 -14
  306. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  307. package/dist/tools/builtin/select/adapterPointQuery.js +22 -18
  308. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  309. package/dist/tools/builtin/select/selectionContributions.js +1 -1
  310. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  311. package/dist/tools/builtin/select/useSelectTool.js +2 -1
  312. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  313. package/dist/tools/builtin/slice/useSliceTool.js +42 -40
  314. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  315. package/dist/tools/builtin/star/useStarTool.js +18 -16
  316. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  317. package/dist/tools/builtin/text/useTextTool.js +2 -2
  318. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  319. package/dist/{types-CIKDwlsP.d.ts → types-DBbbCy0i.d.ts} +22 -15
  320. package/dist/version.js +1 -1
  321. package/package.json +22 -22
  322. package/dist/canvas/surface.module.js +0 -6
  323. package/dist/canvas/surface.module.js.map +0 -1
  324. package/dist/canvas/surfaceBox.js +0 -16
  325. package/dist/canvas/surfaceBox.js.map +0 -1
  326. package/dist/layout/arrivals.js +0 -33
  327. package/dist/layout/arrivals.js.map +0 -1
@@ -12,26 +12,26 @@ import { pathFromPlane as oe } from "./planeClips.js";
12
12
  import { createDispatcherPreviewSources as se, createGestureSource as ce } from "./SceneCanvas/dispatcherGestureBounds.js";
13
13
  import { useOptionalViewInputs as le } from "./viewInputs.js";
14
14
  import { createSceneLayerGate as ue, viewPaintedLayers as de } from "./sceneLayerPaint.js";
15
- import { IDENTITY_VIEW as s, UNMEASURED_DIMS as c, useOptionalViewRegistry as fe } from "./viewRegistry.js";
16
- import { useCallback as l, useEffect as u, useImperativeHandle as pe, useInsertionEffect as me, useLayoutEffect as he, useMemo as d, useRef as ge, useState as _e } from "react";
15
+ import { IDENTITY_VIEW as s, UNMEASURED_DIMS as c, surfaceLocal as fe, useOptionalViewRegistry as pe } from "./viewRegistry.js";
16
+ import { useCallback as l, useEffect as u, useImperativeHandle as me, useInsertionEffect as he, useLayoutEffect as ge, useMemo as d, useRef as _e, useState as ve } from "react";
17
17
  import { useLatest as f } from "@weasel-js/react";
18
- import { createDispatcher as ve } from "@weasel-js/routing";
19
- import { useOptionalDepRegistry as ye } from "@weasel-js/routing/react";
18
+ import { createDispatcher as ye } from "@weasel-js/routing";
19
+ import { useOptionalDepRegistry as be } from "@weasel-js/routing/react";
20
20
  //#region src/canvas/CanvasView.tsx
21
- var be = {
21
+ var xe = {
22
22
  adapter: void 0,
23
23
  geometry: o,
24
24
  boundsOf: void 0
25
- }, xe = () => !0, p = (e) => ({
25
+ }, Se = () => !0, p = (e) => ({
26
26
  width: e.w,
27
27
  height: e.h
28
- }), Se = (e) => e;
28
+ }), Ce = (e) => e;
29
29
  function m(o) {
30
- let { id: m, bounds: Ce, view: h, defaultView: we, onViewChange: Te, viewBounds: Ee, layers: De = Se, layerVisibility: Oe, layerOrder: ke, background: g, order: _ = Infinity, label: v, cameraRef: Ae, selection: je, selectionOptions: y, interactive: b = !0, paint: x = !0 } = o, S = fe(), Me = ye(), C = f(Me), w = a(y), T = je ?? (y ? w : void 0), E = le(), D = T ?? E?.selectionApi ?? w, O = f({
31
- bounds: Ce,
32
- layers: De,
33
- layerVisibility: Oe,
34
- layerOrder: ke,
30
+ let { id: m, bounds: we, view: h, defaultView: Te, onViewChange: Ee, viewBounds: De, layers: Oe = Ce, layerVisibility: ke, layerOrder: Ae, background: g, order: _ = Infinity, label: v, cameraRef: je, selection: Me, selectionOptions: y, interactive: b = !0, paint: x = !0 } = o, S = pe(), Ne = be(), C = f(Ne), w = a(y), T = Me ?? (y ? w : void 0), E = le(), D = T ?? E?.selectionApi ?? w, O = f({
31
+ bounds: we,
32
+ layers: Oe,
33
+ layerVisibility: ke,
34
+ layerOrder: Ae,
35
35
  viewProp: h,
36
36
  viewSelection: T,
37
37
  selection: D
@@ -41,18 +41,18 @@ function m(o) {
41
41
  }, [O]), A = l(() => {
42
42
  let e = S?.surface();
43
43
  return k(e?.view() ?? s, e?.dims() ?? c);
44
- }, [S, k]), { getView: j, setView: M, setViewFromInput: N, subscribeView: P, adoptControlled: Ne, announceControlled: Pe, clearSubscribers: F } = te({
44
+ }, [S, k]), { getView: j, setView: M, setViewFromInput: N, subscribeView: P, adoptControlled: Pe, announceControlled: Fe, clearSubscribers: F } = te({
45
45
  view: typeof h == "function" ? () => {
46
46
  let e = S?.surface();
47
47
  return h(e?.view() ?? s, e?.dims() ?? c);
48
48
  } : h,
49
- defaultView: we,
50
- onViewChange: Te,
51
- viewBounds: Ee,
49
+ defaultView: Te,
50
+ onViewChange: Ee,
51
+ viewBounds: De,
52
52
  dims: () => p(A()),
53
53
  requestRedraw: () => S?.surface()?.requestRedraw()
54
54
  });
55
- me(Ne), he(Pe), u(() => F, [F]), pe(Ae, () => ({
55
+ he(Pe), ge(Fe), u(() => F, [F]), me(je, () => ({
56
56
  getView: j,
57
57
  setView: M,
58
58
  subscribeView: P
@@ -64,7 +64,7 @@ function m(o) {
64
64
  let I = l((t, n) => {
65
65
  let r = O.current.viewProp;
66
66
  return typeof r == "function" ? e(r(t, n)) : j();
67
- }, [O, j]), L = l(() => de(S?.surface()?.layers() ?? [], O.current), [S, O]), [R] = _e(ue), z = l((e) => R(S?.surface()?.layers() ?? [], O.current)(e), [
67
+ }, [O, j]), L = l(() => de(S?.surface()?.layers() ?? [], O.current), [S, O]), [R] = ve(ue), z = l((e) => R(S?.surface()?.layers() ?? [], O.current)(e), [
68
68
  S,
69
69
  R,
70
70
  O
@@ -96,29 +96,26 @@ function m(o) {
96
96
  j,
97
97
  A,
98
98
  C
99
- ]), H = ge(null);
100
- H.current ||= ve();
101
- let U = E?.rotationBadge ?? null, Fe = d(() => ({
99
+ ]), H = _e(null);
100
+ H.current ||= ye();
101
+ let U = E?.rotationBadge ?? null, Ie = d(() => ({
102
102
  gestureSource: ce(() => H.current),
103
103
  ...se(() => H.current)
104
104
  }), []), W = f(E), G = l(() => ({
105
105
  selection: O.current.selection.get(),
106
106
  view: j(),
107
107
  action: H.current.getActiveAction()
108
- }), [j, O]), K = E?.boundsOf, Ie = d(() => K ? (e) => K(e, j()) : void 0, [K, j]), q = E?.boundsOfPose, Le = d(() => q ? (e, t) => q(e, t, j()) : void 0, [q, j]), { helpers: Re } = ee({
109
- ...E ?? be,
110
- boundsOf: Ie,
111
- boundsOfPose: Le,
112
- ...Fe,
108
+ }), [j, O]), K = E?.boundsOf, Le = d(() => K ? (e) => K(e, j()) : void 0, [K, j]), q = E?.boundsOfPose, Re = d(() => q ? (e, t) => q(e, t, j()) : void 0, [q, j]), { helpers: ze } = ee({
109
+ ...E ?? xe,
110
+ boundsOf: Le,
111
+ boundsOfPose: Re,
112
+ ...Ie,
113
113
  selection: D.current,
114
- getIsVisible: () => W.current?.chromeCaps?.isVisible(G()) ?? xe
115
- }), J = f(Re), Y = l((e, t) => {
116
- let n = S?.surface()?.origin() ?? {
117
- left: 0,
118
- top: 0
119
- }, i = A(), [a, o] = r(e, t, {
120
- left: n.left + i.x,
121
- top: n.top + i.y
114
+ getIsVisible: () => W.current?.chromeCaps?.isVisible(G()) ?? Se
115
+ }), J = f(ze), Y = l((e, t) => {
116
+ let n = fe(S?.surface() ?? null, e, t), i = A(), [a, o] = r(n.x, n.y, {
117
+ left: i.x,
118
+ top: i.y
122
119
  }, j());
123
120
  return {
124
121
  x: a,
@@ -154,7 +151,7 @@ function m(o) {
154
151
  L,
155
152
  U,
156
153
  J
157
- ]), ze = d(() => {
154
+ ]), Be = d(() => {
158
155
  let e = ie(() => O.current.selection.get(), (e, t) => {
159
156
  let n = W.current, r = {
160
157
  ...j(),
@@ -192,7 +189,7 @@ function m(o) {
192
189
  target: {
193
190
  dispatcher: H.current,
194
191
  affordanceAt: Q,
195
- classifyTarget: ze,
192
+ classifyTarget: Be,
196
193
  clientToWorld: Y,
197
194
  deps: () => ({
198
195
  view: B,
@@ -213,7 +210,7 @@ function m(o) {
213
210
  I,
214
211
  B,
215
212
  Q,
216
- ze,
213
+ Be,
217
214
  Y,
218
215
  G,
219
216
  V,
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasView.js","names":["NO_INPUTS","AUTO_POSE_DESCRIPTOR","ALWAYS_VISIBLE","sizeOf","rect","ALL_LAYERS","s","CanvasView","viewProp","selectionProp","props","registry","useOptionalViewRegistry","depRegistry","useOptionalDepRegistry","depRegistryRef","useLatest","ownSelection","useSelection","selectionOptions","viewSelection","inputs","useOptionalViewInputs","selection","live","rectAt","useCallback","b","outer","dims","rectNow","surface","IDENTITY_VIEW","UNMEASURED_DIMS","camera","useCanvasView","useInsertionEffect","adoptControlled","useLayoutEffect","announceControlled","useEffect","clearSubscribers","useImperativeHandle","cameraRef","setView","subscribeView","cameraAt","v","normalizeView","drawnLayers","viewPaintedLayers","sceneLayerGate","useState","createSceneLayerGate","layerIsPainted","layerId","viewApi","useMemo","setViewFromInput","ingestionApi","base","viewportWorldRect","dispatcherRef","useRef","createDispatcher","rotationBadge","own","createGestureSource","createDispatcherPreviewSources","inputsRef","ruleInputs","surfaceBoundsOf","boundsOf","id","surfaceBoundsOfPose","boundsOfPose","pose","useViewHelpers","helpersRef","helpers","clientToWorldHere","canvas","x","y","clientToWorld","cx","cy","getAnchorState","anchorStateFrom","pathFromPlane","path","useDeviceProfile","affordanceAt","inner","buildAffordanceAt","extra","world","layerAffordance","targetScale","classifyTarget","buildClassifyTarget","i","frame","wx","wy","ids","registration","createViewportLayer","label","background","reason","order","interactive","paint"],"sources":["../../src/canvas/CanvasView.tsx"],"sourcesContent":["/**\n * `<CanvasView>` — a second view on an existing canvas: its own camera over a\n * rect of the surface, with input routed to it.\n *\n * Mount one inside `<SceneCanvas>`, or declare the same thing through the\n * surface's `views` prop, which renders one of these per descriptor.\n */\nimport {\n useCallback, useEffect, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState,\n type Ref,\n} from 'react';\nimport type { CanvasViewCamera } from './canvasExtension';\nimport type { Dims, RenderLayer } from 'core/layers/render';\nimport { normalizeView, type View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { createViewportLayer } from 'features/viewports/viewportLayer';\nimport { createDispatcher } from '@weasel-js/routing';\nimport type { IngestionDep, ViewApi } from 'interactions/actions/depSchema';\nimport { viewportWorldRect } from 'core/viewport/viewportWorldRect';\nimport { useSelection, type SelectionApi, type UseSelectionOptions } from 'core/selection/useSelection';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport type { PoseDescriptor } from 'interactions/actions/resize/geometry';\nimport { useViewHelpers } from './useViewHelpers';\nimport { useCanvasView } from './useCanvasView';\nimport { anchorStateFrom, buildAffordanceAt, buildClassifyTarget, layerAffordance } from './affordanceAt';\nimport { pathFromPlane } from './planeClips';\nimport { useOptionalDepRegistry } from '@weasel-js/routing/react';\nimport { useLatest } from '@weasel-js/react';\nimport { useDeviceProfile } from 'core/device/useDeviceProfile';\nimport {\n createGestureSource,\n createDispatcherPreviewSources,\n} from './SceneCanvas/dispatcherGestureBounds';\nimport { useOptionalViewInputs, type SurfaceViewInputs, type ViewRuleInputs } from './viewInputs';\nimport { createSceneLayerGate, viewPaintedLayers } from './sceneLayerPaint';\nimport {\n useOptionalViewRegistry,\n IDENTITY_VIEW,\n UNMEASURED_DIMS,\n type ViewRegistration,\n} from './viewRegistry';\n\n/** A rect on the surface, in CSS pixels from the canvas top-left. */\nexport interface ViewRect { x: number; y: number; w: number; h: number }\n\n/** Props for `<CanvasView>`. @experimental */\nexport interface CanvasViewProps {\n /** Identifies the view to the surface and to input routing. Must be unique\n * among the views on one canvas. */\n id: string;\n /** Where this view paints, recomputed every frame so the rect can track the\n * outer camera. A plain rect is accepted for a fixed panel. */\n bounds: ViewRect | ((outer: View, dims: Dims) => ViewRect);\n /** Camera. Supply this to control it; otherwise the view keeps its own,\n * seeded from `defaultView`. `onViewChange` fires either way.\n *\n * A thunk is a camera derived from the canvas's — a loupe following the\n * pointer — read fresh at every paint and every event, so the two cannot\n * disagree mid-gesture. It is controlled: a pan inside the view reaches\n * only `onViewChange`. */\n view?: View | ((outer: View, dims: Dims) => View);\n defaultView?: View;\n onViewChange?: (v: View) => void;\n /** Pan limits, applied to every camera change the same way `<Canvas>`\n * applies its own. */\n viewBounds?: Bounds;\n /** Receives this view's camera, to read, drive, and watch from outside it. */\n cameraRef?: Ref<CanvasViewCamera>;\n /** Which of the surface's layers this view paints. Defaults to all of them —\n * the same content through a second camera. */\n layers?: (surface: readonly RenderLayer<unknown>[]) => readonly RenderLayer<unknown>[];\n /**\n * Show or hide layers in this view only, by id — the map `<Canvas>` takes,\n * applied after `layers` narrows the stack. A scene layer paints as\n * `scene:<layerId>`; one hidden here neither paints nor picks in this view,\n * and a marquee or Cmd+A routed here passes over it. The surface and every\n * other view are unaffected.\n */\n layerVisibility?: Record<string, boolean>;\n /** Draw order for this view, by layer id, bottom first. A listed order is\n * the whole list, so a layer left out of it is neither painted nor picked\n * here. */\n layerOrder?: string[];\n /** Opaque ground painted before the source layers, so the surface does not\n * show through where the inner camera sees nothing. */\n background?: string;\n /** Paint and hit order. Defaults to `Infinity` — after every view the\n * surface declared as a prop. */\n order?: number;\n /** Label for debug overlays. Defaults to the id. */\n label?: string;\n /**\n * Whether input over the view resolves through its camera. Default `true`:\n * a press selects what the view shows, and a drag moves it in the view's\n * world units. `false` paints only, and input over it reaches the canvas\n * beneath as though the view were not there.\n *\n * Views do not nest. A view paints and routes the surface's own stack,\n * never another view; overlapping views are hit in paint order.\n */\n interactive?: boolean;\n /**\n * Whether the surface paints the view. Default `true`. `false` is for a\n * host that draws the view inside chrome of its own — a HUD window's\n * interior — through `SceneCanvasApi.addView`'s `draw`, so it lands in\n * that chrome's z-order rather than the surface's.\n */\n paint?: boolean;\n /** A selection of this view's own, which actions dispatched inside it read\n * and write instead of the surface's. Omit both this and\n * `selectionOptions` and the view shares the surface's selection — the\n * default, so undo restores one selection rather than N. */\n selection?: SelectionApi;\n /** Opts this view into owning a selection, configured thus. Ignored when\n * `selection` is supplied. */\n selectionOptions?: UseSelectionOptions;\n}\n\n/** What a view builds its helpers from outside a surface: nothing but the\n * default geometry, which answers `null` for every lookup. */\n// A view outside a surface has no inputs to inherit — including a selection,\n// so it falls back to owning one.\nconst NO_INPUTS: Omit<SurfaceViewInputs, 'selectionApi'> = {\n adapter: undefined,\n geometry: AUTO_POSE_DESCRIPTOR as unknown as PoseDescriptor<unknown>,\n boundsOf: undefined,\n};\n\nconst ALWAYS_VISIBLE = (): boolean => true;\n\nconst sizeOf = (rect: ViewRect): Dims => ({ width: rect.w, height: rect.h });\n\nconst ALL_LAYERS = (s: readonly RenderLayer<unknown>[]): readonly RenderLayer<unknown>[] => s;\n\n/**\n * @experimental\n *\n * One view on a shared canvas. Owns a camera, contributes the viewport node\n * that paints it, and registers the dispatch record that sends gestures inside\n * its rect to that camera rather than to the canvas's.\n *\n * Renders nothing itself — it is a declaration, and the surface does the\n * drawing. Outside a surface that mounts a view registry it is inert.\n */\nexport function CanvasView(props: CanvasViewProps): null {\n const {\n id, bounds, view: viewProp, defaultView, onViewChange, viewBounds,\n layers = ALL_LAYERS, layerVisibility, layerOrder, background, order = Infinity, label, cameraRef,\n selection: selectionProp, selectionOptions, interactive = true, paint = true,\n } = props;\n\n const registry = useOptionalViewRegistry();\n const depRegistry = useOptionalDepRegistry();\n const depRegistryRef = useLatest(depRegistry);\n\n // Hooks run unconditionally; the owned selection goes unused unless this\n // view asked for one.\n const ownSelection = useSelection(selectionOptions);\n const viewSelection = selectionProp ?? (selectionOptions ? ownSelection : undefined);\n\n const inputs = useOptionalViewInputs();\n // The selection this view acts on: its own when it has one, the surface's\n // otherwise.\n const selection = viewSelection ?? inputs?.selectionApi ?? ownSelection;\n\n // Everything the registration reads is behind a ref: the registration object\n // is registered once and must not churn, but what it answers with has to be\n // the last committed render's.\n const live = useLatest({\n bounds, layers, layerVisibility, layerOrder, viewProp, viewSelection, selection,\n });\n\n const rectAt = useCallback((outer: View, dims: Dims): ViewRect => {\n const b = live.current.bounds;\n return typeof b === 'function' ? b(outer, dims) : b;\n }, [live]);\n\n /** The rect for the surface's current frame — what a client point and a\n * clamp are measured against outside a draw call. */\n const rectNow = useCallback((): ViewRect => {\n const surface = registry?.surface();\n return rectAt(surface?.view() ?? IDENTITY_VIEW, surface?.dims() ?? UNMEASURED_DIMS);\n }, [registry, rectAt]);\n\n const {\n getView: camera, setView, setViewFromInput, subscribeView,\n adoptControlled, announceControlled, clearSubscribers,\n } = useCanvasView({\n view: typeof viewProp === 'function'\n ? () => {\n const surface = registry?.surface();\n return viewProp(surface?.view() ?? IDENTITY_VIEW, surface?.dims() ?? UNMEASURED_DIMS);\n }\n : viewProp,\n defaultView,\n onViewChange,\n viewBounds,\n dims: () => sizeOf(rectNow()),\n requestRedraw: () => registry?.surface()?.requestRedraw(),\n });\n useInsertionEffect(adoptControlled);\n useLayoutEffect(announceControlled);\n useEffect(() => clearSubscribers, [clearSubscribers]);\n useImperativeHandle(cameraRef, () => ({ getView: camera, setView, subscribeView }), [camera, setView, subscribeView]);\n\n /** The camera for a frame the caller names. A derived camera is asked for\n * that frame; any other is the same whatever the surface is doing. */\n const cameraAt = useCallback((outer: View, dims: Dims): View => {\n const v = live.current.viewProp;\n return typeof v === 'function' ? normalizeView(v(outer, dims)) : camera();\n }, [live, camera]);\n\n /** The surface's layers this view draws, in the order it draws them. */\n const drawnLayers = useCallback((): readonly RenderLayer<unknown>[] => (\n viewPaintedLayers(registry?.surface()?.layers() ?? [], live.current)\n ), [registry, live]);\n\n const [sceneLayerGate] = useState(createSceneLayerGate);\n /** What this view's picks, marquees and select-alls ask of a scene layer. */\n const layerIsPainted = useCallback((layerId: string): boolean => (\n sceneLayerGate(registry?.surface()?.layers() ?? [], live.current)(layerId)\n ), [registry, sceneLayerGate, live]);\n\n const viewApi = useMemo<ViewApi>(() => ({\n get: camera,\n set: setViewFromInput,\n hostSize: () => sizeOf(rectNow()),\n layerIsPainted,\n }), [camera, rectNow, setViewFromInput, layerIsPainted]);\n\n // Paste placement is a camera question, so it is this view's when the paste\n // routed here. The rest of the dep — `resolveSrc`, `svg`, `clipboard` — is\n // the surface's one wiring, read live off the canvas registry.\n const ingestionApi = useMemo<IngestionDep>(() => {\n const base = (): IngestionDep | undefined => depRegistryRef.current?.get('ingestion');\n return {\n viewportWorldRect: () => viewportWorldRect(camera(), sizeOf(rectNow())),\n get resolveSrc() { return base()?.resolveSrc; },\n get svg() { return base()?.svg; },\n get clipboard() { return base()?.clipboard; },\n };\n }, [camera, rectNow, depRegistryRef]);\n\n // One dispatcher per view: in-flight handles are per-view state, and two\n // views must not be able to see each other's.\n const dispatcherRef = useRef<ReturnType<typeof createDispatcher> | null>(null);\n if (!dispatcherRef.current) dispatcherRef.current = createDispatcher();\n\n // This view's overlay-aware state. The scene half comes from the surface —\n // same adapter, same tools — but everything gesture-shaped is read off this\n // view's own dispatcher, which is where a gesture inside this view lands.\n const rotationBadge = inputs?.rotationBadge ?? null;\n const own = useMemo(() => ({\n gestureSource: createGestureSource(() => dispatcherRef.current),\n ...createDispatcherPreviewSources(() => dispatcherRef.current),\n }), []);\n\n const inputsRef = useLatest(inputs);\n\n /** The chrome-caps context this view answers for: its selection, its camera,\n * its dispatcher's in-flight action. */\n const ruleInputs = useCallback((): ViewRuleInputs => ({\n selection: live.current.selection.get(),\n view: camera(),\n action: dispatcherRef.current!.getActiveAction(),\n }), [camera, live]);\n\n // The surface's resolver, asked for this view's camera.\n const surfaceBoundsOf = inputs?.boundsOf;\n const boundsOf = useMemo(\n () => (surfaceBoundsOf ? (id: string) => surfaceBoundsOf(id, camera()) : undefined),\n [surfaceBoundsOf, camera],\n );\n const surfaceBoundsOfPose = inputs?.boundsOfPose;\n const boundsOfPose = useMemo(\n () => (surfaceBoundsOfPose\n ? (id: string, pose: unknown) => surfaceBoundsOfPose(id, pose, camera())\n : undefined),\n [surfaceBoundsOfPose, camera],\n );\n\n const { helpers } = useViewHelpers<unknown>({\n ...(inputs ?? NO_INPUTS),\n boundsOf,\n boundsOfPose,\n ...own,\n selection: selection.current,\n getIsVisible: () =>\n inputsRef.current?.chromeCaps?.isVisible(ruleInputs()) ?? ALWAYS_VISIBLE,\n });\n const helpersRef = useLatest(helpers);\n\n /** A client point in this view's world. The rect moves with the outer\n * camera, so it is read per call rather than closed over. */\n const clientToWorldHere = useCallback((cx: number, cy: number): { x: number; y: number } => {\n const canvas = registry?.surface()?.origin() ?? { left: 0, top: 0 };\n const rect = rectNow();\n const [x, y] = clientToWorld(\n cx, cy,\n { left: canvas.left + rect.x, top: canvas.top + rect.y },\n camera(),\n );\n return { x, y };\n }, [registry, rectNow, camera]);\n\n // Anchors are hit in this view's camera world, where its plane draws them.\n const getAnchorState = useMemo(() => anchorStateFrom(\n () => depRegistryRef.current,\n (id, path) => pathFromPlane(path, inputsRef.current?.planeOfNode?.(id, camera()) ?? null),\n ), [camera, depRegistryRef, inputsRef]);\n\n const { targetScale } = useDeviceProfile();\n\n // Selection chrome hit-testing for this view: same construction the surface\n // does for its own, against this view's chrome and camera.\n const affordanceAt = useMemo(() => {\n const inner = buildAffordanceAt({\n getChromeState: () => helpersRef.current.getChromeState(),\n getView: camera,\n targetScale,\n rotationBadge,\n getAnchorState,\n getIsVisible: () => helpersRef.current.getIsVisible(),\n });\n return (world: { x: number; y: number }) => {\n // A registered layer this view paints gets first refusal, on this\n // view's frame and envelope. One painted over the surface already had\n // its chance: it occludes the view before routing reaches here.\n const extra = registry?.surface()?.hitTestExtras(\n world.x, world.y, camera(), sizeOf(rectNow()), helpersRef.current, drawnLayers(),\n );\n return extra ? layerAffordance(extra.layerId, extra.hit) : inner(world);\n };\n }, [getAnchorState, rectNow, registry, targetScale, camera, drawnLayers, rotationBadge, helpersRef]);\n\n const classifyTarget = useMemo(() => {\n const inner = buildClassifyTarget(\n () => live.current.selection.get(),\n (wx, wy) => {\n const i = inputsRef.current;\n // This view's camera: the dispatcher converted with `clientToWorldHere`,\n // and a screen-pixel tolerance needs the scale that produced it. The\n // layer gate is this view's too, never the surface's.\n const frame = { ...camera(), layerIsPainted };\n if (i?.pickBest) return i.pickBest(wx, wy, frame);\n const ids = i?.pickEvery?.(wx, wy, frame) ?? [];\n return ids.length > 0 ? ids[ids.length - 1]! : null;\n },\n (id) => inputsRef.current?.kindOfNode?.(id),\n );\n return (world: { x: number; y: number }) => inner(world);\n }, [camera, layerIsPainted, live, inputsRef]);\n\n const registration = useMemo<ViewRegistration>(() => ({\n id,\n order,\n interactive,\n paint,\n layer: createViewportLayer<unknown, unknown>({\n id,\n label: label ?? id,\n source: drawnLayers,\n view: cameraAt,\n bounds: (outer, dims) => rectAt(outer, dims),\n // The surface half of the envelope passes through; the view half is\n // this view's, so its layers paint its chrome rather than the\n // surface's.\n data: (outer) => ({ ...(outer as object), ...helpersRef.current, viewId: id }),\n ...(background !== undefined ? { background } : {}),\n }),\n layerIsPainted,\n target: {\n dispatcher: dispatcherRef.current!,\n affordanceAt,\n classifyTarget,\n clientToWorld: clientToWorldHere,\n deps: () => ({\n view: viewApi,\n ingestion: ingestionApi,\n // An Escape here cancels what is in flight here.\n dispatcher: { cancelAll: (reason) => dispatcherRef.current!.cancelAll(reason) },\n // Only a view with its own selection overlays that one; otherwise the\n // surface's answer stands, wrappers (`selectable`) included.\n ...(live.current.viewSelection ? { selection: live.current.viewSelection } : {}),\n }),\n // Action eligibility is chrome-caps evaluated against this view, so a\n // rule that hides an action in one panel cannot decline a gesture in\n // another.\n getRuleCtx: () => inputsRef.current?.chromeCaps?.ruleCtx(ruleInputs()),\n },\n }), [id, order, interactive, paint, label, background, rectAt, cameraAt, viewApi,\n affordanceAt, classifyTarget, clientToWorldHere, ruleInputs, ingestionApi, drawnLayers,\n layerIsPainted, live, inputsRef, helpersRef]);\n\n useEffect(() => {\n if (!registry) return;\n return registry.register(registration);\n }, [registry, registration]);\n\n // Apart from the registration, which is replaced whenever a prop it reads\n // changes: only the view going away ends what is in flight over it.\n useEffect(() => () => dispatcherRef.current?.cancelAll('cancel'), []);\n\n // A controlled camera change is invisible until the surface repaints; an\n // uncontrolled one asks for its repaint in `setView`.\n useEffect(() => {\n registry?.surface()?.requestRedraw();\n }, [registry, viewProp]);\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CanvasView.js","names":["NO_INPUTS","AUTO_POSE_DESCRIPTOR","ALWAYS_VISIBLE","sizeOf","rect","ALL_LAYERS","s","CanvasView","viewProp","selectionProp","props","registry","useOptionalViewRegistry","depRegistry","useOptionalDepRegistry","depRegistryRef","useLatest","ownSelection","useSelection","selectionOptions","viewSelection","inputs","useOptionalViewInputs","selection","live","rectAt","useCallback","b","outer","dims","rectNow","surface","IDENTITY_VIEW","UNMEASURED_DIMS","camera","useCanvasView","useInsertionEffect","adoptControlled","useLayoutEffect","announceControlled","useEffect","clearSubscribers","useImperativeHandle","cameraRef","setView","subscribeView","cameraAt","v","normalizeView","drawnLayers","viewPaintedLayers","sceneLayerGate","useState","createSceneLayerGate","layerIsPainted","layerId","viewApi","useMemo","setViewFromInput","ingestionApi","base","viewportWorldRect","dispatcherRef","useRef","createDispatcher","rotationBadge","own","createGestureSource","createDispatcherPreviewSources","inputsRef","ruleInputs","surfaceBoundsOf","boundsOf","id","surfaceBoundsOfPose","boundsOfPose","pose","useViewHelpers","helpersRef","helpers","clientToWorldHere","local","surfaceLocal","cx","cy","x","y","clientToWorld","getAnchorState","anchorStateFrom","pathFromPlane","path","useDeviceProfile","affordanceAt","inner","buildAffordanceAt","extra","world","layerAffordance","targetScale","classifyTarget","buildClassifyTarget","i","frame","wx","wy","ids","registration","createViewportLayer","label","background","reason","order","interactive","paint"],"sources":["../../src/canvas/CanvasView.tsx"],"sourcesContent":["/**\n * `<CanvasView>` — a second view on an existing canvas: its own camera over a\n * rect of the surface, with input routed to it.\n *\n * Mount one inside `<SceneCanvas>`, or declare the same thing through the\n * surface's `views` prop, which renders one of these per descriptor.\n */\nimport {\n useCallback, useEffect, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState,\n type Ref,\n} from 'react';\nimport type { CanvasViewCamera } from './canvasExtension';\nimport type { Dims, RenderLayer } from 'core/layers/render';\nimport { normalizeView, type View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { createViewportLayer } from 'features/viewports/viewportLayer';\nimport { createDispatcher } from '@weasel-js/routing';\nimport type { IngestionDep, ViewApi } from 'interactions/actions/depSchema';\nimport { viewportWorldRect } from 'core/viewport/viewportWorldRect';\nimport { useSelection, type SelectionApi, type UseSelectionOptions } from 'core/selection/useSelection';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport type { PoseDescriptor } from 'interactions/actions/resize/geometry';\nimport { useViewHelpers } from './useViewHelpers';\nimport { useCanvasView } from './useCanvasView';\nimport { anchorStateFrom, buildAffordanceAt, buildClassifyTarget, layerAffordance } from './affordanceAt';\nimport { pathFromPlane } from './planeClips';\nimport { useOptionalDepRegistry } from '@weasel-js/routing/react';\nimport { useLatest } from '@weasel-js/react';\nimport { useDeviceProfile } from 'core/device/useDeviceProfile';\nimport {\n createGestureSource,\n createDispatcherPreviewSources,\n} from './SceneCanvas/dispatcherGestureBounds';\nimport { useOptionalViewInputs, type SurfaceViewInputs, type ViewRuleInputs } from './viewInputs';\nimport { createSceneLayerGate, viewPaintedLayers } from './sceneLayerPaint';\nimport {\n useOptionalViewRegistry,\n surfaceLocal,\n IDENTITY_VIEW,\n UNMEASURED_DIMS,\n type ViewRegistration,\n} from './viewRegistry';\n\n/** A rect on the surface, in CSS pixels from the canvas top-left. */\nexport interface ViewRect { x: number; y: number; w: number; h: number }\n\n/** Props for `<CanvasView>`. @experimental */\nexport interface CanvasViewProps {\n /** Identifies the view to the surface and to input routing. Must be unique\n * among the views on one canvas. */\n id: string;\n /** Where this view paints, recomputed every frame so the rect can track the\n * outer camera. A plain rect is accepted for a fixed panel. */\n bounds: ViewRect | ((outer: View, dims: Dims) => ViewRect);\n /** Camera. Supply this to control it; otherwise the view keeps its own,\n * seeded from `defaultView`. `onViewChange` fires either way.\n *\n * A thunk is a camera derived from the canvas's — a loupe following the\n * pointer — read fresh at every paint and every event, so the two cannot\n * disagree mid-gesture. It is controlled: a pan inside the view reaches\n * only `onViewChange`. */\n view?: View | ((outer: View, dims: Dims) => View);\n defaultView?: View;\n onViewChange?: (v: View) => void;\n /** Pan limits, applied to every camera change the same way `<Canvas>`\n * applies its own. */\n viewBounds?: Bounds;\n /** Receives this view's camera, to read, drive, and watch from outside it. */\n cameraRef?: Ref<CanvasViewCamera>;\n /** Which of the surface's layers this view paints. Defaults to all of them —\n * the same content through a second camera. */\n layers?: (surface: readonly RenderLayer<unknown>[]) => readonly RenderLayer<unknown>[];\n /**\n * Show or hide layers in this view only, by id — the map `<Canvas>` takes,\n * applied after `layers` narrows the stack. A scene layer paints as\n * `scene:<layerId>`; one hidden here neither paints nor picks in this view,\n * and a marquee or Cmd+A routed here passes over it. The surface and every\n * other view are unaffected.\n */\n layerVisibility?: Record<string, boolean>;\n /** Draw order for this view, by layer id, bottom first. A listed order is\n * the whole list, so a layer left out of it is neither painted nor picked\n * here. */\n layerOrder?: string[];\n /** Opaque ground painted before the source layers, so the surface does not\n * show through where the inner camera sees nothing. */\n background?: string;\n /** Paint and hit order. Defaults to `Infinity` — after every view the\n * surface declared as a prop. */\n order?: number;\n /** Label for debug overlays. Defaults to the id. */\n label?: string;\n /**\n * Whether input over the view resolves through its camera. Default `true`:\n * a press selects what the view shows, and a drag moves it in the view's\n * world units. `false` paints only, and input over it reaches the canvas\n * beneath as though the view were not there.\n *\n * Views do not nest. A view paints and routes the surface's own stack,\n * never another view; overlapping views are hit in paint order.\n */\n interactive?: boolean;\n /**\n * Whether the surface paints the view. Default `true`. `false` is for a\n * host that draws the view inside chrome of its own — a HUD window's\n * interior — through `SceneCanvasApi.addView`'s `draw`, so it lands in\n * that chrome's z-order rather than the surface's.\n */\n paint?: boolean;\n /** A selection of this view's own, which actions dispatched inside it read\n * and write instead of the surface's. Omit both this and\n * `selectionOptions` and the view shares the surface's selection — the\n * default, so undo restores one selection rather than N. */\n selection?: SelectionApi;\n /** Opts this view into owning a selection, configured thus. Ignored when\n * `selection` is supplied. */\n selectionOptions?: UseSelectionOptions;\n}\n\n/** What a view builds its helpers from outside a surface: nothing but the\n * default geometry, which answers `null` for every lookup. */\n// A view outside a surface has no inputs to inherit — including a selection,\n// so it falls back to owning one.\nconst NO_INPUTS: Omit<SurfaceViewInputs, 'selectionApi'> = {\n adapter: undefined,\n geometry: AUTO_POSE_DESCRIPTOR as unknown as PoseDescriptor<unknown>,\n boundsOf: undefined,\n};\n\nconst ALWAYS_VISIBLE = (): boolean => true;\n\nconst sizeOf = (rect: ViewRect): Dims => ({ width: rect.w, height: rect.h });\n\nconst ALL_LAYERS = (s: readonly RenderLayer<unknown>[]): readonly RenderLayer<unknown>[] => s;\n\n/**\n * @experimental\n *\n * One view on a shared canvas. Owns a camera, contributes the viewport node\n * that paints it, and registers the dispatch record that sends gestures inside\n * its rect to that camera rather than to the canvas's.\n *\n * Renders nothing itself — it is a declaration, and the surface does the\n * drawing. Outside a surface that mounts a view registry it is inert.\n */\nexport function CanvasView(props: CanvasViewProps): null {\n const {\n id, bounds, view: viewProp, defaultView, onViewChange, viewBounds,\n layers = ALL_LAYERS, layerVisibility, layerOrder, background, order = Infinity, label, cameraRef,\n selection: selectionProp, selectionOptions, interactive = true, paint = true,\n } = props;\n\n const registry = useOptionalViewRegistry();\n const depRegistry = useOptionalDepRegistry();\n const depRegistryRef = useLatest(depRegistry);\n\n // Hooks run unconditionally; the owned selection goes unused unless this\n // view asked for one.\n const ownSelection = useSelection(selectionOptions);\n const viewSelection = selectionProp ?? (selectionOptions ? ownSelection : undefined);\n\n const inputs = useOptionalViewInputs();\n // The selection this view acts on: its own when it has one, the surface's\n // otherwise.\n const selection = viewSelection ?? inputs?.selectionApi ?? ownSelection;\n\n // Everything the registration reads is behind a ref: the registration object\n // is registered once and must not churn, but what it answers with has to be\n // the last committed render's.\n const live = useLatest({\n bounds, layers, layerVisibility, layerOrder, viewProp, viewSelection, selection,\n });\n\n const rectAt = useCallback((outer: View, dims: Dims): ViewRect => {\n const b = live.current.bounds;\n return typeof b === 'function' ? b(outer, dims) : b;\n }, [live]);\n\n /** The rect for the surface's current frame — what a client point and a\n * clamp are measured against outside a draw call. */\n const rectNow = useCallback((): ViewRect => {\n const surface = registry?.surface();\n return rectAt(surface?.view() ?? IDENTITY_VIEW, surface?.dims() ?? UNMEASURED_DIMS);\n }, [registry, rectAt]);\n\n const {\n getView: camera, setView, setViewFromInput, subscribeView,\n adoptControlled, announceControlled, clearSubscribers,\n } = useCanvasView({\n view: typeof viewProp === 'function'\n ? () => {\n const surface = registry?.surface();\n return viewProp(surface?.view() ?? IDENTITY_VIEW, surface?.dims() ?? UNMEASURED_DIMS);\n }\n : viewProp,\n defaultView,\n onViewChange,\n viewBounds,\n dims: () => sizeOf(rectNow()),\n requestRedraw: () => registry?.surface()?.requestRedraw(),\n });\n useInsertionEffect(adoptControlled);\n useLayoutEffect(announceControlled);\n useEffect(() => clearSubscribers, [clearSubscribers]);\n useImperativeHandle(cameraRef, () => ({ getView: camera, setView, subscribeView }), [camera, setView, subscribeView]);\n\n /** The camera for a frame the caller names. A derived camera is asked for\n * that frame; any other is the same whatever the surface is doing. */\n const cameraAt = useCallback((outer: View, dims: Dims): View => {\n const v = live.current.viewProp;\n return typeof v === 'function' ? normalizeView(v(outer, dims)) : camera();\n }, [live, camera]);\n\n /** The surface's layers this view draws, in the order it draws them. */\n const drawnLayers = useCallback((): readonly RenderLayer<unknown>[] => (\n viewPaintedLayers(registry?.surface()?.layers() ?? [], live.current)\n ), [registry, live]);\n\n const [sceneLayerGate] = useState(createSceneLayerGate);\n /** What this view's picks, marquees and select-alls ask of a scene layer. */\n const layerIsPainted = useCallback((layerId: string): boolean => (\n sceneLayerGate(registry?.surface()?.layers() ?? [], live.current)(layerId)\n ), [registry, sceneLayerGate, live]);\n\n const viewApi = useMemo<ViewApi>(() => ({\n get: camera,\n set: setViewFromInput,\n hostSize: () => sizeOf(rectNow()),\n layerIsPainted,\n }), [camera, rectNow, setViewFromInput, layerIsPainted]);\n\n // Paste placement is a camera question, so it is this view's when the paste\n // routed here. The rest of the dep — `resolveSrc`, `svg`, `clipboard` — is\n // the surface's one wiring, read live off the canvas registry.\n const ingestionApi = useMemo<IngestionDep>(() => {\n const base = (): IngestionDep | undefined => depRegistryRef.current?.get('ingestion');\n return {\n viewportWorldRect: () => viewportWorldRect(camera(), sizeOf(rectNow())),\n get resolveSrc() { return base()?.resolveSrc; },\n get svg() { return base()?.svg; },\n get clipboard() { return base()?.clipboard; },\n };\n }, [camera, rectNow, depRegistryRef]);\n\n // One dispatcher per view: in-flight handles are per-view state, and two\n // views must not be able to see each other's.\n const dispatcherRef = useRef<ReturnType<typeof createDispatcher> | null>(null);\n if (!dispatcherRef.current) dispatcherRef.current = createDispatcher();\n\n // This view's overlay-aware state. The scene half comes from the surface —\n // same adapter, same tools — but everything gesture-shaped is read off this\n // view's own dispatcher, which is where a gesture inside this view lands.\n const rotationBadge = inputs?.rotationBadge ?? null;\n const own = useMemo(() => ({\n gestureSource: createGestureSource(() => dispatcherRef.current),\n ...createDispatcherPreviewSources(() => dispatcherRef.current),\n }), []);\n\n const inputsRef = useLatest(inputs);\n\n /** The chrome-caps context this view answers for: its selection, its camera,\n * its dispatcher's in-flight action. */\n const ruleInputs = useCallback((): ViewRuleInputs => ({\n selection: live.current.selection.get(),\n view: camera(),\n action: dispatcherRef.current!.getActiveAction(),\n }), [camera, live]);\n\n // The surface's resolver, asked for this view's camera.\n const surfaceBoundsOf = inputs?.boundsOf;\n const boundsOf = useMemo(\n () => (surfaceBoundsOf ? (id: string) => surfaceBoundsOf(id, camera()) : undefined),\n [surfaceBoundsOf, camera],\n );\n const surfaceBoundsOfPose = inputs?.boundsOfPose;\n const boundsOfPose = useMemo(\n () => (surfaceBoundsOfPose\n ? (id: string, pose: unknown) => surfaceBoundsOfPose(id, pose, camera())\n : undefined),\n [surfaceBoundsOfPose, camera],\n );\n\n const { helpers } = useViewHelpers<unknown>({\n ...(inputs ?? NO_INPUTS),\n boundsOf,\n boundsOfPose,\n ...own,\n selection: selection.current,\n getIsVisible: () =>\n inputsRef.current?.chromeCaps?.isVisible(ruleInputs()) ?? ALWAYS_VISIBLE,\n });\n const helpersRef = useLatest(helpers);\n\n /** A client point in this view's world. The rect moves with the outer\n * camera, so it is read per call rather than closed over. */\n const clientToWorldHere = useCallback((cx: number, cy: number): { x: number; y: number } => {\n const local = surfaceLocal(registry?.surface() ?? null, cx, cy);\n const rect = rectNow();\n const [x, y] = clientToWorld(local.x, local.y, { left: rect.x, top: rect.y }, camera());\n return { x, y };\n }, [registry, rectNow, camera]);\n\n // Anchors are hit in this view's camera world, where its plane draws them.\n const getAnchorState = useMemo(() => anchorStateFrom(\n () => depRegistryRef.current,\n (id, path) => pathFromPlane(path, inputsRef.current?.planeOfNode?.(id, camera()) ?? null),\n ), [camera, depRegistryRef, inputsRef]);\n\n const { targetScale } = useDeviceProfile();\n\n // Selection chrome hit-testing for this view: same construction the surface\n // does for its own, against this view's chrome and camera.\n const affordanceAt = useMemo(() => {\n const inner = buildAffordanceAt({\n getChromeState: () => helpersRef.current.getChromeState(),\n getView: camera,\n targetScale,\n rotationBadge,\n getAnchorState,\n getIsVisible: () => helpersRef.current.getIsVisible(),\n });\n return (world: { x: number; y: number }) => {\n // A registered layer this view paints gets first refusal, on this\n // view's frame and envelope. One painted over the surface already had\n // its chance: it occludes the view before routing reaches here.\n const extra = registry?.surface()?.hitTestExtras(\n world.x, world.y, camera(), sizeOf(rectNow()), helpersRef.current, drawnLayers(),\n );\n return extra ? layerAffordance(extra.layerId, extra.hit) : inner(world);\n };\n }, [getAnchorState, rectNow, registry, targetScale, camera, drawnLayers, rotationBadge, helpersRef]);\n\n const classifyTarget = useMemo(() => {\n const inner = buildClassifyTarget(\n () => live.current.selection.get(),\n (wx, wy) => {\n const i = inputsRef.current;\n // This view's camera: the dispatcher converted with `clientToWorldHere`,\n // and a screen-pixel tolerance needs the scale that produced it. The\n // layer gate is this view's too, never the surface's.\n const frame = { ...camera(), layerIsPainted };\n if (i?.pickBest) return i.pickBest(wx, wy, frame);\n const ids = i?.pickEvery?.(wx, wy, frame) ?? [];\n return ids.length > 0 ? ids[ids.length - 1]! : null;\n },\n (id) => inputsRef.current?.kindOfNode?.(id),\n );\n return (world: { x: number; y: number }) => inner(world);\n }, [camera, layerIsPainted, live, inputsRef]);\n\n const registration = useMemo<ViewRegistration>(() => ({\n id,\n order,\n interactive,\n paint,\n layer: createViewportLayer<unknown, unknown>({\n id,\n label: label ?? id,\n source: drawnLayers,\n view: cameraAt,\n bounds: (outer, dims) => rectAt(outer, dims),\n // The surface half of the envelope passes through; the view half is\n // this view's, so its layers paint its chrome rather than the\n // surface's.\n data: (outer) => ({ ...(outer as object), ...helpersRef.current, viewId: id }),\n ...(background !== undefined ? { background } : {}),\n }),\n layerIsPainted,\n target: {\n dispatcher: dispatcherRef.current!,\n affordanceAt,\n classifyTarget,\n clientToWorld: clientToWorldHere,\n deps: () => ({\n view: viewApi,\n ingestion: ingestionApi,\n // An Escape here cancels what is in flight here.\n dispatcher: { cancelAll: (reason) => dispatcherRef.current!.cancelAll(reason) },\n // Only a view with its own selection overlays that one; otherwise the\n // surface's answer stands, wrappers (`selectable`) included.\n ...(live.current.viewSelection ? { selection: live.current.viewSelection } : {}),\n }),\n // Action eligibility is chrome-caps evaluated against this view, so a\n // rule that hides an action in one panel cannot decline a gesture in\n // another.\n getRuleCtx: () => inputsRef.current?.chromeCaps?.ruleCtx(ruleInputs()),\n },\n }), [id, order, interactive, paint, label, background, rectAt, cameraAt, viewApi,\n affordanceAt, classifyTarget, clientToWorldHere, ruleInputs, ingestionApi, drawnLayers,\n layerIsPainted, live, inputsRef, helpersRef]);\n\n useEffect(() => {\n if (!registry) return;\n return registry.register(registration);\n }, [registry, registration]);\n\n // Apart from the registration, which is replaced whenever a prop it reads\n // changes: only the view going away ends what is in flight over it.\n useEffect(() => () => dispatcherRef.current?.cancelAll('cancel'), []);\n\n // A controlled camera change is invisible until the surface repaints; an\n // uncontrolled one asks for its repaint in `setView`.\n useEffect(() => {\n registry?.surface()?.requestRedraw();\n }, [registry, viewProp]);\n\n return null;\n}\n"],"mappings":"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"}
@@ -23,10 +23,10 @@ function f({ canvasRef: u, anchorRef: d, viewRef: f, toWorld: m, offset: h }) {
23
23
  x: h?.right ?? 8,
24
24
  y: h?.top ?? 8
25
25
  }
26
- }), C = i(0), w = i(0), T = s(() => {
26
+ }), C = i(0), w = i(0), T = s((e, t) => {
27
27
  C.current++;
28
- let e = performance.now(), t = e - w.current;
29
- t >= 1e3 && (b(Math.round(C.current * 1e3 / t)), C.current = 0, w.current = e), T.request();
28
+ let n = performance.now(), r = n - w.current;
29
+ r >= 1e3 && (b(Math.round(C.current * 1e3 / r)), C.current = 0, w.current = n), t.request();
30
30
  }, { onResume: () => {
31
31
  C.current = 0, w.current = performance.now();
32
32
  } });
@@ -1 +1 @@
1
- {"version":3,"file":"CursorCoordsHud.js","names":["s","hud_module_default","CursorCoordsHud","toWorldRef","useLatest","toWorld","state","setState","useState","fps","setFps","anchorStyle","useHostAnchor","anchorRef","canvasRef","offset","framesRef","useRef","lastFlushRef","fpsLoop","useVisibleRaf","now","dt","useEffect","onMove","canvas","view","viewRef","client","e","rect","inCanvas","wx","wy","clientToWorld","point","at","decimal","qty","x","y"],"sources":["../../src/canvas/CursorCoordsHud.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * Fixed-position dev HUD that shows the cursor's current viewport\n * (client) coords next to the equivalent canvas (world) coords. Pins to the\n * top-right corner of the canvas's host; listens to `document` pointermove so it\n * reads the cursor even when it leaves the canvas.\n *\n * Mount inside a `<SceneCanvas>` subtree (or anywhere with access to a\n * canvas + view ref) for quick coord-reconciliation during gesture\n * debugging.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { decimal, qty } from '@weasel-js/quantity';\nimport { useLatest, useVisibleRaf } from '@weasel-js/react';\nimport s from './hud.module.css';\nimport { useHostAnchor } from './useHostAnchor';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\n\n/** Props for `<CursorCoordsHud>`. */\nexport interface CursorCoordsHudProps {\n canvasRef: React.RefObject<HTMLElement | null>;\n /** Element the HUD pins its corner to. Defaults to the canvas's parent — the\n * wrapper a bare `<canvas>` sits in. A detached canvas passes its own input\n * box, whose parent is the shared surface every pane sits in. */\n anchorRef?: React.RefObject<HTMLElement | null>;\n viewRef: React.RefObject<View>;\n /** Client coords to world. Defaults to the canvas's rect and `viewRef`. A\n * canvas whose routing converts some other way (a CSS transform, a 3D host)\n * passes that conversion, so the readout agrees with the picks. */\n toWorld?: (clientX: number, clientY: number) => [number, number];\n /** Inset from the canvas's top-right corner, in px. Default 8 on both axes. */\n offset?: { top?: number; right?: number };\n}\n\ninterface HudState {\n client: { x: number; y: number };\n world: { x: number; y: number } | null;\n inCanvas: boolean;\n}\n\n/** Debug overlay showing the pointer's client and world coordinates and the\n * current frame rate, pinned to the canvas's top-right corner. */\nexport function CursorCoordsHud({ canvasRef, anchorRef, viewRef, toWorld, offset }: CursorCoordsHudProps) {\n const toWorldRef = useLatest(toWorld);\n const [state, setState] = useState<HudState>({\n client: { x: 0, y: 0 }, world: null, inCanvas: false,\n });\n const [fps, setFps] = useState<number>(0);\n const { ref, style: anchorStyle } = useHostAnchor(\n () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,\n {\n align: { x: 'end', y: 'start' },\n offset: { x: offset?.right ?? 8, y: offset?.top ?? 8 },\n },\n );\n\n // FPS counter: tally frames per rAF tick; flush once a second.\n const framesRef = useRef(0);\n const lastFlushRef = useRef(0);\n const fpsLoop = useVisibleRaf(\n () => {\n framesRef.current++;\n const now = performance.now();\n const dt = now - lastFlushRef.current;\n if (dt >= 1000) {\n setFps(Math.round((framesRef.current * 1000) / dt));\n framesRef.current = 0;\n lastFlushRef.current = now;\n }\n fpsLoop.request();\n },\n // Frames not drawn while hidden are not frames that were slow to draw:\n // without this the readout would flush a near-zero rate on resume.\n {\n onResume: () => {\n framesRef.current = 0;\n lastFlushRef.current = performance.now();\n },\n },\n );\n\n useEffect(() => {\n lastFlushRef.current = performance.now();\n fpsLoop.request();\n return () => fpsLoop.cancel();\n }, [fpsLoop]);\n\n useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const canvas = canvasRef.current;\n const view = viewRef.current;\n const client = { x: e.clientX, y: e.clientY };\n if (!canvas || !view) {\n setState({ client, world: null, inCanvas: false });\n return;\n }\n const rect = canvas.getBoundingClientRect();\n const inCanvas =\n e.clientX >= rect.left && e.clientX <= rect.right &&\n e.clientY >= rect.top && e.clientY <= rect.bottom;\n const [wx, wy] = toWorldRef.current?.(e.clientX, e.clientY)\n ?? clientToWorld(e.clientX, e.clientY, rect, view);\n const world = { x: wx, y: wy };\n setState({ client, world, inCanvas });\n };\n\n document.addEventListener('pointermove', onMove);\n\n return () => {\n document.removeEventListener('pointermove', onMove);\n };\n }, [canvasRef, viewRef, toWorldRef]);\n\n if (!anchorStyle) return null;\n\n return (\n <div ref={ref} className={s.hud} style={anchorStyle}>\n <dl className={s.readings}>\n <dt className={s.muted}>fps</dt>\n <dd>{fps}</dd>\n <dt className={s.muted}>client</dt>\n <dd>{point(state.client, 0)}</dd>\n <dt className={s.muted}>world</dt>\n {state.world ? (\n <dd>\n {point(state.world, 1)}\n {state.inCanvas ? null : <span className={s.absent}> off-canvas</span>}\n </dd>\n ) : (\n <dd className={s.absent}>— no canvas or view yet</dd>\n )}\n </dl>\n </div>\n );\n}\n\n/** `(x, y)` at `places` decimals, its negatives written with U+2212. */\nfunction point({ x, y }: { x: number; y: number }, places: number): string {\n const at = decimal({ places, grouping: false });\n return `(${qty(x, at).text}, ${qty(y, at).text})`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CursorCoordsHud.js","names":["s","hud_module_default","CursorCoordsHud","toWorldRef","useLatest","toWorld","state","setState","useState","fps","setFps","anchorStyle","useHostAnchor","anchorRef","canvasRef","offset","framesRef","useRef","lastFlushRef","fpsLoop","useVisibleRaf","now","dt","useEffect","onMove","canvas","view","viewRef","client","e","rect","inCanvas","wx","wy","clientToWorld","point","at","decimal","qty","x","y"],"sources":["../../src/canvas/CursorCoordsHud.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * Fixed-position dev HUD that shows the cursor's current viewport\n * (client) coords next to the equivalent canvas (world) coords. Pins to the\n * top-right corner of the canvas's host; listens to `document` pointermove so it\n * reads the cursor even when it leaves the canvas.\n *\n * Mount inside a `<SceneCanvas>` subtree (or anywhere with access to a\n * canvas + view ref) for quick coord-reconciliation during gesture\n * debugging.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { decimal, qty } from '@weasel-js/quantity';\nimport { useLatest, useVisibleRaf } from '@weasel-js/react';\nimport s from './hud.module.css';\nimport { useHostAnchor } from './useHostAnchor';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\n\n/** Props for `<CursorCoordsHud>`. */\nexport interface CursorCoordsHudProps {\n canvasRef: React.RefObject<HTMLElement | null>;\n /** Element the HUD pins its corner to. Defaults to the canvas's parent — the\n * wrapper a bare `<canvas>` sits in. A detached canvas passes its own input\n * box, whose parent is the shared surface every pane sits in. */\n anchorRef?: React.RefObject<HTMLElement | null>;\n viewRef: React.RefObject<View>;\n /** Client coords to world. Defaults to the canvas's rect and `viewRef`. A\n * canvas whose routing converts some other way (a CSS transform, a 3D host)\n * passes that conversion, so the readout agrees with the picks. */\n toWorld?: (clientX: number, clientY: number) => [number, number];\n /** Inset from the canvas's top-right corner, in px. Default 8 on both axes. */\n offset?: { top?: number; right?: number };\n}\n\ninterface HudState {\n client: { x: number; y: number };\n world: { x: number; y: number } | null;\n inCanvas: boolean;\n}\n\n/** Debug overlay showing the pointer's client and world coordinates and the\n * current frame rate, pinned to the canvas's top-right corner. */\nexport function CursorCoordsHud({ canvasRef, anchorRef, viewRef, toWorld, offset }: CursorCoordsHudProps) {\n const toWorldRef = useLatest(toWorld);\n const [state, setState] = useState<HudState>({\n client: { x: 0, y: 0 }, world: null, inCanvas: false,\n });\n const [fps, setFps] = useState<number>(0);\n const { ref, style: anchorStyle } = useHostAnchor(\n () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,\n {\n align: { x: 'end', y: 'start' },\n offset: { x: offset?.right ?? 8, y: offset?.top ?? 8 },\n },\n );\n\n // FPS counter: tally frames per rAF tick; flush once a second.\n const framesRef = useRef(0);\n const lastFlushRef = useRef(0);\n const fpsLoop = useVisibleRaf(\n (_time, fpsLoop) => {\n framesRef.current++;\n const now = performance.now();\n const dt = now - lastFlushRef.current;\n if (dt >= 1000) {\n setFps(Math.round((framesRef.current * 1000) / dt));\n framesRef.current = 0;\n lastFlushRef.current = now;\n }\n fpsLoop.request();\n },\n // Frames not drawn while hidden are not frames that were slow to draw:\n // without this the readout would flush a near-zero rate on resume.\n {\n onResume: () => {\n framesRef.current = 0;\n lastFlushRef.current = performance.now();\n },\n },\n );\n\n useEffect(() => {\n lastFlushRef.current = performance.now();\n fpsLoop.request();\n return () => fpsLoop.cancel();\n }, [fpsLoop]);\n\n useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const canvas = canvasRef.current;\n const view = viewRef.current;\n const client = { x: e.clientX, y: e.clientY };\n if (!canvas || !view) {\n setState({ client, world: null, inCanvas: false });\n return;\n }\n const rect = canvas.getBoundingClientRect();\n const inCanvas =\n e.clientX >= rect.left && e.clientX <= rect.right &&\n e.clientY >= rect.top && e.clientY <= rect.bottom;\n const [wx, wy] = toWorldRef.current?.(e.clientX, e.clientY)\n ?? clientToWorld(e.clientX, e.clientY, rect, view);\n const world = { x: wx, y: wy };\n setState({ client, world, inCanvas });\n };\n\n document.addEventListener('pointermove', onMove);\n\n return () => {\n document.removeEventListener('pointermove', onMove);\n };\n }, [canvasRef, viewRef, toWorldRef]);\n\n if (!anchorStyle) return null;\n\n return (\n <div ref={ref} className={s.hud} style={anchorStyle}>\n <dl className={s.readings}>\n <dt className={s.muted}>fps</dt>\n <dd>{fps}</dd>\n <dt className={s.muted}>client</dt>\n <dd>{point(state.client, 0)}</dd>\n <dt className={s.muted}>world</dt>\n {state.world ? (\n <dd>\n {point(state.world, 1)}\n {state.inCanvas ? null : <span className={s.absent}> off-canvas</span>}\n </dd>\n ) : (\n <dd className={s.absent}>— no canvas or view yet</dd>\n )}\n </dl>\n </div>\n );\n}\n\n/** `(x, y)` at `places` decimals, its negatives written with U+2212. */\nfunction point({ x, y }: { x: number; y: number }, places: number): string {\n const at = decimal({ places, grouping: false });\n return `(${qty(x, at).text}, ${qty(y, at).text})`;\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { backgroundFillCommands as e } from "../core/layers/backgroundFill.js";
2
2
  import { normalizeView as t } from "../core/viewport/view.js";
3
3
  import { useCanvasSurface as n } from "./useCanvasSurface.js";
4
- import { surfaceBox as r } from "./surfaceBox.js";
4
+ import { SurfaceCanvas as r } from "./SurfaceCanvas.js";
5
5
  import { viewToMat3 as i } from "@weasel-js/geom";
6
6
  import { useCallback as a, useRef as o } from "react";
7
7
  import { assignRef as s } from "@weasel-js/react";
@@ -43,11 +43,11 @@ function u(u) {
43
43
  dpr: g,
44
44
  redrawOn: h,
45
45
  paintOnCommit: !0
46
- }), /* @__PURE__ */ c("canvas", {
46
+ }), /* @__PURE__ */ c(r, {
47
47
  ref: x,
48
48
  width: d,
49
49
  height: f,
50
- ...r(d, f, _)
50
+ className: _
51
51
  });
52
52
  }
53
53
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"DrawCanvas.js","names":["IDENTITY_VIEW","DrawCanvas","props","view","normalizeView","canvasElRef","useRef","setRefs","useCallback","el","assignRef","canvasRef","useCanvasSurface","content","draw","commands","background","backgroundFillCommands","viewToMat3","lease","surfaceBox","width","height","className"],"sources":["../../src/canvas/DrawCanvas.tsx"],"sourcesContent":["/**\n * `<DrawCanvas>` — a sized, DPR-correct WebGL2 surface that paints a list of\n * draw commands, with no scene, tools or dispatcher behind it.\n *\n * It paints through the same surface hook as `<SceneViewCanvas>`\n * (`useCanvasSurface`), whose frame loop stops while the canvas is off screen\n * or the tab is hidden. Like `<SceneViewCanvas>` it attaches no event\n * listeners. Its size is `width` × `height` unless a `className` rule sizes\n * the element; the drawing buffer stays `width` × `height` either way.\n */\nimport { useCallback, useRef } from 'react';\nimport type { Ref } from 'react';\nimport { assignRef } from '@weasel-js/react';\nimport type { Paint } from '@weasel-js/paint';\nimport { useCanvasSurface } from './useCanvasSurface';\nimport { surfaceBox } from './surfaceBox';\nimport type { CanvasRendererLease } from './canvasRenderer';\nimport { viewToMat3 } from '@weasel-js/geom';\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport type { RedrawSource } from '../core/layers/render';\nimport { backgroundFillCommands } from '../core/layers/backgroundFill';\nimport { normalizeView, type View } from '../core/viewport/view';\n\n/** What a `<DrawCanvas>` paints: a command list, or a function returning one\n * that is called on every paint with the surface's CSS-pixel size. */\nexport type DrawCanvasDraw =\n | readonly DrawCommand[]\n | ((size: { width: number; height: number }) => readonly DrawCommand[]);\n\n/** Props for `<DrawCanvas>`. */\nexport interface DrawCanvasProps {\n /** CSS-pixel width. The drawing buffer is `width × dpr`. */\n width: number;\n /** CSS-pixel height. */\n height: number;\n /** The commands to paint, in the coordinate space `view` maps to the\n * screen — CSS pixels when `view` is omitted. A new array repaints on the\n * next frame. A function is read at paint time, so state it reads outside\n * React repaints when one of `redrawOn`'s sources notifies. */\n draw: DrawCanvasDraw;\n /** Camera over `draw`'s commands. Defaults to the identity view. */\n view?: View;\n /** Fills the whole surface beneath `draw`, in screen space. The canvas is\n * transparent without it. */\n background?: Paint;\n /** External state a `draw` function reads. Each source is subscribed while\n * mounted and repaints the canvas when it notifies. */\n redrawOn?: readonly RedrawSource[];\n /** Device-pixel ratio. Defaults to `window.devicePixelRatio`, read per\n * paint. */\n dpr?: number;\n /** CSS class for the `<canvas>` element. */\n className?: string;\n /** Receives the underlying `<canvas>`, for pointer listeners or `toBlob`. */\n canvasRef?: Ref<HTMLCanvasElement>;\n}\n\nconst IDENTITY_VIEW: View = { x: 0, y: 0, scale: { x: 1, y: 1 } };\n\n/**\n * Paint draw commands onto a canvas of its own. For a surface that only draws —\n * a package demo, a swatch, a preview — where a `<SceneCanvas>` would bring a\n * scene, tools and an input dispatcher that nothing uses.\n */\nexport function DrawCanvas(props: DrawCanvasProps) {\n const { width, height, draw, background, redrawOn, dpr, className, canvasRef } = props;\n const view = props.view ? normalizeView(props.view) : IDENTITY_VIEW;\n\n const canvasElRef = useRef<HTMLCanvasElement | null>(null);\n const setRefs = useCallback((el: HTMLCanvasElement | null) => {\n canvasElRef.current = el;\n assignRef(canvasRef, el);\n }, [canvasRef]);\n\n const paint = (lease: CanvasRendererLease): boolean => {\n const el = canvasElRef.current;\n if (!el) return false;\n const content = typeof draw === 'function' ? draw({ width, height }) : draw;\n const commands: DrawCommand[] = background ? backgroundFillCommands(background, { width, height }) : [];\n commands.push({ kind: 'group', transform: viewToMat3(view), children: [...content] });\n return lease.paint(el, commands, view, { width, height, dpr });\n };\n useCanvasSurface(paint, { target: canvasElRef, dpr, redrawOn, paintOnCommit: true });\n\n return <canvas ref={setRefs} width={width} height={height} {...surfaceBox(width, height, className)} />;\n}\n"],"mappings":";;;;;;;;;AAyDA,IAAMA,IAAsB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;EAAE,GAAG;EAAG,GAAG;CAAE;AAAE;AAOhE,SAAgBC,EAAW,GAAwB;CACjD,IAAM,EAAE,UAAO,WAAQ,SAAM,eAAY,aAAU,QAAK,cAAW,iBAAcC,GAC3EC,IAAOD,EAAM,OAAOE,EAAcF,EAAM,IAAI,IAAIF,GAEhDK,IAAcC,EAAiC,IAAI,GACnDC,IAAUC,GAAa,MAAiC;EAE5D,AADA,EAAY,UAAUC,GACtBC,EAAUC,GAAWF,CAAE;CACzB,GAAG,CAACE,CAAS,CAAC;CAYd,OAFAC,GARe,MAAwC;EACrD,IAAMH,IAAKJ,EAAY;EACvB,IAAI,CAACI,GAAI,OAAO;EAChB,IAAMI,IAAU,OAAOC,KAAS,aAAaA,EAAK;GAAE;GAAO;EAAO,CAAC,IAAIA,GACjEC,IAA0BC,IAAaC,EAAuBD,GAAY;GAAE;GAAO;EAAO,CAAC,IAAI,CAAC;EAEtG,OADAD,EAAS,KAAK;GAAE,MAAM;GAAS,WAAWG,EAAWf,CAAI;GAAG,UAAU,CAAC,GAAGU,CAAO;EAAE,CAAC,GAC7EM,EAAM,MAAMV,GAAIM,GAAUZ,GAAM;GAAE;GAAO;GAAQ;EAAI,CAAC;CAC/D,GACwB;EAAE,QAAQE;EAAa;EAAK;EAAU,eAAe;CAAK,CAAC,GAE5E,kBAAC,UAAD;EAAQ,KAAKE;EAAgB;EAAe;EAAQ,GAAIa,EAAWC,GAAOC,GAAQC,CAAS;CAAI,CAAA;AACxG"}
1
+ {"version":3,"file":"DrawCanvas.js","names":["IDENTITY_VIEW","DrawCanvas","props","view","normalizeView","canvasElRef","useRef","setRefs","useCallback","el","assignRef","canvasRef","useCanvasSurface","content","draw","commands","background","backgroundFillCommands","viewToMat3","lease","SurfaceCanvas"],"sources":["../../src/canvas/DrawCanvas.tsx"],"sourcesContent":["/**\n * `<DrawCanvas>` — a sized, DPR-correct WebGL2 surface that paints a list of\n * draw commands, with no scene, tools or dispatcher behind it.\n *\n * It paints through the same surface hook as `<SceneViewCanvas>`\n * (`useCanvasSurface`), whose frame loop stops while the canvas is off screen\n * or the tab is hidden. Like `<SceneViewCanvas>` it attaches no event\n * listeners. Its size is `width` × `height` unless a `className` rule sizes\n * the element; the drawing buffer stays `width` × `height` either way.\n */\nimport { useCallback, useRef } from 'react';\nimport type { Ref } from 'react';\nimport { assignRef } from '@weasel-js/react';\nimport type { Paint } from '@weasel-js/paint';\nimport { useCanvasSurface } from './useCanvasSurface';\nimport { SurfaceCanvas } from './SurfaceCanvas';\nimport type { CanvasRendererLease } from './canvasRenderer';\nimport { viewToMat3 } from '@weasel-js/geom';\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport type { RedrawSource } from '../core/layers/render';\nimport { backgroundFillCommands } from '../core/layers/backgroundFill';\nimport { normalizeView, type View } from '../core/viewport/view';\n\n/** What a `<DrawCanvas>` paints: a command list, or a function returning one\n * that is called on every paint with the surface's CSS-pixel size. */\nexport type DrawCanvasDraw =\n | readonly DrawCommand[]\n | ((size: { width: number; height: number }) => readonly DrawCommand[]);\n\n/** Props for `<DrawCanvas>`. */\nexport interface DrawCanvasProps {\n /** CSS-pixel width. The drawing buffer is `width × dpr`. */\n width: number;\n /** CSS-pixel height. */\n height: number;\n /** The commands to paint, in the coordinate space `view` maps to the\n * screen — CSS pixels when `view` is omitted. A new array repaints on the\n * next frame. A function is read at paint time, so state it reads outside\n * React repaints when one of `redrawOn`'s sources notifies. */\n draw: DrawCanvasDraw;\n /** Camera over `draw`'s commands. Defaults to the identity view. */\n view?: View;\n /** Fills the whole surface beneath `draw`, in screen space. The canvas is\n * transparent without it. */\n background?: Paint;\n /** External state a `draw` function reads. Each source is subscribed while\n * mounted and repaints the canvas when it notifies. */\n redrawOn?: readonly RedrawSource[];\n /** Device-pixel ratio. Defaults to `window.devicePixelRatio`, read per\n * paint. */\n dpr?: number;\n /** CSS class for the `<canvas>` element. */\n className?: string;\n /** Receives the underlying `<canvas>`, for pointer listeners or `toBlob`. */\n canvasRef?: Ref<HTMLCanvasElement>;\n}\n\nconst IDENTITY_VIEW: View = { x: 0, y: 0, scale: { x: 1, y: 1 } };\n\n/**\n * Paint draw commands onto a canvas of its own. For a surface that only draws —\n * a package demo, a swatch, a preview — where a `<SceneCanvas>` would bring a\n * scene, tools and an input dispatcher that nothing uses.\n */\nexport function DrawCanvas(props: DrawCanvasProps) {\n const { width, height, draw, background, redrawOn, dpr, className, canvasRef } = props;\n const view = props.view ? normalizeView(props.view) : IDENTITY_VIEW;\n\n const canvasElRef = useRef<HTMLCanvasElement | null>(null);\n const setRefs = useCallback((el: HTMLCanvasElement | null) => {\n canvasElRef.current = el;\n assignRef(canvasRef, el);\n }, [canvasRef]);\n\n const paint = (lease: CanvasRendererLease): boolean => {\n const el = canvasElRef.current;\n if (!el) return false;\n const content = typeof draw === 'function' ? draw({ width, height }) : draw;\n const commands: DrawCommand[] = background ? backgroundFillCommands(background, { width, height }) : [];\n commands.push({ kind: 'group', transform: viewToMat3(view), children: [...content] });\n return lease.paint(el, commands, view, { width, height, dpr });\n };\n useCanvasSurface(paint, { target: canvasElRef, dpr, redrawOn, paintOnCommit: true });\n\n return <SurfaceCanvas ref={setRefs} width={width} height={height} className={className} />;\n}\n"],"mappings":";;;;;;;;;AAyDA,IAAMA,IAAsB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;EAAE,GAAG;EAAG,GAAG;CAAE;AAAE;AAOhE,SAAgBC,EAAW,GAAwB;CACjD,IAAM,EAAE,UAAO,WAAQ,SAAM,eAAY,aAAU,QAAK,cAAW,iBAAcC,GAC3EC,IAAOD,EAAM,OAAOE,EAAcF,EAAM,IAAI,IAAIF,GAEhDK,IAAcC,EAAiC,IAAI,GACnDC,IAAUC,GAAa,MAAiC;EAE5D,AADA,EAAY,UAAUC,GACtBC,EAAUC,GAAWF,CAAE;CACzB,GAAG,CAACE,CAAS,CAAC;CAYd,OAFAC,GARe,MAAwC;EACrD,IAAMH,IAAKJ,EAAY;EACvB,IAAI,CAACI,GAAI,OAAO;EAChB,IAAMI,IAAU,OAAOC,KAAS,aAAaA,EAAK;GAAE;GAAO;EAAO,CAAC,IAAIA,GACjEC,IAA0BC,IAAaC,EAAuBD,GAAY;GAAE;GAAO;EAAO,CAAC,IAAI,CAAC;EAEtG,OADAD,EAAS,KAAK;GAAE,MAAM;GAAS,WAAWG,EAAWf,CAAI;GAAG,UAAU,CAAC,GAAGU,CAAO;EAAE,CAAC,GAC7EM,EAAM,MAAMV,GAAIM,GAAUZ,GAAM;GAAE;GAAO;GAAQ;EAAI,CAAC;CAC/D,GACwB;EAAE,QAAQE;EAAa;EAAK;EAAU,eAAe;CAAK,CAAC,GAE5E,kBAACe,GAAD;EAAe,KAAKb;EAAgB;EAAe;EAAmB;CAAY,CAAA;AAC3F"}
@@ -1,47 +1,48 @@
1
1
  import { useOptionalViewRegistry as e } from "../viewRegistry.js";
2
2
  import { worldPointAt as t } from "./worldPointAt.js";
3
3
  import { useEffect as n } from "react";
4
- import { PointerContextProvider as r, usePointerContext as i } from "@weasel-js/routing/react";
5
- import { Fragment as a, jsx as o } from "react/jsx-runtime";
4
+ import { heldPointers as r } from "@weasel-js/gestures";
5
+ import { PointerContextProvider as i, usePointerContext as a } from "@weasel-js/routing/react";
6
+ import { Fragment as o, jsx as s } from "react/jsx-runtime";
6
7
  //#region src/canvas/SceneCanvas/PointerProviderIfRoot.tsx
7
- function s({ children: e }) {
8
- return i() ? /* @__PURE__ */ o(a, { children: e }) : /* @__PURE__ */ o(r, { children: e });
8
+ function c({ children: e }) {
9
+ return a() ? /* @__PURE__ */ s(o, { children: e }) : /* @__PURE__ */ s(i, { children: e });
9
10
  }
10
- function c({ canvasRef: r, canvasApiRef: a }) {
11
- let o = i(), s = e();
11
+ function l({ canvasRef: i, canvasApiRef: o }) {
12
+ let s = a(), c = e();
12
13
  return n(() => {
13
- if (!o) return;
14
- let e = r.current;
14
+ if (!s) return;
15
+ let e = i.current;
15
16
  if (!e) return;
16
17
  let n = (e, n, r) => {
17
- let i = a.current;
18
+ let i = o.current;
18
19
  if (!i) return;
19
- let c = s?.resolver.at(e, n, r), [l, u] = t(i, c, n, r);
20
- o.set({
20
+ let a = c?.resolver.at(e, n, r), [l, u] = t(i, a, n, r);
21
+ s.set({
21
22
  worldX: l,
22
23
  worldY: u,
23
- viewId: c?.id ?? null
24
+ viewId: a?.id ?? null
24
25
  });
25
- }, i = (e) => n(e.pointerId, e.clientX, e.clientY), c = (e) => {
26
- if (e.buttons !== 0) {
26
+ }, a = (e) => n(e.pointerId, e.clientX, e.clientY), l = r(e), u = (e) => {
27
+ if (l.count() > 0) {
27
28
  n(e.pointerId, e.clientX, e.clientY);
28
29
  return;
29
30
  }
30
- o.set(null);
31
- }, l = (t) => {
32
- t.target !== e && t.buttons !== 0 && n(t.pointerId, t.clientX, t.clientY);
31
+ s.set(null);
32
+ }, d = (t) => {
33
+ t.target !== e && l.count() !== 0 && n(t.pointerId, t.clientX, t.clientY);
33
34
  };
34
- return e.addEventListener("pointermove", i), e.addEventListener("pointerleave", c), document.addEventListener("pointermove", l), () => {
35
- e.removeEventListener("pointermove", i), e.removeEventListener("pointerleave", c), document.removeEventListener("pointermove", l);
35
+ return e.addEventListener("pointermove", a), e.addEventListener("pointerleave", u), document.addEventListener("pointermove", d), () => {
36
+ e.removeEventListener("pointermove", a), e.removeEventListener("pointerleave", u), document.removeEventListener("pointermove", d), l.release();
36
37
  };
37
38
  }, [
39
+ s,
40
+ i,
38
41
  o,
39
- r,
40
- a,
41
- s
42
+ c
42
43
  ]), null;
43
44
  }
44
45
  //#endregion
45
- export { s as PointerProviderIfRoot, c as PointerPublisher };
46
+ export { c as PointerProviderIfRoot, l as PointerPublisher };
46
47
 
47
48
  //# sourceMappingURL=PointerProviderIfRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PointerProviderIfRoot.js","names":["_Fragment","PointerProviderIfRoot","usePointerContext","Fragment","PointerContextProvider","PointerPublisher","ctx","registry","useOptionalViewRegistry","useEffect","el","canvasRef","publish","api","canvasApiRef","target","pointerId","clientX","clientY","worldX","worldY","worldPointAt","onMove","onLeave","onDocMove","e"],"sources":["../../../src/canvas/SceneCanvas/PointerProviderIfRoot.tsx"],"sourcesContent":["/**\n * Conditional `<PointerContextProvider>` wrapper. Mounts a provider only\n * when no parent provider is in scope — otherwise renders children unwrapped\n * so SceneCanvas defers to the host's existing scope.\n *\n * Pairs with `<PointerPublisher>` which attaches native pointermove/leave\n * listeners to the canvas element and writes world-space coords into the\n * surrounding context's `pointerRef`.\n */\nimport { useEffect, type MutableRefObject, type ReactNode, type RefObject } from 'react';\nimport { PointerContextProvider, usePointerContext } from '@weasel-js/routing/react';\nimport type { CanvasExtensionApi } from '../canvasExtension';\nimport { useOptionalViewRegistry } from '../viewRegistry';\nimport { worldPointAt } from './worldPointAt';\n\n/** Mount a `<PointerContextProvider>` only when none is already in scope. */\nexport function PointerProviderIfRoot({ children }: { children: ReactNode }) {\n const parent = usePointerContext();\n if (parent) return <>{children}</>;\n return <PointerContextProvider>{children}</PointerContextProvider>;\n}\n\n/**\n * Attaches native `pointermove` / `pointerleave` listeners to the supplied\n * canvas element and publishes the world-space pointer coordinates into the\n * surrounding `<PointerContextProvider>`. Renders nothing. No-op when no\n * provider is in scope (matches \"publish if anyone is listening\").\n *\n * Lives inside the provider scope so it sees both consumer-mounted providers\n * and SceneCanvas's auto-mounted one.\n */\nexport function PointerPublisher({\n canvasRef,\n canvasApiRef,\n}: {\n canvasRef: MutableRefObject<HTMLElement | null>;\n canvasApiRef: RefObject<CanvasExtensionApi | null>;\n}) {\n const ctx = usePointerContext();\n const registry = useOptionalViewRegistry();\n useEffect(() => {\n if (!ctx) return;\n const el = canvasRef.current;\n if (!el) return;\n // The surface's one resolver answers which camera a client point belongs\n // to, so paste-at-pointer lands in the panel the cursor is over. With no\n // views declared it answers the canvas's own camera and rect.\n const publish = (pointerId: number | null, clientX: number, clientY: number): void => {\n const api = canvasApiRef.current;\n if (!api) return;\n const target = registry?.resolver.at(pointerId, clientX, clientY);\n const [worldX, worldY] = worldPointAt(api, target, clientX, clientY);\n ctx.set({ worldX, worldY, viewId: target?.id ?? null });\n };\n const onMove = (e: PointerEvent): void => publish(e.pointerId, e.clientX, e.clientY);\n const onLeave = (e: PointerEvent): void => {\n // Don't clear coords mid-drag: any pointer button down means the user\n // is still actively manipulating the canvas, and downstream consumers\n // (resize/move/etc.) need the latest world position even when the\n // cursor leaves the canvas rect. The `useGestureDispatcher`-side\n // `setPointerCapture` keeps pointermove flowing in that case, so we\n // get fresh values; this guard just prevents the leave event from\n // racing in and nulling them between captured moves.\n if (e.buttons !== 0) {\n publish(e.pointerId, e.clientX, e.clientY);\n return;\n }\n ctx.set(null);\n };\n // Document-level pointermove backstop so the HUD keeps updating when the\n // pointer drifts off the canvas during a drag (pointer capture routes\n // events back to the canvas, but the leave-window edge case is covered\n // here too). Filter to events whose target isn't the canvas to avoid\n // double-publishing.\n const onDocMove = (e: PointerEvent): void => {\n if (e.target === el) return;\n // Only forward off-canvas moves during an active drag — idle hover\n // outside the canvas shouldn't be reported as a canvas pointer position.\n if (e.buttons === 0) return;\n publish(e.pointerId, e.clientX, e.clientY);\n };\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerleave', onLeave);\n document.addEventListener('pointermove', onDocMove);\n return () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerleave', onLeave);\n document.removeEventListener('pointermove', onDocMove);\n };\n // canvasRef + registry + ctx identity are all stable across the lifetime\n // of the surrounding provider; effect runs once per mount.\n }, [ctx, canvasRef, canvasApiRef, registry]);\n return null;\n}\n"],"mappings":";;;;;;AAgBA,SAAgBC,EAAsB,EAAE,eAAqC;CAG3E,OAFeC,EACX,IAAe,kBAAAF,GAAA,EAAG,YAAW,CAAA,IAC1B,kBAACI,GAAD,EAAyB,YAAiC,CAAA;AACnE;AAWA,SAAgBC,EAAiB,EAC/B,cACA,mBAIC;CACD,IAAMC,IAAMJ,EAAkB,GACxBK,IAAWC,EAAwB;CAqDzC,OApDAC,QAAgB;EACd,IAAI,CAACH,GAAK;EACV,IAAMI,IAAKC,EAAU;EACrB,IAAI,CAACD,GAAI;EAIT,IAAME,KAAW,GAA0B,GAAiB,MAA0B;GACpF,IAAMC,IAAMC,EAAa;GACzB,IAAI,CAACD,GAAK;GACV,IAAME,IAASR,GAAU,SAAS,GAAGS,GAAWC,GAASC,CAAO,GAC1D,CAACC,GAAQC,KAAUC,EAAaR,GAAKE,GAAQE,GAASC,CAAO;GACnE,EAAI,IAAI;IAAE;IAAQ;IAAQ,QAAQH,GAAQ,MAAM;GAAK,CAAC;EACxD,GACMO,KAAU,MAA0BV,EAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAC7EW,KAAW,MAA0B;GAQzC,IAAI,EAAE,YAAY,GAAG;IACnB,EAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO;IACzC;GACF;GACA,EAAI,IAAI,IAAI;EACd,GAMMC,KAAa,MAA0B;GAC3C,AAAIC,EAAE,WAAWf,KAGbe,EAAE,YAAY,KAClBb,EAAQa,EAAE,WAAWA,EAAE,SAASA,EAAE,OAAO;EAC3C;EAIA,OAHAf,EAAG,iBAAiB,eAAeY,CAAM,GACzCZ,EAAG,iBAAiB,gBAAgBa,CAAO,GAC3C,SAAS,iBAAiB,eAAeC,CAAS,SACrC;GAGX,AAFAd,EAAG,oBAAoB,eAAeY,CAAM,GAC5CZ,EAAG,oBAAoB,gBAAgBa,CAAO,GAC9C,SAAS,oBAAoB,eAAeC,CAAS;EACvD;CAGF,GAAG;EAAClB;EAAKK;EAAWG;EAAcP;CAAQ,CAAC,GACpC;AACT"}
1
+ {"version":3,"file":"PointerProviderIfRoot.js","names":["_Fragment","PointerProviderIfRoot","usePointerContext","Fragment","PointerContextProvider","PointerPublisher","ctx","registry","useOptionalViewRegistry","useEffect","el","canvasRef","publish","api","canvasApiRef","target","pointerId","clientX","clientY","worldX","worldY","worldPointAt","onMove","held","heldPointers","onLeave","onDocMove","e"],"sources":["../../../src/canvas/SceneCanvas/PointerProviderIfRoot.tsx"],"sourcesContent":["/**\n * Conditional `<PointerContextProvider>` wrapper. Mounts a provider only\n * when no parent provider is in scope — otherwise renders children unwrapped\n * so SceneCanvas defers to the host's existing scope.\n *\n * Pairs with `<PointerPublisher>` which attaches native pointermove/leave\n * listeners to the canvas element and writes world-space coords into the\n * surrounding context's `pointerRef`.\n */\nimport { useEffect, type MutableRefObject, type ReactNode, type RefObject } from 'react';\nimport { heldPointers } from '@weasel-js/gestures';\nimport { PointerContextProvider, usePointerContext } from '@weasel-js/routing/react';\nimport type { CanvasExtensionApi } from '../canvasExtension';\nimport { useOptionalViewRegistry } from '../viewRegistry';\nimport { worldPointAt } from './worldPointAt';\n\n/** Mount a `<PointerContextProvider>` only when none is already in scope. */\nexport function PointerProviderIfRoot({ children }: { children: ReactNode }) {\n const parent = usePointerContext();\n if (parent) return <>{children}</>;\n return <PointerContextProvider>{children}</PointerContextProvider>;\n}\n\n/**\n * Attaches native `pointermove` / `pointerleave` listeners to the supplied\n * canvas element and publishes the world-space pointer coordinates into the\n * surrounding `<PointerContextProvider>`. Renders nothing. No-op when no\n * provider is in scope (matches \"publish if anyone is listening\").\n *\n * Lives inside the provider scope so it sees both consumer-mounted providers\n * and SceneCanvas's auto-mounted one.\n */\nexport function PointerPublisher({\n canvasRef,\n canvasApiRef,\n}: {\n canvasRef: MutableRefObject<HTMLElement | null>;\n canvasApiRef: RefObject<CanvasExtensionApi | null>;\n}) {\n const ctx = usePointerContext();\n const registry = useOptionalViewRegistry();\n useEffect(() => {\n if (!ctx) return;\n const el = canvasRef.current;\n if (!el) return;\n // The surface's one resolver answers which camera a client point belongs\n // to, so paste-at-pointer lands in the panel the cursor is over. With no\n // views declared it answers the canvas's own camera and rect.\n const publish = (pointerId: number | null, clientX: number, clientY: number): void => {\n const api = canvasApiRef.current;\n if (!api) return;\n const target = registry?.resolver.at(pointerId, clientX, clientY);\n const [worldX, worldY] = worldPointAt(api, target, clientX, clientY);\n ctx.set({ worldX, worldY, viewId: target?.id ?? null });\n };\n const onMove = (e: PointerEvent): void => publish(e.pointerId, e.clientX, e.clientY);\n const held = heldPointers(el);\n const onLeave = (e: PointerEvent): void => {\n // A pointer held on the canvas is still working it once it leaves the\n // rect, and what it drives needs the latest world position.\n if (held.count() > 0) {\n publish(e.pointerId, e.clientX, e.clientY);\n return;\n }\n ctx.set(null);\n };\n // A drag that began on the canvas keeps reporting once it is off it; the\n // canvas's own listener has the moves that still target it.\n const onDocMove = (e: PointerEvent): void => {\n if (e.target === el) return;\n if (held.count() === 0) return;\n publish(e.pointerId, e.clientX, e.clientY);\n };\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerleave', onLeave);\n document.addEventListener('pointermove', onDocMove);\n return () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerleave', onLeave);\n document.removeEventListener('pointermove', onDocMove);\n held.release();\n };\n // canvasRef + registry + ctx identity are all stable across the lifetime\n // of the surrounding provider; effect runs once per mount.\n }, [ctx, canvasRef, canvasApiRef, registry]);\n return null;\n}\n"],"mappings":";;;;;;;AAiBA,SAAgBC,EAAsB,EAAE,eAAqC;CAG3E,OAFeC,EACX,IAAe,kBAAAF,GAAA,EAAG,YAAW,CAAA,IAC1B,kBAACI,GAAD,EAAyB,YAAiC,CAAA;AACnE;AAWA,SAAgBC,EAAiB,EAC/B,cACA,mBAIC;CACD,IAAMC,IAAMJ,EAAkB,GACxBK,IAAWC,EAAwB;CA6CzC,OA5CAC,QAAgB;EACd,IAAI,CAACH,GAAK;EACV,IAAMI,IAAKC,EAAU;EACrB,IAAI,CAACD,GAAI;EAIT,IAAME,KAAW,GAA0B,GAAiB,MAA0B;GACpF,IAAMC,IAAMC,EAAa;GACzB,IAAI,CAACD,GAAK;GACV,IAAME,IAASR,GAAU,SAAS,GAAGS,GAAWC,GAASC,CAAO,GAC1D,CAACC,GAAQC,KAAUC,EAAaR,GAAKE,GAAQE,GAASC,CAAO;GACnE,EAAI,IAAI;IAAE;IAAQ;IAAQ,QAAQH,GAAQ,MAAM;GAAK,CAAC;EACxD,GACMO,KAAU,MAA0BV,EAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,GAC7EW,IAAOC,EAAad,CAAE,GACtBe,KAAW,MAA0B;GAGzC,IAAIF,EAAK,MAAM,IAAI,GAAG;IACpB,EAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO;IACzC;GACF;GACA,EAAI,IAAI,IAAI;EACd,GAGMG,KAAa,MAA0B;GAC3C,AAAIC,EAAE,WAAWjB,KACba,EAAK,MAAM,MAAM,KACrBX,EAAQe,EAAE,WAAWA,EAAE,SAASA,EAAE,OAAO;EAC3C;EAIA,OAHAjB,EAAG,iBAAiB,eAAeY,CAAM,GACzCZ,EAAG,iBAAiB,gBAAgBe,CAAO,GAC3C,SAAS,iBAAiB,eAAeC,CAAS,SACrC;GAIX,AAHAhB,EAAG,oBAAoB,eAAeY,CAAM,GAC5CZ,EAAG,oBAAoB,gBAAgBe,CAAO,GAC9C,SAAS,oBAAoB,eAAeC,CAAS,GACrDH,EAAK,QAAQ;EACf;CAGF,GAAG;EAACjB;EAAKK;EAAWG;EAAcP;CAAQ,CAAC,GACpC;AACT"}
@@ -2,63 +2,54 @@ import { useDecayLoop as e } from "../../core/viewport/useDecayLoop.js";
2
2
  import { useStandardActions as t } from "../../interactions/actions/useStandardActions.js";
3
3
  import { usePoseDescriptorDepSource as n } from "../deps/poseDescriptor.js";
4
4
  import { useSliceDepSource as r } from "../deps/slice.js";
5
- import { useLayoutArrivals as i } from "../../layout/arrivals.js";
6
- import { useViewDepSource as a } from "../deps/view.js";
7
- import { useAreaSelectDepSource as o } from "../deps/areaSelect.js";
8
- import { useNodeAtPointDepSource as s } from "../deps/nodeAtPoint.js";
9
- import { useLassoSelectDepSource as c } from "../deps/lassoSelect.js";
10
- import { useTextEditDepSource as l } from "../deps/textEdit.js";
11
- import { useEditAnchorsDepSource as u } from "../deps/editAnchors.js";
12
- import { useInsertDepSource as d } from "../deps/insert.js";
13
- import { useSnapDepSource as f } from "../deps/snap.js";
14
- import { useDebugDepSource as p } from "../deps/debug.js";
15
- import { useDepChangeNotices as m } from "../deps/changes.js";
16
- import { useDispatcherDepSource as h } from "../deps/dispatcher.js";
17
- import { useLayoutDepSource as g } from "../deps/layout.js";
18
- import { useIngestionDepSource as ee } from "../deps/ingestion.js";
19
- import { GeometryProjectionRegistrar as te, ResizePolicyRegistrar as ne } from "./poseRegistrars.js";
20
- import { useActionsPropResolver as re } from "./useActionsPropResolver.js";
21
- import { useViewportActions as ie } from "./useViewportActions.js";
22
- import { useEffect as _ } from "react";
23
- import { useActionsRegistry as v, useDepSource as y, usePointerContext as b } from "@weasel-js/routing/react";
24
- import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
5
+ import { useViewDepSource as i } from "../deps/view.js";
6
+ import { useAreaSelectDepSource as a } from "../deps/areaSelect.js";
7
+ import { useNodeAtPointDepSource as o } from "../deps/nodeAtPoint.js";
8
+ import { useLassoSelectDepSource as s } from "../deps/lassoSelect.js";
9
+ import { useTextEditDepSource as c } from "../deps/textEdit.js";
10
+ import { useEditAnchorsDepSource as l } from "../deps/editAnchors.js";
11
+ import { useInsertDepSource as ee } from "../deps/insert.js";
12
+ import { useSnapDepSource as u } from "../deps/snap.js";
13
+ import { useDebugDepSource as d } from "../deps/debug.js";
14
+ import { useDepChangeNotices as f } from "../deps/changes.js";
15
+ import { useDispatcherDepSource as p } from "../deps/dispatcher.js";
16
+ import { useLayoutDepSource as te } from "../deps/layout.js";
17
+ import { useIngestionDepSource as ne } from "../deps/ingestion.js";
18
+ import { GeometryProjectionRegistrar as re, ResizePolicyRegistrar as m } from "./poseRegistrars.js";
19
+ import { useActionsPropResolver as h } from "./useActionsPropResolver.js";
20
+ import { useActionTunings as g } from "./useActionTunings.js";
21
+ import { useViewportActions as _ } from "./useViewportActions.js";
22
+ import { useEffect as v } from "react";
23
+ import { useActionsRegistry as y, useDepSource as b, usePointerContext as x } from "@weasel-js/routing/react";
24
+ import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
25
25
  //#region src/canvas/SceneCanvas/StandardActionsRegistrar.tsx
26
- function w({ selection: w, scene: T, adapter: E, actions: D, excludeActions: O, currentViewRef: k, onViewChange: A, resizeOptions: j, poseDescriptor: M, geometryProjection: N, dispatcher: P, getActionRef: F, pickEvery: I, layerIsPainted: ae, alphaOf: L, viewportPanEnabled: R, viewportZoom: z, viewportPinchZoom: B, viewportRecenter: V, viewAnimation: H, editAnchorsExternalState: U, layouts: W, layoutDropTarget: G, reflowTransition: K, insertNodeFactories: q, insertPaint: J, snapPoint: oe, canvasRef: Y, canvasApiRef: se, ingestionResolveSrc: ce, ingestionSvg: le, ingestionClipboard: ue, actionsRegistryRef: X }) {
27
- let Z = v();
28
- _(() => (X.current = Z, () => {
29
- X.current = null;
30
- }), [Z, X]), _(() => {
31
- if (Z) return Z.setDispatcher(P);
32
- }, [Z, P]), _(() => {
33
- if (Z) return F.current = (e) => Z.list().find((t) => t.id === e), () => {
34
- F.current = null;
35
- };
36
- }, [Z, F]);
37
- let Q = e(), $ = a(k, A, V, () => {
38
- let e = Y.current;
26
+ function T({ selection: T, scene: E, adapter: D, actions: O, tune: k, excludeActions: A, currentViewRef: j, onViewChange: M, resizeOptions: N, poseDescriptor: P, geometryProjection: F, dispatcher: I, pickEvery: L, layerIsPainted: R, alphaOf: z, viewportPanEnabled: B, viewportZoom: V, viewportPinchZoom: H, viewportRecenter: U, viewAnimation: W, editAnchorsExternalState: G, layoutDropTarget: K, reflowTransition: q, insertNodeFactories: J, insertPaint: Y, snapPoint: X, canvasRef: Z, canvasApiRef: ie, ingestionResolveSrc: ae, ingestionSvg: oe, ingestionClipboard: se }) {
27
+ let Q = y();
28
+ v(() => {
29
+ if (Q) return Q.setDispatcher(I);
30
+ }, [Q, I]);
31
+ let ce = e(), $ = i(j, M, U, () => {
32
+ let e = Z.current;
39
33
  return e ? {
40
34
  width: e.clientWidth,
41
35
  height: e.clientHeight
42
36
  } : null;
43
- }, H, Q, ae);
37
+ }, W, ce, R);
44
38
  t({
45
- selection: w,
46
- scene: T,
39
+ selection: T,
40
+ scene: E,
47
41
  view: $,
48
- history: T.history,
49
- exclude: O
50
- }), y("rootView", () => $);
51
- let de = b();
52
- return y("pointer", () => de ?? void 0), ie({
53
- pan: R,
54
- zoom: z,
55
- pinchZoom: B
56
- }), o(T, w, M, L), s(I), g(T, W, G, K), i(T, {
57
- layouts: W,
58
- poseDescriptor: M
59
- }), d(T, E, q, J), r(T, w, E, M), f(oe), p(se), m(T, w.current), ee(Y, () => k.current, ce, le, ue), c(T, w, M, L), l(T), u(T, w, E, U), h(P), n(M), re(D, O.join("|")), /* @__PURE__ */ C(x, { children: [j ? /* @__PURE__ */ S(ne, { options: j }) : null, N ? /* @__PURE__ */ S(te, { projection: N }) : null] });
42
+ history: E.history,
43
+ exclude: A
44
+ }), b("rootView", () => $);
45
+ let le = x();
46
+ return b("pointer", () => le ?? void 0), _({
47
+ pan: B,
48
+ zoom: V,
49
+ pinchZoom: H
50
+ }), a(E, T, P, z), o(L), te(E, K, q), ee(E, D, J, Y), r(E, T, D, P), u(X), d(ie), f(E, T.current), ne(Z, () => j.current, ae, oe, se), s(E, T, P, z), c(E), l(E, T, D, G), p(I), n(P), h(O, A.join("|")), g(k), /* @__PURE__ */ w(S, { children: [N ? /* @__PURE__ */ C(m, { options: N }) : null, F ? /* @__PURE__ */ C(re, { projection: F }) : null] });
60
51
  }
61
52
  //#endregion
62
- export { w as StandardActionsRegistrar };
53
+ export { T as StandardActionsRegistrar };
63
54
 
64
55
  //# sourceMappingURL=StandardActionsRegistrar.js.map