@weasel-js/core 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (741) hide show
  1. package/CHANGELOG.md +300 -0
  2. package/README.md +8 -12
  3. package/dist/affordances/hitAffordanceRegions.js +1 -1
  4. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  5. package/dist/affordances/pathAnchors.js.map +1 -1
  6. package/dist/animation/clipTargets.js +1 -1
  7. package/dist/animation/clipTargets.js.map +1 -1
  8. package/dist/animation/poseTarget.js +5 -32
  9. package/dist/animation/poseTarget.js.map +1 -1
  10. package/dist/{autoPoseDescriptor-CZ1eXbzY.d.ts → autoPoseDescriptor-C25QVb0W.d.ts} +1 -1
  11. package/dist/barrel/canvas.js +8 -8
  12. package/dist/barrel/chrome.js +9 -9
  13. package/dist/barrel/input.js +1 -1
  14. package/dist/barrel/interactions.js +3 -3
  15. package/dist/barrel/paint.js +2 -2
  16. package/dist/barrel/paths.js +19 -17
  17. package/dist/barrel/renderer.js +11 -7
  18. package/dist/barrel/routing.js +4 -1
  19. package/dist/barrel/scene.js +16 -12
  20. package/dist/barrel/text.js +5 -5
  21. package/dist/barrel/viewport.js +8 -8
  22. package/dist/canvas/Canvas.js +2 -2
  23. package/dist/canvas/Canvas.js.map +1 -1
  24. package/dist/canvas/CanvasView.js +20 -14
  25. package/dist/canvas/CanvasView.js.map +1 -1
  26. package/dist/canvas/GestureReason.js +64 -0
  27. package/dist/canvas/GestureReason.js.map +1 -0
  28. package/dist/canvas/GestureReason.module.js +7 -0
  29. package/dist/canvas/GestureReason.module.js.map +1 -0
  30. package/dist/canvas/LeanSceneCanvas.js +3 -1
  31. package/dist/canvas/LeanSceneCanvas.js.map +1 -1
  32. package/dist/canvas/NodeShape.js +2 -0
  33. package/dist/canvas/NodeShape.js.map +1 -1
  34. package/dist/canvas/PickHud.js +7 -3
  35. package/dist/canvas/PickHud.js.map +1 -1
  36. package/dist/canvas/SceneCanvas/CanvasKitProviders.js +1 -1
  37. package/dist/canvas/SceneCanvas/CanvasKitProviders.js.map +1 -1
  38. package/dist/canvas/SceneCanvas/DevHuds.js +2 -2
  39. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -1
  40. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +4 -2
  41. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  42. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +3 -1
  43. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
  44. package/dist/canvas/SceneCanvas/brushOverlay.js.map +1 -1
  45. package/dist/canvas/SceneCanvas/builtinToolSets.js +17 -9
  46. package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -1
  47. package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -1
  48. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
  49. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +75 -19
  50. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  51. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +7 -1
  52. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  53. package/dist/canvas/SceneCanvas/defaultTextEditor.js +108 -0
  54. package/dist/canvas/SceneCanvas/defaultTextEditor.js.map +1 -0
  55. package/dist/canvas/SceneCanvas/describePresets.js +47 -0
  56. package/dist/canvas/SceneCanvas/describePresets.js.map +1 -0
  57. package/dist/canvas/SceneCanvas/features.js +57 -16
  58. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/mergeLayers.js +10 -1
  60. package/dist/canvas/SceneCanvas/mergeLayers.js.map +1 -1
  61. package/dist/canvas/SceneCanvas/namedPresets.js +52 -24
  62. package/dist/canvas/SceneCanvas/namedPresets.js.map +1 -1
  63. package/dist/canvas/SceneCanvas/presets/arrange.js +35 -10
  64. package/dist/canvas/SceneCanvas/presets/arrange.js.map +1 -1
  65. package/dist/canvas/SceneCanvas/presets/baseline.js +9 -0
  66. package/dist/canvas/SceneCanvas/presets/baseline.js.map +1 -0
  67. package/dist/canvas/SceneCanvas/presets/chrome.js.map +1 -1
  68. package/dist/canvas/SceneCanvas/presets/composites.js +43 -0
  69. package/dist/canvas/SceneCanvas/presets/composites.js.map +1 -0
  70. package/dist/canvas/SceneCanvas/presets/edit.js +79 -26
  71. package/dist/canvas/SceneCanvas/presets/edit.js.map +1 -1
  72. package/dist/canvas/SceneCanvas/presets/ingest.js +1 -0
  73. package/dist/canvas/SceneCanvas/presets/ingest.js.map +1 -1
  74. package/dist/canvas/SceneCanvas/presets/paths.js +58 -16
  75. package/dist/canvas/SceneCanvas/presets/paths.js.map +1 -1
  76. package/dist/canvas/SceneCanvas/presets/select.js +4 -2
  77. package/dist/canvas/SceneCanvas/presets/select.js.map +1 -1
  78. package/dist/canvas/SceneCanvas/presets/tools.js +24 -0
  79. package/dist/canvas/SceneCanvas/presets/tools.js.map +1 -0
  80. package/dist/canvas/SceneCanvas/presets/transform.js +4 -0
  81. package/dist/canvas/SceneCanvas/presets/transform.js.map +1 -1
  82. package/dist/canvas/SceneCanvas/presets/view.js +3 -1
  83. package/dist/canvas/SceneCanvas/presets/view.js.map +1 -1
  84. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  85. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +1 -1
  86. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/toolRegistry.js +5 -4
  88. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
  89. package/dist/canvas/SceneCanvas/useCanvasTools.js +26 -10
  90. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  91. package/dist/canvas/SceneCanvas/useContributionRoles.js +15 -2
  92. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js +5 -4
  94. package/dist/canvas/SceneCanvas/useDepartureGhostLayer.js.map +1 -1
  95. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +1 -1
  96. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -1
  97. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +9 -8
  98. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  99. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js +2 -2
  100. package/dist/canvas/SceneCanvas/useSceneCanvasPathEdit.js.map +1 -1
  101. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +4 -1
  102. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
  103. package/dist/canvas/SceneCanvas/useSceneChrome.js +7 -4
  104. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
  105. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +9 -9
  106. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
  107. package/dist/canvas/SceneCanvas/useScenePicking.js +4 -7
  108. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
  109. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +2 -1
  110. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -1
  111. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +6 -6
  112. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  113. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +2 -2
  114. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
  115. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +1 -1
  116. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -1
  117. package/dist/canvas/SceneCanvas/useSurfaceViewInputs.js.map +1 -1
  118. package/dist/canvas/SceneCanvas/useToolKeybindings.js +2 -2
  119. package/dist/canvas/SceneCanvas/useToolKeybindings.js.map +1 -1
  120. package/dist/canvas/SceneCanvas/useViewportActions.js +5 -2
  121. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  122. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -1
  123. package/dist/canvas/SceneCanvas.js +22 -11
  124. package/dist/canvas/SceneCanvas.js.map +1 -1
  125. package/dist/canvas/SceneViewCanvas.js +1 -0
  126. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  127. package/dist/canvas/ViewMarker.js.map +1 -1
  128. package/dist/canvas/accentColor.js +14 -1
  129. package/dist/canvas/accentColor.js.map +1 -1
  130. package/dist/canvas/affordanceAt.js +2 -2
  131. package/dist/canvas/affordanceAt.js.map +1 -1
  132. package/dist/canvas/buildSceneTree.js +5 -3
  133. package/dist/canvas/buildSceneTree.js.map +1 -1
  134. package/dist/canvas/deps/editAnchors.js +4 -4
  135. package/dist/canvas/deps/editAnchors.js.map +1 -1
  136. package/dist/canvas/deps/enteredGroup.js +14 -5
  137. package/dist/canvas/deps/enteredGroup.js.map +1 -1
  138. package/dist/canvas/deps/ingestion.js +5 -1
  139. package/dist/canvas/deps/ingestion.js.map +1 -1
  140. package/dist/canvas/deps/insert.js.map +1 -1
  141. package/dist/canvas/deps/insertSite.js +5 -3
  142. package/dist/canvas/deps/insertSite.js.map +1 -1
  143. package/dist/canvas/deps/nodeAtPoint.js +1 -12
  144. package/dist/canvas/deps/nodeAtPoint.js.map +1 -1
  145. package/dist/canvas/deps/pathEditCommits.js +3 -3
  146. package/dist/canvas/deps/pathEditCommits.js.map +1 -1
  147. package/dist/canvas/deps/slice.js +16 -2
  148. package/dist/canvas/deps/slice.js.map +1 -1
  149. package/dist/canvas/deps/snap.js +5 -5
  150. package/dist/canvas/deps/snap.js.map +1 -1
  151. package/dist/canvas/deps/textEdit.js +5 -6
  152. package/dist/canvas/deps/textEdit.js.map +1 -1
  153. package/dist/canvas/derivedPath.js +8 -3
  154. package/dist/canvas/derivedPath.js.map +1 -1
  155. package/dist/canvas/getNodeAtPoint.js +2 -2
  156. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  157. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  158. package/dist/canvas/layerSlots.js.map +1 -1
  159. package/dist/canvas/nodeShapes/measurePainter.js +1 -1
  160. package/dist/canvas/nodeShapes/measurePainter.js.map +1 -1
  161. package/dist/canvas/nodeShapes/strokedBounds.js +5 -3
  162. package/dist/canvas/nodeShapes/strokedBounds.js.map +1 -1
  163. package/dist/canvas/overlayRoleStrokes.js +6 -0
  164. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  165. package/dist/canvas/pickIndex/scenePickIndex.js +10 -12
  166. package/dist/canvas/pickIndex/scenePickIndex.js.map +1 -1
  167. package/dist/canvas/sceneAdapter.js +10 -19
  168. package/dist/canvas/sceneAdapter.js.map +1 -1
  169. package/dist/canvas/sceneClipboard.js +17 -4
  170. package/dist/canvas/sceneClipboard.js.map +1 -1
  171. package/dist/canvas/sceneViewRender.js +3 -2
  172. package/dist/canvas/sceneViewRender.js.map +1 -1
  173. package/dist/canvas/surfaceContribution.js.map +1 -1
  174. package/dist/canvas/useCanvasPaint.js +10 -4
  175. package/dist/canvas/useCanvasPaint.js.map +1 -1
  176. package/dist/canvas/useHitObserver.js +1 -1
  177. package/dist/canvas/useHitObserver.js.map +1 -1
  178. package/dist/canvas/useViewAim.js +1 -1
  179. package/dist/canvas/useViewAim.js.map +1 -1
  180. package/dist/canvas/useViewHelpers.js +8 -5
  181. package/dist/canvas/useViewHelpers.js.map +1 -1
  182. package/dist/canvas/useViewNesting.js +39 -12
  183. package/dist/canvas/useViewNesting.js.map +1 -1
  184. package/dist/canvas/viewInputs.js.map +1 -1
  185. package/dist/canvas/viewMarkers.js +2 -2
  186. package/dist/canvas/viewMarkers.js.map +1 -1
  187. package/dist/canvas/viewRegistry.js +2 -2
  188. package/dist/canvas/viewRegistry.js.map +1 -1
  189. package/dist/canvas/viewSnap.js +67 -0
  190. package/dist/canvas/viewSnap.js.map +1 -0
  191. package/dist/clipboard.d.ts +6 -12
  192. package/dist/{clone-qb2e1F5p.d.ts → clone-Bz4iqGfE.d.ts} +10 -5
  193. package/dist/clone.d.ts +5 -5
  194. package/dist/core/geometry/booleanOfPaths.js +23 -0
  195. package/dist/core/geometry/booleanOfPaths.js.map +1 -0
  196. package/dist/core/geometry/pathPoseDescriptor.js +12 -9
  197. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -1
  198. package/dist/core/geometry/poseDescriptor.js +12 -3
  199. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  200. package/dist/core/geometry/targetFrame.js +2 -13
  201. package/dist/core/geometry/targetFrame.js.map +1 -1
  202. package/dist/core/layers/render.js +2 -1
  203. package/dist/core/layers/render.js.map +1 -1
  204. package/dist/core/layers/retain.js +5 -3
  205. package/dist/core/layers/retain.js.map +1 -1
  206. package/dist/core/ops/setPath.js +3 -0
  207. package/dist/core/ops/setPath.js.map +1 -1
  208. package/dist/core/paint/meshKindLazy.js.map +1 -1
  209. package/dist/core/paint/paintKindEntry.js.map +1 -1
  210. package/dist/core/paint/paintKinds.js +8 -1
  211. package/dist/core/paint/paintKinds.js.map +1 -1
  212. package/dist/core/scene/NodeProperties.js.map +1 -1
  213. package/dist/core/scene/NodeRouting.js.map +1 -1
  214. package/dist/core/scene/booleanGroup.js +33 -0
  215. package/dist/core/scene/booleanGroup.js.map +1 -0
  216. package/dist/core/scene/booleanOfChildren.js +53 -0
  217. package/dist/core/scene/booleanOfChildren.js.map +1 -0
  218. package/dist/core/scene/carryDescendants.js +18 -6
  219. package/dist/core/scene/carryDescendants.js.map +1 -1
  220. package/dist/core/scene/composeFrame.js +42 -5
  221. package/dist/core/scene/composeFrame.js.map +1 -1
  222. package/dist/core/scene/composePose.js +35 -16
  223. package/dist/core/scene/composePose.js.map +1 -1
  224. package/dist/core/scene/depMemo.js +36 -18
  225. package/dist/core/scene/depMemo.js.map +1 -1
  226. package/dist/core/scene/derivedParts.js +2 -23
  227. package/dist/core/scene/derivedParts.js.map +1 -1
  228. package/dist/core/scene/effectivePose.js +10 -0
  229. package/dist/core/scene/effectivePose.js.map +1 -1
  230. package/dist/core/scene/historyForm.js +5 -4
  231. package/dist/core/scene/historyForm.js.map +1 -1
  232. package/dist/core/scene/kitOps.js +5 -71
  233. package/dist/core/scene/kitOps.js.map +1 -1
  234. package/dist/core/scene/kitRegistry.js +5 -0
  235. package/dist/core/scene/kitRegistry.js.map +1 -1
  236. package/dist/core/scene/layerOps.js +82 -0
  237. package/dist/core/scene/layerOps.js.map +1 -0
  238. package/dist/core/scene/layoutPass.js +14 -12
  239. package/dist/core/scene/layoutPass.js.map +1 -1
  240. package/dist/core/scene/lockGuard.js +9 -3
  241. package/dist/core/scene/lockGuard.js.map +1 -1
  242. package/dist/core/scene/nestedHit.js +5 -5
  243. package/dist/core/scene/nestedHit.js.map +1 -1
  244. package/dist/core/scene/nodeFlags.js +8 -2
  245. package/dist/core/scene/nodeFlags.js.map +1 -1
  246. package/dist/core/scene/nodeGates.js +31 -2
  247. package/dist/core/scene/nodeGates.js.map +1 -1
  248. package/dist/core/scene/pathEffects/effects.js +22 -3
  249. package/dist/core/scene/pathEffects/effects.js.map +1 -1
  250. package/dist/core/scene/pathEffects/textAlong.js +16 -3
  251. package/dist/core/scene/pathEffects/textAlong.js.map +1 -1
  252. package/dist/core/scene/pathEffects/textAlongBands.js +65 -0
  253. package/dist/core/scene/pathEffects/textAlongBands.js.map +1 -0
  254. package/dist/core/scene/reconcileSpecs.js +1 -1
  255. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  256. package/dist/core/scene/scene.js +11 -5
  257. package/dist/core/scene/scene.js.map +1 -1
  258. package/dist/core/scene/sceneEdits.js +5 -2
  259. package/dist/core/scene/sceneEdits.js.map +1 -1
  260. package/dist/core/scene/scenePoseAdapter.js +10 -1
  261. package/dist/core/scene/scenePoseAdapter.js.map +1 -1
  262. package/dist/core/scene/scrollOffsets.js +93 -0
  263. package/dist/core/scene/scrollOffsets.js.map +1 -0
  264. package/dist/core/scene/serialization.js +15 -5
  265. package/dist/core/scene/serialization.js.map +1 -1
  266. package/dist/core/scene/statedFields.js +2 -1
  267. package/dist/core/scene/statedFields.js.map +1 -1
  268. package/dist/core/scene/strategyView.js +35 -0
  269. package/dist/core/scene/strategyView.js.map +1 -0
  270. package/dist/core/scene/types.js.map +1 -1
  271. package/dist/core/scene/useScene.js +2 -0
  272. package/dist/core/scene/useScene.js.map +1 -1
  273. package/dist/core/scene/worldSave.js +87 -0
  274. package/dist/core/scene/worldSave.js.map +1 -0
  275. package/dist/core/selection/selectionTarget.js +1 -1
  276. package/dist/core/selection/selectionTarget.js.map +1 -1
  277. package/dist/{cornerHandles-CNCb7aTY.d.ts → cornerHandles-DpmQM_z5.d.ts} +1 -1
  278. package/dist/{depSchema-CpIQzKWQ.d.ts → depSchema-C3BwxitB.d.ts} +119 -99
  279. package/dist/devtools-protocol.d.ts +2 -2
  280. package/dist/devtools.d.ts +2 -2
  281. package/dist/{features → domains}/chrome-caps/buildChromeCtx.js +1 -1
  282. package/dist/domains/chrome-caps/buildChromeCtx.js.map +1 -0
  283. package/dist/{features → domains}/chrome-caps/conditions.js +1 -1
  284. package/dist/domains/chrome-caps/conditions.js.map +1 -0
  285. package/dist/{features → domains}/chrome-caps/defaults.js +1 -1
  286. package/dist/domains/chrome-caps/defaults.js.map +1 -0
  287. package/dist/{features → domains}/chrome-caps/resolve.js +1 -1
  288. package/dist/domains/chrome-caps/resolve.js.map +1 -0
  289. package/dist/{features → domains}/chrome-caps/useChromeCaps.js +1 -1
  290. package/dist/domains/chrome-caps/useChromeCaps.js.map +1 -0
  291. package/dist/{features → domains}/chrome-caps/useHoverTracking.js +1 -1
  292. package/dist/domains/chrome-caps/useHoverTracking.js.map +1 -0
  293. package/dist/{features → domains}/ingestion/contentHandlers.js +20 -3
  294. package/dist/domains/ingestion/contentHandlers.js.map +1 -0
  295. package/dist/domains/ingestion/ghost.js +56 -0
  296. package/dist/domains/ingestion/ghost.js.map +1 -0
  297. package/dist/{features → domains}/ingestion/imageHandler.js +1 -1
  298. package/dist/domains/ingestion/imageHandler.js.map +1 -0
  299. package/dist/domains/ingestion/kitHandlers.js +22 -0
  300. package/dist/domains/ingestion/kitHandlers.js.map +1 -0
  301. package/dist/{features → domains}/ingestion/openFilePicker.js +1 -1
  302. package/dist/domains/ingestion/openFilePicker.js.map +1 -0
  303. package/dist/{features → domains}/ingestion/placement.js +1 -1
  304. package/dist/domains/ingestion/placement.js.map +1 -0
  305. package/dist/{features → domains}/ingestion/svgHandler.js +1 -1
  306. package/dist/domains/ingestion/svgHandler.js.map +1 -0
  307. package/dist/{features → domains}/ingestion/textHandler.js +9 -7
  308. package/dist/domains/ingestion/textHandler.js.map +1 -0
  309. package/dist/{features → domains}/ingestion/useCanvasIngestion.js +13 -15
  310. package/dist/domains/ingestion/useCanvasIngestion.js.map +1 -0
  311. package/dist/{features → domains}/ingestion/weaselJsonHandler.js +1 -1
  312. package/dist/domains/ingestion/weaselJsonHandler.js.map +1 -0
  313. package/dist/{features → domains}/longPress/longPressFeedback.js +1 -1
  314. package/dist/domains/longPress/longPressFeedback.js.map +1 -0
  315. package/dist/{features → domains}/measure/actionIds.js +1 -1
  316. package/dist/domains/measure/actionIds.js.map +1 -0
  317. package/dist/{features → domains}/measure/measureCommands.js +1 -1
  318. package/dist/domains/measure/measureCommands.js.map +1 -0
  319. package/dist/{features → domains}/measure/measureContribution.js +1 -1
  320. package/dist/domains/measure/measureContribution.js.map +1 -0
  321. package/dist/{features → domains}/measure/measureEdits.js +1 -1
  322. package/dist/domains/measure/measureEdits.js.map +1 -0
  323. package/dist/{features → domains}/measure/measureGestures.js +4 -7
  324. package/dist/domains/measure/measureGestures.js.map +1 -0
  325. package/dist/{features → domains}/measure/measureHit.js +1 -1
  326. package/dist/domains/measure/measureHit.js.map +1 -0
  327. package/dist/{features → domains}/measure/measureLayer.js +1 -1
  328. package/dist/domains/measure/measureLayer.js.map +1 -0
  329. package/dist/{features → domains}/measure/measurement.js +1 -1
  330. package/dist/domains/measure/measurement.js.map +1 -0
  331. package/dist/{features → domains}/measure/measurements.js +2 -2
  332. package/dist/domains/measure/measurements.js.map +1 -0
  333. package/dist/{features → domains}/modes/modeLayers.js +1 -1
  334. package/dist/domains/modes/modeLayers.js.map +1 -0
  335. package/dist/{features → domains}/modes/modeTriggers.js +3 -6
  336. package/dist/domains/modes/modeTriggers.js.map +1 -0
  337. package/dist/{features → domains}/pathEffects/effectSources.js +1 -1
  338. package/dist/domains/pathEffects/effectSources.js.map +1 -0
  339. package/dist/{features → domains}/pathEffects/index.js +1 -1
  340. package/dist/domains/pathEffects/index.js.map +1 -0
  341. package/dist/{features → domains}/pathEffects/readSource.js +1 -1
  342. package/dist/domains/pathEffects/readSource.js.map +1 -0
  343. package/dist/{features → domains}/pathEffects/textItems.js +11 -2
  344. package/dist/domains/pathEffects/textItems.js.map +1 -0
  345. package/dist/{features → domains}/pathEffects/useEffectSourcesLayer.js +1 -1
  346. package/dist/domains/pathEffects/useEffectSourcesLayer.js.map +1 -0
  347. package/dist/{features → domains}/paths/anchorData.js +1 -1
  348. package/dist/domains/paths/anchorData.js.map +1 -0
  349. package/dist/{features → domains}/paths/anchorMarkers.js +9 -7
  350. package/dist/domains/paths/anchorMarkers.js.map +1 -0
  351. package/dist/{features → domains}/paths/editablePath.js +1 -1
  352. package/dist/domains/paths/editablePath.js.map +1 -0
  353. package/dist/{features → domains}/paths/index.js +3 -3
  354. package/dist/{features → domains}/paths/originProjection.js +1 -1
  355. package/dist/domains/paths/originProjection.js.map +1 -0
  356. package/dist/{features → domains}/paths/pathEditExtension.js +1 -1
  357. package/dist/domains/paths/pathEditExtension.js.map +1 -0
  358. package/dist/{features → domains}/paths/pathEditState.js +1 -1
  359. package/dist/domains/paths/pathEditState.js.map +1 -0
  360. package/dist/{features → domains}/paths/pathEditingOverlayLayer.js +1 -1
  361. package/dist/domains/paths/pathEditingOverlayLayer.js.map +1 -0
  362. package/dist/{features → domains}/paths/pathLayer.js +1 -1
  363. package/dist/domains/paths/pathLayer.js.map +1 -0
  364. package/dist/{features → domains}/paths/pathRepresentation.js +1 -1
  365. package/dist/domains/paths/pathRepresentation.js.map +1 -0
  366. package/dist/{features → domains}/paths/pathSnap/glyphs.js +1 -1
  367. package/dist/domains/paths/pathSnap/glyphs.js.map +1 -0
  368. package/dist/{features → domains}/paths/pathSnap/pathSnapSource.js +1 -1
  369. package/dist/domains/paths/pathSnap/pathSnapSource.js.map +1 -0
  370. package/dist/{features → domains}/paths/pathSnap/sceneIndex.js +1 -1
  371. package/dist/domains/paths/pathSnap/sceneIndex.js.map +1 -0
  372. package/dist/{features → domains}/paths/pathSnap/snapGeometry.js +3 -2
  373. package/dist/domains/paths/pathSnap/snapGeometry.js.map +1 -0
  374. package/dist/{features → domains}/paths/penPreviewLayer.js +1 -1
  375. package/dist/domains/paths/penPreviewLayer.js.map +1 -0
  376. package/dist/{features → domains}/paths/shapeGenerator.js +6 -4
  377. package/dist/domains/paths/shapeGenerator.js.map +1 -0
  378. package/dist/{features → domains}/paths/strokeOutline.js +1 -1
  379. package/dist/domains/paths/strokeOutline.js.map +1 -0
  380. package/dist/{features → domains}/paths/useAnchorFields.js +1 -1
  381. package/dist/domains/paths/useAnchorFields.js.map +1 -0
  382. package/dist/{features → domains}/paths/usePathEdit.js +1 -1
  383. package/dist/domains/paths/usePathEdit.js.map +1 -0
  384. package/dist/{features → domains}/poseRun/usePoseRun.js +1 -1
  385. package/dist/domains/poseRun/usePoseRun.js.map +1 -0
  386. package/dist/{features → domains}/selection/enteredGroupFrame.js +49 -10
  387. package/dist/domains/selection/enteredGroupFrame.js.map +1 -0
  388. package/dist/{features → domains}/selection/enteredGroupScope.js +1 -1
  389. package/dist/domains/selection/enteredGroupScope.js.map +1 -0
  390. package/dist/domains/selection/enteredOperands.js +29 -0
  391. package/dist/domains/selection/enteredOperands.js.map +1 -0
  392. package/dist/{features → domains}/selection/handleCommands.js +1 -1
  393. package/dist/domains/selection/handleCommands.js.map +1 -0
  394. package/dist/{features → domains}/selection/overlay.js +1 -1
  395. package/dist/domains/selection/overlay.js.map +1 -0
  396. package/dist/{features → domains}/selection/selectionPose.js +1 -1
  397. package/dist/domains/selection/selectionPose.js.map +1 -0
  398. package/dist/{features → domains}/snap/angle2d.js +1 -1
  399. package/dist/domains/snap/angle2d.js.map +1 -0
  400. package/dist/{features → domains}/snap/debugCandidates.js +1 -1
  401. package/dist/domains/snap/debugCandidates.js.map +1 -0
  402. package/dist/{features → domains}/snap/gather.js +1 -1
  403. package/dist/domains/snap/gather.js.map +1 -0
  404. package/dist/{features → domains}/snap/inputSubspace.js +1 -1
  405. package/dist/domains/snap/inputSubspace.js.map +1 -0
  406. package/dist/{features → domains}/snap/lazySession.js +1 -1
  407. package/dist/domains/snap/lazySession.js.map +1 -0
  408. package/dist/{features → domains}/snap/marks.js +1 -1
  409. package/dist/domains/snap/marks.js.map +1 -0
  410. package/dist/{features → domains}/snap/outcomeStore.js +1 -1
  411. package/dist/domains/snap/outcomeStore.js.map +1 -0
  412. package/dist/{features → domains}/snap/pointSnap.js +1 -1
  413. package/dist/domains/snap/pointSnap.js.map +1 -0
  414. package/dist/{features → domains}/snap/probes2d.js +1 -1
  415. package/dist/domains/snap/probes2d.js.map +1 -0
  416. package/dist/{features → domains}/snap/readoutDraw.js +1 -1
  417. package/dist/domains/snap/readoutDraw.js.map +1 -0
  418. package/dist/{features → domains}/snap/readoutLayer.js +1 -1
  419. package/dist/domains/snap/readoutLayer.js.map +1 -0
  420. package/dist/{features → domains}/snap/registry.js +1 -1
  421. package/dist/domains/snap/registry.js.map +1 -0
  422. package/dist/{features → domains}/snap/resizeBox.js +1 -1
  423. package/dist/domains/snap/resizeBox.js.map +1 -0
  424. package/dist/{features → domains}/snap/roles.js +1 -1
  425. package/dist/domains/snap/roles.js.map +1 -0
  426. package/dist/{features → domains}/snap/rotationSource.js +1 -1
  427. package/dist/domains/snap/rotationSource.js.map +1 -0
  428. package/dist/{features → domains}/snap/sceneReads.js +24 -3
  429. package/dist/domains/snap/sceneReads.js.map +1 -0
  430. package/dist/{features → domains}/snap/sceneSession2d.js +3 -2
  431. package/dist/domains/snap/sceneSession2d.js.map +1 -0
  432. package/dist/{features → domains}/snap/screen.js +1 -1
  433. package/dist/domains/snap/screen.js.map +1 -0
  434. package/dist/{features → domains}/snap/session2d.js +3 -2
  435. package/dist/domains/snap/session2d.js.map +1 -0
  436. package/dist/{features → domains}/snap/spanSnap.js +1 -1
  437. package/dist/domains/snap/spanSnap.js.map +1 -0
  438. package/dist/{features → domains}/snap/stepAngles.js +1 -1
  439. package/dist/domains/snap/stepAngles.js.map +1 -0
  440. package/dist/{features → domains}/text/editingDrawOne.js +4 -4
  441. package/dist/domains/text/editingDrawOne.js.map +1 -0
  442. package/dist/domains/text/hostTextEditors.js +24 -0
  443. package/dist/domains/text/hostTextEditors.js.map +1 -0
  444. package/dist/{features → domains}/text/index.js +1 -1
  445. package/dist/{features → domains}/text/sceneTextDrafts.js +1 -1
  446. package/dist/domains/text/sceneTextDrafts.js.map +1 -0
  447. package/dist/{features → domains}/text/textHitAt.js +18 -2
  448. package/dist/domains/text/textHitAt.js.map +1 -0
  449. package/dist/{features → domains}/text/textLayer.js +1 -1
  450. package/dist/domains/text/textLayer.js.map +1 -0
  451. package/dist/{features → domains}/text/useSceneTextEdit.js +11 -3
  452. package/dist/domains/text/useSceneTextEdit.js.map +1 -0
  453. package/dist/{features → domains}/viewports/aim.js +1 -1
  454. package/dist/domains/viewports/aim.js.map +1 -0
  455. package/dist/{features → domains}/viewports/viewMarker.js +23 -5
  456. package/dist/domains/viewports/viewMarker.js.map +1 -0
  457. package/dist/{features → domains}/viewports/viewMarkerDrag.js +3 -3
  458. package/dist/domains/viewports/viewMarkerDrag.js.map +1 -0
  459. package/dist/{features → domains}/viewports/viewResolver.js +1 -1
  460. package/dist/domains/viewports/viewResolver.js.map +1 -0
  461. package/dist/{features → domains}/viewports/viewportLayer.js +1 -1
  462. package/dist/domains/viewports/viewportLayer.js.map +1 -0
  463. package/dist/icons.table.js +1 -1
  464. package/dist/icons.table.js.map +1 -1
  465. package/dist/icons.table.json +106 -6
  466. package/dist/index.d.ts +1441 -1050
  467. package/dist/index.js +90 -77
  468. package/dist/interactions/actions/admitsChild.js +6 -2
  469. package/dist/interactions/actions/admitsChild.js.map +1 -1
  470. package/dist/interactions/actions/align/align.js +1 -4
  471. package/dist/interactions/actions/align/align.js.map +1 -1
  472. package/dist/interactions/actions/booleans/booleanGroupAction.js +66 -0
  473. package/dist/interactions/actions/booleans/booleanGroupAction.js.map +1 -0
  474. package/dist/interactions/actions/booleans/keymap.js +52 -0
  475. package/dist/interactions/actions/booleans/keymap.js.map +1 -0
  476. package/dist/interactions/actions/booleans/operands.js +1 -1
  477. package/dist/interactions/actions/booleans/pieces.js +4 -11
  478. package/dist/interactions/actions/booleans/pieces.js.map +1 -1
  479. package/dist/interactions/actions/clipboard/action.js +3 -7
  480. package/dist/interactions/actions/clipboard/action.js.map +1 -1
  481. package/dist/interactions/actions/clipboard/clipboardOps.js +1 -1
  482. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  483. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  484. package/dist/interactions/actions/defaults/anchorEditing.js +6 -6
  485. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  486. package/dist/interactions/actions/defaults/bendSegment.js +1 -1
  487. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
  488. package/dist/interactions/actions/defaults/containerScroll.js +170 -0
  489. package/dist/interactions/actions/defaults/containerScroll.js.map +1 -0
  490. package/dist/interactions/actions/defaults/contextMenu.js +2 -5
  491. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
  492. package/dist/interactions/actions/defaults/delete.js +1 -1
  493. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  494. package/dist/interactions/actions/defaults/duplicate.js +1 -3
  495. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  496. package/dist/interactions/actions/defaults/enterGroup.js +7 -12
  497. package/dist/interactions/actions/defaults/enterGroup.js.map +1 -1
  498. package/dist/interactions/actions/defaults/enterPathEdit.js +4 -8
  499. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  500. package/dist/interactions/actions/defaults/group.js +12 -24
  501. package/dist/interactions/actions/defaults/group.js.map +1 -1
  502. package/dist/interactions/actions/defaults/ingest.js +18 -10
  503. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  504. package/dist/interactions/actions/defaults/insertPathAnchor.js +3 -3
  505. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  506. package/dist/interactions/actions/defaults/nudgeSteps.js +3 -21
  507. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -1
  508. package/dist/interactions/actions/defaults/pathEditMarks.js.map +1 -1
  509. package/dist/interactions/actions/defaults/selectDeep.js +2 -2
  510. package/dist/interactions/actions/defaults/selectDeep.js.map +1 -1
  511. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  512. package/dist/interactions/actions/dropVerdict.js +9 -0
  513. package/dist/interactions/actions/dropVerdict.js.map +1 -0
  514. package/dist/interactions/actions/edit-anchors/action.js +2 -2
  515. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  516. package/dist/interactions/actions/edit-anchors/extensionDrags.js.map +1 -1
  517. package/dist/interactions/actions/edit-anchors/geometry.js +8 -6
  518. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  519. package/dist/interactions/actions/edit-anchors/handleDrag.js.map +1 -1
  520. package/dist/interactions/actions/edit-anchors/preview.js +1 -1
  521. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
  522. package/dist/interactions/actions/flip/action.js +3 -2
  523. package/dist/interactions/actions/flip/action.js.map +1 -1
  524. package/dist/interactions/actions/geometryProjection.js +8 -3
  525. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  526. package/dist/interactions/actions/gestureFrames.js +1 -0
  527. package/dist/interactions/actions/gestureFrames.js.map +1 -1
  528. package/dist/interactions/actions/insert/action.js +6 -2
  529. package/dist/interactions/actions/insert/action.js.map +1 -1
  530. package/dist/interactions/actions/insert/frame.js +1 -1
  531. package/dist/interactions/actions/insert/frame.js.map +1 -1
  532. package/dist/interactions/actions/insert/placeAction.js +6 -8
  533. package/dist/interactions/actions/insert/placeAction.js.map +1 -1
  534. package/dist/interactions/actions/insert/session.js +2 -2
  535. package/dist/interactions/actions/insert/session.js.map +1 -1
  536. package/dist/interactions/actions/move/action.js +6 -15
  537. package/dist/interactions/actions/move/action.js.map +1 -1
  538. package/dist/interactions/actions/move/behaviors/layoutDrop.js +12 -2
  539. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
  540. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +29 -10
  541. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -1
  542. package/dist/interactions/actions/move/behaviors/snapToContainer.js +42 -6
  543. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  544. package/dist/interactions/actions/move/capture.js +4 -8
  545. package/dist/interactions/actions/move/capture.js.map +1 -1
  546. package/dist/interactions/actions/move/commit/index.js.map +1 -1
  547. package/dist/interactions/actions/move/commit/layoutDrop.js +4 -3
  548. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -1
  549. package/dist/interactions/actions/move/commit/layoutRelease.js +15 -9
  550. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -1
  551. package/dist/interactions/actions/move/commit/reparent.js +19 -13
  552. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  553. package/dist/interactions/actions/move/delta.js +51 -5
  554. package/dist/interactions/actions/move/delta.js.map +1 -1
  555. package/dist/interactions/actions/move/frame.js +8 -4
  556. package/dist/interactions/actions/move/frame.js.map +1 -1
  557. package/dist/interactions/actions/move/layout/container.js +19 -9
  558. package/dist/interactions/actions/move/layout/container.js.map +1 -1
  559. package/dist/interactions/actions/move/layout/dragged.js +2 -2
  560. package/dist/interactions/actions/move/layout/dragged.js.map +1 -1
  561. package/dist/interactions/actions/move/layout/dropPass.js +36 -18
  562. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
  563. package/dist/interactions/actions/move/layout/exits.js +2 -2
  564. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  565. package/dist/interactions/actions/move/layout/glide.js +5 -5
  566. package/dist/interactions/actions/move/layout/glide.js.map +1 -1
  567. package/dist/interactions/actions/move/layout/view.js +55 -0
  568. package/dist/interactions/actions/move/layout/view.js.map +1 -0
  569. package/dist/interactions/actions/move/refusal.js +52 -0
  570. package/dist/interactions/actions/move/refusal.js.map +1 -0
  571. package/dist/interactions/actions/move/session.js +9 -8
  572. package/dist/interactions/actions/move/session.js.map +1 -1
  573. package/dist/interactions/actions/move/translate.js +10 -4
  574. package/dist/interactions/actions/move/translate.js.map +1 -1
  575. package/dist/interactions/actions/moveNodes.js +21 -5
  576. package/dist/interactions/actions/moveNodes.js.map +1 -1
  577. package/dist/interactions/actions/pathCommands/pathNodes.js +3 -3
  578. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -1
  579. package/dist/interactions/actions/planeInput.js +14 -13
  580. package/dist/interactions/actions/planeInput.js.map +1 -1
  581. package/dist/interactions/actions/poseFrame.js +21 -8
  582. package/dist/interactions/actions/poseFrame.js.map +1 -1
  583. package/dist/interactions/actions/resize/action.js +1 -1
  584. package/dist/interactions/actions/resize/action.js.map +1 -1
  585. package/dist/interactions/actions/resize/aspect.js +1 -1
  586. package/dist/interactions/actions/resize/aspect.js.map +1 -1
  587. package/dist/interactions/actions/resize/commit.js +10 -1
  588. package/dist/interactions/actions/resize/commit.js.map +1 -1
  589. package/dist/interactions/actions/resize/frame.js +3 -2
  590. package/dist/interactions/actions/resize/frame.js.map +1 -1
  591. package/dist/interactions/actions/resize/held.js +44 -0
  592. package/dist/interactions/actions/resize/held.js.map +1 -0
  593. package/dist/interactions/actions/resize/session.js +3 -1
  594. package/dist/interactions/actions/resize/session.js.map +1 -1
  595. package/dist/interactions/actions/resolveOverlays.js +9 -0
  596. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  597. package/dist/interactions/actions/resolvePreviews.js +23 -7
  598. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  599. package/dist/interactions/actions/rotate/action.js +1 -1
  600. package/dist/interactions/actions/rotate/action.js.map +1 -1
  601. package/dist/interactions/actions/rotate/frame.js +1 -1
  602. package/dist/interactions/actions/rotate/frame.js.map +1 -1
  603. package/dist/interactions/actions/rotate/session.js +2 -2
  604. package/dist/interactions/actions/rotate/session.js.map +1 -1
  605. package/dist/interactions/actions/selectionSubtree.js +2 -4
  606. package/dist/interactions/actions/selectionSubtree.js.map +1 -1
  607. package/dist/interactions/actions/spatialReference.js +4 -9
  608. package/dist/interactions/actions/spatialReference.js.map +1 -1
  609. package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -1
  610. package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -1
  611. package/dist/kitSettingsSchema.js +2 -2
  612. package/dist/kitSettingsSchema.js.map +1 -1
  613. package/dist/{math-C_elShP_.d.ts → math-B_unOnF4.d.ts} +2 -2
  614. package/dist/math.d.ts +3 -3
  615. package/dist/move.d.ts +6 -6
  616. package/dist/{options-ClEm3SEl.d.ts → options-DAjkhbcs.d.ts} +5 -5
  617. package/dist/{poseDescriptor-DN2yfnq_.d.ts → poseDescriptor-CvSxVhCd.d.ts} +17 -4
  618. package/dist/resize.d.ts +6 -6
  619. package/dist/style.css +14 -0
  620. package/dist/test-seams.d.ts +11 -15
  621. package/dist/test-seams.js +1 -1
  622. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +3 -6
  623. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  624. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  625. package/dist/tools/builtin/measure/useMeasureTool.js +2 -2
  626. package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
  627. package/dist/tools/builtin/pen/penHandle.js +2 -2
  628. package/dist/tools/builtin/pen/penHandle.js.map +1 -1
  629. package/dist/tools/builtin/pen/usePenTool.js +13 -19
  630. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  631. package/dist/tools/builtin/polygon/usePolygonTool.js +1 -1
  632. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  633. package/dist/tools/builtin/select/groupEntry.js +1 -1
  634. package/dist/tools/builtin/select/groupEntry.js.map +1 -1
  635. package/dist/tools/builtin/select/selectionContributions.js +1 -1
  636. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  637. package/dist/tools/builtin/select/useSelectTool.js +7 -7
  638. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  639. package/dist/tools/builtin/slice/useSliceTool.js +5 -8
  640. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  641. package/dist/tools/builtin/star/useStarTool.js +1 -1
  642. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  643. package/dist/tools/index.js +2 -1
  644. package/dist/{types-49uYJN3j.d.ts → types-A_sNJYRd.d.ts} +8 -0
  645. package/dist/{types-BEdRIhNc.d.ts → types-DW14eu9B.d.ts} +131 -36
  646. package/dist/{types-p2alu-R1.d.ts → types-VCtfchp-.d.ts} +4 -6
  647. package/dist/util/color.js +12 -14
  648. package/dist/util/color.js.map +1 -1
  649. package/dist/version.js +1 -1
  650. package/package.json +25 -24
  651. package/dist/canvas/poseCascade.js +0 -65
  652. package/dist/canvas/poseCascade.js.map +0 -1
  653. package/dist/features/chrome-caps/buildChromeCtx.js.map +0 -1
  654. package/dist/features/chrome-caps/conditions.js.map +0 -1
  655. package/dist/features/chrome-caps/defaults.js.map +0 -1
  656. package/dist/features/chrome-caps/resolve.js.map +0 -1
  657. package/dist/features/chrome-caps/useChromeCaps.js.map +0 -1
  658. package/dist/features/chrome-caps/useHoverTracking.js.map +0 -1
  659. package/dist/features/ingestion/contentHandlers.js.map +0 -1
  660. package/dist/features/ingestion/imageHandler.js.map +0 -1
  661. package/dist/features/ingestion/openFilePicker.js.map +0 -1
  662. package/dist/features/ingestion/placement.js.map +0 -1
  663. package/dist/features/ingestion/registerKitHandlers.js +0 -43
  664. package/dist/features/ingestion/registerKitHandlers.js.map +0 -1
  665. package/dist/features/ingestion/svgHandler.js.map +0 -1
  666. package/dist/features/ingestion/textHandler.js.map +0 -1
  667. package/dist/features/ingestion/useCanvasIngestion.js.map +0 -1
  668. package/dist/features/ingestion/weaselJsonHandler.js.map +0 -1
  669. package/dist/features/longPress/longPressFeedback.js.map +0 -1
  670. package/dist/features/measure/actionIds.js.map +0 -1
  671. package/dist/features/measure/measureCommands.js.map +0 -1
  672. package/dist/features/measure/measureContribution.js.map +0 -1
  673. package/dist/features/measure/measureEdits.js.map +0 -1
  674. package/dist/features/measure/measureGestures.js.map +0 -1
  675. package/dist/features/measure/measureHit.js.map +0 -1
  676. package/dist/features/measure/measureLayer.js.map +0 -1
  677. package/dist/features/measure/measurement.js.map +0 -1
  678. package/dist/features/measure/measurements.js.map +0 -1
  679. package/dist/features/modes/modeLayers.js.map +0 -1
  680. package/dist/features/modes/modeTriggers.js.map +0 -1
  681. package/dist/features/pathEffects/effectSources.js.map +0 -1
  682. package/dist/features/pathEffects/index.js.map +0 -1
  683. package/dist/features/pathEffects/readSource.js.map +0 -1
  684. package/dist/features/pathEffects/textItems.js.map +0 -1
  685. package/dist/features/pathEffects/useEffectSourcesLayer.js.map +0 -1
  686. package/dist/features/paths/anchorData.js.map +0 -1
  687. package/dist/features/paths/anchorMarkers.js.map +0 -1
  688. package/dist/features/paths/editablePath.js.map +0 -1
  689. package/dist/features/paths/originProjection.js.map +0 -1
  690. package/dist/features/paths/pathEditExtension.js.map +0 -1
  691. package/dist/features/paths/pathEditState.js.map +0 -1
  692. package/dist/features/paths/pathEditingOverlayLayer.js.map +0 -1
  693. package/dist/features/paths/pathLayer.js.map +0 -1
  694. package/dist/features/paths/pathRepresentation.js.map +0 -1
  695. package/dist/features/paths/pathSnap/glyphs.js.map +0 -1
  696. package/dist/features/paths/pathSnap/pathSnapSource.js.map +0 -1
  697. package/dist/features/paths/pathSnap/sceneIndex.js.map +0 -1
  698. package/dist/features/paths/pathSnap/snapGeometry.js.map +0 -1
  699. package/dist/features/paths/penPreviewLayer.js.map +0 -1
  700. package/dist/features/paths/shapeGenerator.js.map +0 -1
  701. package/dist/features/paths/strokeOutline.js.map +0 -1
  702. package/dist/features/paths/useAnchorFields.js.map +0 -1
  703. package/dist/features/paths/usePathEdit.js.map +0 -1
  704. package/dist/features/poseRun/usePoseRun.js.map +0 -1
  705. package/dist/features/selection/enteredGroupFrame.js.map +0 -1
  706. package/dist/features/selection/enteredGroupScope.js.map +0 -1
  707. package/dist/features/selection/handleCommands.js.map +0 -1
  708. package/dist/features/selection/overlay.js.map +0 -1
  709. package/dist/features/selection/selectionPose.js.map +0 -1
  710. package/dist/features/snap/angle2d.js.map +0 -1
  711. package/dist/features/snap/debugCandidates.js.map +0 -1
  712. package/dist/features/snap/gather.js.map +0 -1
  713. package/dist/features/snap/inputSubspace.js.map +0 -1
  714. package/dist/features/snap/lazySession.js.map +0 -1
  715. package/dist/features/snap/marks.js.map +0 -1
  716. package/dist/features/snap/outcomeStore.js.map +0 -1
  717. package/dist/features/snap/pointSnap.js.map +0 -1
  718. package/dist/features/snap/probes2d.js.map +0 -1
  719. package/dist/features/snap/readoutDraw.js.map +0 -1
  720. package/dist/features/snap/readoutLayer.js.map +0 -1
  721. package/dist/features/snap/registry.js.map +0 -1
  722. package/dist/features/snap/resizeBox.js.map +0 -1
  723. package/dist/features/snap/roles.js.map +0 -1
  724. package/dist/features/snap/rotationSource.js.map +0 -1
  725. package/dist/features/snap/sceneReads.js.map +0 -1
  726. package/dist/features/snap/sceneSession2d.js.map +0 -1
  727. package/dist/features/snap/screen.js.map +0 -1
  728. package/dist/features/snap/session2d.js.map +0 -1
  729. package/dist/features/snap/spanSnap.js.map +0 -1
  730. package/dist/features/snap/stepAngles.js.map +0 -1
  731. package/dist/features/text/editingDrawOne.js.map +0 -1
  732. package/dist/features/text/sceneTextDrafts.js.map +0 -1
  733. package/dist/features/text/textHitAt.js.map +0 -1
  734. package/dist/features/text/textLayer.js.map +0 -1
  735. package/dist/features/text/useSceneTextEdit.js.map +0 -1
  736. package/dist/features/viewports/aim.js.map +0 -1
  737. package/dist/features/viewports/viewMarker.js.map +0 -1
  738. package/dist/features/viewports/viewMarkerDrag.js.map +0 -1
  739. package/dist/features/viewports/viewResolver.js.map +0 -1
  740. package/dist/features/viewports/viewportLayer.js.map +0 -1
  741. /package/dist/{features → domains}/chrome-caps/index.js +0 -0
@@ -1,12 +1,12 @@
1
1
  import { VERSION } from "../version.js";
2
2
  import { DEFAULT_MAX_ZOOM, DEFAULT_MIN_ZOOM, ZOOM_FLOOR, normalizeZoom as normalizeZoom$1 } from "../core/viewport/zoomBounds.js";
3
3
  import { normalizeView, viewToTransform, viewZoom } from "../core/viewport/view.js";
4
- import { createViewportLayer } from "../features/viewports/viewportLayer.js";
5
- import { createViewResolver } from "../features/viewports/viewResolver.js";
4
+ import { createViewportLayer } from "../domains/viewports/viewportLayer.js";
5
+ import { createViewResolver } from "../domains/viewports/viewResolver.js";
6
6
  import { fitViewToBounds } from "../core/viewport/fitViewToBounds.js";
7
- import { aimSpace2d, isRectAim, rectAim, viewForAim } from "../features/viewports/aim.js";
7
+ import { aimSpace2d, isRectAim, rectAim, viewForAim } from "../domains/viewports/aim.js";
8
8
  import { deriveParallaxView, fromPlane, planeMap, planeMatrix, planeToPlane, rectFromPlane, rectToPlane, toPlane } from "../core/viewport/parallax.js";
9
- import { usePoseRun } from "../features/poseRun/usePoseRun.js";
9
+ import { usePoseRun } from "../domains/poseRun/usePoseRun.js";
10
10
  import { watchDevicePixelRatio } from "../core/device/watchDevicePixelRatio.js";
11
11
  import { DeviceProfileProvider, useDeviceProfile } from "../core/device/useDeviceProfile.js";
12
12
  import { useCanvasSize, useElementSize } from "../core/viewport/useCanvasSize.js";
@@ -35,10 +35,10 @@ import { useVelocityTracker } from "../core/viewport/useVelocityTracker.js";
35
35
  import { useDecayLoop } from "../core/viewport/useDecayLoop.js";
36
36
  import { interpolateView } from "../core/viewport/interpolateView.js";
37
37
  import { VIEW_ANIMATION_KEY, useViewAnimation, useViewAnimationOn, viewAxes } from "../core/viewport/useViewAnimation.js";
38
- import { VIEW_MARKER_DEFAULT_STYLE, VIEW_MARKER_HIT_SLOP_PX, createViewMarkerLayer, grabViewMarker } from "../features/viewports/viewMarker.js";
38
+ import { VIEW_MARKER_DEFAULT_STYLE, VIEW_MARKER_HIT_SLOP_PX, createViewMarkerLayer, grabViewMarker } from "../domains/viewports/viewMarker.js";
39
39
  import { CanvasView } from "../canvas/CanvasView.js";
40
40
  import { ViewMarker } from "../canvas/ViewMarker.js";
41
- import { VIEW_MARKER_DRAG, createViewMarkerContribution, viewMarkerDragAction } from "../features/viewports/viewMarkerDrag.js";
41
+ import { VIEW_MARKER_DRAG, createViewMarkerContribution, viewMarkerDragAction } from "../domains/viewports/viewMarkerDrag.js";
42
42
  import { SceneViewCanvas } from "../canvas/SceneViewCanvas.js";
43
43
  import { DrawCanvas } from "../canvas/DrawCanvas.js";
44
44
  import { FALLBACK_ACCENT, accentColorOf } from "../canvas/accentColor.js";
@@ -46,7 +46,7 @@ import { gateLayer } from "../core/layers/gateLayer.js";
46
46
  import { meanScale as meanScale$1, pxExtent as pxExtent$1, scaleDelta as scaleDelta$1, screenAngleOf as screenAngleOf$1, standoff as standoff$1, withinPxBox, withinPxRadius as withinPxRadius$1 } from "@weasel-js/geom";
47
47
  import { DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_VELOCITY_DECAY, createSimulation } from "@weasel-js/simulation";
48
48
  import { useSimulation } from "@weasel-js/simulation/react";
49
- import { useCanvasFocus, useFrameClock, useVisibleRaf as useVisibleRaf$1 } from "@weasel-js/react";
49
+ import { useCanvasFocus, useVisibleRaf as useVisibleRaf$1 } from "@weasel-js/react";
50
50
  import { clientToCanvas as clientToCanvas$1 } from "@weasel-js/routing";
51
51
 
52
- export { ANCHOR_HIT_BASE_PX, COARSE_TARGET_SCALE, CanvasView, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEVICE_PROFILE$1 as DEFAULT_DEVICE_PROFILE, DEFAULT_MAX_ZOOM, DEFAULT_MIN_ZOOM, DEFAULT_VELOCITY_DECAY, DeviceProfileProvider, DrawCanvas, FALLBACK_ACCENT, HANDLE_BASE_PX, PAGES_DOC_KEY, ROTATION_HANDLE_BASE_PX, SceneViewCanvas, VERSION, VIEW_ANIMATION_KEY, VIEW_MARKER_DEFAULT_STYLE, VIEW_MARKER_DRAG, VIEW_MARKER_HIT_SLOP_PX, ViewMarker, WHEEL_ZOOM_STEP, ZOOM_FLOOR, accentColorOf, addPage, adjacentPage, aimSpace2d, axisZoomFactor, clampView, clientToCanvas$1 as clientToCanvas, computeFitViewport, computeWheelAction, createSimulation, createVelocityTracker, createViewMarkerContribution, createViewMarkerLayer, createViewResolver, createViewportLayer, deriveParallaxView, fitToBounds, fitViewToBounds, fitViewToPage, fitZoom, fromPlane, gateLayer, grabViewMarker, interpolateView, isPlainObject, isRectAim, layoutPages, meanScale$1 as meanScale, movePage, nextPageId, normalizeView, normalizeZoom$1 as normalizeZoom, pageAt, pageHolding, pageInView, pageMembers, pageName, pageOfBounds, pagesBounds, pagesLayer, pagesOf, placedPagesOf, planeMap, planeMatrix, planeToPlane, pxExtent$1 as pxExtent, rectAim, rectFromPlane, rectToPlane, removePage, renamePage, resizePage, resolveDeviceProfile$1 as resolveDeviceProfile, scaleDelta$1 as scaleDelta, sceneNodeClientRect, screenAngleOf$1 as screenAngleOf, screenToWorld, setPages, stableStringify, standoff$1 as standoff, startThresholdDrag, toPlane, useAutoCenter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDragHandle, useDropZone, useElementSize, useFrameClock, useHandleDrag, useNodeOverlayFrame, usePoseRun, useSimulation, useVelocityTracker, useViewAnimation, useViewAnimationOn, useVisibleRaf$1 as useVisibleRaf, viewAxes, viewForAim, viewMarkerDragAction, viewToTransform, viewZoom, viewportWorldRect, watchDevicePixelRatio, wheelPan, wheelZoom, wheelZoomFactor, withinPxBox, withinPxRadius$1 as withinPxRadius, worldToScreen, zoomAt };
52
+ export { ANCHOR_HIT_BASE_PX, COARSE_TARGET_SCALE, CanvasView, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEVICE_PROFILE$1 as DEFAULT_DEVICE_PROFILE, DEFAULT_MAX_ZOOM, DEFAULT_MIN_ZOOM, DEFAULT_VELOCITY_DECAY, DeviceProfileProvider, DrawCanvas, FALLBACK_ACCENT, HANDLE_BASE_PX, PAGES_DOC_KEY, ROTATION_HANDLE_BASE_PX, SceneViewCanvas, VERSION, VIEW_ANIMATION_KEY, VIEW_MARKER_DEFAULT_STYLE, VIEW_MARKER_DRAG, VIEW_MARKER_HIT_SLOP_PX, ViewMarker, WHEEL_ZOOM_STEP, ZOOM_FLOOR, accentColorOf, addPage, adjacentPage, aimSpace2d, axisZoomFactor, clampView, clientToCanvas$1 as clientToCanvas, computeFitViewport, computeWheelAction, createSimulation, createVelocityTracker, createViewMarkerContribution, createViewMarkerLayer, createViewResolver, createViewportLayer, deriveParallaxView, fitToBounds, fitViewToBounds, fitViewToPage, fitZoom, fromPlane, gateLayer, grabViewMarker, interpolateView, isPlainObject, isRectAim, layoutPages, meanScale$1 as meanScale, movePage, nextPageId, normalizeView, normalizeZoom$1 as normalizeZoom, pageAt, pageHolding, pageInView, pageMembers, pageName, pageOfBounds, pagesBounds, pagesLayer, pagesOf, placedPagesOf, planeMap, planeMatrix, planeToPlane, pxExtent$1 as pxExtent, rectAim, rectFromPlane, rectToPlane, removePage, renamePage, resizePage, resolveDeviceProfile$1 as resolveDeviceProfile, scaleDelta$1 as scaleDelta, sceneNodeClientRect, screenAngleOf$1 as screenAngleOf, screenToWorld, setPages, stableStringify, standoff$1 as standoff, startThresholdDrag, toPlane, useAutoCenter, useCanvasFocus, useCanvasSize, useDecayLoop, useDeviceProfile, useDragHandle, useDropZone, useElementSize, useHandleDrag, useNodeOverlayFrame, usePoseRun, useSimulation, useVelocityTracker, useViewAnimation, useViewAnimationOn, useVisibleRaf$1 as useVisibleRaf, viewAxes, viewForAim, viewMarkerDragAction, viewToTransform, viewZoom, viewportWorldRect, watchDevicePixelRatio, wheelPan, wheelZoom, wheelZoomFactor, withinPxBox, withinPxRadius$1 as withinPxRadius, worldToScreen, zoomAt };
@@ -118,7 +118,7 @@ function CanvasInner(props, ref) {
118
118
  gestureSource: props.gestureSource,
119
119
  previewPoseExtra: props.previewPoseExtra,
120
120
  getScale: () => viewRef.current.scale,
121
- selection: props.selection?.current ?? NO_SELECTION,
121
+ selection: () => props.selection?.current ?? NO_SELECTION,
122
122
  getIsVisible: () => gateRef.current.getIsVisible?.() ?? alwaysVisible,
123
123
  layerIsPainted: useViewLayerGate(layerVisibility, layerOrder, () => layers)
124
124
  });
@@ -166,7 +166,7 @@ function CanvasInner(props, ref) {
166
166
  ...frame,
167
167
  inputsRef: paintInputsRef,
168
168
  gateRef
169
- }, markPainted);
169
+ }, markPainted, requestRedraw);
170
170
  useEffect(() => clearSubscribers, [clearSubscribers]);
171
171
  useToolCursor(cursorSink, tools, detached ? inputElement : null, style?.cursor);
172
172
  useSurfaceInput(canvasRef, {
@@ -1 +1 @@
1
- {"version":3,"file":"Canvas.js","names":[],"sources":["../../src/canvas/Canvas.tsx"],"sourcesContent":["/**\n * Low-level WebGL surface + viewport primitive. Composes layers into a single GL render pass,\n * applies a view transform, and delivers hover to the layers that ask for it. It routes no\n * gesture: `<SceneCanvas>` mounts the gesture dispatcher on this same element. Canvas owns NO\n * scene-shaped state — selection, picking, kind registry, scene-aware overlays all live in\n * `<SceneCanvas>`, which wraps it.\n *\n * The `layers` prop is a map keyed by slot name, every slot already a layer. Standard slots\n * render at a canonical position; custom entries (any other key, value carrying `.layer`) insert\n * at `after`/`before` an existing slot, defaulting to the top.\n *\n * @internal\n * @deprecated Bare `<Canvas>` is not a supported consumer surface.\n * Use `<SceneCanvas>` instead.\n */\n\nimport { forwardRef, useCallback, useEffect, useInsertionEffect, useLayoutEffect, useRef } from 'react';\nimport type React from 'react';\nimport type { CanvasExtensionApi } from './canvasExtension';\nimport { registerMountedCanvas } from './mountedCanvases';\nimport { useViewHelpers } from './useViewHelpers';\nimport { useViewLayerGate } from './useViewLayerGate';\nimport { useSurfaceInput } from './useSurfaceInput';\nimport { useOptionalViewRegistry } from './viewRegistry';\nimport { useCanvasSurface } from './useCanvasSurface';\nimport type { CanvasHelpers } from './useViewHelpers';\nimport type { CanvasProps } from './canvasProps';\nimport { useLatest } from '@weasel-js/react';\nimport { SurfaceCanvas } from './SurfaceCanvas';\nimport { useSurfaceSize } from './useSurfaceSize';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport type { PoseDescriptor } from 'interactions/actions/resize/geometry';\nimport { useDebugSink } from '../debug/useDebugSink';\nimport { useToolCursor } from './useToolCursor';\nimport { useCanvasElements } from './useCanvasElements';\nimport { alwaysVisible, useExtraLayers } from './useExtraLayers';\nimport { usePaintedCursor } from './usePaintedCursor';\nimport { useCanvasHandle } from './useCanvasHandle';\nimport { useComposedLayers, useSlotLayers } from './useLayerStack';\nimport { useViewRegistrySurface } from './useViewRegistrySurface';\nimport { useCanvasPaint, usePaintedVersion } from './useCanvasPaint';\nimport { layerHover } from './layerHover';\nimport { useClientToWorld } from './useClientToWorld';\n\nexport type { CanvasProps, CanvasRetainOptions } from './canvasProps';\n\nconst NO_SELECTION: SelectionApi['current'] = [];\n\nfunction CanvasInner<TPose>(\n props: CanvasProps<TPose>,\n ref: React.ForwardedRef<CanvasExtensionApi>,\n) {\n const {\n paintInto, inputElement, tools, viewState, style, getIsVisible, layerVisibility, layerOrder,\n helpersRef, debugSinkRef,\n poseDescriptor: geometry = AUTO_POSE_DESCRIPTOR as unknown as PoseDescriptor<TPose>,\n } = props;\n\n const { sink: debugSink, overlay: debugOverlay, frameStats, getDebug } = useDebugSink(props.debug);\n const elements = useCanvasElements(paintInto, inputElement);\n const { canvasRef, ownCanvasRef, detached } = elements;\n const { width, height } = useSurfaceSize(props, ownCanvasRef);\n\n // Read by `hitTestExtras`, which is built once and must see live values.\n const helpersForLayersRef = useRef<CanvasHelpers<TPose> | null>(null);\n const dimsRef = useLatest({ width, height });\n // Which layers reach the screen, and which chrome within them: asked by the\n // paint and by every hit-test.\n const gateRef = useLatest({ getIsVisible, layerVisibility, layerOrder });\n\n // The frame loop paints; a committed render only marks the surface dirty, so\n // no prop can reach the paint without repainting it. The thunk defers to\n // `useCanvasPaint` below, which needs inputs this render has not computed yet.\n const paintRef = useRef<() => boolean>(() => false);\n const { lease, requestRedraw, subscribeFrame, subscribeBeforePaint, subscribeResume } = useCanvasSurface(\n useCallback(() => paintRef.current(), []),\n { syncPaint: props.syncPaint ?? false, target: canvasRef, dpr: props.dpr, redrawOn: props.redrawOn, shaders: props.shaders, onCommit: 'redraw' },\n );\n const { getPaintedVersion, markPainted } = usePaintedVersion(props.contentVersion);\n const { extrasRef, extrasVersion, registerLayer, hitTestExtrasIn } = useExtraLayers(gateRef);\n\n const {\n viewRef, setView, getView, subscribeView,\n adoptControlled, announceControlled, clearSubscribers,\n } = viewState;\n\n const toWorld = useClientToWorld(canvasRef, props.clientToWorld, viewRef);\n\n useLayoutEffect(() => {\n const element = canvasRef.current;\n if (!element) return;\n return registerMountedCanvas({ element, getView });\n }, [canvasRef, detached, inputElement, getView]);\n\n const { paintedCursor, paintedCursorLayer, cursorSink } = usePaintedCursor(canvasRef, requestRedraw);\n\n const frame = { viewRef, dimsRef, helpersRef: helpersForLayersRef };\n useCanvasHandle(ref, { ...elements, inputElement, paintCanvas: paintInto?.canvas }, frame, {\n hitTestExtrasIn, clientToWorld: toWorld, requestRedraw, subscribeFrame, subscribeBeforePaint,\n subscribeResume, registerLayer, getView, setView, subscribeView,\n getPaintedVersion, paintedCursor, cursorSink, getDebug,\n });\n\n const viewRegistry = useOptionalViewRegistry();\n\n // One view's overlay-aware state. A hook, so N views are N components each\n // calling it once — not a loop in this body.\n const layers = useSlotLayers(props.layers, tools, props.backgroundFill, props.decorationLayer);\n const { helpers: viewHelpers } = useViewHelpers<TPose>({\n adapter: props.adapter, geometry, boundsOf: props.boundsOf, boundsOfPose: props.boundsOfPose,\n nodes: props.nodes, gestureSource: props.gestureSource, previewPoseExtra: props.previewPoseExtra,\n getScale: () => viewRef.current.scale,\n selection: props.selection?.current ?? NO_SELECTION,\n getIsVisible: () => gateRef.current.getIsVisible?.() ?? alwaysVisible,\n layerIsPainted: useViewLayerGate(layerVisibility, layerOrder, () => layers),\n });\n const helpersForLayers: CanvasHelpers<TPose> = { ...viewHelpers, getDebug: () => debugSink, viewId: null };\n\n useViewRegistrySurface(viewRegistry, layers, frame, { requestRedraw, hitTestExtrasIn, clientToWorld: toWorld, setView: viewState.setViewFromInput });\n const layersWithDebug = useComposedLayers(layers, {\n viewRegistry, debugOverlay, extrasRef, extrasVersion, cursorLayer: paintedCursorLayer,\n }, requestRedraw);\n\n // Everything the paint, hit-testing and the view registry read that a React\n // render owns. `useLatest` and the insertion effect below publish committed\n // renders only, ahead of every layout effect in the commit, any of which may\n // ask for a sync paint.\n const paintInputsRef = useLatest({\n layers: layersWithDebug, width, height, debugSink, frameStats,\n dpr: props.dpr, layerGroups: props.layerGroups, shaders: props.shaders,\n flattenTolerance: props.flattenTolerance, retain: props.retain, imageMinification: props.imageMinification,\n });\n useInsertionEffect(() => {\n adoptControlled();\n helpersForLayersRef.current = helpersForLayers;\n if (helpersRef) helpersRef.current = helpersForLayers;\n if (debugSinkRef) debugSinkRef.current = debugSink;\n });\n useLayoutEffect(() => {\n announceControlled();\n });\n\n useCanvasPaint(paintRef, lease, elements, { ...frame, inputsRef: paintInputsRef, gateRef }, markPainted);\n useEffect(() => clearSubscribers, [clearSubscribers]);\n\n useToolCursor(cursorSink, tools, detached ? inputElement : null, style?.cursor);\n\n useSurfaceInput(canvasRef, {\n focusOnPress: props.autoFocusOnPointerDown ?? true,\n onFocus: props.onFocus,\n onBlur: props.onBlur,\n ...layerHover(layersWithDebug, {\n viewRef, toWorld, layerVisibility, layerOrder, dims: { width, height },\n }),\n });\n\n if (detached) return null;\n\n return (\n <SurfaceCanvas\n ref={elements.setOwnCanvas}\n width={props.width}\n height={props.height}\n tabIndex={props.tabIndex ?? 0} aria-label={props['aria-label']}\n className={props.className} style={style}\n />\n );\n}\n\n/** Forward-ref'd `<canvas>` wrapper. Generic over the pose type, inferred from the\n * `adapter` prop. */\nexport const Canvas = forwardRef(CanvasInner) as <TPose = unknown>(\n props: CanvasProps<TPose> & { ref?: React.ForwardedRef<CanvasExtensionApi> },\n) => ReturnType<typeof CanvasInner>;\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,IAAM,eAAwC,CAAC;AAE/C,SAAS,YACP,OACA,KACA;CACA,MAAM,EACJ,WAAW,cAAc,OAAO,WAAW,OAAO,cAAc,iBAAiB,YACjF,YAAY,cACZ,gBAAgB,WAAW,yBACzB;CAEJ,MAAM,EAAE,MAAM,WAAW,SAAS,cAAc,YAAY,aAAa,aAAa,MAAM,KAAK;CACjG,MAAM,WAAW,kBAAkB,WAAW,YAAY;CAC1D,MAAM,EAAE,WAAW,cAAc,aAAa;CAC9C,MAAM,EAAE,OAAO,WAAW,eAAe,OAAO,YAAY;CAG5D,MAAM,sBAAsB,OAAoC,IAAI;CACpE,MAAM,UAAU,UAAU;EAAE;EAAO;CAAO,CAAC;CAG3C,MAAM,UAAU,UAAU;EAAE;EAAc;EAAiB;CAAW,CAAC;CAKvE,MAAM,WAAW,aAA4B,KAAK;CAClD,MAAM,EAAE,OAAO,eAAe,gBAAgB,sBAAsB,oBAAoB,iBACtF,kBAAkB,SAAS,QAAQ,GAAG,CAAC,CAAC,GACxC;EAAE,WAAW,MAAM,aAAa;EAAO,QAAQ;EAAW,KAAK,MAAM;EAAK,UAAU,MAAM;EAAU,SAAS,MAAM;EAAS,UAAU;CAAS,CACjJ;CACA,MAAM,EAAE,mBAAmB,gBAAgB,kBAAkB,MAAM,cAAc;CACjF,MAAM,EAAE,WAAW,eAAe,eAAe,oBAAoB,eAAe,OAAO;CAE3F,MAAM,EACJ,SAAS,SAAS,SAAS,eAC3B,iBAAiB,oBAAoB,qBACnC;CAEJ,MAAM,UAAU,iBAAiB,WAAW,MAAM,eAAe,OAAO;CAExE,sBAAsB;EACpB,MAAM,UAAU,UAAU;EAC1B,IAAI,CAAC,SAAS;EACd,OAAO,sBAAsB;GAAE;GAAS;EAAQ,CAAC;CACnD,GAAG;EAAC;EAAW;EAAU;EAAc;CAAO,CAAC;CAE/C,MAAM,EAAE,eAAe,oBAAoB,eAAe,iBAAiB,WAAW,aAAa;CAEnG,MAAM,QAAQ;EAAE;EAAS;EAAS,YAAY;CAAoB;CAClE,gBAAgB,KAAK;EAAE,GAAG;EAAU;EAAc,aAAa,WAAW;CAAO,GAAG,OAAO;EACzF;EAAiB,eAAe;EAAS;EAAe;EAAgB;EACxE;EAAiB;EAAe;EAAS;EAAS;EAClD;EAAmB;EAAe;EAAY;CAChD,CAAC;CAED,MAAM,eAAe,wBAAwB;CAI7C,MAAM,SAAS,cAAc,MAAM,QAAQ,OAAO,MAAM,gBAAgB,MAAM,eAAe;CAC7F,MAAM,EAAE,SAAS,gBAAgB,eAAsB;EACrD,SAAS,MAAM;EAAS;EAAU,UAAU,MAAM;EAAU,cAAc,MAAM;EAChF,OAAO,MAAM;EAAO,eAAe,MAAM;EAAe,kBAAkB,MAAM;EAChF,gBAAgB,QAAQ,QAAQ;EAChC,WAAW,MAAM,WAAW,WAAW;EACvC,oBAAoB,QAAQ,QAAQ,eAAe,KAAK;EACxD,gBAAgB,iBAAiB,iBAAiB,kBAAkB,MAAM;CAC5E,CAAC;CACD,MAAM,mBAAyC;EAAE,GAAG;EAAa,gBAAgB;EAAW,QAAQ;CAAK;CAEzG,uBAAuB,cAAc,QAAQ,OAAO;EAAE;EAAe;EAAiB,eAAe;EAAS,SAAS,UAAU;CAAiB,CAAC;CACnJ,MAAM,kBAAkB,kBAAkB,QAAQ;EAChD;EAAc;EAAc;EAAW;EAAe,aAAa;CACrE,GAAG,aAAa;CAMhB,MAAM,iBAAiB,UAAU;EAC/B,QAAQ;EAAiB;EAAO;EAAQ;EAAW;EACnD,KAAK,MAAM;EAAK,aAAa,MAAM;EAAa,SAAS,MAAM;EAC/D,kBAAkB,MAAM;EAAkB,QAAQ,MAAM;EAAQ,mBAAmB,MAAM;CAC3F,CAAC;CACD,yBAAyB;EACvB,gBAAgB;EAChB,oBAAoB,UAAU;EAC9B,IAAI,YAAY,WAAW,UAAU;EACrC,IAAI,cAAc,aAAa,UAAU;CAC3C,CAAC;CACD,sBAAsB;EACpB,mBAAmB;CACrB,CAAC;CAED,eAAe,UAAU,OAAO,UAAU;EAAE,GAAG;EAAO,WAAW;EAAgB;CAAQ,GAAG,WAAW;CACvG,gBAAgB,kBAAkB,CAAC,gBAAgB,CAAC;CAEpD,cAAc,YAAY,OAAO,WAAW,eAAe,MAAM,OAAO,MAAM;CAE9E,gBAAgB,WAAW;EACzB,cAAc,MAAM,0BAA0B;EAC9C,SAAS,MAAM;EACf,QAAQ,MAAM;EACd,GAAG,WAAW,iBAAiB;GAC7B;GAAS;GAAS;GAAiB;GAAY,MAAM;IAAE;IAAO;GAAO;EACvE,CAAC;CACH,CAAC;CAED,IAAI,UAAU,OAAO;CAErB,OACE,oBAAC,eAAD;EACE,KAAK,SAAS;EACd,OAAO,MAAM;EACb,QAAQ,MAAM;EACd,UAAU,MAAM,YAAY;EAAG,cAAY,MAAM;EACjD,WAAW,MAAM;EAAkB;CACpC,CAAA;AAEL;;;AAIA,IAAa,SAAS,WAAW,WAAW"}
1
+ {"version":3,"file":"Canvas.js","names":[],"sources":["../../src/canvas/Canvas.tsx"],"sourcesContent":["/**\n * Low-level WebGL surface + viewport primitive. Composes layers into a single GL render pass,\n * applies a view transform, and delivers hover to the layers that ask for it. It routes no\n * gesture: `<SceneCanvas>` mounts the gesture dispatcher on this same element. Canvas owns NO\n * scene-shaped state — selection, picking, kind registry, scene-aware overlays all live in\n * `<SceneCanvas>`, which wraps it.\n *\n * The `layers` prop is a map keyed by slot name, every slot already a layer. Standard slots\n * render at a canonical position; custom entries (any other key, value carrying `.layer`) insert\n * at `after`/`before` an existing slot, defaulting to the top.\n *\n * @internal\n * @deprecated Bare `<Canvas>` is not a supported consumer surface.\n * Use `<SceneCanvas>` instead.\n */\n\nimport { forwardRef, useCallback, useEffect, useInsertionEffect, useLayoutEffect, useRef } from 'react';\nimport type React from 'react';\nimport type { CanvasExtensionApi } from './canvasExtension';\nimport { registerMountedCanvas } from './mountedCanvases';\nimport { useViewHelpers } from './useViewHelpers';\nimport { useViewLayerGate } from './useViewLayerGate';\nimport { useSurfaceInput } from './useSurfaceInput';\nimport { useOptionalViewRegistry } from './viewRegistry';\nimport { useCanvasSurface } from './useCanvasSurface';\nimport type { CanvasHelpers } from './useViewHelpers';\nimport type { CanvasProps } from './canvasProps';\nimport { useLatest } from '@weasel-js/react';\nimport { SurfaceCanvas } from './SurfaceCanvas';\nimport { useSurfaceSize } from './useSurfaceSize';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport { AUTO_POSE_DESCRIPTOR } from 'core/geometry/autoPoseDescriptor';\nimport type { PoseDescriptor } from 'interactions/actions/resize/geometry';\nimport { useDebugSink } from '../debug/useDebugSink';\nimport { useToolCursor } from './useToolCursor';\nimport { useCanvasElements } from './useCanvasElements';\nimport { alwaysVisible, useExtraLayers } from './useExtraLayers';\nimport { usePaintedCursor } from './usePaintedCursor';\nimport { useCanvasHandle } from './useCanvasHandle';\nimport { useComposedLayers, useSlotLayers } from './useLayerStack';\nimport { useViewRegistrySurface } from './useViewRegistrySurface';\nimport { useCanvasPaint, usePaintedVersion } from './useCanvasPaint';\nimport { layerHover } from './layerHover';\nimport { useClientToWorld } from './useClientToWorld';\n\nexport type { CanvasProps, CanvasRetainOptions } from './canvasProps';\n\nconst NO_SELECTION: SelectionApi['current'] = [];\n\nfunction CanvasInner<TPose>(\n props: CanvasProps<TPose>,\n ref: React.ForwardedRef<CanvasExtensionApi>,\n) {\n const {\n paintInto, inputElement, tools, viewState, style, getIsVisible, layerVisibility, layerOrder,\n helpersRef, debugSinkRef,\n poseDescriptor: geometry = AUTO_POSE_DESCRIPTOR as unknown as PoseDescriptor<TPose>,\n } = props;\n\n const { sink: debugSink, overlay: debugOverlay, frameStats, getDebug } = useDebugSink(props.debug);\n const elements = useCanvasElements(paintInto, inputElement);\n const { canvasRef, ownCanvasRef, detached } = elements;\n const { width, height } = useSurfaceSize(props, ownCanvasRef);\n\n // Read by `hitTestExtras`, which is built once and must see live values.\n const helpersForLayersRef = useRef<CanvasHelpers<TPose> | null>(null);\n const dimsRef = useLatest({ width, height });\n // Which layers reach the screen, and which chrome within them: asked by the\n // paint and by every hit-test.\n const gateRef = useLatest({ getIsVisible, layerVisibility, layerOrder });\n\n // The frame loop paints; a committed render only marks the surface dirty, so\n // no prop can reach the paint without repainting it. The thunk defers to\n // `useCanvasPaint` below, which needs inputs this render has not computed yet.\n const paintRef = useRef<() => boolean>(() => false);\n const { lease, requestRedraw, subscribeFrame, subscribeBeforePaint, subscribeResume } = useCanvasSurface(\n useCallback(() => paintRef.current(), []),\n { syncPaint: props.syncPaint ?? false, target: canvasRef, dpr: props.dpr, redrawOn: props.redrawOn, shaders: props.shaders, onCommit: 'redraw' },\n );\n const { getPaintedVersion, markPainted } = usePaintedVersion(props.contentVersion);\n const { extrasRef, extrasVersion, registerLayer, hitTestExtrasIn } = useExtraLayers(gateRef);\n\n const {\n viewRef, setView, getView, subscribeView,\n adoptControlled, announceControlled, clearSubscribers,\n } = viewState;\n\n const toWorld = useClientToWorld(canvasRef, props.clientToWorld, viewRef);\n\n useLayoutEffect(() => {\n const element = canvasRef.current;\n if (!element) return;\n return registerMountedCanvas({ element, getView });\n }, [canvasRef, detached, inputElement, getView]);\n\n const { paintedCursor, paintedCursorLayer, cursorSink } = usePaintedCursor(canvasRef, requestRedraw);\n\n const frame = { viewRef, dimsRef, helpersRef: helpersForLayersRef };\n useCanvasHandle(ref, { ...elements, inputElement, paintCanvas: paintInto?.canvas }, frame, {\n hitTestExtrasIn, clientToWorld: toWorld, requestRedraw, subscribeFrame, subscribeBeforePaint,\n subscribeResume, registerLayer, getView, setView, subscribeView,\n getPaintedVersion, paintedCursor, cursorSink, getDebug,\n });\n\n const viewRegistry = useOptionalViewRegistry();\n\n // One view's overlay-aware state. A hook, so N views are N components each\n // calling it once — not a loop in this body.\n const layers = useSlotLayers(props.layers, tools, props.backgroundFill, props.decorationLayer);\n const { helpers: viewHelpers } = useViewHelpers<TPose>({\n adapter: props.adapter, geometry, boundsOf: props.boundsOf, boundsOfPose: props.boundsOfPose,\n nodes: props.nodes, gestureSource: props.gestureSource, previewPoseExtra: props.previewPoseExtra,\n getScale: () => viewRef.current.scale,\n selection: () => props.selection?.current ?? NO_SELECTION,\n getIsVisible: () => gateRef.current.getIsVisible?.() ?? alwaysVisible,\n layerIsPainted: useViewLayerGate(layerVisibility, layerOrder, () => layers),\n });\n const helpersForLayers: CanvasHelpers<TPose> = { ...viewHelpers, getDebug: () => debugSink, viewId: null };\n\n useViewRegistrySurface(viewRegistry, layers, frame, { requestRedraw, hitTestExtrasIn, clientToWorld: toWorld, setView: viewState.setViewFromInput });\n const layersWithDebug = useComposedLayers(layers, {\n viewRegistry, debugOverlay, extrasRef, extrasVersion, cursorLayer: paintedCursorLayer,\n }, requestRedraw);\n\n // Everything the paint, hit-testing and the view registry read that a React\n // render owns. `useLatest` and the insertion effect below publish committed\n // renders only, ahead of every layout effect in the commit, any of which may\n // ask for a sync paint.\n const paintInputsRef = useLatest({\n layers: layersWithDebug, width, height, debugSink, frameStats,\n dpr: props.dpr, layerGroups: props.layerGroups, shaders: props.shaders,\n flattenTolerance: props.flattenTolerance, retain: props.retain, imageMinification: props.imageMinification,\n });\n useInsertionEffect(() => {\n adoptControlled();\n helpersForLayersRef.current = helpersForLayers;\n if (helpersRef) helpersRef.current = helpersForLayers;\n if (debugSinkRef) debugSinkRef.current = debugSink;\n });\n useLayoutEffect(() => {\n announceControlled();\n });\n\n useCanvasPaint(paintRef, lease, elements, { ...frame, inputsRef: paintInputsRef, gateRef }, markPainted, requestRedraw);\n useEffect(() => clearSubscribers, [clearSubscribers]);\n\n useToolCursor(cursorSink, tools, detached ? inputElement : null, style?.cursor);\n\n useSurfaceInput(canvasRef, {\n focusOnPress: props.autoFocusOnPointerDown ?? true,\n onFocus: props.onFocus,\n onBlur: props.onBlur,\n ...layerHover(layersWithDebug, {\n viewRef, toWorld, layerVisibility, layerOrder, dims: { width, height },\n }),\n });\n\n if (detached) return null;\n\n return (\n <SurfaceCanvas\n ref={elements.setOwnCanvas}\n width={props.width}\n height={props.height}\n tabIndex={props.tabIndex ?? 0} aria-label={props['aria-label']}\n className={props.className} style={style}\n />\n );\n}\n\n/** Forward-ref'd `<canvas>` wrapper. Generic over the pose type, inferred from the\n * `adapter` prop. */\nexport const Canvas = forwardRef(CanvasInner) as <TPose = unknown>(\n props: CanvasProps<TPose> & { ref?: React.ForwardedRef<CanvasExtensionApi> },\n) => ReturnType<typeof CanvasInner>;\n\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { createViewportLayer } from "../features/viewports/viewportLayer.js";
1
+ import { createViewportLayer } from "../domains/viewports/viewportLayer.js";
2
2
  import { useDeviceProfile } from "../core/device/useDeviceProfile.js";
3
3
  import { viewportWorldRect } from "../core/viewport/viewportWorldRect.js";
4
4
  import { clientToWorld } from "../core/viewport/clientToWorld.js";
@@ -34,6 +34,7 @@ var NO_INPUTS = {
34
34
  boundsOf: void 0
35
35
  };
36
36
  var ALWAYS_VISIBLE = () => true;
37
+ var selectionOverlay = (selection) => selection ? { selection } : {};
37
38
  var ALL_LAYERS = (s) => s;
38
39
  /**
39
40
  * One view on a shared canvas. Owns a camera, contributes the viewport node
@@ -44,24 +45,25 @@ var ALL_LAYERS = (s) => s;
44
45
  * drawing. Outside a surface that mounts a view registry it is inert.
45
46
  */
46
47
  function CanvasView(props) {
47
- const { id, parent, bounds, layers = ALL_LAYERS, layerVisibility, layerOrder, background, order = Infinity, label, cameraRef, selection: selectionProp, selectionOptions, interactive = true, paint = true } = props;
48
+ const { id, parent, follows, bounds, layers = ALL_LAYERS, layerVisibility, layerOrder, background, order = Infinity, label, cameraRef, selection: selectionProp, selectionOptions, interactive = true, paint = true } = props;
48
49
  const registry = useOptionalViewRegistry();
49
50
  const depRegistry = useOptionalDepRegistry();
50
51
  const depRegistryRef = useLatest(depRegistry);
51
52
  const ownSelection = useSelection(selectionOptions);
52
53
  const viewSelection = selectionProp ?? (selectionOptions ? ownSelection : void 0);
53
54
  const inputs = useOptionalViewInputs();
54
- const selection = viewSelection ?? inputs?.selectionApi ?? ownSelection;
55
+ const shared = inputs?.selectionApi ?? ownSelection;
55
56
  const live = useLatest({
56
57
  parent,
58
+ follows,
57
59
  bounds,
58
60
  layers,
59
61
  layerVisibility,
60
62
  layerOrder,
61
63
  viewSelection,
62
- selection
64
+ shared
63
65
  });
64
- const { frameIn, rectAt, derivedAt, drawnLayers, layerIsPainted } = useViewNesting(registry, live);
66
+ const { frameIn, rectAt, derivedAt, drawnLayers, layerIsPainted, ownedSelection, selectionNow } = useViewNesting(registry, live);
65
67
  /** The rect for the surface's current frame — what a client point and a
66
68
  * clamp are measured against outside a draw call. */
67
69
  const rectNow = useCallback(() => {
@@ -111,6 +113,9 @@ function CanvasView(props) {
111
113
  },
112
114
  get clipboard() {
113
115
  return base()?.clipboard;
116
+ },
117
+ get handlers() {
118
+ return base()?.handlers;
114
119
  }
115
120
  };
116
121
  }, [
@@ -129,10 +134,10 @@ function CanvasView(props) {
129
134
  /** The chrome-caps context this view answers for: its selection, its camera,
130
135
  * its dispatcher's in-flight action. */
131
136
  const ruleInputs = useCallback(() => ({
132
- selection: live.current.selection.get(),
137
+ selection: selectionNow().get(),
133
138
  view: camera(),
134
139
  action: dispatcherRef.current.getActiveAction()
135
- }), [camera, live]);
140
+ }), [camera, selectionNow]);
136
141
  const surfaceBoundsOf = inputs?.boundsOf;
137
142
  const boundsOf = useMemo(() => surfaceBoundsOf ? (id) => surfaceBoundsOf(id, camera()) : void 0, [surfaceBoundsOf, camera]);
138
143
  const surfaceBoundsOfPose = inputs?.boundsOfPose;
@@ -142,7 +147,7 @@ function CanvasView(props) {
142
147
  boundsOf,
143
148
  boundsOfPose,
144
149
  ...own,
145
- selection: selection.current,
150
+ selection: () => selectionNow().current,
146
151
  layerIsPainted,
147
152
  getIsVisible: () => inputsRef.current?.chromeCaps?.isVisible(ruleInputs()) ?? ALWAYS_VISIBLE
148
153
  });
@@ -198,19 +203,19 @@ function CanvasView(props) {
198
203
  inputs?.resizeHandles,
199
204
  helpersRef
200
205
  ]);
201
- const classifyTarget = useMemo(() => buildClassifyTarget(() => live.current.selection.get(), (wx, wy) => {
206
+ const classifyTarget = useMemo(() => buildClassifyTarget(() => selectionNow().get(), (world) => {
202
207
  const i = inputsRef.current;
203
208
  const frame = {
204
209
  ...camera(),
205
210
  layerIsPainted
206
211
  };
207
- if (i?.pickBest) return i.pickBest(wx, wy, frame);
208
- const ids = i?.pickEvery?.(wx, wy, frame) ?? [];
212
+ if (i?.pickBest) return i.pickBest(world, frame);
213
+ const ids = i?.pickEvery?.(world, frame) ?? [];
209
214
  return ids.length > 0 ? ids[ids.length - 1] : null;
210
215
  }, (id) => inputsRef.current?.kindOfNode?.(id), (id) => inputsRef.current?.doubleClickNames?.(id) ?? id), [
211
216
  camera,
212
217
  layerIsPainted,
213
- live,
218
+ selectionNow,
214
219
  inputsRef
215
220
  ]);
216
221
  const registration = useMemo(() => ({
@@ -238,6 +243,7 @@ function CanvasView(props) {
238
243
  }),
239
244
  layerIsPainted,
240
245
  drawnLayers,
246
+ selection: ownedSelection,
241
247
  target: {
242
248
  dispatcher: dispatcherRef.current,
243
249
  affordanceAt,
@@ -248,7 +254,7 @@ function CanvasView(props) {
248
254
  ingestion: ingestionApi,
249
255
  hitAt: hitAtOf(classifyTarget),
250
256
  dispatcher: { cancelAll: (reason) => dispatcherRef.current.cancelAll(reason) },
251
- ...live.current.viewSelection ? { selection: live.current.viewSelection } : {}
257
+ ...selectionOverlay(ownedSelection())
252
258
  }),
253
259
  getRuleCtx: () => inputsRef.current?.chromeCaps?.ruleCtx(ruleInputs())
254
260
  }
@@ -273,7 +279,7 @@ function CanvasView(props) {
273
279
  ingestionApi,
274
280
  drawnLayers,
275
281
  layerIsPainted,
276
- live,
282
+ ownedSelection,
277
283
  inputsRef,
278
284
  helpersRef,
279
285
  frameIn,
@@ -1 +1 @@
1
- {"version":3,"file":"CanvasView.js","names":[],"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,\n} from 'react';\nimport type { Dims, RenderLayer } from 'core/layers/render';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\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 } 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 { useViewAim } from './useViewAim';\nimport { hitAtOf } from './deps/dispatchSources';\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 type { CanvasViewProps, ViewRect } from './canvasViewProps';\nexport type { CanvasViewProps, ViewRect } from './canvasViewProps';\nimport { NO_RECT, sizeOf, useViewNesting } from './useViewNesting';\nimport {\n useOptionalViewRegistry,\n surfaceLocal,\n IDENTITY_VIEW,\n UNMEASURED_DIMS,\n type ViewRegistration,\n} from './viewRegistry';\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 ALL_LAYERS = (s: readonly RenderLayer<unknown>[]): readonly RenderLayer<unknown>[] => s;\n\n\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, parent, bounds,\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 parent, bounds, layers, layerVisibility, layerOrder, viewSelection, selection,\n });\n\n const { frameIn, rectAt, derivedAt, drawnLayers, layerIsPainted } = useViewNesting(registry, 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, held, aim, setAim, cameraAt,\n } = useViewAim({ props, id, registry, derivedAt, rectAt, rectNow });\n useInsertionEffect(adoptControlled);\n useLayoutEffect(announceControlled);\n useEffect(() => clearSubscribers, [clearSubscribers]);\n useImperativeHandle(cameraRef, () => ({ getView: camera, setView, subscribeView }), [camera, setView, subscribeView]);\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 layerIsPainted,\n getIsVisible: () => 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, handleHitRadius: inputs?.resizeHandles?.hitRadiusPx, edgeHandles: inputs?.resizeHandles?.edges,\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) : registry?.markerAt(id, world) ?? inner(world);\n };\n }, [id, getAnchorState, rectNow, registry, targetScale, camera, drawnLayers, rotationBadge, inputs?.resizeHandles, helpersRef]);\n\n const classifyTarget = useMemo(() => 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 (id) => inputsRef.current?.doubleClickNames?.(id) ?? id,\n ), [camera, layerIsPainted, live, inputsRef]);\n\n const registration = useMemo<ViewRegistration>(() => ({\n id,\n ...(parent !== undefined ? { parent } : {}),\n order,\n interactive,\n paint,\n held,\n aim,\n setAim,\n layer: createViewportLayer<unknown, unknown>({\n id,\n label: label ?? id,\n source: () => [...drawnLayers(), ...(registry?.markerLayers(id) ?? [])],\n view: cameraAt,\n bounds: (outer, dims) => rectAt(outer, dims),\n ...(parent !== undefined ? { clip: (outer: View, dims: Dims) => frameIn(outer, dims)?.clip ?? NO_RECT } : {}),\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 drawnLayers,\n target: {\n dispatcher: dispatcherRef.current!,\n affordanceAt,\n classifyTarget,\n clientToWorld: clientToWorldHere,\n deps: () => ({\n view: viewApi, ingestion: ingestionApi, hitAt: hitAtOf(classifyTarget),\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, parent, order, interactive, paint, held, aim, setAim, label, background, rectAt, cameraAt, viewApi,\n affordanceAt, classifyTarget, clientToWorldHere, ruleInputs, ingestionApi, drawnLayers,\n layerIsPainted, live, inputsRef, helpersRef, frameIn, registry]);\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 // The surface paints this view from `live`, so any committed render of it —\n // a controlled camera, its bounds, its layer gate — needs a frame.\n useEffect(() => {\n registry?.surface()?.requestRedraw();\n });\n\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CanvasView.js","names":[],"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,\n} from 'react';\nimport type { Dims, RenderLayer } from 'core/layers/render';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\nimport { createViewportLayer } from 'domains/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 } 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 { useViewAim } from './useViewAim';\nimport { hitAtOf } from './deps/dispatchSources';\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 type { CanvasViewProps, ViewRect } from './canvasViewProps';\nexport type { CanvasViewProps, ViewRect } from './canvasViewProps';\nimport { NO_RECT, sizeOf, useViewNesting } from './useViewNesting';\nimport {\n useOptionalViewRegistry,\n surfaceLocal,\n IDENTITY_VIEW,\n UNMEASURED_DIMS,\n type ViewRegistration,\n} from './viewRegistry';\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\n// Only a view that owns a selection, or follows one that does, overlays it; otherwise the surface's answer\n// stands, wrappers (`selectable`) included.\nconst selectionOverlay = (selection: SelectionApi | undefined) => (selection ? { selection } : {});\n\nconst ALL_LAYERS = (s: readonly RenderLayer<unknown>[]): readonly RenderLayer<unknown>[] => s;\n\n\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, parent, follows, bounds,\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 const shared = 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 parent, follows, bounds, layers, layerVisibility, layerOrder, viewSelection, shared,\n });\n\n const {\n frameIn, rectAt, derivedAt, drawnLayers, layerIsPainted, ownedSelection, selectionNow,\n } = useViewNesting(registry, 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, held, aim, setAim, cameraAt,\n } = useViewAim({ props, id, registry, derivedAt, rectAt, rectNow });\n useInsertionEffect(adoptControlled);\n useLayoutEffect(announceControlled);\n useEffect(() => clearSubscribers, [clearSubscribers]);\n useImperativeHandle(cameraRef, () => ({ getView: camera, setView, subscribeView }), [camera, setView, subscribeView]);\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`, `handlers` — 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; }, get handlers() { return base()?.handlers; },\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: selectionNow().get(),\n view: camera(),\n action: dispatcherRef.current!.getActiveAction(),\n }), [camera, selectionNow]);\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: () => selectionNow().current,\n layerIsPainted,\n getIsVisible: () => 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, handleHitRadius: inputs?.resizeHandles?.hitRadiusPx, edgeHandles: inputs?.resizeHandles?.edges,\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) : registry?.markerAt(id, world) ?? inner(world);\n };\n }, [id, getAnchorState, rectNow, registry, targetScale, camera, drawnLayers, rotationBadge, inputs?.resizeHandles, helpersRef]);\n\n const classifyTarget = useMemo(() => buildClassifyTarget(\n () => selectionNow().get(),\n (world) => {\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(world, frame);\n const ids = i?.pickEvery?.(world, frame) ?? [];\n return ids.length > 0 ? ids[ids.length - 1]! : null;\n },\n (id) => inputsRef.current?.kindOfNode?.(id),\n (id) => inputsRef.current?.doubleClickNames?.(id) ?? id,\n ), [camera, layerIsPainted, selectionNow, inputsRef]);\n\n const registration = useMemo<ViewRegistration>(() => ({\n id,\n ...(parent !== undefined ? { parent } : {}),\n order,\n interactive,\n paint,\n held,\n aim,\n setAim,\n layer: createViewportLayer<unknown, unknown>({\n id,\n label: label ?? id,\n source: () => [...drawnLayers(), ...(registry?.markerLayers(id) ?? [])],\n view: cameraAt,\n bounds: (outer, dims) => rectAt(outer, dims),\n ...(parent !== undefined ? { clip: (outer: View, dims: Dims) => frameIn(outer, dims)?.clip ?? NO_RECT } : {}),\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 drawnLayers,\n selection: ownedSelection,\n target: {\n dispatcher: dispatcherRef.current!,\n affordanceAt,\n classifyTarget,\n clientToWorld: clientToWorldHere,\n deps: () => ({\n view: viewApi, ingestion: ingestionApi, hitAt: hitAtOf(classifyTarget),\n // An Escape here cancels what is in flight here.\n dispatcher: { cancelAll: (reason) => dispatcherRef.current!.cancelAll(reason) },\n ...selectionOverlay(ownedSelection()),\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, parent, order, interactive, paint, held, aim, setAim, label, background, rectAt, cameraAt, viewApi,\n affordanceAt, classifyTarget, clientToWorldHere, ruleInputs, ingestionApi, drawnLayers,\n layerIsPainted, ownedSelection, inputsRef, helpersRef, frameIn, registry]);\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 // The surface paints this view from `live`, so any committed render of it —\n // a controlled camera, its bounds, its layer gate — needs a frame.\n useEffect(() => {\n registry?.surface()?.requestRedraw();\n });\n\n return null;\n}\n"],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ import { viewToTransform } from "../core/viewport/view.js";
2
+ import { worldToScreen } from "../core/viewport/viewTransform.js";
3
+ import { resolveOverlays } from "../interactions/actions/resolveOverlays.js";
4
+ import GestureReason_module_default from "./GestureReason.module.js";
5
+ import { useEffect, useState } from "react";
6
+ import { overlaysOf } from "@weasel-js/routing";
7
+ import { jsx } from "react/jsx-runtime";
8
+
9
+ //#region src/canvas/GestureReason.tsx
10
+ /**
11
+ * The reason an in-flight gesture cannot land where it is, beside the pointer:
12
+ * the DOM half of the `reason` overlay, which the canvas layers cannot paint
13
+ * as text.
14
+ */
15
+ /** How far below and right of the pointer the reason sits, in CSS pixels. */
16
+ var OFFSET = 14;
17
+ /** The first `reason` overlay of the dispatcher's in-flight gestures, shown beside the pointer. */
18
+ function GestureReason({ dispatcher, canvasRef, viewRef }) {
19
+ const [shown, setShown] = useState(null);
20
+ useEffect(() => {
21
+ if (!dispatcher) return;
22
+ const read = () => {
23
+ const all = [...dispatcher.getInFlightHandles()].flatMap((h) => [...overlaysOf(h)]);
24
+ const reason = resolveOverlays(all).find((o) => o.kind === "reason");
25
+ const canvas = canvasRef.current;
26
+ const view = viewRef.current;
27
+ if (reason?.kind !== "reason" || !canvas || !view) {
28
+ setShown(null);
29
+ return;
30
+ }
31
+ const r = canvas.getBoundingClientRect();
32
+ const [sx, sy] = worldToScreen(reason.at.x, reason.at.y, viewToTransform(view));
33
+ setShown({
34
+ left: r.left + sx + OFFSET,
35
+ top: r.top + sy + OFFSET,
36
+ text: reason.text
37
+ });
38
+ };
39
+ read();
40
+ const off = dispatcher.subscribe(read);
41
+ return () => {
42
+ off();
43
+ setShown(null);
44
+ };
45
+ }, [
46
+ dispatcher,
47
+ canvasRef,
48
+ viewRef
49
+ ]);
50
+ if (shown === null) return null;
51
+ return /* @__PURE__ */ jsx("div", {
52
+ role: "status",
53
+ className: GestureReason_module_default.reason,
54
+ style: {
55
+ left: shown.left,
56
+ top: shown.top
57
+ },
58
+ children: shown.text
59
+ });
60
+ }
61
+
62
+ //#endregion
63
+ export { GestureReason };
64
+ //# sourceMappingURL=GestureReason.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GestureReason.js","names":["s"],"sources":["../../src/canvas/GestureReason.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * The reason an in-flight gesture cannot land where it is, beside the pointer:\n * the DOM half of the `reason` overlay, which the canvas layers cannot paint\n * as text.\n */\nimport { useEffect, useState, type RefObject } from 'react';\nimport { overlaysOf, type Dispatcher } from '@weasel-js/routing';\nimport { viewToTransform, type View } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\nimport { resolveOverlays } from 'interactions/actions/resolveOverlays';\nimport s from './GestureReason.module.css';\n\n/** How far below and right of the pointer the reason sits, in CSS pixels. */\nconst OFFSET = 14;\n\nexport interface GestureReasonProps {\n dispatcher: Dispatcher | null | undefined;\n canvasRef: RefObject<HTMLElement | null>;\n viewRef: RefObject<View>;\n}\n\ninterface Shown { left: number; top: number; text: string }\n\n/** The first `reason` overlay of the dispatcher's in-flight gestures, shown beside the pointer. */\nexport function GestureReason({ dispatcher, canvasRef, viewRef }: GestureReasonProps) {\n const [shown, setShown] = useState<Shown | null>(null);\n useEffect(() => {\n if (!dispatcher) return;\n const read = () => {\n const all = [...dispatcher.getInFlightHandles()].flatMap((h) => [...overlaysOf(h)]);\n const reason = resolveOverlays(all).find((o) => o.kind === 'reason');\n const canvas = canvasRef.current;\n const view = viewRef.current;\n if (reason?.kind !== 'reason' || !canvas || !view) {\n setShown(null);\n return;\n }\n const r = canvas.getBoundingClientRect();\n const [sx, sy] = worldToScreen(reason.at.x, reason.at.y, viewToTransform(view));\n setShown({ left: r.left + sx + OFFSET, top: r.top + sy + OFFSET, text: reason.text });\n };\n read();\n const off = dispatcher.subscribe(read);\n return () => {\n off();\n setShown(null);\n };\n }, [dispatcher, canvasRef, viewRef]);\n if (shown === null) return null;\n // The pointer moves it every frame; nothing but an inline position can follow it.\n return <div role=\"status\" className={s.reason} style={{ left: shown.left, top: shown.top }}>{shown.text}</div>;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAcA,IAAM,SAAS;;AAWf,SAAgB,cAAc,EAAE,YAAY,WAAW,WAA+B;CACpF,MAAM,CAAC,OAAO,YAAY,SAAuB,IAAI;CACrD,gBAAgB;EACd,IAAI,CAAC,YAAY;EACjB,MAAM,aAAa;GACjB,MAAM,MAAM,CAAC,GAAG,WAAW,mBAAmB,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC;GAClF,MAAM,SAAS,gBAAgB,GAAG,CAAC,CAAC,MAAM,MAAM,EAAE,SAAS,QAAQ;GACnE,MAAM,SAAS,UAAU;GACzB,MAAM,OAAO,QAAQ;GACrB,IAAI,QAAQ,SAAS,YAAY,CAAC,UAAU,CAAC,MAAM;IACjD,SAAS,IAAI;IACb;GACF;GACA,MAAM,IAAI,OAAO,sBAAsB;GACvC,MAAM,CAAC,IAAI,MAAM,cAAc,OAAO,GAAG,GAAG,OAAO,GAAG,GAAG,gBAAgB,IAAI,CAAC;GAC9E,SAAS;IAAE,MAAM,EAAE,OAAO,KAAK;IAAQ,KAAK,EAAE,MAAM,KAAK;IAAQ,MAAM,OAAO;GAAK,CAAC;EACtF;EACA,KAAK;EACL,MAAM,MAAM,WAAW,UAAU,IAAI;EACrC,aAAa;GACX,IAAI;GACJ,SAAS,IAAI;EACf;CACF,GAAG;EAAC;EAAY;EAAW;CAAO,CAAC;CACnC,IAAI,UAAU,MAAM,OAAO;CAE3B,OAAO,oBAAC,OAAD;EAAK,MAAK;EAAS,WAAWA,6BAAE;EAAQ,OAAO;GAAE,MAAM,MAAM;GAAM,KAAK,MAAM;EAAI;EAAI,UAAA,MAAM;CAAU,CAAA;AAC/G"}
@@ -0,0 +1,7 @@
1
+ //#region src/canvas/GestureReason.module.css
2
+ var reason = "_reason_0cabc7";
3
+ var GestureReason_module_default = { reason };
4
+
5
+ //#endregion
6
+ export { GestureReason_module_default as default, reason };
7
+ //# sourceMappingURL=GestureReason.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GestureReason.module.js","names":[],"sources":["../../src/canvas/GestureReason.module.css"],"sourcesContent":["/* A refusal's reason, held beside the pointer while a drag is over what refuses it. */\n.reason {\n position: fixed;\n z-index: var(--wzl-z-hud, 900);\n max-width: 280px;\n padding: var(--wzl-space-2, 4px) var(--wzl-space-3, 6px);\n border-left: 3px solid var(--wzl-danger, #d93636);\n border-radius: var(--wzl-radius-sm, 3px);\n background: var(--wzl-surface-popover, #fff);\n color: var(--wzl-fg, #1a1a1a);\n box-shadow: var(--wzl-shadow, 0 1px 4px rgba(0, 0, 0, 0.25));\n font: var(--wzl-font-size-sm, 12px) / 1.35 system-ui, sans-serif;\n pointer-events: none;\n}\n"],"mappings":""}
@@ -1,11 +1,13 @@
1
1
  import { toolDrivenActions } from "./SceneCanvas/presets/toolDriven.js";
2
+ import { BASELINE_ACTIONS } from "./SceneCanvas/presets/baseline.js";
2
3
  import { renderSceneCanvas } from "./SceneCanvas.js";
3
4
  import { forwardRef } from "react";
4
5
 
5
6
  //#region src/canvas/LeanSceneCanvas.tsx
6
7
  var LEAN_SOURCE = {
7
8
  named: null,
8
- pool: toolDrivenActions
9
+ pool: toolDrivenActions,
10
+ baseline: BASELINE_ACTIONS
9
11
  };
10
12
  function LeanSceneCanvasWrapper(props, ref) {
11
13
  return renderSceneCanvas(LEAN_SOURCE, props, ref);
@@ -1 +1 @@
1
- {"version":3,"file":"LeanSceneCanvas.js","names":[],"sources":["../../src/canvas/LeanSceneCanvas.tsx"],"sourcesContent":["import type React from 'react';\nimport { forwardRef } from 'react';\nimport type { SceneCanvasApi } from './canvasExtension';\nimport { renderSceneCanvas } from './SceneCanvas';\nimport type { FeaturePreset, PresetSource } from './SceneCanvas/features';\nimport type { SceneCanvasProps } from './SceneCanvas/props';\nimport { toolDrivenActions } from './SceneCanvas/presets/toolDriven';\n\nconst LEAN_SOURCE: PresetSource = { named: null, pool: toolDrivenActions };\n\n/** Props for {@link LeanSceneCanvas}: `<SceneCanvas>`'s, with `features`\n * taking preset objects only. */\nexport type LeanSceneCanvasProps<TData, TLayer extends string, TPose> =\n Omit<SceneCanvasProps<TData, TLayer, TPose>, 'features'> & { features?: readonly FeaturePreset[] };\n\nfunction LeanSceneCanvasWrapper<TData, TLayer extends string, TPose>(\n props: LeanSceneCanvasProps<TData, TLayer, TPose>,\n ref: React.ForwardedRef<SceneCanvasApi>,\n) {\n return renderSceneCanvas(LEAN_SOURCE, props, ref);\n}\n\n/**\n * `<SceneCanvas>` without core's preset names: `features` takes preset\n * objects (`selectPreset`, `editPreset`, a package's own), and a preset the\n * app does not import is not in its bundle. `viewport` does not imply\n * `viewPreset` here; pass it.\n */\nexport const LeanSceneCanvas = forwardRef(LeanSceneCanvasWrapper) as <\n TData, TLayer extends string, TPose,\n>(\n props: LeanSceneCanvasProps<TData, TLayer, TPose> & { ref?: React.Ref<SceneCanvasApi> },\n) => React.ReactElement;\n"],"mappings":";;;;;AAQA,IAAM,cAA4B;CAAE,OAAO;CAAM,MAAM;AAAkB;AAOzE,SAAS,uBACP,OACA,KACA;CACA,OAAO,kBAAkB,aAAa,OAAO,GAAG;AAClD;;;;;;;AAQA,IAAa,kBAAkB,WAAW,sBAAsB"}
1
+ {"version":3,"file":"LeanSceneCanvas.js","names":[],"sources":["../../src/canvas/LeanSceneCanvas.tsx"],"sourcesContent":["import type React from 'react';\nimport { forwardRef } from 'react';\nimport type { SceneCanvasApi } from './canvasExtension';\nimport { renderSceneCanvas } from './SceneCanvas';\nimport type { FeaturePreset, PresetSource } from './SceneCanvas/features';\nimport type { SceneCanvasProps } from './SceneCanvas/props';\nimport { toolDrivenActions } from './SceneCanvas/presets/toolDriven';\nimport { BASELINE_ACTIONS } from './SceneCanvas/presets/baseline';\n\nconst LEAN_SOURCE: PresetSource = { named: null, pool: toolDrivenActions, baseline: BASELINE_ACTIONS };\n\n/** Props for {@link LeanSceneCanvas}: `<SceneCanvas>`'s, with `features`\n * taking preset objects only. */\nexport type LeanSceneCanvasProps<TData, TLayer extends string, TPose> =\n Omit<SceneCanvasProps<TData, TLayer, TPose>, 'features'> & { features?: readonly FeaturePreset[] };\n\nfunction LeanSceneCanvasWrapper<TData, TLayer extends string, TPose>(\n props: LeanSceneCanvasProps<TData, TLayer, TPose>,\n ref: React.ForwardedRef<SceneCanvasApi>,\n) {\n return renderSceneCanvas(LEAN_SOURCE, props, ref);\n}\n\n/**\n * `<SceneCanvas>` without core's preset names: `features` takes preset\n * objects (`selectPreset`, `editPreset`, a package's own), and a preset the\n * app does not import is not in its bundle. `viewport` does not imply\n * `viewPreset` here; pass it.\n */\nexport const LeanSceneCanvas = forwardRef(LeanSceneCanvasWrapper) as <\n TData, TLayer extends string, TPose,\n>(\n props: LeanSceneCanvasProps<TData, TLayer, TPose> & { ref?: React.Ref<SceneCanvasApi> },\n) => React.ReactElement;\n"],"mappings":";;;;;;AASA,IAAM,cAA4B;CAAE,OAAO;CAAM,MAAM;CAAmB,UAAU;AAAiB;AAOrG,SAAS,uBACP,OACA,KACA;CACA,OAAO,kBAAkB,aAAa,OAAO,GAAG;AAClD;;;;;;;AAQA,IAAa,kBAAkB,WAAW,sBAAsB"}
@@ -1,4 +1,5 @@
1
1
  import { bumpNodeMemoGeneration, nodeMemo } from "../core/scene/nodeMemo.js";
2
+ import { setDepOutlineReader } from "../core/scene/booleanOfChildren.js";
2
3
  import { hasSlop, slopForStrokeHit, widenSlop } from "../core/viewport/screenSlop.js";
3
4
  import { derivesPath } from "./nodeShapes/memo.js";
4
5
  import { DERIVED_PAINTER } from "./nodeShapes/derivedPainter.js";
@@ -104,6 +105,7 @@ function findShapeSilhouette(node, pose, ctx) {
104
105
  }
105
106
  return nodeMemo(node, SILHOUETTE_SLOT, pose, build);
106
107
  }
108
+ setDepOutlineReader((dep) => findShapeSilhouette(dep.node, dep.pose, { derivedPath: dep.path }));
107
109
  /** Find the painter for `node` and ask how it inks its silhouette. Returns
108
110
  * the painter's declared {@link NodeInk}, or `null` when no painter matches
109
111
  * or it declares none — callers substitute {@link DEFAULT_INK}. */
@@ -1 +1 @@
1
- {"version":3,"file":"NodeShape.js","names":[],"sources":["../../src/canvas/NodeShape.ts"],"sourcesContent":["/**\n * NodeShape — the **shape trait's** registry: the per-kind `paint` + `silhouette` used by\n * `defaultDrawOne`, clipping, non-rect hit-testing, and lasso/area-select. Teaching the kit\n * about a new kind of shape goes through this registry rather than by overriding `drawOne`.\n *\n * The first entry whose `matches` predicate returns true paints the node: `'high'` entries\n * first, then the built-ins, then `'normal'` ones, in registration order within a tier. Every\n * built-in but `kit:derived` additionally requires a rect-shaped pose — a scene whose poses are\n * some other shape matches none of them, and paints through a consumer painter or not at all.\n */\nimport { glyphGeneration } from '@weasel-js/font';\nimport {\n pathContainsPoint,\n strokeHitTest,\n type Path\n} from '@weasel-js/geom';\nimport { pathThroughPoseFrame } from '@weasel-js/geom';\nimport { bumpNodeMemoGeneration, nodeMemo } from 'core/scene/nodeMemo';\nimport type { Node } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { hasSlop, slopForStrokeHit, widenSlop, type PickSlop } from 'core/viewport/screenSlop';\nimport { DERIVED_PAINTER } from './nodeShapes/derivedPainter';\nimport { IMAGE_PAINTER } from './nodeShapes/imagePainter';\nimport { MEASURE_PAINTER } from './nodeShapes/measurePainter';\nimport { derivesPath } from './nodeShapes/memo';\nimport { PATH_PAINTER } from './nodeShapes/pathPainter';\nimport { paintsPose } from './nodeShapes/poseBox';\nimport { RECT_FALLBACK_PAINTER } from './nodeShapes/rectFallbackPainter';\nimport { SHAPE_PAINTER } from './nodeShapes/shapePainter';\nimport { TEXT_PAINTER } from './nodeShapes/textPainter';\nimport type { NodeShapeEntry, NodeInk, NodeSilhouetteCtx, NodeInkCtx } from './nodeShapeTypes';\nexport type { NodePaintCtx, SceneViewDrawOne, NodeShapeEntry, NodeInk, NodeSilhouetteCtx, NodeInkCtx } from './nodeShapeTypes';\nexport type { InheritedPaint } from 'core/scene/inheritedPaint';\n\n/** What a painter that declares no `ink` is assumed to do. */\nexport const DEFAULT_INK: Readonly<NodeInk> = Object.freeze({ filled: true, outset: 0, inset: 0 });\n\n/** Options for `registerNodeShape`. */\nexport interface RegisterNodeShapeOptions {\n /** `'high'` puts the painter ahead of all normally-registered ones (so\n * it can win over a kit built-in). `'normal'` appends at the end. */\n priority?: 'high' | 'normal';\n}\n\nconst PAINTERS: { high: NodeShapeEntry[]; normal: NodeShapeEntry[] } = {\n high: [],\n normal: [],\n};\n\n// The built-ins go in on first use, not at module load: a bundler may drop an\n// import kept only for its side effect, and the registry would come up empty.\nlet builtInsRegistered = false;\nfunction ensureBuiltIns(): void {\n if (builtInsRegistered) return;\n builtInsRegistered = true;\n registerBuiltInShapePainters();\n}\n\n/** Register a shape painter. Returns a disposer that removes it. */\nexport function registerNodeShape<TData, TPose>(\n painter: NodeShapeEntry<TData, TPose>,\n opts: RegisterNodeShapeOptions = {},\n): () => void {\n ensureBuiltIns();\n const list = opts.priority === 'high' ? PAINTERS.high : PAINTERS.normal;\n list.push(painter as NodeShapeEntry);\n // The painter set is exactly the ambient state `findNodeShape` reads, and a\n // memo keyed on the node alone cannot see it change. See `nodeMemo`.\n bumpNodeMemoGeneration();\n return () => {\n const i = list.indexOf(painter as NodeShapeEntry);\n if (i >= 0) list.splice(i, 1);\n bumpNodeMemoGeneration();\n };\n}\n\n/**\n * Slot names for what picking asks per node per pointer move: which painter matches, and that\n * painter's silhouette path. Both go through {@link nodeMemo}, so they invalidate on `data`\n * (and, for the silhouette, `pose`) reference changes and on a painter registration.\n *\n * Separate slots rather than one entry: they mostly invalidate together, but not always, and a\n * shared entry would force the stricter key on both.\n */\nconst PAINTER_SLOT = 'shape:painter';\nconst PAINTER_SLOT_NONRECT = 'shape:painter:nonrect';\nconst PAINTER_SLOT_DERIVED = 'shape:painter:derived';\nconst PAINTER_SLOT_DERIVED_NONRECT = 'shape:painter:derived:nonrect';\nconst SILHOUETTE_SLOT = 'shape:silhouette';\nconst TEXT_SILHOUETTE_SLOT = 'shape:silhouette:text';\n\n/** The painter that will render `node` — first match in priority order — or undefined if\n * none accepts it. */\nexport function findNodeShape<TData, TPose>(\n node: Node<TData, string, TPose>,\n): NodeShapeEntry<TData, TPose> | undefined {\n // Built-in painters also gate on pose shape and on whether the node derives\n // its path, neither of which shows in `data`, so the key carries both.\n const rect = paintsPose(node.pose);\n const slot = derivesPath(node)\n ? (rect ? PAINTER_SLOT_DERIVED : PAINTER_SLOT_DERIVED_NONRECT)\n : (rect ? PAINTER_SLOT : PAINTER_SLOT_NONRECT);\n return nodeMemo(node as { data?: unknown }, slot, undefined, () =>\n matchNodeShape(node),\n );\n}\n\nfunction matchNodeShape<TData, TPose>(\n node: Node<TData, string, TPose>,\n): NodeShapeEntry<TData, TPose> | undefined {\n ensureBuiltIns();\n for (const p of PAINTERS.high) {\n if (p.matches(node as Node<unknown, string, unknown>)) {\n return p as NodeShapeEntry<TData, TPose>;\n }\n }\n for (const p of PAINTERS.normal) {\n if (p.matches(node as Node<unknown, string, unknown>)) {\n return p as NodeShapeEntry<TData, TPose>;\n }\n }\n return undefined;\n}\n\n/** The silhouette path of `node`, in **world** coords, or null if no painter matches or the\n * matching painter has none.\n *\n * Painters return their silhouette in the pose's local (unrotated) frame;\n * this bakes the pose's frame (`poseFrameOf`: its rotation and `transform`)\n * on top, so clips/area-select of a turned or skewed node use the boundary\n * the renderer draws. */\nexport function findShapeSilhouette<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeSilhouetteCtx,\n): Path | null {\n const build = (): Path | null => {\n const sil = findNodeShape(node)?.silhouette?.(node, pose, ctx) ?? null;\n return sil && pathThroughPoseFrame(sil, pose);\n };\n // `SILHOUETTE_SLOT`'s key is (node, pose, data) and cannot see\n // `ctx.derivedPath` — the same reason `kit:derived` skips `PAINT_SLOT`.\n // Memoizing here would serve one caller's silhouette to a caller that\n // passed a different path. Only an actual path skips it: a scene-backed\n // source answers `null` for every ordinary node, and treating that as a\n // reason to bypass would retire the memo for the whole scene.\n if (ctx?.derivedPath != null) return build();\n // Line boxes follow font metrics, and a face landing changes those with no\n // change to the node, so the text entry is checked against the glyph epoch.\n if (findNodeShape(node) === (TEXT_PAINTER as NodeShapeEntry<unknown, unknown>)) {\n const epoch = glyphGeneration();\n const held = nodeMemo(node as { data?: unknown }, TEXT_SILHOUETTE_SLOT, pose,\n (): { epoch: number; path: Path | null } => ({ epoch, path: build() }));\n if (held.epoch !== epoch) {\n held.epoch = epoch;\n held.path = build();\n }\n return held.path;\n }\n return nodeMemo(node as { data?: unknown }, SILHOUETTE_SLOT, pose, build);\n}\n\n/** Find the painter for `node` and ask how it inks its silhouette. Returns\n * the painter's declared {@link NodeInk}, or `null` when no painter matches\n * or it declares none — callers substitute {@link DEFAULT_INK}. */\nexport function findShapeInk<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeInkCtx,\n): NodeInk | null {\n return findNodeShape(node)?.ink?.(node, pose, ctx) ?? null;\n}\n\n/** Find the painter for `node` and ask for the box its paint fits in. `null`\n * when no painter matches, or the one that does cannot say — see\n * {@link NodeShapeEntry.bounds}. */\nexport function findShapeBounds<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeInkCtx,\n): Bounds | null {\n return findNodeShape(node)?.bounds?.(node, pose, ctx) ?? null;\n}\n\n/** Options for {@link shapeCoversPoint}. */\nexport interface ShapeCoversPointOptions {\n /** Extra grab distance around the outline: **world** units as a number,\n * or screen pixels under a view scale (`{ px, scale }`), which is measured\n * on screen and so stays exact under non-uniform zoom. Defaults to `0`,\n * where a hairline is too thin a target to hit. */\n tolerance?: PickSlop;\n /** View scale, passed to the painter's `ink`, and what a screen reach is\n * read at under a world `tolerance`. Defaults to 1. */\n scale?: number;\n /** The node's derived path — see {@link NodeSilhouetteCtx.derivedPath}.\n * Without it a derived node reports no silhouette and this answers `true`\n * everywhere, which degrades picking to the caller's AABB: for an edge,\n * a zero-sized pose. */\n derivedPath?: Path | null;\n /** See {@link NodeInkCtx.inherited}. Without it an `'inherit'` field is\n * read as none. */\n inherited?: NodeInkCtx['inherited'];\n}\n\n/**\n * Does the shape `node` actually paints cover the world point? Asks the painter's silhouette,\n * the same boundary used for clipping and area-select, rather than the pose rect.\n *\n * The ink counts too: a shape whose interior isn't filled is grabbable along its outline and\n * not through its empty middle. The outline's grab width is the stroke's half-width plus\n * `tolerance`.\n *\n * A painter with no `silhouette`, or one that returns `null` for this node, reports `true` —\n * \"no opinion\" — so callers should keep their own AABB test as a pre-filter.\n */\nexport function shapeCoversPoint<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n x: number,\n y: number,\n opts: ShapeCoversPointOptions = {},\n): boolean {\n // A group paints nothing, so its interior is its box, which the caller's pre-filter tested.\n if (node.kind === 'group') return true;\n const sil = findShapeSilhouette(node, pose, { derivedPath: opts.derivedPath });\n if (sil === null) return true;\n const ink = findShapeInk(node, pose, { scale: opts.scale, inherited: opts.inherited }) ?? DEFAULT_INK;\n const inside = pathContainsPoint(sil, x, y);\n if (ink.filled && inside) return true;\n // The stroke reaches a different distance on each side, so which side the point is on\n // picks the reach. `tolerance` also makes a filled shape grabbable a few pixels outside\n // its edge.\n const slop = widenSlop(opts.tolerance, (inside ? ink.insetPx : ink.outsetPx) ?? 0, opts.scale);\n const { extra, opts: hit } = slopForStrokeHit(slop);\n const reach = (inside ? ink.inset : ink.outset) + extra;\n return (reach > 0 || hasSlop(slop)) && strokeHitTest(sil, x, y, reach, hit);\n}\n\n/** The current painters in evaluation order — `'high'` tier first, then `'normal'`. */\nexport function getNodeShapes(): readonly NodeShapeEntry[] {\n ensureBuiltIns();\n return [...PAINTERS.high, ...PAINTERS.normal];\n}\n\n/** Test-only: clear the registry and re-register the built-ins. */\nexport function _resetShapePaintersForTests(): void {\n PAINTERS.high.length = 0;\n PAINTERS.normal.length = 0;\n builtInsRegistered = false;\n ensureBuiltIns();\n // `registerNodeShape` already bumps, but the clearing above happens without one.\n bumpNodeMemoGeneration();\n}\n\nfunction registerBuiltInShapePainters(): void {\n registerNodeShape(TEXT_PAINTER);\n registerNodeShape(MEASURE_PAINTER);\n // Ahead of path/shape/image: a derived node whose `data` also carries a\n // `path`, `shape` or `image` means the derived path, and those three match\n // on the presence of the field alone.\n registerNodeShape(DERIVED_PAINTER);\n registerNodeShape(PATH_PAINTER);\n registerNodeShape(SHAPE_PAINTER);\n registerNodeShape(IMAGE_PAINTER);\n registerNodeShape(RECT_FALLBACK_PAINTER);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"NodeShape.js","names":[],"sources":["../../src/canvas/NodeShape.ts"],"sourcesContent":["/**\n * NodeShape — the **shape trait's** registry: the per-kind `paint` + `silhouette` used by\n * `defaultDrawOne`, clipping, non-rect hit-testing, and lasso/area-select. Teaching the kit\n * about a new kind of shape goes through this registry rather than by overriding `drawOne`.\n *\n * The first entry whose `matches` predicate returns true paints the node: `'high'` entries\n * first, then the built-ins, then `'normal'` ones, in registration order within a tier. Every\n * built-in but `kit:derived` additionally requires a rect-shaped pose — a scene whose poses are\n * some other shape matches none of them, and paints through a consumer painter or not at all.\n */\nimport { glyphGeneration } from '@weasel-js/font';\nimport {\n pathContainsPoint,\n strokeHitTest,\n type Path\n} from '@weasel-js/geom';\nimport { pathThroughPoseFrame } from '@weasel-js/geom';\nimport { bumpNodeMemoGeneration, nodeMemo } from 'core/scene/nodeMemo';\nimport { setDepOutlineReader } from 'core/scene/booleanOfChildren';\nimport type { Node } from 'core/scene/types';\nimport type { Bounds } from 'core/viewport/fitViewToBounds';\nimport { hasSlop, slopForStrokeHit, widenSlop, type PickSlop } from 'core/viewport/screenSlop';\nimport { DERIVED_PAINTER } from './nodeShapes/derivedPainter';\nimport { IMAGE_PAINTER } from './nodeShapes/imagePainter';\nimport { MEASURE_PAINTER } from './nodeShapes/measurePainter';\nimport { derivesPath } from './nodeShapes/memo';\nimport { PATH_PAINTER } from './nodeShapes/pathPainter';\nimport { paintsPose } from './nodeShapes/poseBox';\nimport { RECT_FALLBACK_PAINTER } from './nodeShapes/rectFallbackPainter';\nimport { SHAPE_PAINTER } from './nodeShapes/shapePainter';\nimport { TEXT_PAINTER } from './nodeShapes/textPainter';\nimport type { NodeShapeEntry, NodeInk, NodeSilhouetteCtx, NodeInkCtx } from './nodeShapeTypes';\nexport type { NodePaintCtx, SceneViewDrawOne, NodeShapeEntry, NodeInk, NodeSilhouetteCtx, NodeInkCtx } from './nodeShapeTypes';\nexport type { InheritedPaint } from 'core/scene/inheritedPaint';\n\n/** What a painter that declares no `ink` is assumed to do. */\nexport const DEFAULT_INK: Readonly<NodeInk> = Object.freeze({ filled: true, outset: 0, inset: 0 });\n\n/** Options for `registerNodeShape`. */\nexport interface RegisterNodeShapeOptions {\n /** `'high'` puts the painter ahead of all normally-registered ones (so\n * it can win over a kit built-in). `'normal'` appends at the end. */\n priority?: 'high' | 'normal';\n}\n\nconst PAINTERS: { high: NodeShapeEntry[]; normal: NodeShapeEntry[] } = {\n high: [],\n normal: [],\n};\n\n// The built-ins go in on first use, not at module load: a bundler may drop an\n// import kept only for its side effect, and the registry would come up empty.\nlet builtInsRegistered = false;\nfunction ensureBuiltIns(): void {\n if (builtInsRegistered) return;\n builtInsRegistered = true;\n registerBuiltInShapePainters();\n}\n\n/** Register a shape painter. Returns a disposer that removes it. */\nexport function registerNodeShape<TData, TPose>(\n painter: NodeShapeEntry<TData, TPose>,\n opts: RegisterNodeShapeOptions = {},\n): () => void {\n ensureBuiltIns();\n const list = opts.priority === 'high' ? PAINTERS.high : PAINTERS.normal;\n list.push(painter as NodeShapeEntry);\n // The painter set is exactly the ambient state `findNodeShape` reads, and a\n // memo keyed on the node alone cannot see it change. See `nodeMemo`.\n bumpNodeMemoGeneration();\n return () => {\n const i = list.indexOf(painter as NodeShapeEntry);\n if (i >= 0) list.splice(i, 1);\n bumpNodeMemoGeneration();\n };\n}\n\n/**\n * Slot names for what picking asks per node per pointer move: which painter matches, and that\n * painter's silhouette path. Both go through {@link nodeMemo}, so they invalidate on `data`\n * (and, for the silhouette, `pose`) reference changes and on a painter registration.\n *\n * Separate slots rather than one entry: they mostly invalidate together, but not always, and a\n * shared entry would force the stricter key on both.\n */\nconst PAINTER_SLOT = 'shape:painter';\nconst PAINTER_SLOT_NONRECT = 'shape:painter:nonrect';\nconst PAINTER_SLOT_DERIVED = 'shape:painter:derived';\nconst PAINTER_SLOT_DERIVED_NONRECT = 'shape:painter:derived:nonrect';\nconst SILHOUETTE_SLOT = 'shape:silhouette';\nconst TEXT_SILHOUETTE_SLOT = 'shape:silhouette:text';\n\n/** The painter that will render `node` — first match in priority order — or undefined if\n * none accepts it. */\nexport function findNodeShape<TData, TPose>(\n node: Node<TData, string, TPose>,\n): NodeShapeEntry<TData, TPose> | undefined {\n // Built-in painters also gate on pose shape and on whether the node derives\n // its path, neither of which shows in `data`, so the key carries both.\n const rect = paintsPose(node.pose);\n const slot = derivesPath(node)\n ? (rect ? PAINTER_SLOT_DERIVED : PAINTER_SLOT_DERIVED_NONRECT)\n : (rect ? PAINTER_SLOT : PAINTER_SLOT_NONRECT);\n return nodeMemo(node as { data?: unknown }, slot, undefined, () =>\n matchNodeShape(node),\n );\n}\n\nfunction matchNodeShape<TData, TPose>(\n node: Node<TData, string, TPose>,\n): NodeShapeEntry<TData, TPose> | undefined {\n ensureBuiltIns();\n for (const p of PAINTERS.high) {\n if (p.matches(node as Node<unknown, string, unknown>)) {\n return p as NodeShapeEntry<TData, TPose>;\n }\n }\n for (const p of PAINTERS.normal) {\n if (p.matches(node as Node<unknown, string, unknown>)) {\n return p as NodeShapeEntry<TData, TPose>;\n }\n }\n return undefined;\n}\n\n/** The silhouette path of `node`, in **world** coords, or null if no painter matches or the\n * matching painter has none.\n *\n * Painters return their silhouette in the pose's local (unrotated) frame;\n * this bakes the pose's frame (`poseFrameOf`: its rotation and `transform`)\n * on top, so clips/area-select of a turned or skewed node use the boundary\n * the renderer draws. */\nexport function findShapeSilhouette<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeSilhouetteCtx,\n): Path | null {\n const build = (): Path | null => {\n const sil = findNodeShape(node)?.silhouette?.(node, pose, ctx) ?? null;\n return sil && pathThroughPoseFrame(sil, pose);\n };\n // `SILHOUETTE_SLOT`'s key is (node, pose, data) and cannot see\n // `ctx.derivedPath` — the same reason `kit:derived` skips `PAINT_SLOT`.\n // Memoizing here would serve one caller's silhouette to a caller that\n // passed a different path. Only an actual path skips it: a scene-backed\n // source answers `null` for every ordinary node, and treating that as a\n // reason to bypass would retire the memo for the whole scene.\n if (ctx?.derivedPath != null) return build();\n // Line boxes follow font metrics, and a face landing changes those with no\n // change to the node, so the text entry is checked against the glyph epoch.\n if (findNodeShape(node) === (TEXT_PAINTER as NodeShapeEntry<unknown, unknown>)) {\n const epoch = glyphGeneration();\n const held = nodeMemo(node as { data?: unknown }, TEXT_SILHOUETTE_SLOT, pose,\n (): { epoch: number; path: Path | null } => ({ epoch, path: build() }));\n if (held.epoch !== epoch) {\n held.epoch = epoch;\n held.path = build();\n }\n return held.path;\n }\n return nodeMemo(node as { data?: unknown }, SILHOUETTE_SLOT, pose, build);\n}\n\n// A boolean group's operands are its children's outlines.\nsetDepOutlineReader((dep) => findShapeSilhouette(dep.node, dep.pose, { derivedPath: dep.path }));\n\n/** Find the painter for `node` and ask how it inks its silhouette. Returns\n * the painter's declared {@link NodeInk}, or `null` when no painter matches\n * or it declares none — callers substitute {@link DEFAULT_INK}. */\nexport function findShapeInk<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeInkCtx,\n): NodeInk | null {\n return findNodeShape(node)?.ink?.(node, pose, ctx) ?? null;\n}\n\n/** Find the painter for `node` and ask for the box its paint fits in. `null`\n * when no painter matches, or the one that does cannot say — see\n * {@link NodeShapeEntry.bounds}. */\nexport function findShapeBounds<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeInkCtx,\n): Bounds | null {\n return findNodeShape(node)?.bounds?.(node, pose, ctx) ?? null;\n}\n\n/** Options for {@link shapeCoversPoint}. */\nexport interface ShapeCoversPointOptions {\n /** Extra grab distance around the outline: **world** units as a number,\n * or screen pixels under a view scale (`{ px, scale }`), which is measured\n * on screen and so stays exact under non-uniform zoom. Defaults to `0`,\n * where a hairline is too thin a target to hit. */\n tolerance?: PickSlop;\n /** View scale, passed to the painter's `ink`, and what a screen reach is\n * read at under a world `tolerance`. Defaults to 1. */\n scale?: number;\n /** The node's derived path — see {@link NodeSilhouetteCtx.derivedPath}.\n * Without it a derived node reports no silhouette and this answers `true`\n * everywhere, which degrades picking to the caller's AABB: for an edge,\n * a zero-sized pose. */\n derivedPath?: Path | null;\n /** See {@link NodeInkCtx.inherited}. Without it an `'inherit'` field is\n * read as none. */\n inherited?: NodeInkCtx['inherited'];\n}\n\n/**\n * Does the shape `node` actually paints cover the world point? Asks the painter's silhouette,\n * the same boundary used for clipping and area-select, rather than the pose rect.\n *\n * The ink counts too: a shape whose interior isn't filled is grabbable along its outline and\n * not through its empty middle. The outline's grab width is the stroke's half-width plus\n * `tolerance`.\n *\n * A painter with no `silhouette`, or one that returns `null` for this node, reports `true` —\n * \"no opinion\" — so callers should keep their own AABB test as a pre-filter.\n */\nexport function shapeCoversPoint<TData, TPose>(\n node: Node<TData, string, TPose>,\n pose: TPose,\n x: number,\n y: number,\n opts: ShapeCoversPointOptions = {},\n): boolean {\n // A group paints nothing, so its interior is its box, which the caller's pre-filter tested.\n if (node.kind === 'group') return true;\n const sil = findShapeSilhouette(node, pose, { derivedPath: opts.derivedPath });\n if (sil === null) return true;\n const ink = findShapeInk(node, pose, { scale: opts.scale, inherited: opts.inherited }) ?? DEFAULT_INK;\n const inside = pathContainsPoint(sil, x, y);\n if (ink.filled && inside) return true;\n // The stroke reaches a different distance on each side, so which side the point is on\n // picks the reach. `tolerance` also makes a filled shape grabbable a few pixels outside\n // its edge.\n const slop = widenSlop(opts.tolerance, (inside ? ink.insetPx : ink.outsetPx) ?? 0, opts.scale);\n const { extra, opts: hit } = slopForStrokeHit(slop);\n const reach = (inside ? ink.inset : ink.outset) + extra;\n return (reach > 0 || hasSlop(slop)) && strokeHitTest(sil, x, y, reach, hit);\n}\n\n/** The current painters in evaluation order — `'high'` tier first, then `'normal'`. */\nexport function getNodeShapes(): readonly NodeShapeEntry[] {\n ensureBuiltIns();\n return [...PAINTERS.high, ...PAINTERS.normal];\n}\n\n/** Test-only: clear the registry and re-register the built-ins. */\nexport function _resetShapePaintersForTests(): void {\n PAINTERS.high.length = 0;\n PAINTERS.normal.length = 0;\n builtInsRegistered = false;\n ensureBuiltIns();\n // `registerNodeShape` already bumps, but the clearing above happens without one.\n bumpNodeMemoGeneration();\n}\n\nfunction registerBuiltInShapePainters(): void {\n registerNodeShape(TEXT_PAINTER);\n registerNodeShape(MEASURE_PAINTER);\n // Ahead of path/shape/image: a derived node whose `data` also carries a\n // `path`, `shape` or `image` means the derived path, and those three match\n // on the presence of the field alone.\n registerNodeShape(DERIVED_PAINTER);\n registerNodeShape(PATH_PAINTER);\n registerNodeShape(SHAPE_PAINTER);\n registerNodeShape(IMAGE_PAINTER);\n registerNodeShape(RECT_FALLBACK_PAINTER);\n}\n"],"mappings":"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"}
@@ -54,16 +54,20 @@ function PickHud({ canvasRef, anchorRef, viewRef, toWorld, pickEvery, pickBest,
54
54
  });
55
55
  return;
56
56
  }
57
- const [worldX, worldY] = toWorldRef.current?.(e.clientX, e.clientY) ?? clientToWorld(e.clientX, e.clientY, rect, view);
57
+ const [x, y] = toWorldRef.current?.(e.clientX, e.clientY) ?? clientToWorld(e.clientX, e.clientY, rect, view);
58
+ const world = {
59
+ x,
60
+ y
61
+ };
58
62
  let ids = [];
59
63
  try {
60
- ids = pickEvery(worldX, worldY);
64
+ ids = pickEvery(world);
61
65
  } catch {
62
66
  ids = [];
63
67
  }
64
68
  let best = null;
65
69
  if (pickBest) try {
66
- best = pickBest(worldX, worldY);
70
+ best = pickBest(world);
67
71
  } catch {
68
72
  best = null;
69
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"PickHud.js","names":["s"],"sources":["../../src/canvas/PickHud.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * Dev HUD listing the ids returned by `pickEvery(world)` under the cursor.\n *\n * Anchors to the canvas's top-right corner like `CursorCoordsHud`, offset\n * downward so it sits just below that HUD. Updates on `document`\n * pointermove. Refreshes its position on scroll / resize so it tracks the\n * canvas through layout changes.\n */\nimport { useEffect, useState } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\nimport { useHostAnchor } from './useHostAnchor';\nimport s from './hud.module.css';\n\n/** Props for `<PickHud>`. */\nexport interface PickHudProps {\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 /** World-space hit-test. Same shape as `useSelectTool`'s `pickEvery`. */\n pickEvery: (worldX: number, worldY: number) => readonly string[];\n /** Optional single-best resolver — the id this point would select on a\n * bare click. When supplied, that id is rendered bold in the list. */\n pickBest?: (worldX: number, worldY: number) => string | null;\n /** Inset from the canvas's top-right corner. Default `{ top: 76, right: 8 }`\n * so the HUD clears `CursorCoordsHud` (~64 px tall in its 3-line form). */\n offset?: { top?: number; right?: number };\n}\n\ninterface HudState {\n ids: readonly string[];\n best: string | null;\n inCanvas: boolean;\n}\n\n/** Debug overlay listing every node under the pointer, with the one a click\n * would actually select shown in bold. */\nexport function PickHud({ canvasRef, anchorRef, viewRef, toWorld, pickEvery, pickBest, offset }: PickHudProps) {\n const toWorldRef = useLatest(toWorld);\n const [state, setState] = useState<HudState>({\n ids: [], best: null, inCanvas: false,\n });\n const { ref, style } = 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 ?? 76 },\n },\n );\n\n useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const canvas = canvasRef.current;\n const view = viewRef.current;\n if (!canvas || !view) {\n setState({ ids: [], best: 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 if (!inCanvas) {\n setState({ ids: [], best: null, inCanvas: false });\n return;\n }\n const [worldX, worldY] = toWorldRef.current?.(e.clientX, e.clientY)\n ?? clientToWorld(e.clientX, e.clientY, rect, view);\n let ids: readonly string[] = [];\n try {\n ids = pickEvery(worldX, worldY);\n } catch {\n ids = [];\n }\n let best: string | null = null;\n if (pickBest) {\n try { best = pickBest(worldX, worldY); } catch { best = null; }\n }\n setState({ ids, best, inCanvas: true });\n };\n\n document.addEventListener('pointermove', onMove);\n\n return () => {\n document.removeEventListener('pointermove', onMove);\n };\n }, [canvasRef, viewRef, pickEvery, pickBest, toWorldRef]);\n\n if (!style) return null;\n\n return (\n <div ref={ref} className={`${s.hud} ${s.sized}`} style={style}>\n <div className={`${s.header} ${s.muted}`}>pickEvery ({state.ids.length})</div>\n {state.ids.length === 0 ? (\n <div className={s.absent}>{state.inCanvas ? '—' : 'off-canvas'}</div>\n ) : (\n <ul className={s.list}>\n {/* pickEvery returns back-to-front (topmost last). Display top-first. */}\n {state.ids.slice().reverse().map((id) => (\n <li\n key={id}\n className={id === state.best ? `${s.item} ${s.itemBest}` : s.item}\n >\n {id}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA8CA,SAAgB,QAAQ,EAAE,WAAW,WAAW,SAAS,SAAS,WAAW,UAAU,UAAwB;CAC7G,MAAM,aAAa,UAAU,OAAO;CACpC,MAAM,CAAC,OAAO,YAAY,SAAmB;EAC3C,KAAK,CAAC;EAAG,MAAM;EAAM,UAAU;CACjC,CAAC;CACD,MAAM,EAAE,KAAK,UAAU,oBACf,WAAW,WAAW,UAAU,SAAS,iBAAiB,UAAU,SAC1E;EACE,OAAO;GAAE,GAAG;GAAO,GAAG;EAAQ;EAC9B,QAAQ;GAAE,GAAG,QAAQ,SAAS;GAAG,GAAG,QAAQ,OAAO;EAAG;CACxD,CACF;CAEA,gBAAgB;EACd,MAAM,UAAU,MAAoB;GAClC,MAAM,SAAS,UAAU;GACzB,MAAM,OAAO,QAAQ;GACrB,IAAI,CAAC,UAAU,CAAC,MAAM;IACpB,SAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,MAAM,OAAO,OAAO,sBAAsB;GAI1C,IAAI,EAFF,EAAE,WAAW,KAAK,QAAQ,EAAE,WAAW,KAAK,SAC5C,EAAE,WAAW,KAAK,OAAQ,EAAE,WAAW,KAAK,SAC/B;IACb,SAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,MAAM,CAAC,QAAQ,UAAU,WAAW,UAAU,EAAE,SAAS,EAAE,OAAO,KAC7D,cAAc,EAAE,SAAS,EAAE,SAAS,MAAM,IAAI;GACnD,IAAI,MAAyB,CAAC;GAC9B,IAAI;IACF,MAAM,UAAU,QAAQ,MAAM;GAChC,QAAQ;IACN,MAAM,CAAC;GACT;GACA,IAAI,OAAsB;GAC1B,IAAI,UACF,IAAI;IAAE,OAAO,SAAS,QAAQ,MAAM;GAAG,QAAQ;IAAE,OAAO;GAAM;GAEhE,SAAS;IAAE;IAAK;IAAM,UAAU;GAAK,CAAC;EACxC;EAEA,SAAS,iBAAiB,eAAe,MAAM;EAE/C,aAAa;GACX,SAAS,oBAAoB,eAAe,MAAM;EACpD;CACF,GAAG;EAAC;EAAW;EAAS;EAAW;EAAU;CAAU,CAAC;CAExD,IAAI,CAAC,OAAO,OAAO;CAEnB,OACE,qBAAC,OAAD;EAAU;EAAK,WAAW,GAAGA,mBAAE,IAAI,GAAGA,mBAAE;EAAgB;EAAxD,UAAA,CACE,qBAAC,OAAD;GAAK,WAAW,GAAGA,mBAAE,OAAO,GAAGA,mBAAE;GAAjC,UAAA;IAA0C;IAAY,MAAM,IAAI;IAAO;GAAM;EAC5E,CAAA,GAAA,MAAM,IAAI,WAAW,IACpB,oBAAC,OAAD;GAAK,WAAWA,mBAAE;GAAS,UAAA,MAAM,WAAW,MAAM;EAAkB,CAAA,IAEpE,oBAAC,MAAD;GAAI,WAAWA,mBAAE;GAEd,UAAA,MAAM,IAAI,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,OAChC,oBAAC,MAAD;IAEE,WAAW,OAAO,MAAM,OAAO,GAAGA,mBAAE,KAAK,GAAGA,mBAAE,aAAaA,mBAAE;IAE5D,UAAA;GACC,GAJG,EAIH,CACL;EACC,CAAA,CAEH;;AAET"}
1
+ {"version":3,"file":"PickHud.js","names":["s"],"sources":["../../src/canvas/PickHud.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * Dev HUD listing the ids returned by `pickEvery(world)` under the cursor.\n *\n * Anchors to the canvas's top-right corner like `CursorCoordsHud`, offset\n * downward so it sits just below that HUD. Updates on `document`\n * pointermove. Refreshes its position on scroll / resize so it tracks the\n * canvas through layout changes.\n */\nimport { useEffect, useState } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { View } from 'core/viewport/view';\nimport type { WorldPoint } from '@weasel-js/routing';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\nimport { useHostAnchor } from './useHostAnchor';\nimport s from './hud.module.css';\n\n/** Props for `<PickHud>`. */\nexport interface PickHudProps {\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 /** World-space hit-test. Same shape as `useSelectTool`'s `pickEvery`. */\n pickEvery: (world: WorldPoint) => readonly string[];\n /** Optional single-best resolver — the id this point would select on a\n * bare click. When supplied, that id is rendered bold in the list. */\n pickBest?: (world: WorldPoint) => string | null;\n /** Inset from the canvas's top-right corner. Default `{ top: 76, right: 8 }`\n * so the HUD clears `CursorCoordsHud` (~64 px tall in its 3-line form). */\n offset?: { top?: number; right?: number };\n}\n\ninterface HudState {\n ids: readonly string[];\n best: string | null;\n inCanvas: boolean;\n}\n\n/** Debug overlay listing every node under the pointer, with the one a click\n * would actually select shown in bold. */\nexport function PickHud({ canvasRef, anchorRef, viewRef, toWorld, pickEvery, pickBest, offset }: PickHudProps) {\n const toWorldRef = useLatest(toWorld);\n const [state, setState] = useState<HudState>({\n ids: [], best: null, inCanvas: false,\n });\n const { ref, style } = 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 ?? 76 },\n },\n );\n\n useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const canvas = canvasRef.current;\n const view = viewRef.current;\n if (!canvas || !view) {\n setState({ ids: [], best: 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 if (!inCanvas) {\n setState({ ids: [], best: null, inCanvas: false });\n return;\n }\n const [x, y] = toWorldRef.current?.(e.clientX, e.clientY)\n ?? clientToWorld(e.clientX, e.clientY, rect, view);\n const world = { x, y };\n let ids: readonly string[] = [];\n try {\n ids = pickEvery(world);\n } catch {\n ids = [];\n }\n let best: string | null = null;\n if (pickBest) {\n try { best = pickBest(world); } catch { best = null; }\n }\n setState({ ids, best, inCanvas: true });\n };\n\n document.addEventListener('pointermove', onMove);\n\n return () => {\n document.removeEventListener('pointermove', onMove);\n };\n }, [canvasRef, viewRef, pickEvery, pickBest, toWorldRef]);\n\n if (!style) return null;\n\n return (\n <div ref={ref} className={`${s.hud} ${s.sized}`} style={style}>\n <div className={`${s.header} ${s.muted}`}>pickEvery ({state.ids.length})</div>\n {state.ids.length === 0 ? (\n <div className={s.absent}>{state.inCanvas ? '—' : 'off-canvas'}</div>\n ) : (\n <ul className={s.list}>\n {/* pickEvery returns back-to-front (topmost last). Display top-first. */}\n {state.ids.slice().reverse().map((id) => (\n <li\n key={id}\n className={id === state.best ? `${s.item} ${s.itemBest}` : s.item}\n >\n {id}\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+CA,SAAgB,QAAQ,EAAE,WAAW,WAAW,SAAS,SAAS,WAAW,UAAU,UAAwB;CAC7G,MAAM,aAAa,UAAU,OAAO;CACpC,MAAM,CAAC,OAAO,YAAY,SAAmB;EAC3C,KAAK,CAAC;EAAG,MAAM;EAAM,UAAU;CACjC,CAAC;CACD,MAAM,EAAE,KAAK,UAAU,oBACf,WAAW,WAAW,UAAU,SAAS,iBAAiB,UAAU,SAC1E;EACE,OAAO;GAAE,GAAG;GAAO,GAAG;EAAQ;EAC9B,QAAQ;GAAE,GAAG,QAAQ,SAAS;GAAG,GAAG,QAAQ,OAAO;EAAG;CACxD,CACF;CAEA,gBAAgB;EACd,MAAM,UAAU,MAAoB;GAClC,MAAM,SAAS,UAAU;GACzB,MAAM,OAAO,QAAQ;GACrB,IAAI,CAAC,UAAU,CAAC,MAAM;IACpB,SAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,MAAM,OAAO,OAAO,sBAAsB;GAI1C,IAAI,EAFF,EAAE,WAAW,KAAK,QAAQ,EAAE,WAAW,KAAK,SAC5C,EAAE,WAAW,KAAK,OAAQ,EAAE,WAAW,KAAK,SAC/B;IACb,SAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,MAAM,CAAC,GAAG,KAAK,WAAW,UAAU,EAAE,SAAS,EAAE,OAAO,KACnD,cAAc,EAAE,SAAS,EAAE,SAAS,MAAM,IAAI;GACnD,MAAM,QAAQ;IAAE;IAAG;GAAE;GACrB,IAAI,MAAyB,CAAC;GAC9B,IAAI;IACF,MAAM,UAAU,KAAK;GACvB,QAAQ;IACN,MAAM,CAAC;GACT;GACA,IAAI,OAAsB;GAC1B,IAAI,UACF,IAAI;IAAE,OAAO,SAAS,KAAK;GAAG,QAAQ;IAAE,OAAO;GAAM;GAEvD,SAAS;IAAE;IAAK;IAAM,UAAU;GAAK,CAAC;EACxC;EAEA,SAAS,iBAAiB,eAAe,MAAM;EAE/C,aAAa;GACX,SAAS,oBAAoB,eAAe,MAAM;EACpD;CACF,GAAG;EAAC;EAAW;EAAS;EAAW;EAAU;CAAU,CAAC;CAExD,IAAI,CAAC,OAAO,OAAO;CAEnB,OACE,qBAAC,OAAD;EAAU;EAAK,WAAW,GAAGA,mBAAE,IAAI,GAAGA,mBAAE;EAAgB;EAAxD,UAAA,CACE,qBAAC,OAAD;GAAK,WAAW,GAAGA,mBAAE,OAAO,GAAGA,mBAAE;GAAjC,UAAA;IAA0C;IAAY,MAAM,IAAI;IAAO;GAAM;EAC5E,CAAA,GAAA,MAAM,IAAI,WAAW,IACpB,oBAAC,OAAD;GAAK,WAAWA,mBAAE;GAAS,UAAA,MAAM,WAAW,MAAM;EAAkB,CAAA,IAEpE,oBAAC,MAAD;GAAI,WAAWA,mBAAE;GAEd,UAAA,MAAM,IAAI,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,OAChC,oBAAC,MAAD;IAEE,WAAW,OAAO,MAAM,OAAO,GAAGA,mBAAE,KAAK,GAAGA,mBAAE,aAAaA,mBAAE;IAE5D,UAAA;GACC,GAJG,EAIH,CACL;EACC,CAAA,CAEH;;AAET"}