@weasel-js/core 1.9.4 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1092) hide show
  1. package/CHANGELOG.md +750 -0
  2. package/README.md +5 -3
  3. package/dist/WeaselProvider.js +5 -7
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +91 -83
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +3 -2
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +54 -100
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js.map +1 -1
  12. package/dist/affordances/rotationHandle.js +5 -4
  13. package/dist/affordances/rotationHandle.js.map +1 -1
  14. package/dist/animation/behaviors/coast.js +21 -0
  15. package/dist/animation/behaviors/coast.js.map +1 -0
  16. package/dist/animation/behaviors/coastByWrite.js +107 -0
  17. package/dist/animation/behaviors/coastByWrite.js.map +1 -0
  18. package/dist/animation/behaviors/coastOnTargets.js +94 -0
  19. package/dist/animation/behaviors/coastOnTargets.js.map +1 -0
  20. package/dist/animation/behaviors/momentum.js +48 -136
  21. package/dist/animation/behaviors/momentum.js.map +1 -1
  22. package/dist/animation/clipTargets.js +12 -0
  23. package/dist/animation/clipTargets.js.map +1 -0
  24. package/dist/animation/index.js +15 -20
  25. package/dist/animation/poseHelpers.js +112 -33
  26. package/dist/animation/poseHelpers.js.map +1 -1
  27. package/dist/animation/poseTarget.js +115 -0
  28. package/dist/animation/poseTarget.js.map +1 -0
  29. package/dist/animation/reflow.js +113 -83
  30. package/dist/animation/reflow.js.map +1 -1
  31. package/dist/animation/rewind.js +66 -0
  32. package/dist/animation/rewind.js.map +1 -0
  33. package/dist/animation/rig/bindRig.js +85 -53
  34. package/dist/animation/rig/bindRig.js.map +1 -1
  35. package/dist/animation/rig/rigNode.js +93 -0
  36. package/dist/animation/rig/rigNode.js.map +1 -0
  37. package/dist/animation/rig/rigSeat.js +26 -0
  38. package/dist/animation/rig/rigSeat.js.map +1 -0
  39. package/dist/animation/rig/skinBinding.js +56 -0
  40. package/dist/animation/rig/skinBinding.js.map +1 -0
  41. package/dist/animation/rig/useRig.js +31 -16
  42. package/dist/animation/rig/useRig.js.map +1 -1
  43. package/dist/animation/wrappers/animateLifecycle.js +8 -7
  44. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  45. package/dist/animation/wrappers/animateOnSetPose.js +31 -31
  46. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  47. package/dist/animation/wrappers/instantPose.js.map +1 -1
  48. package/dist/animation/writtenPoseTarget.js +33 -0
  49. package/dist/animation/writtenPoseTarget.js.map +1 -0
  50. package/dist/autoPoseDescriptor-DHg5KqaJ.d.ts +27 -0
  51. package/dist/barrel/canvas.js +31 -0
  52. package/dist/barrel/chrome.js +10 -10
  53. package/dist/barrel/input.js +16 -17
  54. package/dist/barrel/interactions.js +35 -39
  55. package/dist/barrel/paint.js +11 -18
  56. package/dist/barrel/paths.js +12 -19
  57. package/dist/barrel/renderer.js +14 -20
  58. package/dist/barrel/routing.js +42 -36
  59. package/dist/barrel/scene.js +37 -0
  60. package/dist/barrel/text.js +9 -18
  61. package/dist/barrel/viewport.js +41 -51
  62. package/dist/canvas/Canvas.js +281 -475
  63. package/dist/canvas/Canvas.js.map +1 -1
  64. package/dist/canvas/CanvasView.js +169 -188
  65. package/dist/canvas/CanvasView.js.map +1 -1
  66. package/dist/canvas/CursorCoordsHud.js +22 -23
  67. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  68. package/dist/canvas/DrawCanvas.js +39 -56
  69. package/dist/canvas/DrawCanvas.js.map +1 -1
  70. package/dist/canvas/ModalityHud.js.map +1 -1
  71. package/dist/canvas/NodeShape.js +28 -29
  72. package/dist/canvas/NodeShape.js.map +1 -1
  73. package/dist/canvas/PickHud.js.map +1 -1
  74. package/dist/canvas/SceneCanvas/DevHuds.js +40 -0
  75. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -0
  76. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +66 -107
  77. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -1
  78. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +27 -31
  79. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  80. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +51 -54
  81. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -1
  82. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +3 -3
  83. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -1
  84. package/dist/canvas/SceneCanvas/coordTrace.js +37 -1
  85. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  86. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +40 -29
  87. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  88. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +1 -1
  89. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  90. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  91. package/dist/canvas/SceneCanvas/features.js +73 -43
  92. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/isDev.js.map +1 -1
  94. package/dist/canvas/SceneCanvas/poseGeometry.js +33 -37
  95. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  96. package/dist/canvas/SceneCanvas/props.js +15 -14
  97. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  98. package/dist/canvas/SceneCanvas/toolRegistry.js +23 -0
  99. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -0
  100. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +6 -1
  101. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  102. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  103. package/dist/canvas/SceneCanvas/useBuiltinTools.js +21 -0
  104. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -0
  105. package/dist/canvas/SceneCanvas/useCanvasCamera.js +38 -0
  106. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -0
  107. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +20 -0
  108. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -0
  109. package/dist/canvas/SceneCanvas/useCanvasSelection.js +16 -0
  110. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -0
  111. package/dist/canvas/SceneCanvas/useCanvasTools.js +67 -0
  112. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -0
  113. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +29 -29
  114. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  115. package/dist/canvas/SceneCanvas/useHeldModifiers.js +20 -0
  116. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -0
  117. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +26 -0
  118. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -0
  119. package/dist/canvas/SceneCanvas/useNodeKinds.js +26 -0
  120. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -0
  121. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +39 -37
  122. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  123. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +47 -0
  124. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -0
  125. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +66 -0
  126. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -0
  127. package/dist/canvas/SceneCanvas/useSceneChrome.js +59 -0
  128. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -0
  129. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +23 -0
  130. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -0
  131. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +76 -80
  132. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  133. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +37 -0
  134. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -0
  135. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +38 -0
  136. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -0
  137. package/dist/canvas/SceneCanvas/useViewLayerGate.js +20 -0
  138. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +1 -0
  139. package/dist/canvas/SceneCanvas/useViewportActions.js +9 -1
  140. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  141. package/dist/canvas/SceneCanvas/worldPointAt.js +9 -0
  142. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -0
  143. package/dist/canvas/SceneCanvas.js +303 -707
  144. package/dist/canvas/SceneCanvas.js.map +1 -1
  145. package/dist/canvas/SceneViewCanvas.js +41 -47
  146. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  147. package/dist/canvas/adapterDerivedPath.js +26 -0
  148. package/dist/canvas/adapterDerivedPath.js.map +1 -0
  149. package/dist/canvas/affordanceAt.js +11 -1
  150. package/dist/canvas/affordanceAt.js.map +1 -1
  151. package/dist/canvas/buildSceneLayer.js +81 -61
  152. package/dist/canvas/buildSceneLayer.js.map +1 -1
  153. package/dist/canvas/buildSceneTree.js.map +1 -1
  154. package/dist/canvas/canvasRenderer.js +40 -44
  155. package/dist/canvas/canvasRenderer.js.map +1 -1
  156. package/dist/canvas/colorOverrides.js.map +1 -1
  157. package/dist/canvas/defaultDrawOne.js +12 -12
  158. package/dist/canvas/defaultDrawOne.js.map +1 -1
  159. package/dist/canvas/deps/areaSelect.js +4 -4
  160. package/dist/canvas/deps/areaSelect.js.map +1 -1
  161. package/dist/canvas/deps/debug.js.map +1 -1
  162. package/dist/canvas/deps/editAnchors.js +49 -68
  163. package/dist/canvas/deps/editAnchors.js.map +1 -1
  164. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  165. package/dist/canvas/deps/hitTestArea.js +31 -26
  166. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  167. package/dist/canvas/deps/insert.js +65 -54
  168. package/dist/canvas/deps/insert.js.map +1 -1
  169. package/dist/canvas/deps/lassoSelect.js +5 -5
  170. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  171. package/dist/canvas/deps/poseDescriptor.js +1 -1
  172. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  173. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  174. package/dist/canvas/deps/slice.js +44 -45
  175. package/dist/canvas/deps/slice.js.map +1 -1
  176. package/dist/canvas/deps/textEdit.js +8 -8
  177. package/dist/canvas/deps/textEdit.js.map +1 -1
  178. package/dist/canvas/deps/view.js.map +1 -1
  179. package/dist/canvas/derivedPath.js +43 -41
  180. package/dist/canvas/derivedPath.js.map +1 -1
  181. package/dist/canvas/drawEnvelope.js +8 -4
  182. package/dist/canvas/drawEnvelope.js.map +1 -1
  183. package/dist/canvas/getNodeAtPoint.js +2 -6
  184. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  185. package/dist/canvas/hud.module.js.map +1 -1
  186. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  187. package/dist/canvas/layerOrder.js.map +1 -1
  188. package/dist/canvas/layerSlots.js +6 -1
  189. package/dist/canvas/layerSlots.js.map +1 -1
  190. package/dist/canvas/nodeShapes/derivedPainter.js +12 -12
  191. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  192. package/dist/canvas/nodeShapes/imagePainter.js +10 -10
  193. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  194. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  195. package/dist/canvas/nodeShapes/nodePaint.js +34 -23
  196. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  197. package/dist/canvas/nodeShapes/pathPainter.js +23 -22
  198. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  199. package/dist/canvas/nodeShapes/poseBox.js +6 -6
  200. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  201. package/dist/canvas/nodeShapes/rectFallbackPainter.js +8 -8
  202. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  203. package/dist/canvas/nodeShapes/shapePainter.js +16 -16
  204. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  205. package/dist/canvas/nodeShapes/textPainter.js +1 -1
  206. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  207. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  208. package/dist/canvas/paintCull.js +6 -8
  209. package/dist/canvas/paintCull.js.map +1 -1
  210. package/dist/{features/cursor → canvas}/paintedCursorLayer.js +2 -2
  211. package/dist/canvas/paintedCursorLayer.js.map +1 -0
  212. package/dist/canvas/pickWalk.js +52 -50
  213. package/dist/canvas/pickWalk.js.map +1 -1
  214. package/dist/canvas/planeClips.js +18 -19
  215. package/dist/canvas/planeClips.js.map +1 -1
  216. package/dist/canvas/poseCascade.js +41 -0
  217. package/dist/canvas/poseCascade.js.map +1 -0
  218. package/dist/canvas/poseRotation.js +1 -3
  219. package/dist/canvas/poseRotation.js.map +1 -1
  220. package/dist/canvas/rasterReadback.js +22 -0
  221. package/dist/canvas/rasterReadback.js.map +1 -0
  222. package/dist/canvas/renderDebugSnapshot.js +12 -12
  223. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  224. package/dist/canvas/renderNeeds.js +3 -3
  225. package/dist/canvas/renderNeeds.js.map +1 -1
  226. package/dist/canvas/renderSceneToPixels.js +64 -83
  227. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  228. package/dist/canvas/sceneAdapter.js +68 -132
  229. package/dist/canvas/sceneAdapter.js.map +1 -1
  230. package/dist/canvas/sceneClipboard.js +1 -1
  231. package/dist/canvas/sceneClipboard.js.map +1 -1
  232. package/dist/canvas/sceneLayerPaint.js +4 -4
  233. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  234. package/dist/canvas/sceneSlotWiring.js +4 -4
  235. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  236. package/dist/canvas/sceneViewRender.js +36 -35
  237. package/dist/canvas/sceneViewRender.js.map +1 -1
  238. package/dist/canvas/slopsDebugLayer.js +4 -4
  239. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  240. package/dist/canvas/surface.module.js +6 -0
  241. package/dist/canvas/surface.module.js.map +1 -0
  242. package/dist/canvas/surfaceBox.js +16 -0
  243. package/dist/canvas/surfaceBox.js.map +1 -0
  244. package/dist/canvas/useCanvasRenderer.js +23 -11
  245. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  246. package/dist/canvas/useCanvasSurface.js +31 -0
  247. package/dist/canvas/useCanvasSurface.js.map +1 -0
  248. package/dist/canvas/useCanvasView.js +46 -37
  249. package/dist/canvas/useCanvasView.js.map +1 -1
  250. package/dist/canvas/useFrameLoop.js +11 -12
  251. package/dist/canvas/useFrameLoop.js.map +1 -1
  252. package/dist/canvas/useHostAnchor.js +35 -33
  253. package/dist/canvas/useHostAnchor.js.map +1 -1
  254. package/dist/canvas/useLateContentRedraw.js +8 -8
  255. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  256. package/dist/canvas/useSceneLayerList.js +4 -14
  257. package/dist/canvas/useSceneLayerList.js.map +1 -1
  258. package/dist/canvas/useSurfaceInput.js +42 -0
  259. package/dist/canvas/useSurfaceInput.js.map +1 -0
  260. package/dist/canvas/useToolCursor.js +29 -0
  261. package/dist/canvas/useToolCursor.js.map +1 -0
  262. package/dist/canvas/useViewHelpers.js +46 -85
  263. package/dist/canvas/useViewHelpers.js.map +1 -1
  264. package/dist/canvas/viewInputs.js.map +1 -1
  265. package/dist/canvas/viewRegistry.js +25 -27
  266. package/dist/canvas/viewRegistry.js.map +1 -1
  267. package/dist/canvas/watchElementMove.js +43 -0
  268. package/dist/canvas/watchElementMove.js.map +1 -0
  269. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  270. package/dist/clipboard.d.ts +7 -14
  271. package/dist/{types-B4iJRHC3.d.ts → clone-2a5hVbBd.d.ts} +122 -77
  272. package/dist/clone.d.ts +4 -8
  273. package/dist/clone.js +0 -2
  274. package/dist/core/device/targets.js.map +1 -1
  275. package/dist/core/device/useDeviceProfile.js +13 -13
  276. package/dist/core/device/useDeviceProfile.js.map +1 -1
  277. package/dist/{interactions/actions/resize → core/geometry}/autoPoseDescriptor.js +8 -7
  278. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -0
  279. package/dist/core/geometry/pathPoseDescriptor.js +88 -0
  280. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -0
  281. package/dist/core/geometry/poseDescriptor.js +61 -14
  282. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  283. package/dist/core/geometry/regionHit.js +35 -37
  284. package/dist/core/geometry/regionHit.js.map +1 -1
  285. package/dist/core/geometry/targetFrame.js +94 -0
  286. package/dist/core/geometry/targetFrame.js.map +1 -0
  287. package/dist/core/geometry/unionBounds.js +4 -5
  288. package/dist/core/geometry/unionBounds.js.map +1 -1
  289. package/dist/core/layers/backgroundFill.js +31 -0
  290. package/dist/core/layers/backgroundFill.js.map +1 -0
  291. package/dist/{features/groups → core/layers}/children.js +1 -1
  292. package/dist/core/layers/children.js.map +1 -0
  293. package/dist/{features/focus → core/layers}/gateLayer.js +2 -2
  294. package/dist/core/layers/gateLayer.js.map +1 -0
  295. package/dist/core/layers/layerGroup.js +40 -0
  296. package/dist/core/layers/layerGroup.js.map +1 -0
  297. package/dist/core/layers/render.js +50 -76
  298. package/dist/core/layers/render.js.map +1 -1
  299. package/dist/core/ops/createHistory.js +9 -9
  300. package/dist/core/ops/createHistory.js.map +1 -1
  301. package/dist/core/ops/delete.js.map +1 -1
  302. package/dist/core/paint/meshKind.js +16 -0
  303. package/dist/core/paint/meshKind.js.map +1 -0
  304. package/dist/{features/meshPaint/lazyKind.js → core/paint/meshKindLazy.js} +103 -92
  305. package/dist/core/paint/meshKindLazy.js.map +1 -0
  306. package/dist/core/paint/paintKindEntry.js +8 -0
  307. package/dist/core/paint/paintKindEntry.js.map +1 -0
  308. package/dist/core/paint/paintKinds.js +144 -0
  309. package/dist/core/paint/paintKinds.js.map +1 -0
  310. package/dist/core/paint/registerMesh.js +7 -0
  311. package/dist/core/paint/registerMesh.js.map +1 -0
  312. package/dist/core/scene/NodeProperties.js.map +1 -1
  313. package/dist/core/scene/NodeRouting.js.map +1 -1
  314. package/dist/core/scene/arrivalWindow.js +65 -64
  315. package/dist/core/scene/arrivalWindow.js.map +1 -1
  316. package/dist/core/scene/boundOps.js +40 -0
  317. package/dist/core/scene/boundOps.js.map +1 -0
  318. package/dist/core/scene/composeFrame.js +9 -6
  319. package/dist/core/scene/composeFrame.js.map +1 -1
  320. package/dist/{features/groups → core/scene}/composePose.js +18 -18
  321. package/dist/core/scene/composePose.js.map +1 -0
  322. package/dist/core/scene/depMemo.js +31 -6
  323. package/dist/core/scene/depMemo.js.map +1 -1
  324. package/dist/core/scene/derivedPath.js +19 -20
  325. package/dist/core/scene/derivedPath.js.map +1 -1
  326. package/dist/core/scene/editMode.js +26 -0
  327. package/dist/core/scene/editMode.js.map +1 -0
  328. package/dist/core/scene/effectivePose.js +38 -39
  329. package/dist/core/scene/effectivePose.js.map +1 -1
  330. package/dist/core/scene/fieldEdits.js +98 -0
  331. package/dist/core/scene/fieldEdits.js.map +1 -0
  332. package/dist/core/scene/historyFacade.js +116 -70
  333. package/dist/core/scene/historyFacade.js.map +1 -1
  334. package/dist/core/scene/historyForm.js +6 -0
  335. package/dist/core/scene/historyForm.js.map +1 -0
  336. package/dist/core/scene/kitOps.js +83 -71
  337. package/dist/core/scene/kitOps.js.map +1 -1
  338. package/dist/core/scene/kitRegistry.js.map +1 -1
  339. package/dist/core/scene/layerStack.js +105 -12
  340. package/dist/core/scene/layerStack.js.map +1 -1
  341. package/dist/core/scene/layoutPass.js +58 -59
  342. package/dist/core/scene/layoutPass.js.map +1 -1
  343. package/dist/{features/groups → core/scene}/nestedHit.js +3 -3
  344. package/dist/core/scene/nestedHit.js.map +1 -0
  345. package/dist/core/scene/nodeFnFields.js +9 -9
  346. package/dist/core/scene/nodeFnFields.js.map +1 -1
  347. package/dist/core/scene/nodeMemo.js.map +1 -1
  348. package/dist/core/scene/nodeStore.js +72 -71
  349. package/dist/core/scene/nodeStore.js.map +1 -1
  350. package/dist/core/scene/notifier.js +37 -0
  351. package/dist/core/scene/notifier.js.map +1 -0
  352. package/dist/core/scene/opTable.js +50 -0
  353. package/dist/core/scene/opTable.js.map +1 -0
  354. package/dist/core/scene/outerOps.js +66 -0
  355. package/dist/core/scene/outerOps.js.map +1 -0
  356. package/dist/core/scene/poseHold.js +39 -0
  357. package/dist/core/scene/poseHold.js.map +1 -0
  358. package/dist/core/scene/poseOverrides.js +44 -36
  359. package/dist/core/scene/poseOverrides.js.map +1 -1
  360. package/dist/core/scene/poseSnapshot.js.map +1 -1
  361. package/dist/core/scene/reconcileSpecs.js +3 -2
  362. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  363. package/dist/core/scene/recorder.js +86 -0
  364. package/dist/core/scene/recorder.js.map +1 -0
  365. package/dist/core/scene/renderOrder.js.map +1 -1
  366. package/dist/core/scene/scene.js +81 -690
  367. package/dist/core/scene/scene.js.map +1 -1
  368. package/dist/core/scene/sceneEdits.js +58 -0
  369. package/dist/core/scene/sceneEdits.js.map +1 -0
  370. package/dist/core/scene/sceneMutators.js +49 -0
  371. package/dist/core/scene/sceneMutators.js.map +1 -0
  372. package/dist/core/scene/scenePoseAdapter.js +16 -0
  373. package/dist/core/scene/scenePoseAdapter.js.map +1 -0
  374. package/dist/core/scene/sceneRecording.js +90 -0
  375. package/dist/core/scene/sceneRecording.js.map +1 -0
  376. package/dist/core/scene/sceneSelection.js +28 -0
  377. package/dist/core/scene/sceneSelection.js.map +1 -0
  378. package/dist/core/scene/sceneState.js +49 -0
  379. package/dist/core/scene/sceneState.js.map +1 -0
  380. package/dist/core/scene/serialization.js +8 -5
  381. package/dist/core/scene/serialization.js.map +1 -1
  382. package/dist/core/scene/staleReplay.js +51 -0
  383. package/dist/core/scene/staleReplay.js.map +1 -0
  384. package/dist/core/scene/statedFields.js +9 -0
  385. package/dist/core/scene/statedFields.js.map +1 -0
  386. package/dist/core/scene/treeEdits.js +127 -0
  387. package/dist/core/scene/treeEdits.js.map +1 -0
  388. package/dist/core/scene/treeReads.js +26 -0
  389. package/dist/core/scene/treeReads.js.map +1 -0
  390. package/dist/core/scene/types.js.map +1 -1
  391. package/dist/{features/groups → core/scene}/unionOfChildren.js +3 -3
  392. package/dist/core/scene/unionOfChildren.js.map +1 -0
  393. package/dist/core/scene/unitScopes.js +13 -0
  394. package/dist/core/scene/unitScopes.js.map +1 -0
  395. package/dist/core/scene/useScene.js.map +1 -1
  396. package/dist/core/selection/readOnlySelection.js +32 -0
  397. package/dist/core/selection/readOnlySelection.js.map +1 -0
  398. package/dist/core/selection/usePublishSceneSelection.js +26 -0
  399. package/dist/core/selection/usePublishSceneSelection.js.map +1 -0
  400. package/dist/core/selection/useSelection.js +34 -25
  401. package/dist/core/selection/useSelection.js.map +1 -1
  402. package/dist/core/shapeKinds.js.map +1 -1
  403. package/dist/core/stylus/stylus.js.map +1 -1
  404. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  405. package/dist/core/usePaintKinds.js +1 -1
  406. package/dist/core/usePaintKinds.js.map +1 -1
  407. package/dist/core/viewport/clientToWorld.js.map +1 -1
  408. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  409. package/dist/core/viewport/parallax.js.map +1 -1
  410. package/dist/core/viewport/screenSlop.js +11 -11
  411. package/dist/core/viewport/screenSlop.js.map +1 -1
  412. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  413. package/dist/core/viewport/useDecayLoop.js +8 -8
  414. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  415. package/dist/core/viewport/useNodeOverlayFrame.js +84 -0
  416. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -0
  417. package/dist/core/viewport/useViewAnimation.js +102 -43
  418. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  419. package/dist/core/viewport/view.js +7 -7
  420. package/dist/core/viewport/view.js.map +1 -1
  421. package/dist/core/viewport/wheelHandler.js.map +1 -1
  422. package/dist/{cornerHandles-CtCb8a3G.d.ts → cornerHandles-BEshc4z3.d.ts} +11 -24
  423. package/dist/debug/createDebugOverlayLayer.js +100 -100
  424. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  425. package/dist/debug/createDebugSink.js.map +1 -1
  426. package/dist/debug/frameStats.js.map +1 -1
  427. package/dist/debug/useDebugSink.js +52 -0
  428. package/dist/debug/useDebugSink.js.map +1 -0
  429. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  430. package/dist/features/chrome-caps/conditions.js.map +1 -1
  431. package/dist/features/chrome-caps/defaults.js.map +1 -1
  432. package/dist/features/chrome-caps/resolve.js.map +1 -1
  433. package/dist/features/chrome-caps/useChromeCaps.js +54 -0
  434. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -0
  435. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  436. package/dist/features/ingestion/contentHandlers.js +25 -19
  437. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  438. package/dist/features/ingestion/imageHandler.js +21 -24
  439. package/dist/features/ingestion/imageHandler.js.map +1 -1
  440. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  441. package/dist/features/ingestion/placement.js +16 -0
  442. package/dist/features/ingestion/placement.js.map +1 -0
  443. package/dist/features/ingestion/svgHandler.js +5 -0
  444. package/dist/features/ingestion/svgHandler.js.map +1 -1
  445. package/dist/features/ingestion/textHandler.js +28 -0
  446. package/dist/features/ingestion/textHandler.js.map +1 -0
  447. package/dist/features/ingestion/useCanvasIngestion.js +48 -0
  448. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -0
  449. package/dist/features/ingestion/weaselJsonHandler.js +5 -0
  450. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  451. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  452. package/dist/features/modes/modeLayers.js +7 -7
  453. package/dist/features/modes/modeLayers.js.map +1 -1
  454. package/dist/features/paths/editablePath.js +47 -0
  455. package/dist/features/paths/editablePath.js.map +1 -0
  456. package/dist/features/paths/index.js +9 -16
  457. package/dist/features/paths/pathEditState.js +41 -0
  458. package/dist/features/paths/pathEditState.js.map +1 -0
  459. package/dist/features/paths/pathEditingOverlayLayer.js +36 -38
  460. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  461. package/dist/features/paths/pathLayer.js +3 -2
  462. package/dist/features/paths/pathLayer.js.map +1 -1
  463. package/dist/features/paths/penPreviewLayer.js +86 -88
  464. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  465. package/dist/features/paths/usePathEdit.js +34 -0
  466. package/dist/features/paths/usePathEdit.js.map +1 -0
  467. package/dist/features/poseRun/usePoseRun.js +42 -55
  468. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  469. package/dist/features/selection/overlay.js +170 -178
  470. package/dist/features/selection/overlay.js.map +1 -1
  471. package/dist/features/text/index.js +6 -0
  472. package/dist/features/text/textLayer.js +1 -1
  473. package/dist/features/text/textLayer.js.map +1 -1
  474. package/dist/features/text/useSceneTextEdit.js +95 -82
  475. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  476. package/dist/features/viewports/viewportLayer.js +25 -36
  477. package/dist/features/viewports/viewportLayer.js.map +1 -1
  478. package/dist/index.d.ts +4507 -8459
  479. package/dist/index.js +275 -320
  480. package/dist/input/keyState.js +14 -14
  481. package/dist/interactions/actions/actionShortcuts.js.map +1 -1
  482. package/dist/interactions/actions/{defaults/align.js → align/action.js} +15 -16
  483. package/dist/interactions/actions/align/action.js.map +1 -0
  484. package/dist/interactions/actions/align/align.js +23 -23
  485. package/dist/interactions/actions/align/align.js.map +1 -1
  486. package/dist/interactions/actions/booleans/action.js +65 -0
  487. package/dist/interactions/actions/booleans/action.js.map +1 -0
  488. package/dist/interactions/actions/booleans/booleans.js +69 -78
  489. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  490. package/dist/interactions/actions/booleans/operands.js +40 -0
  491. package/dist/interactions/actions/booleans/operands.js.map +1 -0
  492. package/dist/interactions/actions/booleans/pieces.js +45 -0
  493. package/dist/interactions/actions/booleans/pieces.js.map +1 -0
  494. package/dist/interactions/actions/booleans/placement.js +24 -0
  495. package/dist/interactions/actions/booleans/placement.js.map +1 -0
  496. package/dist/interactions/actions/booleans/useBooleans.js +11 -9
  497. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  498. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  499. package/dist/interactions/actions/{defaults/clipboard.js → clipboard/action.js} +19 -19
  500. package/dist/interactions/actions/clipboard/action.js.map +1 -0
  501. package/dist/interactions/actions/clipboard/clipboardOps.js +15 -15
  502. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  503. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  504. package/dist/interactions/actions/clone/action.js +98 -0
  505. package/dist/interactions/actions/clone/action.js.map +1 -0
  506. package/dist/interactions/actions/clone/behaviors.js +52 -0
  507. package/dist/interactions/actions/clone/behaviors.js.map +1 -0
  508. package/dist/interactions/actions/defaultCommitAdapter.js +10 -37
  509. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  510. package/dist/interactions/actions/defaults/anchorEditing.js +41 -43
  511. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  512. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  513. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  514. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  515. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  516. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  517. package/dist/interactions/actions/defaults/duplicate.js +19 -19
  518. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  519. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  520. package/dist/interactions/actions/defaults/group.js +35 -40
  521. package/dist/interactions/actions/defaults/group.js.map +1 -1
  522. package/dist/interactions/actions/defaults/icons/booleanIcons.js +24 -1
  523. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -1
  524. package/dist/interactions/actions/defaults/icons/outlineIcons.js +39 -1
  525. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -1
  526. package/dist/interactions/actions/defaults/ingest.js +19 -15
  527. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  528. package/dist/interactions/actions/defaults/insertPathAnchor.js +14 -15
  529. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  530. package/dist/interactions/actions/defaults/nudge.js +30 -31
  531. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  532. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  533. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  534. package/dist/interactions/actions/defaults/setFill.js +9 -3
  535. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  536. package/dist/interactions/actions/defaults/setFillOpacity.js +4 -1
  537. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  538. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  539. package/dist/interactions/actions/defaults/sliceOps.js +20 -22
  540. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  541. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  542. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  543. package/dist/interactions/actions/defaults/viewportDragPan.js +1 -1
  544. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  545. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  546. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  547. package/dist/interactions/actions/{defaults/distribute.js → distribute/action.js} +18 -19
  548. package/dist/interactions/actions/distribute/action.js.map +1 -0
  549. package/dist/interactions/actions/distribute/distribute.js +11 -11
  550. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  551. package/dist/interactions/actions/{defaults/editAnchors.js → edit-anchors/action.js} +19 -21
  552. package/dist/interactions/actions/edit-anchors/action.js.map +1 -0
  553. package/dist/interactions/actions/edit-anchors/geometry.js +2 -4
  554. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  555. package/dist/interactions/actions/flip/action.js +124 -0
  556. package/dist/interactions/actions/flip/action.js.map +1 -0
  557. package/dist/interactions/actions/flip/helpers.js +1 -1
  558. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  559. package/dist/interactions/actions/gestureFrames.js +18 -0
  560. package/dist/interactions/actions/gestureFrames.js.map +1 -0
  561. package/dist/interactions/actions/gestureLifecycle.js +47 -20
  562. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  563. package/dist/interactions/actions/insert/action.js +72 -0
  564. package/dist/interactions/actions/insert/action.js.map +1 -0
  565. package/dist/interactions/actions/insert/commit.js +28 -0
  566. package/dist/interactions/actions/insert/commit.js.map +1 -0
  567. package/dist/interactions/actions/insert/extras.js +65 -0
  568. package/dist/interactions/actions/insert/extras.js.map +1 -0
  569. package/dist/interactions/actions/insert/frame.js +48 -0
  570. package/dist/interactions/actions/insert/frame.js.map +1 -0
  571. package/dist/interactions/actions/insert/geometry.js +35 -0
  572. package/dist/interactions/actions/insert/geometry.js.map +1 -0
  573. package/dist/interactions/actions/insert/rotateAction.js +21 -0
  574. package/dist/interactions/actions/insert/rotateAction.js.map +1 -0
  575. package/dist/interactions/actions/insert/session.js +59 -0
  576. package/dist/interactions/actions/insert/session.js.map +1 -0
  577. package/dist/interactions/actions/insert/shape.js +34 -0
  578. package/dist/interactions/actions/insert/shape.js.map +1 -0
  579. package/dist/interactions/actions/lasso-select/action.js +143 -0
  580. package/dist/interactions/actions/lasso-select/action.js.map +1 -0
  581. package/dist/interactions/actions/move/action.js +87 -0
  582. package/dist/interactions/actions/move/action.js.map +1 -0
  583. package/dist/interactions/actions/move/behaviors/layoutDrop.js +51 -0
  584. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -0
  585. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +15 -0
  586. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -0
  587. package/dist/interactions/actions/move/behaviors/snapToContainer.js +24 -23
  588. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  589. package/dist/interactions/actions/move/capture.js +99 -0
  590. package/dist/interactions/actions/move/capture.js.map +1 -0
  591. package/dist/interactions/actions/move/commit/index.js +41 -0
  592. package/dist/interactions/actions/move/commit/index.js.map +1 -0
  593. package/dist/interactions/actions/move/commit/layoutDrop.js +44 -0
  594. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -0
  595. package/dist/interactions/actions/move/commit/layoutRelease.js +100 -0
  596. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -0
  597. package/dist/interactions/actions/move/commit/rebase.js +18 -0
  598. package/dist/interactions/actions/move/commit/rebase.js.map +1 -0
  599. package/dist/interactions/actions/move/commit/reparent.js +65 -0
  600. package/dist/interactions/actions/move/commit/reparent.js.map +1 -0
  601. package/dist/interactions/actions/move/delta.js +51 -0
  602. package/dist/interactions/actions/move/delta.js.map +1 -0
  603. package/dist/interactions/actions/move/frame.js +59 -0
  604. package/dist/interactions/actions/move/frame.js.map +1 -0
  605. package/dist/interactions/actions/move/gestureAdapter.js +15 -40
  606. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  607. package/dist/interactions/actions/move/landedDescendants.js +8 -8
  608. package/dist/interactions/actions/move/layout/container.js +94 -0
  609. package/dist/interactions/actions/move/layout/container.js.map +1 -0
  610. package/dist/interactions/actions/move/layout/dragged.js +58 -0
  611. package/dist/interactions/actions/move/layout/dragged.js.map +1 -0
  612. package/dist/interactions/actions/move/layout/dropPass.js +122 -0
  613. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -0
  614. package/dist/interactions/actions/move/layout/exits.js +38 -0
  615. package/dist/interactions/actions/move/layout/exits.js.map +1 -0
  616. package/dist/interactions/actions/move/layout/glide.js +48 -0
  617. package/dist/interactions/actions/move/layout/glide.js.map +1 -0
  618. package/dist/interactions/actions/move/session.js +63 -0
  619. package/dist/interactions/actions/move/session.js.map +1 -0
  620. package/dist/interactions/actions/move/translate.js +61 -0
  621. package/dist/interactions/actions/move/translate.js.map +1 -0
  622. package/dist/interactions/actions/outlines/createOutlines.js +17 -64
  623. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  624. package/dist/interactions/actions/outlines/createOutlinesAction.js +51 -0
  625. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -0
  626. package/dist/interactions/actions/outlines/outlineStroke.js +72 -0
  627. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -0
  628. package/dist/interactions/actions/outlines/outlineStrokeAction.js +37 -0
  629. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -0
  630. package/dist/interactions/actions/outlines/replaceWithPaths.js +54 -0
  631. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -0
  632. package/dist/interactions/actions/outlines/strokeRegion.js +27 -0
  633. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -0
  634. package/dist/interactions/actions/planeInput.js.map +1 -1
  635. package/dist/interactions/actions/pointerState.js +12 -0
  636. package/dist/interactions/actions/pointerState.js.map +1 -0
  637. package/dist/interactions/actions/poseDescriptorDep.js +1 -1
  638. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  639. package/dist/interactions/actions/poseFrame.js +26 -26
  640. package/dist/interactions/actions/poseFrame.js.map +1 -1
  641. package/dist/interactions/actions/resize/action.js +55 -0
  642. package/dist/interactions/actions/resize/action.js.map +1 -0
  643. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -1
  644. package/dist/interactions/actions/resize/boxFrame.js +16 -0
  645. package/dist/interactions/actions/resize/boxFrame.js.map +1 -0
  646. package/dist/interactions/actions/resize/capture.js +85 -0
  647. package/dist/interactions/actions/resize/capture.js.map +1 -0
  648. package/dist/interactions/actions/resize/commit.js +69 -0
  649. package/dist/interactions/actions/resize/commit.js.map +1 -0
  650. package/dist/interactions/actions/resize/frame.js +74 -0
  651. package/dist/interactions/actions/resize/frame.js.map +1 -0
  652. package/dist/interactions/actions/resize/pointSnap.js +111 -0
  653. package/dist/interactions/actions/resize/pointSnap.js.map +1 -0
  654. package/dist/interactions/actions/resize/ruleBounds.js +9 -0
  655. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -0
  656. package/dist/interactions/actions/resize/session.js +49 -0
  657. package/dist/interactions/actions/resize/session.js.map +1 -0
  658. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  659. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  660. package/dist/interactions/actions/rotate/action.js +56 -0
  661. package/dist/interactions/actions/rotate/action.js.map +1 -0
  662. package/dist/interactions/actions/rotate/behaviors/index.js +7 -0
  663. package/dist/interactions/actions/rotate/behaviors/index.js.map +1 -0
  664. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +12 -0
  665. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +1 -0
  666. package/dist/interactions/actions/rotate/commit.js +40 -0
  667. package/dist/interactions/actions/rotate/commit.js.map +1 -0
  668. package/dist/interactions/actions/rotate/frame.js +65 -0
  669. package/dist/interactions/actions/rotate/frame.js.map +1 -0
  670. package/dist/interactions/actions/rotate/handle.js +12 -12
  671. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  672. package/dist/interactions/actions/rotate/session.js +92 -0
  673. package/dist/interactions/actions/rotate/session.js.map +1 -0
  674. package/dist/interactions/actions/spatialReference.js.map +1 -1
  675. package/dist/interactions/actions/useStandardActions.js +77 -72
  676. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  677. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +61 -42
  678. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  679. package/dist/interactions/gestures/shared/originProjection.js +1 -1
  680. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  681. package/dist/interactions/gestures/shared/screenTolerance.js +8 -2
  682. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  683. package/dist/interactions/gestures/shared/snap.js.map +1 -1
  684. package/dist/layout/arrivals.js +20 -23
  685. package/dist/layout/arrivals.js.map +1 -1
  686. package/dist/math-CYUjoyyU.d.ts +33 -0
  687. package/dist/math.d.ts +5 -2
  688. package/dist/math.js +6 -6
  689. package/dist/mesh.d.ts +4 -268
  690. package/dist/mesh.js +3 -7
  691. package/dist/move.d.ts +6 -4
  692. package/dist/{originProjection-gHnOup4e.d.ts → originProjection-PPT88jZv.d.ts} +1 -1
  693. package/dist/patterns-builtin.d.ts +1 -118
  694. package/dist/patterns-builtin.js +2 -3
  695. package/dist/poseDescriptor-Bqk-11Rl.d.ts +73 -0
  696. package/dist/renderer.d.ts +1 -92
  697. package/dist/renderer.js +2 -19
  698. package/dist/resize.d.ts +11 -22
  699. package/dist/resize.js +1 -1
  700. package/dist/style.css +1 -1
  701. package/dist/test-hook/install.js.map +1 -1
  702. package/dist/test-hook/useTestHook.js +22 -0
  703. package/dist/test-hook/useTestHook.js.map +1 -0
  704. package/dist/test-seams-D0pyV3pR.d.ts +149 -0
  705. package/dist/test-seams.d.ts +4 -4
  706. package/dist/test-seams.js +2 -2
  707. package/dist/tools/builtin/bone/boneActions.js +130 -0
  708. package/dist/tools/builtin/bone/boneActions.js.map +1 -0
  709. package/dist/tools/builtin/bone/boneOverlay.js +58 -0
  710. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -0
  711. package/dist/tools/builtin/bone/placedRig.js +24 -0
  712. package/dist/tools/builtin/bone/placedRig.js.map +1 -0
  713. package/dist/tools/builtin/bone/rigEditState.js +21 -0
  714. package/dist/tools/builtin/bone/rigEditState.js.map +1 -0
  715. package/dist/tools/builtin/bone/useBoneTool.js +98 -0
  716. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -0
  717. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  718. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  719. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  720. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  721. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  722. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  723. package/dist/tools/builtin/pen/usePenTool.js +161 -163
  724. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  725. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  726. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  727. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  728. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  729. package/dist/tools/builtin/select/adapterPointQuery.js +36 -0
  730. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -0
  731. package/dist/tools/builtin/select/selectionContributions.js +4 -4
  732. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  733. package/dist/tools/builtin/select/useSelectTool.js +43 -71
  734. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  735. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  736. package/dist/tools/builtin/slice/useSliceTool.js +67 -72
  737. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  738. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  739. package/dist/tools/builtin/text/useTextTool.js +8 -0
  740. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  741. package/dist/tools/builtin/weight/useWeightTool.js +77 -0
  742. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -0
  743. package/dist/tools/builtin/weight/weightActions.js +112 -0
  744. package/dist/tools/builtin/weight/weightActions.js.map +1 -0
  745. package/dist/tools/builtin/weight/weightOverlay.js +61 -0
  746. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -0
  747. package/dist/tools/overlayBinding.js.map +1 -1
  748. package/dist/tools/useKeybindings.js +20 -14
  749. package/dist/tools/useKeybindings.js.map +1 -1
  750. package/dist/{types-k-5Oqh-U.d.ts → types-CIKDwlsP.d.ts} +84 -164
  751. package/dist/util/paint.js +1 -1
  752. package/dist/util/paint.js.map +1 -1
  753. package/dist/version.js +1 -1
  754. package/package.json +26 -21
  755. package/dist/animation/colorHelpers.js +0 -135
  756. package/dist/animation/colorHelpers.js.map +0 -1
  757. package/dist/animation/colorRegistry.js +0 -37
  758. package/dist/animation/colorRegistry.js.map +0 -1
  759. package/dist/animation/engine/axes.js +0 -36
  760. package/dist/animation/engine/axes.js.map +0 -1
  761. package/dist/animation/engine/codec.js +0 -170
  762. package/dist/animation/engine/codec.js.map +0 -1
  763. package/dist/animation/engine/integrator.js +0 -12
  764. package/dist/animation/engine/integrator.js.map +0 -1
  765. package/dist/animation/loop.js +0 -60
  766. package/dist/animation/loop.js.map +0 -1
  767. package/dist/animation/observe.js +0 -23
  768. package/dist/animation/observe.js.map +0 -1
  769. package/dist/animation/rig/blendPoses.js +0 -43
  770. package/dist/animation/rig/blendPoses.js.map +0 -1
  771. package/dist/animation/rig/mirrorPose.js +0 -19
  772. package/dist/animation/rig/mirrorPose.js.map +0 -1
  773. package/dist/animation/rig/resolveSkeleton.js +0 -33
  774. package/dist/animation/rig/resolveSkeleton.js.map +0 -1
  775. package/dist/animation/rig/solveIk.js +0 -103
  776. package/dist/animation/rig/solveIk.js.map +0 -1
  777. package/dist/animation/rig/types.js +0 -12
  778. package/dist/animation/rig/types.js.map +0 -1
  779. package/dist/animation/slew.js +0 -27
  780. package/dist/animation/slew.js.map +0 -1
  781. package/dist/animation/stagger.js +0 -146
  782. package/dist/animation/stagger.js.map +0 -1
  783. package/dist/animation/timeline/booking.js +0 -114
  784. package/dist/animation/timeline/booking.js.map +0 -1
  785. package/dist/animation/timeline/createTimeline.js +0 -125
  786. package/dist/animation/timeline/createTimeline.js.map +0 -1
  787. package/dist/animation/timeline/sampleTrack.js +0 -79
  788. package/dist/animation/timeline/sampleTrack.js.map +0 -1
  789. package/dist/animation/useAnimator.js +0 -388
  790. package/dist/animation/useAnimator.js.map +0 -1
  791. package/dist/autoPoseDescriptor-Ct7yqivU.d.ts +0 -108
  792. package/dist/builtins-DPcdghtB.d.ts +0 -1223
  793. package/dist/canvas/MinimapCanvas.js +0 -140
  794. package/dist/canvas/MinimapCanvas.js.map +0 -1
  795. package/dist/canvas/deps/poseComposition.js +0 -11
  796. package/dist/canvas/deps/poseComposition.js.map +0 -1
  797. package/dist/canvas/minimapMath.js +0 -82
  798. package/dist/canvas/minimapMath.js.map +0 -1
  799. package/dist/canvas/toolPreview.js +0 -39
  800. package/dist/canvas/toolPreview.js.map +0 -1
  801. package/dist/core/adapters/arrayAdapter.js +0 -94
  802. package/dist/core/adapters/arrayAdapter.js.map +0 -1
  803. package/dist/core/adapters/useArrayAdapter.js +0 -13
  804. package/dist/core/adapters/useArrayAdapter.js.map +0 -1
  805. package/dist/core/fillInPoseFrame.js +0 -102
  806. package/dist/core/fillInPoseFrame.js.map +0 -1
  807. package/dist/core/geometry/poseFrame.js +0 -44
  808. package/dist/core/geometry/poseFrame.js.map +0 -1
  809. package/dist/core/geometry/poseRotation.js +0 -58
  810. package/dist/core/geometry/poseRotation.js.map +0 -1
  811. package/dist/core/gradient.js +0 -136
  812. package/dist/core/gradient.js.map +0 -1
  813. package/dist/core/markerInset.js +0 -24
  814. package/dist/core/markerInset.js.map +0 -1
  815. package/dist/core/mixed.js +0 -6
  816. package/dist/core/mixed.js.map +0 -1
  817. package/dist/core/paintKinds.js +0 -156
  818. package/dist/core/paintKinds.js.map +0 -1
  819. package/dist/core/scene/pickability.js +0 -6
  820. package/dist/core/scene/pickability.js.map +0 -1
  821. package/dist/core/strokeMarkerShapes.js +0 -139
  822. package/dist/core/strokeMarkerShapes.js.map +0 -1
  823. package/dist/core/strokeMarkers.js +0 -28
  824. package/dist/core/strokeMarkers.js.map +0 -1
  825. package/dist/core/viewport/meanScale.js +0 -8
  826. package/dist/core/viewport/meanScale.js.map +0 -1
  827. package/dist/core/viewport/pxExtent.js +0 -42
  828. package/dist/core/viewport/pxExtent.js.map +0 -1
  829. package/dist/features/cursor/paintedCursorLayer.js.map +0 -1
  830. package/dist/features/focus/gateLayer.js.map +0 -1
  831. package/dist/features/focus/useCanvasFocus.js +0 -29
  832. package/dist/features/focus/useCanvasFocus.js.map +0 -1
  833. package/dist/features/groups/children.js.map +0 -1
  834. package/dist/features/groups/composePose.js.map +0 -1
  835. package/dist/features/groups/nestedHit.js.map +0 -1
  836. package/dist/features/groups/unionOfChildren.js.map +0 -1
  837. package/dist/features/images/imageCache.js +0 -104
  838. package/dist/features/images/imageCache.js.map +0 -1
  839. package/dist/features/ingestion/index.js +0 -8
  840. package/dist/features/meshPaint/bake.js +0 -79
  841. package/dist/features/meshPaint/bake.js.map +0 -1
  842. package/dist/features/meshPaint/bakeCache.js +0 -59
  843. package/dist/features/meshPaint/bakeCache.js.map +0 -1
  844. package/dist/features/meshPaint/handles.js +0 -86
  845. package/dist/features/meshPaint/handles.js.map +0 -1
  846. package/dist/features/meshPaint/lazyKind.js.map +0 -1
  847. package/dist/features/meshPaint/meshPaint.js +0 -239
  848. package/dist/features/meshPaint/meshPaint.js.map +0 -1
  849. package/dist/features/meshPaint/meshShader.js +0 -6
  850. package/dist/features/meshPaint/meshShader.js.map +0 -1
  851. package/dist/features/meshPaint/register.js +0 -7
  852. package/dist/features/meshPaint/register.js.map +0 -1
  853. package/dist/features/meshPaint/surface.js +0 -110
  854. package/dist/features/meshPaint/surface.js.map +0 -1
  855. package/dist/features/minimap/actions.js +0 -53
  856. package/dist/features/minimap/actions.js.map +0 -1
  857. package/dist/features/minimap/createMinimapContribution.js +0 -96
  858. package/dist/features/minimap/createMinimapContribution.js.map +0 -1
  859. package/dist/features/minimap/layers.js +0 -85
  860. package/dist/features/minimap/layers.js.map +0 -1
  861. package/dist/features/overlays/useNodeOverlayFrame.js +0 -103
  862. package/dist/features/overlays/useNodeOverlayFrame.js.map +0 -1
  863. package/dist/features/parallax/createParallaxLayer.js +0 -26
  864. package/dist/features/parallax/createParallaxLayer.js.map +0 -1
  865. package/dist/features/parallax/createParallaxPlane.js +0 -22
  866. package/dist/features/parallax/createParallaxPlane.js.map +0 -1
  867. package/dist/features/paths/anchorEdits.js +0 -167
  868. package/dist/features/paths/anchorEdits.js.map +0 -1
  869. package/dist/features/paths/anchors.js +0 -159
  870. package/dist/features/paths/anchors.js.map +0 -1
  871. package/dist/features/paths/booleans.js +0 -2
  872. package/dist/features/paths/markerCommands.js +0 -149
  873. package/dist/features/paths/markerCommands.js.map +0 -1
  874. package/dist/features/paths/markerSites.js +0 -59
  875. package/dist/features/paths/markerSites.js.map +0 -1
  876. package/dist/features/paths/markers.js +0 -95
  877. package/dist/features/paths/markers.js.map +0 -1
  878. package/dist/features/paths/nearestAnchor.js +0 -36
  879. package/dist/features/paths/nearestAnchor.js.map +0 -1
  880. package/dist/features/paths/pathInWorld.js +0 -41
  881. package/dist/features/paths/pathInWorld.js.map +0 -1
  882. package/dist/features/paths/poseDescriptor.js +0 -39
  883. package/dist/features/paths/poseDescriptor.js.map +0 -1
  884. package/dist/features/paths/strokeToPath.js +0 -40
  885. package/dist/features/paths/strokeToPath.js.map +0 -1
  886. package/dist/features/paths/tessellate/dash.js +0 -52
  887. package/dist/features/paths/tessellate/dash.js.map +0 -1
  888. package/dist/features/paths/tessellate/insets.js +0 -32
  889. package/dist/features/paths/tessellate/insets.js.map +0 -1
  890. package/dist/features/paths/tessellate/metric.js +0 -72
  891. package/dist/features/paths/tessellate/metric.js.map +0 -1
  892. package/dist/features/paths/tessellate/stroke.js +0 -170
  893. package/dist/features/paths/tessellate/stroke.js.map +0 -1
  894. package/dist/features/paths/tessellate/vertexWidths.js +0 -32
  895. package/dist/features/paths/tessellate/vertexWidths.js.map +0 -1
  896. package/dist/features/patterns/commandPaint.js +0 -18
  897. package/dist/features/patterns/commandPaint.js.map +0 -1
  898. package/dist/features/patterns/index.js +0 -11
  899. package/dist/features/patterns/index.js.map +0 -1
  900. package/dist/features/patterns/patterns-builtin.js +0 -38
  901. package/dist/features/patterns/patterns-builtin.js.map +0 -1
  902. package/dist/features/patterns/rasterizeTile.js +0 -17
  903. package/dist/features/patterns/rasterizeTile.js.map +0 -1
  904. package/dist/features/patterns/resolveSpec.js +0 -65
  905. package/dist/features/patterns/resolveSpec.js.map +0 -1
  906. package/dist/features/patterns/tileGeometry.js +0 -158
  907. package/dist/features/patterns/tileGeometry.js.map +0 -1
  908. package/dist/features/pointer/PointerContext.js +0 -45
  909. package/dist/features/pointer/PointerContext.js.map +0 -1
  910. package/dist/features/selection/SelectionContext.js +0 -51
  911. package/dist/features/selection/SelectionContext.js.map +0 -1
  912. package/dist/features/simulation/createSimulation.js +0 -61
  913. package/dist/features/simulation/createSimulation.js.map +0 -1
  914. package/dist/features/simulation/types.js +0 -6
  915. package/dist/features/simulation/types.js.map +0 -1
  916. package/dist/features/simulation/useSimulation.js +0 -74
  917. package/dist/features/simulation/useSimulation.js.map +0 -1
  918. package/dist/features/text/domOffsets.js +0 -82
  919. package/dist/features/text/domOffsets.js.map +0 -1
  920. package/dist/features/text/domRuns.js +0 -230
  921. package/dist/features/text/domRuns.js.map +0 -1
  922. package/dist/features/text/fitTextPose.js +0 -38
  923. package/dist/features/text/fitTextPose.js.map +0 -1
  924. package/dist/features/text/hitTest.js +0 -48
  925. package/dist/features/text/hitTest.js.map +0 -1
  926. package/dist/features/text/isTextData.js +0 -8
  927. package/dist/features/text/isTextData.js.map +0 -1
  928. package/dist/features/text/overlayDirection.js +0 -15
  929. package/dist/features/text/overlayDirection.js.map +0 -1
  930. package/dist/features/text/renderLabel.js +0 -14
  931. package/dist/features/text/renderLabel.js.map +0 -1
  932. package/dist/features/text/runs/effectiveRangeStyle.js +0 -66
  933. package/dist/features/text/runs/effectiveRangeStyle.js.map +0 -1
  934. package/dist/features/text/runs/flagRange.js +0 -53
  935. package/dist/features/text/runs/flagRange.js.map +0 -1
  936. package/dist/features/text/runs/rangeStyle.js +0 -133
  937. package/dist/features/text/runs/rangeStyle.js.map +0 -1
  938. package/dist/features/text/textCommand.js +0 -60
  939. package/dist/features/text/textCommand.js.map +0 -1
  940. package/dist/features/text/textToPath.js +0 -181
  941. package/dist/features/text/textToPath.js.map +0 -1
  942. package/dist/features/text/useTextEdit.js +0 -491
  943. package/dist/features/text/useTextEdit.js.map +0 -1
  944. package/dist/features/tiling/createTiledLayer.js +0 -65
  945. package/dist/features/tiling/createTiledLayer.js.map +0 -1
  946. package/dist/features/tiling/tiledProject.js +0 -14
  947. package/dist/features/tiling/tiledProject.js.map +0 -1
  948. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +0 -26
  949. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +0 -1
  950. package/dist/interactions/actions/defaults/align.js.map +0 -1
  951. package/dist/interactions/actions/defaults/booleans.js +0 -52
  952. package/dist/interactions/actions/defaults/booleans.js.map +0 -1
  953. package/dist/interactions/actions/defaults/clipboard.js.map +0 -1
  954. package/dist/interactions/actions/defaults/clone.js +0 -91
  955. package/dist/interactions/actions/defaults/clone.js.map +0 -1
  956. package/dist/interactions/actions/defaults/createOutlines.js +0 -47
  957. package/dist/interactions/actions/defaults/createOutlines.js.map +0 -1
  958. package/dist/interactions/actions/defaults/distribute.js.map +0 -1
  959. package/dist/interactions/actions/defaults/editAnchors.js.map +0 -1
  960. package/dist/interactions/actions/defaults/flip.js +0 -125
  961. package/dist/interactions/actions/defaults/flip.js.map +0 -1
  962. package/dist/interactions/actions/defaults/insert.js +0 -287
  963. package/dist/interactions/actions/defaults/insert.js.map +0 -1
  964. package/dist/interactions/actions/defaults/lassoSelect.js +0 -153
  965. package/dist/interactions/actions/defaults/lassoSelect.js.map +0 -1
  966. package/dist/interactions/actions/defaults/move.js +0 -778
  967. package/dist/interactions/actions/defaults/move.js.map +0 -1
  968. package/dist/interactions/actions/defaults/resize.js +0 -341
  969. package/dist/interactions/actions/defaults/resize.js.map +0 -1
  970. package/dist/interactions/actions/defaults/rotate.js +0 -185
  971. package/dist/interactions/actions/defaults/rotate.js.map +0 -1
  972. package/dist/interactions/actions/previewOverrides.js +0 -25
  973. package/dist/interactions/actions/previewOverrides.js.map +0 -1
  974. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +0 -1
  975. package/dist/math-J-ACHyEg.d.ts +0 -159
  976. package/dist/registerProgram-T9S_PfAX.d.ts +0 -208
  977. package/dist/renderer/DrawCommand.js +0 -6
  978. package/dist/renderer/DrawCommand.js.map +0 -1
  979. package/dist/renderer/WeaselRenderer.js +0 -333
  980. package/dist/renderer/WeaselRenderer.js.map +0 -1
  981. package/dist/renderer/batchClip.js +0 -46
  982. package/dist/renderer/batchClip.js.map +0 -1
  983. package/dist/renderer/cache/GLImageCache.js +0 -74
  984. package/dist/renderer/cache/GLImageCache.js.map +0 -1
  985. package/dist/renderer/cache/GLMeshCache.js +0 -102
  986. package/dist/renderer/cache/GLMeshCache.js.map +0 -1
  987. package/dist/renderer/cache/GLTextureCache.js +0 -68
  988. package/dist/renderer/cache/GLTextureCache.js.map +0 -1
  989. package/dist/renderer/cache/GradientRampAtlas.js +0 -82
  990. package/dist/renderer/cache/GradientRampAtlas.js.map +0 -1
  991. package/dist/renderer/cache/cache.js +0 -13
  992. package/dist/renderer/cache/cache.js.map +0 -1
  993. package/dist/renderer/cache/markerCommandCache.js +0 -63
  994. package/dist/renderer/cache/markerCommandCache.js.map +0 -1
  995. package/dist/renderer/cache/outlineMeshCache.js +0 -15
  996. package/dist/renderer/cache/outlineMeshCache.js.map +0 -1
  997. package/dist/renderer/cache/outlineStrokeMeshCache.js +0 -36
  998. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +0 -1
  999. package/dist/renderer/cache/strokeMeshCache.js +0 -55
  1000. package/dist/renderer/cache/strokeMeshCache.js.map +0 -1
  1001. package/dist/renderer/cullDrawCommands.js +0 -90
  1002. package/dist/renderer/cullDrawCommands.js.map +0 -1
  1003. package/dist/renderer/draw/batch.js +0 -133
  1004. package/dist/renderer/draw/batch.js.map +0 -1
  1005. package/dist/renderer/draw/clip.js +0 -89
  1006. package/dist/renderer/draw/clip.js.map +0 -1
  1007. package/dist/renderer/draw/customShader.js +0 -230
  1008. package/dist/renderer/draw/customShader.js.map +0 -1
  1009. package/dist/renderer/draw/drawTriangles.js +0 -8
  1010. package/dist/renderer/draw/drawTriangles.js.map +0 -1
  1011. package/dist/renderer/draw/effects.js +0 -28
  1012. package/dist/renderer/draw/effects.js.map +0 -1
  1013. package/dist/renderer/draw/flushBatch.js +0 -35
  1014. package/dist/renderer/draw/flushBatch.js.map +0 -1
  1015. package/dist/renderer/draw/gradient.js +0 -90
  1016. package/dist/renderer/draw/gradient.js.map +0 -1
  1017. package/dist/renderer/draw/image.js +0 -38
  1018. package/dist/renderer/draw/image.js.map +0 -1
  1019. package/dist/renderer/draw/mesh.js +0 -16
  1020. package/dist/renderer/draw/mesh.js.map +0 -1
  1021. package/dist/renderer/draw/paintBind.js +0 -70
  1022. package/dist/renderer/draw/paintBind.js.map +0 -1
  1023. package/dist/renderer/draw/pathPaint.js +0 -142
  1024. package/dist/renderer/draw/pathPaint.js.map +0 -1
  1025. package/dist/renderer/draw/scratchPass.js +0 -83
  1026. package/dist/renderer/draw/scratchPass.js.map +0 -1
  1027. package/dist/renderer/draw/stencil.js +0 -28
  1028. package/dist/renderer/draw/stencil.js.map +0 -1
  1029. package/dist/renderer/draw/text.js +0 -167
  1030. package/dist/renderer/draw/text.js.map +0 -1
  1031. package/dist/renderer/draw/uniforms.js +0 -77
  1032. package/dist/renderer/draw/uniforms.js.map +0 -1
  1033. package/dist/renderer/draw.js +0 -79
  1034. package/dist/renderer/draw.js.map +0 -1
  1035. package/dist/renderer/drawBatch.js +0 -198
  1036. package/dist/renderer/drawBatch.js.map +0 -1
  1037. package/dist/renderer/effects/EffectTargets.js +0 -48
  1038. package/dist/renderer/effects/EffectTargets.js.map +0 -1
  1039. package/dist/renderer/effects/builtins.js +0 -31
  1040. package/dist/renderer/effects/builtins.js.map +0 -1
  1041. package/dist/renderer/effects/composite.js +0 -11
  1042. package/dist/renderer/effects/composite.js.map +0 -1
  1043. package/dist/renderer/effects/effectPrelude.js +0 -10
  1044. package/dist/renderer/effects/effectPrelude.js.map +0 -1
  1045. package/dist/renderer/effects/types.js +0 -10
  1046. package/dist/renderer/effects/types.js.map +0 -1
  1047. package/dist/renderer/glyphOutlineMesh.js +0 -67
  1048. package/dist/renderer/glyphOutlineMesh.js.map +0 -1
  1049. package/dist/renderer/index.js +0 -20
  1050. package/dist/renderer/math/color.js +0 -321
  1051. package/dist/renderer/math/color.js.map +0 -1
  1052. package/dist/renderer/math/mat3.js +0 -80
  1053. package/dist/renderer/math/mat3.js.map +0 -1
  1054. package/dist/renderer/math/patternSpace.js +0 -22
  1055. package/dist/renderer/math/patternSpace.js.map +0 -1
  1056. package/dist/renderer/math/viewToMat3.js +0 -19
  1057. package/dist/renderer/math/viewToMat3.js.map +0 -1
  1058. package/dist/renderer/paintResources.js +0 -18
  1059. package/dist/renderer/paintResources.js.map +0 -1
  1060. package/dist/renderer/paintScratch.js +0 -37
  1061. package/dist/renderer/paintScratch.js.map +0 -1
  1062. package/dist/renderer/shaders/ShaderProgram.js +0 -74
  1063. package/dist/renderer/shaders/ShaderProgram.js.map +0 -1
  1064. package/dist/renderer/shaders/batchFill.js +0 -119
  1065. package/dist/renderer/shaders/batchFill.js.map +0 -1
  1066. package/dist/renderer/shaders/customPrelude.js +0 -34
  1067. package/dist/renderer/shaders/customPrelude.js.map +0 -1
  1068. package/dist/renderer/shaders/extractUniformNames.js +0 -184
  1069. package/dist/renderer/shaders/extractUniformNames.js.map +0 -1
  1070. package/dist/renderer/shaders/glyphPaint.js +0 -61
  1071. package/dist/renderer/shaders/glyphPaint.js.map +0 -1
  1072. package/dist/renderer/shaders/gradFill.js +0 -31
  1073. package/dist/renderer/shaders/gradFill.js.map +0 -1
  1074. package/dist/renderer/shaders/pathFill.js +0 -14
  1075. package/dist/renderer/shaders/pathFill.js.map +0 -1
  1076. package/dist/renderer/shaders/patternFill.js +0 -25
  1077. package/dist/renderer/shaders/patternFill.js.map +0 -1
  1078. package/dist/renderer/shaders/registerProgram.js +0 -18
  1079. package/dist/renderer/shaders/registerProgram.js.map +0 -1
  1080. package/dist/renderer/spriteSheet.js +0 -14
  1081. package/dist/renderer/spriteSheet.js.map +0 -1
  1082. package/dist/renderer/state/GroupState.js +0 -77
  1083. package/dist/renderer/state/GroupState.js.map +0 -1
  1084. package/dist/renderer/strokeLengths.js +0 -50
  1085. package/dist/renderer/strokeLengths.js.map +0 -1
  1086. package/dist/renderer/syntheticItalic.js +0 -6
  1087. package/dist/renderer/syntheticItalic.js.map +0 -1
  1088. package/dist/renderer/textures/registerTexture.js +0 -34
  1089. package/dist/renderer/textures/registerTexture.js.map +0 -1
  1090. package/dist/scheduling/useVisibleRaf.js +0 -69
  1091. package/dist/scheduling/useVisibleRaf.js.map +0 -1
  1092. package/dist/test-seams-DM2B87-g.d.ts +0 -356
@@ -1,21 +1,20 @@
1
- import { useVisibleRaf as e } from "../scheduling/useVisibleRaf.js";
2
- import { clientToWorld as t } from "../core/viewport/clientToWorld.js";
3
- import n from "./hud.module.js";
4
- import { useHostAnchor as r } from "./useHostAnchor.js";
5
- import { useEffect as i, useRef as a, useState as o } from "react";
6
- import { useLatest as s } from "@weasel-js/react";
1
+ import { clientToWorld as e } from "../core/viewport/clientToWorld.js";
2
+ import t from "./hud.module.js";
3
+ import { useHostAnchor as n } from "./useHostAnchor.js";
4
+ import { useEffect as r, useRef as i, useState as a } from "react";
5
+ import { useLatest as o, useVisibleRaf as s } from "@weasel-js/react";
7
6
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
7
  import { decimal as u, qty as d } from "@weasel-js/quantity";
9
8
  //#region src/canvas/CursorCoordsHud.tsx
10
9
  function f({ canvasRef: u, anchorRef: d, viewRef: f, toWorld: m, offset: h }) {
11
- let g = s(m), [_, v] = o({
10
+ let g = o(m), [_, v] = a({
12
11
  client: {
13
12
  x: 0,
14
13
  y: 0
15
14
  },
16
15
  world: null,
17
16
  inCanvas: !1
18
- }), [y, b] = o(0), { ref: x, style: S } = r(() => d?.current ?? u.current?.parentElement ?? u.current, {
17
+ }), [y, b] = a(0), { ref: x, style: S } = n(() => d?.current ?? u.current?.parentElement ?? u.current, {
19
18
  align: {
20
19
  x: "end",
21
20
  y: "start"
@@ -24,18 +23,18 @@ function f({ canvasRef: u, anchorRef: d, viewRef: f, toWorld: m, offset: h }) {
24
23
  x: h?.right ?? 8,
25
24
  y: h?.top ?? 8
26
25
  }
27
- }), C = a(0), w = a(0), T = e(() => {
26
+ }), C = i(0), w = i(0), T = s(() => {
28
27
  C.current++;
29
28
  let e = performance.now(), t = e - w.current;
30
29
  t >= 1e3 && (b(Math.round(C.current * 1e3 / t)), C.current = 0, w.current = e), T.request();
31
30
  }, { onResume: () => {
32
31
  C.current = 0, w.current = performance.now();
33
32
  } });
34
- return i(() => (w.current = performance.now(), T.request(), () => T.cancel()), [T]), i(() => {
35
- let e = (e) => {
33
+ return r(() => (w.current = performance.now(), T.request(), () => T.cancel()), [T]), r(() => {
34
+ let t = (t) => {
36
35
  let n = u.current, r = f.current, i = {
37
- x: e.clientX,
38
- y: e.clientY
36
+ x: t.clientX,
37
+ y: t.clientY
39
38
  };
40
39
  if (!n || !r) {
41
40
  v({
@@ -45,7 +44,7 @@ function f({ canvasRef: u, anchorRef: d, viewRef: f, toWorld: m, offset: h }) {
45
44
  });
46
45
  return;
47
46
  }
48
- let a = n.getBoundingClientRect(), o = e.clientX >= a.left && e.clientX <= a.right && e.clientY >= a.top && e.clientY <= a.bottom, [s, c] = g.current?.(e.clientX, e.clientY) ?? t(e.clientX, e.clientY, a, r);
47
+ let a = n.getBoundingClientRect(), o = t.clientX >= a.left && t.clientX <= a.right && t.clientY >= a.top && t.clientY <= a.bottom, [s, c] = g.current?.(t.clientX, t.clientY) ?? e(t.clientX, t.clientY, a, r);
49
48
  v({
50
49
  client: i,
51
50
  world: {
@@ -55,8 +54,8 @@ function f({ canvasRef: u, anchorRef: d, viewRef: f, toWorld: m, offset: h }) {
55
54
  inCanvas: o
56
55
  });
57
56
  };
58
- return document.addEventListener("pointermove", e), () => {
59
- document.removeEventListener("pointermove", e);
57
+ return document.addEventListener("pointermove", t), () => {
58
+ document.removeEventListener("pointermove", t);
60
59
  };
61
60
  }, [
62
61
  u,
@@ -64,30 +63,30 @@ function f({ canvasRef: u, anchorRef: d, viewRef: f, toWorld: m, offset: h }) {
64
63
  g
65
64
  ]), S ? /* @__PURE__ */ c("div", {
66
65
  ref: x,
67
- className: n.hud,
66
+ className: t.hud,
68
67
  style: S,
69
68
  children: /* @__PURE__ */ l("dl", {
70
- className: n.readings,
69
+ className: t.readings,
71
70
  children: [
72
71
  /* @__PURE__ */ c("dt", {
73
- className: n.muted,
72
+ className: t.muted,
74
73
  children: "fps"
75
74
  }),
76
75
  /* @__PURE__ */ c("dd", { children: y }),
77
76
  /* @__PURE__ */ c("dt", {
78
- className: n.muted,
77
+ className: t.muted,
79
78
  children: "client"
80
79
  }),
81
80
  /* @__PURE__ */ c("dd", { children: p(_.client, 0) }),
82
81
  /* @__PURE__ */ c("dt", {
83
- className: n.muted,
82
+ className: t.muted,
84
83
  children: "world"
85
84
  }),
86
85
  _.world ? /* @__PURE__ */ l("dd", { children: [p(_.world, 1), _.inCanvas ? null : /* @__PURE__ */ c("span", {
87
- className: n.absent,
86
+ className: t.absent,
88
87
  children: " off-canvas"
89
88
  })] }) : /* @__PURE__ */ c("dd", {
90
- className: n.absent,
89
+ className: t.absent,
91
90
  children: "— no canvas or view yet"
92
91
  })
93
92
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"CursorCoordsHud.js","names":["s","hud_module_default","CursorCoordsHud","toWorldRef","useLatest","toWorld","state","setState","useState","fps","setFps","anchorStyle","useHostAnchor","anchorRef","canvasRef","offset","framesRef","useRef","lastFlushRef","fpsLoop","useVisibleRaf","now","dt","useEffect","onMove","canvas","view","viewRef","client","rect","inCanvas","wx","wy","clientToWorld","point","at","decimal","qty","x","y"],"sources":["../../src/canvas/CursorCoordsHud.tsx"],"sourcesContent":["/**\n * Fixed-position dev HUD that shows the cursor's current viewport\n * (client) coords next to the equivalent canvas (world) coords. Pins to the\n * top-right corner of the canvas's host; listens to `document` pointermove so it\n * reads the cursor even when it leaves the canvas.\n *\n * Mount inside a `<SceneCanvas>` subtree (or anywhere with access to a\n * canvas + view ref) for quick coord-reconciliation during gesture\n * debugging.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { decimal, qty } from '@weasel-js/quantity';\nimport { useLatest } from '@weasel-js/react';\nimport { useVisibleRaf } from '../scheduling/useVisibleRaf';\nimport s from './hud.module.css';\nimport { useHostAnchor } from './useHostAnchor';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\n\n/** Props for `<CursorCoordsHud>`. */\nexport interface CursorCoordsHudProps {\n canvasRef: React.RefObject<HTMLElement | null>;\n /** Element the HUD pins its corner to. Defaults to the canvas's parent — the\n * wrapper a bare `<canvas>` sits in. A detached canvas passes its own input\n * box, whose parent is the shared surface every pane sits in. */\n anchorRef?: React.RefObject<HTMLElement | null>;\n viewRef: React.RefObject<View>;\n /** Client coords to world. Defaults to the canvas's rect and `viewRef`. A\n * canvas whose routing converts some other way (a CSS transform, a 3D host)\n * passes that conversion, so the readout agrees with the picks. */\n toWorld?: (clientX: number, clientY: number) => [number, number];\n /** Inset from the canvas's top-right corner, in px. Default 8 on both axes. */\n offset?: { top?: number; right?: number };\n}\n\ninterface HudState {\n client: { x: number; y: number };\n world: { x: number; y: number } | null;\n inCanvas: boolean;\n}\n\n/** Debug overlay showing the pointer's client and world coordinates and the\n * current frame rate, pinned to the canvas's top-right corner. */\nexport function CursorCoordsHud({ canvasRef, anchorRef, viewRef, toWorld, offset }: CursorCoordsHudProps) {\n const toWorldRef = useLatest(toWorld);\n const [state, setState] = useState<HudState>({\n client: { x: 0, y: 0 }, world: null, inCanvas: false,\n });\n const [fps, setFps] = useState<number>(0);\n const { ref, style: anchorStyle } = useHostAnchor(\n () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,\n {\n align: { x: 'end', y: 'start' },\n offset: { x: offset?.right ?? 8, y: offset?.top ?? 8 },\n },\n );\n\n // FPS counter: tally frames per rAF tick; flush once a second.\n const framesRef = useRef(0);\n const lastFlushRef = useRef(0);\n const fpsLoop = useVisibleRaf(\n () => {\n framesRef.current++;\n const now = performance.now();\n const dt = now - lastFlushRef.current;\n if (dt >= 1000) {\n setFps(Math.round((framesRef.current * 1000) / dt));\n framesRef.current = 0;\n lastFlushRef.current = now;\n }\n fpsLoop.request();\n },\n // Frames not drawn while hidden are not frames that were slow to draw:\n // without this the readout would flush a near-zero rate on resume.\n {\n onResume: () => {\n framesRef.current = 0;\n lastFlushRef.current = performance.now();\n },\n },\n );\n\n useEffect(() => {\n lastFlushRef.current = performance.now();\n fpsLoop.request();\n return () => fpsLoop.cancel();\n }, [fpsLoop]);\n\n useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const canvas = canvasRef.current;\n const view = viewRef.current;\n const client = { x: e.clientX, y: e.clientY };\n if (!canvas || !view) {\n setState({ client, world: null, inCanvas: false });\n return;\n }\n const rect = canvas.getBoundingClientRect();\n const inCanvas =\n e.clientX >= rect.left && e.clientX <= rect.right &&\n e.clientY >= rect.top && e.clientY <= rect.bottom;\n const [wx, wy] = toWorldRef.current?.(e.clientX, e.clientY)\n ?? clientToWorld(e.clientX, e.clientY, rect, view);\n const world = { x: wx, y: wy };\n setState({ client, world, inCanvas });\n };\n\n document.addEventListener('pointermove', onMove);\n\n return () => {\n document.removeEventListener('pointermove', onMove);\n };\n }, [canvasRef, viewRef, toWorldRef]);\n\n if (!anchorStyle) return null;\n\n return (\n <div ref={ref} className={s.hud} style={anchorStyle}>\n <dl className={s.readings}>\n <dt className={s.muted}>fps</dt>\n <dd>{fps}</dd>\n <dt className={s.muted}>client</dt>\n <dd>{point(state.client, 0)}</dd>\n <dt className={s.muted}>world</dt>\n {state.world ? (\n <dd>\n {point(state.world, 1)}\n {state.inCanvas ? null : <span className={s.absent}> off-canvas</span>}\n </dd>\n ) : (\n <dd className={s.absent}>— no canvas or view yet</dd>\n )}\n </dl>\n </div>\n );\n}\n\n/** `(x, y)` at `places` decimals, its negatives written with U+2212. */\nfunction point({ x, y }: { x: number; y: number }, places: number): string {\n const at = decimal({ places, grouping: false });\n return `(${qty(x, at).text}, ${qty(y, at).text})`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"CursorCoordsHud.js","names":["s","hud_module_default","CursorCoordsHud","toWorldRef","useLatest","toWorld","state","setState","useState","fps","setFps","anchorStyle","useHostAnchor","anchorRef","canvasRef","offset","framesRef","useRef","lastFlushRef","fpsLoop","useVisibleRaf","now","dt","useEffect","onMove","canvas","view","viewRef","client","e","rect","inCanvas","wx","wy","clientToWorld","point","at","decimal","qty","x","y"],"sources":["../../src/canvas/CursorCoordsHud.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * Fixed-position dev HUD that shows the cursor's current viewport\n * (client) coords next to the equivalent canvas (world) coords. Pins to the\n * top-right corner of the canvas's host; listens to `document` pointermove so it\n * reads the cursor even when it leaves the canvas.\n *\n * Mount inside a `<SceneCanvas>` subtree (or anywhere with access to a\n * canvas + view ref) for quick coord-reconciliation during gesture\n * debugging.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { decimal, qty } from '@weasel-js/quantity';\nimport { useLatest, useVisibleRaf } from '@weasel-js/react';\nimport s from './hud.module.css';\nimport { useHostAnchor } from './useHostAnchor';\nimport type { View } from 'core/viewport/view';\nimport { clientToWorld } from 'core/viewport/clientToWorld';\n\n/** Props for `<CursorCoordsHud>`. */\nexport interface CursorCoordsHudProps {\n canvasRef: React.RefObject<HTMLElement | null>;\n /** Element the HUD pins its corner to. Defaults to the canvas's parent — the\n * wrapper a bare `<canvas>` sits in. A detached canvas passes its own input\n * box, whose parent is the shared surface every pane sits in. */\n anchorRef?: React.RefObject<HTMLElement | null>;\n viewRef: React.RefObject<View>;\n /** Client coords to world. Defaults to the canvas's rect and `viewRef`. A\n * canvas whose routing converts some other way (a CSS transform, a 3D host)\n * passes that conversion, so the readout agrees with the picks. */\n toWorld?: (clientX: number, clientY: number) => [number, number];\n /** Inset from the canvas's top-right corner, in px. Default 8 on both axes. */\n offset?: { top?: number; right?: number };\n}\n\ninterface HudState {\n client: { x: number; y: number };\n world: { x: number; y: number } | null;\n inCanvas: boolean;\n}\n\n/** Debug overlay showing the pointer's client and world coordinates and the\n * current frame rate, pinned to the canvas's top-right corner. */\nexport function CursorCoordsHud({ canvasRef, anchorRef, viewRef, toWorld, offset }: CursorCoordsHudProps) {\n const toWorldRef = useLatest(toWorld);\n const [state, setState] = useState<HudState>({\n client: { x: 0, y: 0 }, world: null, inCanvas: false,\n });\n const [fps, setFps] = useState<number>(0);\n const { ref, style: anchorStyle } = useHostAnchor(\n () => anchorRef?.current ?? canvasRef.current?.parentElement ?? canvasRef.current,\n {\n align: { x: 'end', y: 'start' },\n offset: { x: offset?.right ?? 8, y: offset?.top ?? 8 },\n },\n );\n\n // FPS counter: tally frames per rAF tick; flush once a second.\n const framesRef = useRef(0);\n const lastFlushRef = useRef(0);\n const fpsLoop = useVisibleRaf(\n () => {\n framesRef.current++;\n const now = performance.now();\n const dt = now - lastFlushRef.current;\n if (dt >= 1000) {\n setFps(Math.round((framesRef.current * 1000) / dt));\n framesRef.current = 0;\n lastFlushRef.current = now;\n }\n fpsLoop.request();\n },\n // Frames not drawn while hidden are not frames that were slow to draw:\n // without this the readout would flush a near-zero rate on resume.\n {\n onResume: () => {\n framesRef.current = 0;\n lastFlushRef.current = performance.now();\n },\n },\n );\n\n useEffect(() => {\n lastFlushRef.current = performance.now();\n fpsLoop.request();\n return () => fpsLoop.cancel();\n }, [fpsLoop]);\n\n useEffect(() => {\n const onMove = (e: PointerEvent) => {\n const canvas = canvasRef.current;\n const view = viewRef.current;\n const client = { x: e.clientX, y: e.clientY };\n if (!canvas || !view) {\n setState({ client, world: null, inCanvas: false });\n return;\n }\n const rect = canvas.getBoundingClientRect();\n const inCanvas =\n e.clientX >= rect.left && e.clientX <= rect.right &&\n e.clientY >= rect.top && e.clientY <= rect.bottom;\n const [wx, wy] = toWorldRef.current?.(e.clientX, e.clientY)\n ?? clientToWorld(e.clientX, e.clientY, rect, view);\n const world = { x: wx, y: wy };\n setState({ client, world, inCanvas });\n };\n\n document.addEventListener('pointermove', onMove);\n\n return () => {\n document.removeEventListener('pointermove', onMove);\n };\n }, [canvasRef, viewRef, toWorldRef]);\n\n if (!anchorStyle) return null;\n\n return (\n <div ref={ref} className={s.hud} style={anchorStyle}>\n <dl className={s.readings}>\n <dt className={s.muted}>fps</dt>\n <dd>{fps}</dd>\n <dt className={s.muted}>client</dt>\n <dd>{point(state.client, 0)}</dd>\n <dt className={s.muted}>world</dt>\n {state.world ? (\n <dd>\n {point(state.world, 1)}\n {state.inCanvas ? null : <span className={s.absent}> off-canvas</span>}\n </dd>\n ) : (\n <dd className={s.absent}>— no canvas or view yet</dd>\n )}\n </dl>\n </div>\n );\n}\n\n/** `(x, y)` at `places` decimals, its negatives written with U+2212. */\nfunction point({ x, y }: { x: number; y: number }, places: number): string {\n const at = decimal({ places, grouping: false });\n return `(${qty(x, at).text}, ${qty(y, at).text})`;\n}\n"],"mappings":"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"}
@@ -1,15 +1,13 @@
1
- import { commandFill as e } from "../features/patterns/commandPaint.js";
2
- import { viewToMat3 as t } from "../renderer/math/viewToMat3.js";
3
- import { normalizeView as n } from "../core/viewport/view.js";
4
- import { useFrameLoop as r } from "./useFrameLoop.js";
5
- import { useLateContentRedraw as i } from "./useLateContentRedraw.js";
6
- import { useCanvasRenderer as a, useRedrawOnDensityChange as o, useRedrawOnRestore as s } from "./useCanvasRenderer.js";
7
- import { useRedrawOn as c } from "./useRedrawOn.js";
8
- import { useCallback as l, useEffect as u, useLayoutEffect as d, useRef as f } from "react";
9
- import { assignRef as p, useLatest as m } from "@weasel-js/react";
10
- import { jsx as h } from "react/jsx-runtime";
1
+ import { backgroundFillCommands as e } from "../core/layers/backgroundFill.js";
2
+ import { normalizeView as t } from "../core/viewport/view.js";
3
+ import { useCanvasSurface as n } from "./useCanvasSurface.js";
4
+ import { surfaceBox as r } from "./surfaceBox.js";
5
+ import { viewToMat3 as i } from "@weasel-js/geom";
6
+ import { useCallback as a, useRef as o } from "react";
7
+ import { assignRef as s } from "@weasel-js/react";
8
+ import { jsx as c } from "react/jsx-runtime";
11
9
  //#region src/canvas/DrawCanvas.tsx
12
- var g = {
10
+ var l = {
13
11
  x: 0,
14
12
  y: 0,
15
13
  scale: {
@@ -17,57 +15,42 @@ var g = {
17
15
  y: 1
18
16
  }
19
17
  };
20
- function _(_) {
21
- let { width: v, height: y, draw: b, background: x, redrawOn: S, dpr: C, className: w, canvasRef: T } = _, E = _.view ? n(_.view) : g, D = f(null), O = l((e) => {
22
- D.current = e, p(T, e);
23
- }, [T]), k = a(), A = m(() => {
24
- let n = D.current;
18
+ function u(u) {
19
+ let { width: d, height: f, draw: p, background: m, redrawOn: h, dpr: g, className: _, canvasRef: v } = u, y = u.view ? t(u.view) : l, b = o(null), x = a((e) => {
20
+ b.current = e, s(v, e);
21
+ }, [v]);
22
+ return n((t) => {
23
+ let n = b.current;
25
24
  if (!n) return !1;
26
- let r = typeof b == "function" ? b({
27
- width: v,
28
- height: y
29
- }) : b, i = [], a = x && e(x, {
30
- x: 0,
31
- y: 0,
32
- width: v,
33
- height: y
34
- });
35
- return a && i.push({
36
- kind: "path",
37
- path: {
38
- kind: "rect",
39
- x: 0,
40
- y: 0,
41
- width: v,
42
- height: y
43
- },
44
- fill: a
45
- }), i.push({
25
+ let r = typeof p == "function" ? p({
26
+ width: d,
27
+ height: f
28
+ }) : p, a = m ? e(m, {
29
+ width: d,
30
+ height: f
31
+ }) : [];
32
+ return a.push({
46
33
  kind: "group",
47
- transform: t(E),
34
+ transform: i(y),
48
35
  children: [...r]
49
- }), k.paint(n, i, E, {
50
- width: v,
51
- height: y,
52
- dpr: C
36
+ }), t.paint(n, a, y, {
37
+ width: d,
38
+ height: f,
39
+ dpr: g
53
40
  });
54
- }), { requestRedraw: j } = r(l(() => A.current(), [A]), { target: D }), M = f(!1);
55
- return d(() => {
56
- if (M.current) {
57
- j();
58
- return;
59
- }
60
- M.current = A.current(), M.current || j();
61
- }), i(j), s(k, j), o(j, C), c(S, j), u(() => () => {
62
- M.current = !1;
63
- }, []), /* @__PURE__ */ h("canvas", {
64
- ref: O,
65
- width: v,
66
- height: y,
67
- className: w
41
+ }, {
42
+ target: b,
43
+ dpr: g,
44
+ redrawOn: h,
45
+ paintOnCommit: !0
46
+ }), /* @__PURE__ */ c("canvas", {
47
+ ref: x,
48
+ width: d,
49
+ height: f,
50
+ ...r(d, f, _)
68
51
  });
69
52
  }
70
53
  //#endregion
71
- export { _ as DrawCanvas };
54
+ export { u as DrawCanvas };
72
55
 
73
56
  //# sourceMappingURL=DrawCanvas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DrawCanvas.js","names":["IDENTITY_VIEW","DrawCanvas","props","view","normalizeView","canvasElRef","useRef","setRefs","useCallback","el","assignRef","canvasRef","lease","useCanvasRenderer","paintRef","useLatest","content","draw","commands","fill","background","commandFill","viewToMat3","useFrameLoop","paintedRef","useLayoutEffect","requestRedraw","useLateContentRedraw","useRedrawOnRestore","useRedrawOnDensityChange","dpr","useRedrawOn","redrawOn","useEffect"],"sources":["../../src/canvas/DrawCanvas.tsx"],"sourcesContent":["/**\n * `<DrawCanvas>` — a sized, DPR-correct WebGL2 surface that paints a list of\n * draw commands, with no scene, tools or dispatcher behind it.\n *\n * It paints through the same per-canvas renderer as `<SceneViewCanvas>`\n * (`useCanvasRenderer`), on a `useFrameLoop` that stops while the canvas is off\n * screen or the tab is hidden. Like `<SceneViewCanvas>` it attaches no event\n * listeners. Its size is `width` × `height`, which the renderer writes as\n * inline style, so `className` positions the element and cannot resize it.\n */\nimport { useCallback, useEffect, useLayoutEffect, useRef } from 'react';\nimport { commandFill } from '../features/patterns/commandPaint';\nimport type { Ref } from 'react';\nimport { assignRef, useLatest } from '@weasel-js/react';\nimport type { FillStyle } from '@weasel-js/paint';\nimport { useFrameLoop } from './useFrameLoop';\nimport { useLateContentRedraw } from './useLateContentRedraw';\nimport { useRedrawOn } from './useRedrawOn';\nimport { useCanvasRenderer, useRedrawOnDensityChange, useRedrawOnRestore } from './useCanvasRenderer';\nimport { viewToMat3 } from '../renderer/math/viewToMat3';\nimport type { DrawCommand } from '../renderer/DrawCommand';\nimport type { RedrawSource } from '../core/layers/render';\nimport { normalizeView, type View } from '../core/viewport/view';\n\n/** What a `<DrawCanvas>` paints: a command list, or a function returning one\n * that is called on every paint with the surface's CSS-pixel size. */\nexport type DrawCanvasDraw =\n | readonly DrawCommand[]\n | ((size: { width: number; height: number }) => readonly DrawCommand[]);\n\n/** Props for `<DrawCanvas>`. */\nexport interface DrawCanvasProps {\n /** CSS-pixel width. The drawing buffer is `width × dpr`. */\n width: number;\n /** CSS-pixel height. */\n height: number;\n /** The commands to paint, in the coordinate space `view` maps to the\n * screen — CSS pixels when `view` is omitted. A new array repaints on the\n * next frame. A function is read at paint time, so state it reads outside\n * React repaints when one of `redrawOn`'s sources notifies. */\n draw: DrawCanvasDraw;\n /** Camera over `draw`'s commands. Defaults to the identity view. */\n view?: View;\n /** Fills the whole surface beneath `draw`, in screen space. The canvas is\n * transparent without it. */\n background?: FillStyle;\n /** External state a `draw` function reads. Each source is subscribed while\n * mounted and repaints the canvas when it notifies. */\n redrawOn?: readonly RedrawSource[];\n /** Device-pixel ratio. Defaults to `window.devicePixelRatio`, read per\n * paint. */\n dpr?: number;\n /** CSS class for the `<canvas>` element. */\n className?: string;\n /** Receives the underlying `<canvas>`, for pointer listeners or `toBlob`. */\n canvasRef?: Ref<HTMLCanvasElement>;\n}\n\nconst IDENTITY_VIEW: View = { x: 0, y: 0, scale: { x: 1, y: 1 } };\n\n/**\n * Paint draw commands onto a canvas of its own. For a surface that only draws —\n * a package demo, a swatch, a preview — where a `<SceneCanvas>` would bring a\n * scene, tools and an input dispatcher that nothing uses.\n */\nexport function DrawCanvas(props: DrawCanvasProps) {\n const { width, height, draw, background, redrawOn, dpr, className, canvasRef } = props;\n const view = props.view ? normalizeView(props.view) : IDENTITY_VIEW;\n\n const canvasElRef = useRef<HTMLCanvasElement | null>(null);\n const setRefs = useCallback((el: HTMLCanvasElement | null) => {\n canvasElRef.current = el;\n assignRef(canvasRef, el);\n }, [canvasRef]);\n\n const lease = useCanvasRenderer();\n const paint = (): boolean => {\n const el = canvasElRef.current;\n if (!el) return false;\n const content = typeof draw === 'function' ? draw({ width, height }) : draw;\n const commands: DrawCommand[] = [];\n const fill = background && commandFill(background, { x: 0, y: 0, width, height });\n if (fill) commands.push({ kind: 'path', path: { kind: 'rect', x: 0, y: 0, width, height }, fill });\n commands.push({ kind: 'group', transform: viewToMat3(view), children: [...content] });\n return lease.paint(el, commands, view, { width, height, dpr });\n };\n const paintRef = useLatest(paint);\n const { requestRedraw } = useFrameLoop(\n useCallback(() => paintRef.current(), [paintRef]),\n { target: canvasElRef },\n );\n\n // Every committed render marks the surface dirty; the first paints in place\n // so the first frame shown is the content rather than a blank canvas.\n const paintedRef = useRef(false);\n useLayoutEffect(() => {\n if (paintedRef.current) { requestRedraw(); return; }\n paintedRef.current = paintRef.current();\n if (!paintedRef.current) requestRedraw();\n });\n\n useLateContentRedraw(requestRedraw);\n useRedrawOnRestore(lease, requestRedraw);\n useRedrawOnDensityChange(requestRedraw, dpr);\n useRedrawOn(redrawOn, requestRedraw);\n\n // `useCanvasRenderer` frees the renderer on unmount; a remount (StrictMode)\n // paints its first frame in place again.\n useEffect(() => () => { paintedRef.current = false; }, []);\n\n return <canvas ref={setRefs} width={width} height={height} className={className} />;\n}\n"],"mappings":";;;;;;;;;;;AA0DA,IAAMA,IAAsB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;EAAE,GAAG;EAAG,GAAG;CAAE;AAAE;AAOhE,SAAgBC,EAAW,GAAwB;CACjD,IAAM,EAAE,UAAO,WAAQ,SAAM,eAAY,aAAU,QAAK,cAAW,iBAAcC,GAC3EC,IAAOD,EAAM,OAAOE,EAAcF,EAAM,IAAI,IAAIF,GAEhDK,IAAcC,EAAiC,IAAI,GACnDC,IAAUC,GAAa,MAAiC;EAE5D,AADA,EAAY,UAAUC,GACtBC,EAAUC,GAAWF,CAAE;CACzB,GAAG,CAACE,CAAS,CAAC,GAERC,IAAQC,EAAkB,GAW1BC,IAAWC,QAVY;EAC3B,IAAMN,IAAKJ,EAAY;EACvB,IAAI,CAACI,GAAI,OAAO;EAChB,IAAMO,IAAU,OAAOC,KAAS,aAAaA,EAAK;GAAE;GAAO;EAAO,CAAC,IAAIA,GACjEC,IAA0B,CAAC,GAC3BC,IAAOC,KAAcC,EAAYD,GAAY;GAAE,GAAG;GAAG,GAAG;GAAG;GAAO;EAAO,CAAC;EAGhF,OAFID,KAAMD,EAAS,KAAK;GAAE,MAAM;GAAQ,MAAM;IAAE,MAAM;IAAQ,GAAG;IAAG,GAAG;IAAG;IAAO;GAAO;GAAG;EAAK,CAAC,GACjGA,EAAS,KAAK;GAAE,MAAM;GAAS,WAAWI,EAAWnB,CAAI;GAAG,UAAU,CAAC,GAAGa,CAAO;EAAE,CAAC,GAC7EJ,EAAM,MAAMH,GAAIS,GAAUf,GAAM;GAAE;GAAO;GAAQ;EAAI,CAAC;CAC/D,CACgC,GAC1B,EAAE,qBAAkBoB,EACxBf,QAAkBM,EAAS,QAAQ,GAAG,CAACA,CAAQ,CAAC,GAChD,EAAE,QAAQT,EAAY,CACxB,GAIMmB,IAAalB,EAAO,EAAK;CAgB/B,OAfAmB,QAAsB;EACpB,IAAID,EAAW,SAAS;GAAE,EAAc;GAAG;EAAQ;EAEnD,AADA,EAAW,UAAUV,EAAS,QAAQ,GACjCU,EAAW,WAASE,EAAc;CACzC,CAAC,GAEDC,EAAqBD,CAAa,GAClCE,EAAmBhB,GAAOc,CAAa,GACvCG,EAAyBH,GAAeI,CAAG,GAC3CC,EAAYC,GAAUN,CAAa,GAInCO,cAAsB;EAAE,EAAW,UAAU;CAAO,GAAG,CAAC,CAAC,GAElD,kBAAC,UAAD;EAAQ,KAAK1B;EAAgB;EAAe;EAAmB;CAAY,CAAA;AACpF"}
1
+ {"version":3,"file":"DrawCanvas.js","names":["IDENTITY_VIEW","DrawCanvas","props","view","normalizeView","canvasElRef","useRef","setRefs","useCallback","el","assignRef","canvasRef","useCanvasSurface","content","draw","commands","background","backgroundFillCommands","viewToMat3","lease","surfaceBox","width","height","className"],"sources":["../../src/canvas/DrawCanvas.tsx"],"sourcesContent":["/**\n * `<DrawCanvas>` — a sized, DPR-correct WebGL2 surface that paints a list of\n * draw commands, with no scene, tools or dispatcher behind it.\n *\n * It paints through the same surface hook as `<SceneViewCanvas>`\n * (`useCanvasSurface`), whose frame loop stops while the canvas is off screen\n * or the tab is hidden. Like `<SceneViewCanvas>` it attaches no event\n * listeners. Its size is `width` × `height` unless a `className` rule sizes\n * the element; the drawing buffer stays `width` × `height` either way.\n */\nimport { useCallback, useRef } from 'react';\nimport type { Ref } from 'react';\nimport { assignRef } from '@weasel-js/react';\nimport type { Paint } from '@weasel-js/paint';\nimport { useCanvasSurface } from './useCanvasSurface';\nimport { surfaceBox } from './surfaceBox';\nimport type { CanvasRendererLease } from './canvasRenderer';\nimport { viewToMat3 } from '@weasel-js/geom';\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport type { RedrawSource } from '../core/layers/render';\nimport { backgroundFillCommands } from '../core/layers/backgroundFill';\nimport { normalizeView, type View } from '../core/viewport/view';\n\n/** What a `<DrawCanvas>` paints: a command list, or a function returning one\n * that is called on every paint with the surface's CSS-pixel size. */\nexport type DrawCanvasDraw =\n | readonly DrawCommand[]\n | ((size: { width: number; height: number }) => readonly DrawCommand[]);\n\n/** Props for `<DrawCanvas>`. */\nexport interface DrawCanvasProps {\n /** CSS-pixel width. The drawing buffer is `width × dpr`. */\n width: number;\n /** CSS-pixel height. */\n height: number;\n /** The commands to paint, in the coordinate space `view` maps to the\n * screen — CSS pixels when `view` is omitted. A new array repaints on the\n * next frame. A function is read at paint time, so state it reads outside\n * React repaints when one of `redrawOn`'s sources notifies. */\n draw: DrawCanvasDraw;\n /** Camera over `draw`'s commands. Defaults to the identity view. */\n view?: View;\n /** Fills the whole surface beneath `draw`, in screen space. The canvas is\n * transparent without it. */\n background?: Paint;\n /** External state a `draw` function reads. Each source is subscribed while\n * mounted and repaints the canvas when it notifies. */\n redrawOn?: readonly RedrawSource[];\n /** Device-pixel ratio. Defaults to `window.devicePixelRatio`, read per\n * paint. */\n dpr?: number;\n /** CSS class for the `<canvas>` element. */\n className?: string;\n /** Receives the underlying `<canvas>`, for pointer listeners or `toBlob`. */\n canvasRef?: Ref<HTMLCanvasElement>;\n}\n\nconst IDENTITY_VIEW: View = { x: 0, y: 0, scale: { x: 1, y: 1 } };\n\n/**\n * Paint draw commands onto a canvas of its own. For a surface that only draws —\n * a package demo, a swatch, a preview — where a `<SceneCanvas>` would bring a\n * scene, tools and an input dispatcher that nothing uses.\n */\nexport function DrawCanvas(props: DrawCanvasProps) {\n const { width, height, draw, background, redrawOn, dpr, className, canvasRef } = props;\n const view = props.view ? normalizeView(props.view) : IDENTITY_VIEW;\n\n const canvasElRef = useRef<HTMLCanvasElement | null>(null);\n const setRefs = useCallback((el: HTMLCanvasElement | null) => {\n canvasElRef.current = el;\n assignRef(canvasRef, el);\n }, [canvasRef]);\n\n const paint = (lease: CanvasRendererLease): boolean => {\n const el = canvasElRef.current;\n if (!el) return false;\n const content = typeof draw === 'function' ? draw({ width, height }) : draw;\n const commands: DrawCommand[] = background ? backgroundFillCommands(background, { width, height }) : [];\n commands.push({ kind: 'group', transform: viewToMat3(view), children: [...content] });\n return lease.paint(el, commands, view, { width, height, dpr });\n };\n useCanvasSurface(paint, { target: canvasElRef, dpr, redrawOn, paintOnCommit: true });\n\n return <canvas ref={setRefs} width={width} height={height} {...surfaceBox(width, height, className)} />;\n}\n"],"mappings":";;;;;;;;;AAyDA,IAAMA,IAAsB;CAAE,GAAG;CAAG,GAAG;CAAG,OAAO;EAAE,GAAG;EAAG,GAAG;CAAE;AAAE;AAOhE,SAAgBC,EAAW,GAAwB;CACjD,IAAM,EAAE,UAAO,WAAQ,SAAM,eAAY,aAAU,QAAK,cAAW,iBAAcC,GAC3EC,IAAOD,EAAM,OAAOE,EAAcF,EAAM,IAAI,IAAIF,GAEhDK,IAAcC,EAAiC,IAAI,GACnDC,IAAUC,GAAa,MAAiC;EAE5D,AADA,EAAY,UAAUC,GACtBC,EAAUC,GAAWF,CAAE;CACzB,GAAG,CAACE,CAAS,CAAC;CAYd,OAFAC,GARe,MAAwC;EACrD,IAAMH,IAAKJ,EAAY;EACvB,IAAI,CAACI,GAAI,OAAO;EAChB,IAAMI,IAAU,OAAOC,KAAS,aAAaA,EAAK;GAAE;GAAO;EAAO,CAAC,IAAIA,GACjEC,IAA0BC,IAAaC,EAAuBD,GAAY;GAAE;GAAO;EAAO,CAAC,IAAI,CAAC;EAEtG,OADAD,EAAS,KAAK;GAAE,MAAM;GAAS,WAAWG,EAAWf,CAAI;GAAG,UAAU,CAAC,GAAGU,CAAO;EAAE,CAAC,GAC7EM,EAAM,MAAMV,GAAIM,GAAUZ,GAAM;GAAE;GAAO;GAAQ;EAAI,CAAC;CAC/D,GACwB;EAAE,QAAQE;EAAa;EAAK;EAAU,eAAe;CAAK,CAAC,GAE5E,kBAAC,UAAD;EAAQ,KAAKE;EAAgB;EAAe;EAAQ,GAAIa,EAAWC,GAAOC,GAAQC,CAAS;CAAI,CAAA;AACxG"}
@@ -1 +1 @@
1
- {"version":3,"file":"ModalityHud.js","names":["s","hud_module_default","ModalityHud","toolCtx","useOptionalActiveToolContext","useHostAnchor","anchorRef","canvasRef","offset","style","active","hotkeys","hotkeyTop","modeId","i","id"],"sources":["../../src/canvas/ModalityHud.tsx"],"sourcesContent":["/**\n * Dev HUD reporting the modality state: active mode, active-slot tool, and\n * the hotkey-engaged tool stack. Anchors below `PickHud` in the canvas's\n * top-right corner.\n *\n * Mode id is supplied by the consumer (apps that haven't yet wired the\n * modality machine pass `undefined`; the line renders as `—`). Active /\n * hotkey state is read live from `useOptionalActiveToolContext` so the HUD\n * stays in sync with tool switches and hotkey engage/disengage without\n * prop plumbing.\n */\nimport { useOptionalActiveToolContext } from '@weasel-js/routing/react';\nimport { useHostAnchor } from './useHostAnchor';\nimport s from './hud.module.css';\n\nexport interface ModalityHudProps {\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 /** Active modality mode id. Omit until the mode machine is wired —\n * the row renders `—` in that case. */\n modeId?: string;\n /** Inset from the canvas's top-right corner. Default `{ top: 220, right: 8 }`\n * so the HUD clears `PickHud` (which itself sits at ~76, with variable\n * height for the id list). Override if the pick list is unusually tall. */\n offset?: { top?: number; right?: number };\n}\n\nexport function ModalityHud({ canvasRef, anchorRef, modeId, offset }: ModalityHudProps) {\n const toolCtx = useOptionalActiveToolContext();\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 ?? 220 },\n },\n );\n\n if (!style) return null;\n\n const active = toolCtx?.active ?? null;\n const hotkeys = toolCtx?.hotkeyStack ?? [];\n const hotkeyTop = hotkeys.length > 0 ? hotkeys[hotkeys.length - 1] : null;\n\n return (\n <div ref={ref} className={`${s.hud} ${s.sized}`} style={style}>\n <div className={s.row}>\n <span className={s.muted}>mode</span>\n <span className={modeId ? undefined : s.absent}>{modeId ?? '—'}</span>\n </div>\n <div className={s.row}>\n <span className={s.muted}>active</span>\n <span className={active ? undefined : s.absent}>{active ?? '—'}</span>\n </div>\n <div className={s.row}>\n <span className={s.muted}>hotkey</span>\n {hotkeys.length <= 1 ? (\n <span className={hotkeyTop ? undefined : s.absent}>{hotkeyTop ?? '—'}</span>\n ) : (\n <span className={s.stack}>\n {hotkeys.slice().reverse().map((id, i) => (\n <span key={`${id}-${i}`} className={i === 0 ? undefined : s.absent}>\n {id}\n </span>\n ))}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AA8BA,SAAgBE,EAAY,EAAE,cAAW,cAAW,WAAQ,aAA4B;CACtF,IAAMC,IAAUC,EAA6B,GACvC,EAAE,QAAK,aAAUC,QACfC,GAAW,WAAWC,EAAU,SAAS,iBAAiBA,EAAU,SAC1E;EACE,OAAO;GAAE,GAAG;GAAO,GAAG;EAAQ;EAC9B,QAAQ;GAAE,GAAGC,GAAQ,SAAS;GAAG,GAAGA,GAAQ,OAAO;EAAI;CACzD,CACF;CAEA,IAAI,CAACC,GAAO,OAAO;CAEnB,IAAMC,IAASP,GAAS,UAAU,MAC5BQ,IAAUR,GAAS,eAAe,CAAC,GACnCS,IAAYD,EAAQ,SAAS,IAAIA,EAAQA,EAAQ,SAAS,KAAK;CAErE,OACE,kBAAC,OAAD;EAAU;EAAK,WAAW,GAAGX,EAAE,IAAI,GAAGA,EAAE;EAAgB;EAAxD,UAAA;GACE,kBAAC,OAAD;IAAK,WAAWA,EAAE;IAAlB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAWA,EAAE;KAAO,UAAA;IAAU,CAAA,GACpC,kBAAC,QAAD;KAAM,WAAWa,IAAS,KAAA,IAAYb,EAAE;KAAS,UAAAa,KAAU;IAAU,CAAA,CAClE;;GACL,kBAAC,OAAD;IAAK,WAAWb,EAAE;IAAlB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAWA,EAAE;KAAO,UAAA;IAAY,CAAA,GACtC,kBAAC,QAAD;KAAM,WAAWU,IAAS,KAAA,IAAYV,EAAE;KAAS,UAAAU,KAAU;IAAU,CAAA,CAClE;;GACL,kBAAC,OAAD;IAAK,WAAWV,EAAE;IAAlB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAWA,EAAE;KAAO,UAAA;IAAY,CAAA,GACrCW,EAAQ,UAAU,IACjB,kBAAC,QAAD;KAAM,WAAWC,IAAY,KAAA,IAAYZ,EAAE;KAAS,UAAAY,KAAa;IAAU,CAAA,IAE3E,kBAAC,QAAD;KAAM,WAAWZ,EAAE;KAChB,UAAAW,EAAQ,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAI,MAClC,kBAAC,QAAD;MAAyB,WAAWG,MAAM,IAAI,KAAA,IAAYd,EAAE;MACzD,UAAAe;KACG,GAFK,GAAGA,EAAG,GAAGD,GAEd,CACP;IACG,CAAA,CAEL;;EACF;;AAET"}
1
+ {"version":3,"file":"ModalityHud.js","names":["s","hud_module_default","ModalityHud","toolCtx","useOptionalActiveToolContext","useHostAnchor","anchorRef","canvasRef","offset","style","active","hotkeys","hotkeyTop","modeId","i","id"],"sources":["../../src/canvas/ModalityHud.tsx"],"sourcesContent":["/// <reference path=\"../css-modules.d.ts\" />\n/**\n * Dev HUD reporting the modality state: active mode, active-slot tool, and\n * the hotkey-engaged tool stack. Anchors below `PickHud` in the canvas's\n * top-right corner.\n *\n * Mode id is supplied by the consumer (apps that haven't yet wired the\n * modality machine pass `undefined`; the line renders as `—`). Active /\n * hotkey state is read live from `useOptionalActiveToolContext` so the HUD\n * stays in sync with tool switches and hotkey engage/disengage without\n * prop plumbing.\n */\nimport { useOptionalActiveToolContext } from '@weasel-js/routing/react';\nimport { useHostAnchor } from './useHostAnchor';\nimport s from './hud.module.css';\n\nexport interface ModalityHudProps {\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 /** Active modality mode id. Omit until the mode machine is wired —\n * the row renders `—` in that case. */\n modeId?: string;\n /** Inset from the canvas's top-right corner. Default `{ top: 220, right: 8 }`\n * so the HUD clears `PickHud` (which itself sits at ~76, with variable\n * height for the id list). Override if the pick list is unusually tall. */\n offset?: { top?: number; right?: number };\n}\n\nexport function ModalityHud({ canvasRef, anchorRef, modeId, offset }: ModalityHudProps) {\n const toolCtx = useOptionalActiveToolContext();\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 ?? 220 },\n },\n );\n\n if (!style) return null;\n\n const active = toolCtx?.active ?? null;\n const hotkeys = toolCtx?.hotkeyStack ?? [];\n const hotkeyTop = hotkeys.length > 0 ? hotkeys[hotkeys.length - 1] : null;\n\n return (\n <div ref={ref} className={`${s.hud} ${s.sized}`} style={style}>\n <div className={s.row}>\n <span className={s.muted}>mode</span>\n <span className={modeId ? undefined : s.absent}>{modeId ?? '—'}</span>\n </div>\n <div className={s.row}>\n <span className={s.muted}>active</span>\n <span className={active ? undefined : s.absent}>{active ?? '—'}</span>\n </div>\n <div className={s.row}>\n <span className={s.muted}>hotkey</span>\n {hotkeys.length <= 1 ? (\n <span className={hotkeyTop ? undefined : s.absent}>{hotkeyTop ?? '—'}</span>\n ) : (\n <span className={s.stack}>\n {hotkeys.slice().reverse().map((id, i) => (\n <span key={`${id}-${i}`} className={i === 0 ? undefined : s.absent}>\n {id}\n </span>\n ))}\n </span>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AA+BA,SAAgBE,EAAY,EAAE,cAAW,cAAW,WAAQ,aAA4B;CACtF,IAAMC,IAAUC,EAA6B,GACvC,EAAE,QAAK,aAAUC,QACfC,GAAW,WAAWC,EAAU,SAAS,iBAAiBA,EAAU,SAC1E;EACE,OAAO;GAAE,GAAG;GAAO,GAAG;EAAQ;EAC9B,QAAQ;GAAE,GAAGC,GAAQ,SAAS;GAAG,GAAGA,GAAQ,OAAO;EAAI;CACzD,CACF;CAEA,IAAI,CAACC,GAAO,OAAO;CAEnB,IAAMC,IAASP,GAAS,UAAU,MAC5BQ,IAAUR,GAAS,eAAe,CAAC,GACnCS,IAAYD,EAAQ,SAAS,IAAIA,EAAQA,EAAQ,SAAS,KAAK;CAErE,OACE,kBAAC,OAAD;EAAU;EAAK,WAAW,GAAGX,EAAE,IAAI,GAAGA,EAAE;EAAgB;EAAxD,UAAA;GACE,kBAAC,OAAD;IAAK,WAAWA,EAAE;IAAlB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAWA,EAAE;KAAO,UAAA;IAAU,CAAA,GACpC,kBAAC,QAAD;KAAM,WAAWa,IAAS,KAAA,IAAYb,EAAE;KAAS,UAAAa,KAAU;IAAU,CAAA,CAClE;;GACL,kBAAC,OAAD;IAAK,WAAWb,EAAE;IAAlB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAWA,EAAE;KAAO,UAAA;IAAY,CAAA,GACtC,kBAAC,QAAD;KAAM,WAAWU,IAAS,KAAA,IAAYV,EAAE;KAAS,UAAAU,KAAU;IAAU,CAAA,CAClE;;GACL,kBAAC,OAAD;IAAK,WAAWV,EAAE;IAAlB,UAAA,CACE,kBAAC,QAAD;KAAM,WAAWA,EAAE;KAAO,UAAA;IAAY,CAAA,GACrCW,EAAQ,UAAU,IACjB,kBAAC,QAAD;KAAM,WAAWC,IAAY,KAAA,IAAYZ,EAAE;KAAS,UAAAY,KAAa;IAAU,CAAA,IAE3E,kBAAC,QAAD;KAAM,WAAWZ,EAAE;KAChB,UAAAW,EAAQ,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,GAAI,MAClC,kBAAC,QAAD;MAAyB,WAAWG,MAAM,IAAI,KAAA,IAAYd,EAAE;MACzD,UAAAe;KACG,GAFK,GAAGA,EAAG,GAAGD,GAEd,CACP;IACG,CAAA,CAEL;;EACF;;AAET"}
@@ -1,16 +1,15 @@
1
1
  import { bumpNodeMemoGeneration as e, nodeMemo as t } from "../core/scene/nodeMemo.js";
2
- import { pathThroughPoseFrame as n } from "../core/geometry/poseFrame.js";
3
- import { hasSlop as r, slopForStrokeHit as i, widenSlop as a } from "../core/viewport/screenSlop.js";
4
- import { derivesPath as o } from "./nodeShapes/memo.js";
5
- import { DERIVED_PAINTER as s } from "./nodeShapes/derivedPainter.js";
6
- import { paintsPose as c } from "./nodeShapes/poseBox.js";
7
- import { IMAGE_PAINTER as l } from "./nodeShapes/imagePainter.js";
8
- import { PATH_PAINTER as u } from "./nodeShapes/pathPainter.js";
9
- import { RECT_FALLBACK_PAINTER as d } from "./nodeShapes/rectFallbackPainter.js";
10
- import { SHAPE_PAINTER as f } from "./nodeShapes/shapePainter.js";
11
- import { TEXT_PAINTER as p } from "./nodeShapes/textPainter.js";
12
- import { glyphGeneration as m } from "@weasel-js/font";
13
- import { pathContainsPoint as h, strokeHitTest as g } from "@weasel-js/geom";
2
+ import { hasSlop as n, slopForStrokeHit as r, widenSlop as i } from "../core/viewport/screenSlop.js";
3
+ import { derivesPath as a } from "./nodeShapes/memo.js";
4
+ import { DERIVED_PAINTER as o } from "./nodeShapes/derivedPainter.js";
5
+ import { paintsPose as s } from "./nodeShapes/poseBox.js";
6
+ import { IMAGE_PAINTER as c } from "./nodeShapes/imagePainter.js";
7
+ import { PATH_PAINTER as l } from "./nodeShapes/pathPainter.js";
8
+ import { RECT_FALLBACK_PAINTER as u } from "./nodeShapes/rectFallbackPainter.js";
9
+ import { SHAPE_PAINTER as d } from "./nodeShapes/shapePainter.js";
10
+ import { TEXT_PAINTER as f } from "./nodeShapes/textPainter.js";
11
+ import { pathContainsPoint as p, pathThroughPoseFrame as m, strokeHitTest as h } from "@weasel-js/geom";
12
+ import { glyphGeneration as g } from "@weasel-js/font";
14
13
  //#region src/canvas/NodeShape.ts
15
14
  var _ = Object.freeze({
16
15
  filled: !0,
@@ -33,7 +32,7 @@ function x(t, n = {}) {
33
32
  }
34
33
  var S = "shape:painter", C = "shape:painter:nonrect", w = "shape:painter:derived", T = "shape:painter:derived:nonrect", E = "shape:silhouette", D = "shape:silhouette:text";
35
34
  function O(e) {
36
- let n = c(e.pose), r = o(e) ? n ? w : T : n ? S : C;
35
+ let n = s(e.pose), r = a(e) ? n ? w : T : n ? S : C;
37
36
  return t(e, r, void 0, () => k(e));
38
37
  }
39
38
  function k(e) {
@@ -41,20 +40,20 @@ function k(e) {
41
40
  for (let t of v.high) if (t.matches(e)) return t;
42
41
  for (let t of v.normal) if (t.matches(e)) return t;
43
42
  }
44
- function A(e, r, i) {
45
- let a = () => {
46
- let t = O(e)?.silhouette?.(e, r, i) ?? null;
47
- return t && n(t, r);
43
+ function A(e, n, r) {
44
+ let i = () => {
45
+ let t = O(e)?.silhouette?.(e, n, r) ?? null;
46
+ return t && m(t, n);
48
47
  };
49
- if (i?.derivedPath != null) return a();
50
- if (O(e) === p) {
51
- let n = m(), i = t(e, D, r, () => ({
52
- epoch: n,
53
- path: a()
48
+ if (r?.derivedPath != null) return i();
49
+ if (O(e) === f) {
50
+ let r = g(), a = t(e, D, n, () => ({
51
+ epoch: r,
52
+ path: i()
54
53
  }));
55
- return i.epoch !== n && (i.epoch = n, i.path = a()), i.path;
54
+ return a.epoch !== r && (a.epoch = r, a.path = i()), a.path;
56
55
  }
57
- return t(e, E, r, a);
56
+ return t(e, E, n, i);
58
57
  }
59
58
  function j(e, t, n) {
60
59
  return O(e)?.ink?.(e, t, n) ?? null;
@@ -62,19 +61,19 @@ function j(e, t, n) {
62
61
  function M(e, t, n) {
63
62
  return O(e)?.bounds?.(e, t, n) ?? null;
64
63
  }
65
- function N(e, t, n, o, s = {}) {
64
+ function N(e, t, a, o, s = {}) {
66
65
  let c = A(e, t, { derivedPath: s.derivedPath });
67
66
  if (c === null) return !0;
68
- let l = j(e, t, { scale: s.scale }) ?? _, u = h(c, n, o);
67
+ let l = j(e, t, { scale: s.scale }) ?? _, u = p(c, a, o);
69
68
  if (l.filled && u) return !0;
70
- let d = a(s.tolerance, (u ? l.insetPx : l.outsetPx) ?? 0, s.scale), { extra: f, opts: p } = i(d), m = (u ? l.inset : l.outset) + f;
71
- return (m > 0 || r(d)) && g(c, n, o, m, p);
69
+ let d = i(s.tolerance, (u ? l.insetPx : l.outsetPx) ?? 0, s.scale), { extra: f, opts: m } = r(d), g = (u ? l.inset : l.outset) + f;
70
+ return (g > 0 || n(d)) && h(c, a, o, g, m);
72
71
  }
73
72
  function P() {
74
73
  return b(), [...v.high, ...v.normal];
75
74
  }
76
75
  function F() {
77
- x(p), x(s), x(u), x(f), x(l), x(d);
76
+ x(f), x(o), x(l), x(d), x(c), x(u);
78
77
  }
79
78
  //#endregion
80
79
  export { _ as DEFAULT_INK, O as findNodeShape, M as findShapeBounds, j as findShapeInk, A as findShapeSilhouette, P as getNodeShapes, x as registerNodeShape, N as shapeCoversPoint };
@@ -1 +1 @@
1
- {"version":3,"file":"NodeShape.js","names":["DEFAULT_INK","PAINTERS","builtInsRegistered","ensureBuiltIns","registerBuiltInShapePainters","registerNodeShape","list","opts","painter","bumpNodeMemoGeneration","i","PAINTER_SLOT","PAINTER_SLOT_NONRECT","PAINTER_SLOT_DERIVED","PAINTER_SLOT_DERIVED_NONRECT","SILHOUETTE_SLOT","TEXT_SILHOUETTE_SLOT","findNodeShape","rect","paintsPose","node","slot","derivesPath","nodeMemo","matchNodeShape","p","findShapeSilhouette","build","sil","pose","ctx","pathThroughPoseFrame","TEXT_PAINTER","epoch","glyphGeneration","held","findShapeInk","findShapeBounds","shapeCoversPoint","ink","inside","pathContainsPoint","x","y","slop","widenSlop","hit","slopForStrokeHit","reach","extra","hasSlop","strokeHitTest","getNodeShapes","DERIVED_PAINTER","PATH_PAINTER","SHAPE_PAINTER","IMAGE_PAINTER","RECT_FALLBACK_PAINTER"],"sources":["../../src/canvas/NodeShape.ts"],"sourcesContent":["/**\n * NodeShape — the **shape trait's** registry. Each trait of a node\n * (shape, routing, label, icon, affordances, …) is its own registry;\n * this one holds the per-kind `paint` + `silhouette` (and future\n * fields) used by `defaultDrawOne`, clipping, non-rect hit-testing,\n * and lasso/area-select.\n *\n * Teaching the kit about a new kind of shape goes through this registry\n * rather than by overriding `drawOne`. Overrides are still possible but\n * shouldn't be the default seam: most consumers want the same dispatch\n * logic, just extended with their own shape kinds (images, custom paths,\n * SVG fragments, etc.).\n *\n * Built-in entries (`kit:text`, `kit:path`, `kit:rect-fallback`) are\n * registered at module load. Consumer entries added via\n * `registerNodeShape` join the chain; the first entry whose\n * `matches` predicate returns true paints the node. Every built-in but\n * `kit:derived` additionally requires a rect-shaped pose — a scene whose\n * poses are some other shape matches none of them, and paints through a\n * consumer painter or not at all.\n *\n * Two priority tiers:\n * - `'high'` — checked before all `'normal'` entries. Use this to\n * override a kit built-in for a specific data shape (e.g. a custom\n * text renderer that wins over `kit:text`).\n * - `'normal'` (default) — appended after the built-ins.\n *\n * Within a tier, entries run in registration order. Each\n * `registerNodeShape` call returns a disposer that removes the\n * entry — useful for tests, for plugin lifecycles, and for swapping\n * implementations at runtime.\n *\n * See `docs/superpowers/specs/2026-05-24-node-traits-reframe-design.md`\n * for the trait taxonomy.\n */\nimport { glyphGeneration } from '@weasel-js/font';\nimport {\n pathContainsPoint,\n strokeHitTest,\n type Path\n} from '@weasel-js/geom';\nimport { pathThroughPoseFrame } from 'core/geometry/poseFrame';\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 type { View } from 'core/viewport/view';\nimport type { VertexColorChannel } from '../animation/colorRegistry';\nimport type { DrawCommand } from '../renderer';\nimport { DERIVED_PAINTER } from './nodeShapes/derivedPainter';\nimport { IMAGE_PAINTER } from './nodeShapes/imagePainter';\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';\n\n/** Optional per-call paint context, threaded through `defaultDrawOne`'s third\n * argument. Lets a rendering entry point override ambient environment reads\n * — the headless `renderSceneToPixels` path supplies its own bitmap resolver\n * here so consumers reuse their own decode caches. Custom painters may\n * ignore it entirely. */\nexport interface NodePaintCtx {\n /** Override bitmap resolution for image nodes. When set it is authoritative:\n * the global `imageCache` is not consulted, and an `undefined` result\n * paints the deterministic grey placeholder outline (never the ambient\n * load-status error variant). */\n resolveImage?: (node: Node<unknown, string, unknown>) => ImageBitmap | undefined;\n /** Device pixels per world unit where this paint will land — the view's\n * scale times the device-pixel ratio. `defaultDrawOne` fills it from its\n * view when absent. Lets a painter size resolution-dependent work, such as\n * re-rasterizing an SVG image; one that has no such work ignores it. */\n pixelScale?: number;\n /** The node's derived path, resolved by the scene-aware `drawOne` wrapper\n * before painting: `paint` has no scene handle, and deriving needs the\n * dependencies' poses. **Absent** for a node that derives from nothing —\n * the wrapper hands such a node the caller's own ctx untouched. `null`\n * means the node derives but has nothing to draw. */\n derivedPath?: Path | null;\n /** A node's animated per-anchor colors: given the colors a painter would paint\n * on `channel`, the colors to paint instead. **Absent** when nothing animates\n * the node. The kit's path painters apply it; see `withColorOverrides`. */\n vertexColors?: (\n channel: VertexColorChannel,\n base: readonly number[] | undefined,\n ) => readonly number[] | undefined;\n}\n\n/**\n * Per-node draw function — the scene-slot `drawOne` signature shared by\n * `<SceneCanvas>`, `renderSceneToCanvas` and `renderSceneToPixels`, so a\n * consumer can reuse one callback across a main canvas and a detached view.\n *\n * Called once per node in the walk. Returned commands are world-space; the\n * caller applies the view transform at the group level. `ctx` is supplied by\n * the scene-aware wrappers — see {@link NodePaintCtx}.\n */\nexport type SceneViewDrawOne<TData, TLayer extends string, TPose> = (\n node: Node<TData, TLayer, TPose>,\n pose: TPose,\n view: View,\n ctx?: NodePaintCtx,\n) => DrawCommand[];\n\n/** A painter for one kind of node: which nodes it claims, and the draw\n * commands it emits for them. Registering one is how a consumer teaches the\n * default renderer to draw its own node kinds. */\nexport interface NodeShapeEntry<TData = unknown, TPose = unknown> {\n /** Stable identifier — used for unregistration and debugging. Pick\n * something descriptive: `'kit:text'`, `'app:image'`, etc. */\n id: string;\n /** Returns true when this painter renders the node. The first matching\n * painter (`'high'` tier first, then `'normal'`) wins. The kit's own\n * painters also require a rect-shaped pose, since their geometry reads\n * `x`/`y`/`width`/`height` off it. */\n matches(node: Node<TData, string, TPose>): boolean;\n /** Emits the draw commands for the node's primary visual. `ctx` is an\n * optional per-call paint context (see `NodePaintCtx`); painters that\n * don't need it can keep a two-argument signature.\n *\n * **The returned array belongs to the painter.** Callers must treat it as\n * immutable and copy before appending — a painter is free to memoize its\n * command list (`kit:shape` and `kit:path` do), and an in-place `push`\n * would grow that list on every frame. `defaultDrawOne` copies before\n * adding its label overlay for exactly this reason. */\n paint(node: Node<TData, string, TPose>, pose: TPose, ctx?: NodePaintCtx): DrawCommand[];\n /** Optional: derive the node's silhouette path from its pose.\n * Used by clipping (when the container has no explicit\n * `clipFromPose`), by non-rect hit-testing, and by lasso/area-select.\n * Painters whose visual has no meaningful closed silhouette (e.g. text)\n * leave this undefined. */\n silhouette?(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeSilhouetteCtx,\n ): Path | null;\n /** Optional: how the silhouette is inked — whether the interior is filled,\n * and how wide the outline is. Read by picking, so that an unfilled shape\n * is grabbable by its outline rather than by its empty middle.\n *\n * This is declared separately from `paint` rather than read back off the\n * emitted draw commands because picking runs on every pointer move, and\n * `paint` is allowed to be expensive (`kit:text` lays out glyphs). Keep it\n * to cheap field reads.\n *\n * Painters that leave it undefined are treated as {@link DEFAULT_INK} —\n * the pre-`ink` behavior, where the whole silhouette interior is grabbable\n * and the outline adds nothing.\n *\n * `ctx.scale` carries the view scale so a `{ px }` stroke width resolves to\n * world units; without it a screen-pixel width is read as world units. */\n ink?(node: Node<TData, string, TPose>, pose: TPose, ctx?: NodeInkCtx): NodeInk | null;\n /** Optional: a box enclosing every pixel `paint` can put down for this node,\n * stroke, markers and miter spikes included, in the frame `paint` emits in\n * — before the pose's rotation is applied around it.\n *\n * Culling reads it to skip `paint` for a node outside the view, so a box\n * that is too small makes the node vanish before it reaches the screen\n * edge. Leave it undefined, or return `null`, when no cheap conservative\n * answer exists (`kit:text` has none short of laying out its glyphs); such\n * a node is always painted. Same cheap-reads rule as `ink`. */\n bounds?(node: Node<TData, string, TPose>, pose: TPose, ctx?: NodeInkCtx): Bounds | null;\n}\n\n/** How a painter inks its silhouette. See {@link NodeShapeEntry.ink}.\n *\n * Reach is per-side because `align` decides which side the ribbon lands on:\n * a centered stroke straddles the outline, `'inner'` puts nothing outside it,\n * `'outer'` nothing inside. */\nexport interface NodeInk {\n /** True when the silhouette's interior is painted, and so grabbable. */\n filled: boolean;\n /** How far the ink reaches outside the outline, world units. */\n outset: number;\n /** How far it reaches inside. */\n inset: number;\n /** Reach past `outset` measured on screen, in pixels — a `{ px }` stroke's,\n * which the renderer holds exact in every direction, so no one world\n * distance stands for it under non-uniform zoom. */\n outsetPx?: number;\n /** Reach past `inset`, likewise. */\n insetPx?: number;\n}\n\n/** Per-call context for {@link NodeShapeEntry.silhouette}. */\nexport interface NodeSilhouetteCtx {\n /** The node's derived path, resolved by the caller — a painter has no scene\n * handle and deriving needs the dependencies' poses. Same convention as\n * {@link NodePaintCtx.derivedPath}: absent for a node that derives from\n * nothing, `null` when it derives but has nothing to draw. */\n derivedPath?: Path | null;\n}\n\n/** Per-call context for {@link NodeShapeEntry.ink}. */\nexport interface NodeInkCtx {\n /** View scale, for resolving `{ px }` lengths to world units — the mean of\n * the two axes' under non-uniform zoom. */\n scale?: number;\n /** The smaller axis's scale, where it differs from `scale`. A box bounding\n * a `{ px }` stroke reads its reach here, where a pixel is the most world. */\n leastScale?: number;\n}\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// ─── Per-node shape memo ────────────────────────────────────────────────────\n\n/**\n * Slot names for the two things picking asks per node per pointer move: which\n * painter matches, and that painter's silhouette path. Both go through\n * {@link nodeMemo}, so they invalidate on `data` (and, for the silhouette,\n * `pose`) reference changes and on a painter registration.\n *\n * Worth memoizing because both are hot and neither is free. `findNodeShape`\n * runs every registered painter's `matches` predicate; `silhouette` *builds*\n * a path — `pathForShape` allocates a fresh `Float32Array` for every ellipse,\n * polygon and star. Picking runs on every pointermove through both the\n * hover-cursor pump and `classifyTarget`, so that's two rebuilds per move per\n * node under the pointer, and shape-accurate picking is now the default.\n *\n * Separate slots rather than one entry: they mostly invalidate together, but\n * not always, and a 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/** Find the painter that will render `node` — first match in priority\n * order. Returns undefined if no painter (including the built-in\n * fallback) accepts the node. */\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/** Find the painter for `node` and ask it for the node's silhouette path,\n * in **world** coords. Returns null if no painter matches, or the matching\n * painter has no `silhouette` method, or the method returns null. Used by\n * clipping, generic non-rect hit-testing and lasso/area-select — anywhere\n * the kit needs the \"closed boundary\" of whatever this kind of node draws as.\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. (`paint()` is unaffected — the render wrap applies\n * the frame, not the silhouette, so nothing is applied twice.) */\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.\n *\n * Without slop a hairline is a mathematically zero-width target: the\n * stroke of a 1px outline is half a world unit wide at scale 1, which no\n * one can hit. Defaults to `0` so a caller that hasn't thought about the\n * view still gets exact geometry rather than a wrong guess. */\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}\n\n/**\n * Does the shape `node` actually paints cover the world point?\n *\n * The pose rect says a node covers its whole bounding box. That is wrong for\n * everything that is not a rectangle: the concave notch of a star, the corner\n * outside an ellipse, the blank right half of a text box. This asks the\n * painter's silhouette instead, which is the same boundary used for clipping\n * and area-select, so \"what you can click\" and \"what is drawn\" answer\n * together.\n *\n * \"What is drawn\" includes the *ink*, not just the boundary. A shape whose\n * interior isn't filled — an outlined rect, a pencil stroke, a bare line — is\n * grabbable along its outline and not through its empty middle, which is the\n * opposite of what a fill test alone answers. The outline's grab width is the\n * stroke's half-width plus `tolerance`.\n *\n * A painter with no `silhouette`, or one that returns `null` for this node\n * (`kit:text` does, for a node with no non-blank lines), reports `true` —\n * \"no opinion\", leaving the caller's own AABB test as the answer. Callers\n * should keep that AABB test as a cheap pre-filter; this is the refinement,\n * not a replacement.\n *\n * Rotation is already baked by `findShapeSilhouette`, so the point is in\n * plain world coordinates.\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 const sil = findShapeSilhouette(node, pose, { derivedPath: opts.derivedPath });\n if (sil === null) return true;\n const ink = findShapeInk(node, pose, { scale: opts.scale }) ?? 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\n // point is on picks the reach. `tolerance` widens it to something a pointer\n // can actually land on, and also makes a filled shape grabbable a few pixels\n // outside its edge — which is what every editor does and what makes\n // edge-dragging feel possible.\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/** Snapshot of the current painters in evaluation order — `'high'` tier\n * first, then `'normal'`. Useful for debugging which painter handles a\n * given node. */\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 // Swapping the painter set out from under a node invalidates anything\n // memoized against the old one. (`registerNodeShape` already bumps, but the\n // clearing above happens without one.)\n bumpNodeMemoGeneration();\n}\n\n// ─── Built-in painters ─────────────────────────────────────────────────\n\nfunction registerBuiltInShapePainters(): void {\n registerNodeShape(TEXT_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":["DEFAULT_INK","PAINTERS","builtInsRegistered","ensureBuiltIns","registerBuiltInShapePainters","registerNodeShape","list","opts","painter","bumpNodeMemoGeneration","i","PAINTER_SLOT","PAINTER_SLOT_NONRECT","PAINTER_SLOT_DERIVED","PAINTER_SLOT_DERIVED_NONRECT","SILHOUETTE_SLOT","TEXT_SILHOUETTE_SLOT","findNodeShape","rect","paintsPose","node","slot","derivesPath","nodeMemo","matchNodeShape","p","findShapeSilhouette","build","sil","pose","ctx","pathThroughPoseFrame","TEXT_PAINTER","epoch","glyphGeneration","held","findShapeInk","findShapeBounds","shapeCoversPoint","ink","inside","pathContainsPoint","x","y","slop","widenSlop","hit","slopForStrokeHit","reach","extra","hasSlop","strokeHitTest","getNodeShapes","DERIVED_PAINTER","PATH_PAINTER","SHAPE_PAINTER","IMAGE_PAINTER","RECT_FALLBACK_PAINTER"],"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 type { View } from 'core/viewport/view';\nimport type { VertexColorChannel } from '@weasel-js/animator';\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport { DERIVED_PAINTER } from './nodeShapes/derivedPainter';\nimport { IMAGE_PAINTER } from './nodeShapes/imagePainter';\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';\n\n/** Optional per-call paint context, threaded through `defaultDrawOne`'s third argument. Lets\n * a rendering entry point override ambient environment reads; custom painters may ignore it\n * entirely. */\nexport interface NodePaintCtx {\n /** Override bitmap resolution for image nodes. When set it is authoritative:\n * the global `imageCache` is not consulted, and an `undefined` result\n * paints the deterministic grey placeholder outline (never the ambient\n * load-status error variant). */\n resolveImage?: (node: Node<unknown, string, unknown>) => ImageBitmap | undefined;\n /** Device pixels per world unit where this paint will land — the view's\n * scale times the device-pixel ratio. `defaultDrawOne` fills it from its\n * view when absent. Lets a painter size resolution-dependent work, such as\n * re-rasterizing an SVG image; one that has no such work ignores it. */\n pixelScale?: number;\n /** The node's derived path, resolved before painting by the `drawOne`\n * wrapper of whichever scene or adapter is drawn: `paint` has no handle on\n * either, and deriving needs the dependencies' poses. **Absent** for a node that derives from nothing —\n * the wrapper hands such a node the caller's own ctx untouched. `null`\n * means the node derives but has nothing to draw. */\n derivedPath?: Path | null;\n /** A node's animated per-anchor colors: given the colors a painter would paint\n * on `channel`, the colors to paint instead. **Absent** when nothing animates\n * the node. The kit's path painters apply it; see `withColorOverrides`. */\n vertexColors?: (\n channel: VertexColorChannel,\n base: readonly number[] | undefined,\n ) => readonly number[] | undefined;\n}\n\n/**\n * Per-node draw function — the scene-slot `drawOne` signature shared by\n * `<SceneCanvas>`, `renderSceneToCanvas` and `renderSceneToPixels`, so a\n * consumer can reuse one callback across a main canvas and a detached view.\n *\n * Called once per node in the walk. Returned commands are world-space; the\n * caller applies the view transform at the group level. `ctx` is supplied by\n * the scene-aware wrappers — see {@link NodePaintCtx}.\n */\nexport type SceneViewDrawOne<TData, TLayer extends string, TPose> = (\n node: Node<TData, TLayer, TPose>,\n pose: TPose,\n view: View,\n ctx?: NodePaintCtx,\n) => DrawCommand[];\n\n/** A painter for one kind of node: which nodes it claims, and the draw\n * commands it emits for them. Registering one is how a consumer teaches the\n * default renderer to draw its own node kinds. */\nexport interface NodeShapeEntry<TData = unknown, TPose = unknown> {\n /** Stable identifier — used for unregistration and debugging. Pick\n * something descriptive: `'kit:text'`, `'app:image'`, etc. */\n id: string;\n /** Returns true when this painter renders the node. The first matching\n * painter (`'high'` tier first, then `'normal'`) wins. The kit's own\n * painters also require a rect-shaped pose, since their geometry reads\n * `x`/`y`/`width`/`height` off it. */\n matches(node: Node<TData, string, TPose>): boolean;\n /** Emits the draw commands for the node's primary visual.\n *\n * **The returned array belongs to the painter.** Callers must treat it as\n * immutable and copy before appending — a painter is free to memoize its\n * command list, and an in-place `push` would grow that list on every frame. */\n paint(node: Node<TData, string, TPose>, pose: TPose, ctx?: NodePaintCtx): DrawCommand[];\n /** Optional: the node's silhouette path from its pose. Used by clipping (when the\n * container has no explicit `clipFromPose`), by non-rect hit-testing, and by\n * lasso/area-select. Painters whose visual has no meaningful closed silhouette\n * leave this undefined. */\n silhouette?(\n node: Node<TData, string, TPose>,\n pose: TPose,\n ctx?: NodeSilhouetteCtx,\n ): Path | null;\n /** Optional: how the silhouette is inked — whether the interior is filled,\n * and how wide the outline is. Read by picking, so that an unfilled shape\n * is grabbable by its outline rather than by its empty middle.\n *\n * Picking runs on every pointer move, so keep it to cheap field reads.\n * Painters that leave it undefined are treated as {@link DEFAULT_INK}: the\n * whole silhouette interior is grabbable and the outline adds nothing.\n *\n * `ctx.scale` carries the view scale so a `{ px }` stroke width resolves to\n * world units; without it a screen-pixel width is read as world units. */\n ink?(node: Node<TData, string, TPose>, pose: TPose, ctx?: NodeInkCtx): NodeInk | null;\n /** Optional: a box enclosing every pixel `paint` can put down for this node,\n * stroke, markers and miter spikes included, in the frame `paint` emits in\n * — before the pose's rotation is applied around it.\n *\n * Culling reads it to skip `paint` for a node outside the view, so a box\n * that is too small makes the node vanish before it reaches the screen\n * edge. Leave it undefined, or return `null`, when no cheap conservative\n * answer exists (`kit:text` has none short of laying out its glyphs); such\n * a node is always painted. Same cheap-reads rule as `ink`. */\n bounds?(node: Node<TData, string, TPose>, pose: TPose, ctx?: NodeInkCtx): Bounds | null;\n}\n\n/** How a painter inks its silhouette. See {@link NodeShapeEntry.ink}.\n *\n * Reach is per-side because `align` decides which side the ribbon lands on:\n * a centered stroke straddles the outline, `'inner'` puts nothing outside it,\n * `'outer'` nothing inside. */\nexport interface NodeInk {\n /** True when the silhouette's interior is painted, and so grabbable. */\n filled: boolean;\n /** How far the ink reaches outside the outline, world units. */\n outset: number;\n /** How far it reaches inside. */\n inset: number;\n /** Reach past `outset` measured on screen, in pixels — a `{ px }` stroke's,\n * which the renderer holds exact in every direction, so no one world\n * distance stands for it under non-uniform zoom. */\n outsetPx?: number;\n /** Reach past `inset`, likewise. */\n insetPx?: number;\n}\n\n/** Per-call context for {@link NodeShapeEntry.silhouette}. */\nexport interface NodeSilhouetteCtx {\n /** The node's derived path, resolved by the caller — a painter has no scene\n * handle and deriving needs the dependencies' poses. Same convention as\n * {@link NodePaintCtx.derivedPath}: absent for a node that derives from\n * nothing, `null` when it derives but has nothing to draw. */\n derivedPath?: Path | null;\n}\n\n/** Per-call context for {@link NodeShapeEntry.ink}. */\nexport interface NodeInkCtx {\n /** View scale, for resolving `{ px }` lengths to world units — the mean of\n * the two axes' under non-uniform zoom. */\n scale?: number;\n /** The smaller axis's scale, where it differs from `scale`. A box bounding\n * a `{ px }` stroke reads its reach here, where a pixel is the most world. */\n leastScale?: number;\n}\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}\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 const sil = findShapeSilhouette(node, pose, { derivedPath: opts.derivedPath });\n if (sil === null) return true;\n const ink = findShapeInk(node, pose, { scale: opts.scale }) ?? 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 // 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 +1 @@
1
- {"version":3,"file":"PickHud.js","names":["s","hud_module_default","PickHud","toWorldRef","useLatest","toWorld","state","setState","useState","useHostAnchor","anchorRef","canvasRef","offset","useEffect","onMove","canvas","view","viewRef","rect","e","worldX","worldY","clientToWorld","ids","pickEvery","best","pickBest","style","id"],"sources":["../../src/canvas/PickHud.tsx"],"sourcesContent":["/**\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":";;;;;;;AA6CA,SAAgBE,EAAQ,EAAE,cAAW,cAAW,YAAS,YAAS,cAAW,aAAU,aAAwB;CAC7G,IAAMC,IAAaC,EAAUC,CAAO,GAC9B,CAACC,GAAOC,KAAYC,EAAmB;EAC3C,KAAK,CAAC;EAAG,MAAM;EAAM,UAAU;CACjC,CAAC,GACK,EAAE,QAAK,aAAUC,QACfC,GAAW,WAAWC,EAAU,SAAS,iBAAiBA,EAAU,SAC1E;EACE,OAAO;GAAE,GAAG;GAAO,GAAG;EAAQ;EAC9B,QAAQ;GAAE,GAAGC,GAAQ,SAAS;GAAG,GAAGA,GAAQ,OAAO;EAAG;CACxD,CACF;CA0CA,OAxCAC,QAAgB;EACd,IAAMC,KAAU,MAAoB;GAClC,IAAMC,IAASJ,EAAU,SACnBK,IAAOC,EAAQ;GACrB,IAAI,CAACF,KAAU,CAACC,GAAM;IACpB,EAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,IAAME,IAAOH,EAAO,sBAAsB;GAI1C,IAAI,EAFFI,EAAE,WAAWD,EAAK,QAAQC,EAAE,WAAWD,EAAK,SAC5CC,EAAE,WAAWD,EAAK,OAAQC,EAAE,WAAWD,EAAK,SAC/B;IACb,EAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,IAAM,CAACE,GAAQC,KAAUlB,EAAW,UAAUgB,EAAE,SAASA,EAAE,OAAO,KAC7DG,EAAcH,EAAE,SAASA,EAAE,SAASD,GAAMF,CAAI,GAC/CO,IAAyB,CAAC;GAC9B,IAAI;IACF,IAAMC,EAAUJ,GAAQC,CAAM;GAChC,QAAQ;IACN,IAAM,CAAC;GACT;GACA,IAAII,IAAsB;GAC1B,IAAIC,GACF,IAAI;IAAE,IAAOA,EAASN,GAAQC,CAAM;GAAG,QAAQ;IAAE,IAAO;GAAM;GAEhE,EAAS;IAAE;IAAK;IAAM,UAAU;GAAK,CAAC;EACxC;EAIA,OAFA,SAAS,iBAAiB,eAAeP,CAAM,SAElC;GACX,SAAS,oBAAoB,eAAeA,CAAM;EACpD;CACF,GAAG;EAACH;EAAWM;EAASO;EAAWE;EAAUvB;CAAU,CAAC,GAEnDwB,IAGH,kBAAC,OAAD;EAAU;EAAK,WAAW,GAAG3B,EAAE,IAAI,GAAGA,EAAE;EAAgB;EAAxD,UAAA,CACE,kBAAC,OAAD;GAAK,WAAW,GAAGA,EAAE,OAAO,GAAGA,EAAE;GAAjC,UAAA;IAA0C;IAAYM,EAAM,IAAI;IAAO;GAAM;EAC5E,CAAA,GAAAA,EAAM,IAAI,WAAW,IACpB,kBAAC,OAAD;GAAK,WAAWN,EAAE;GAAS,UAAAM,EAAM,WAAW,MAAM;EAAkB,CAAA,IAEpE,kBAAC,MAAD;GAAI,WAAWN,EAAE;GAEd,UAAAM,EAAM,IAAI,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,MAChC,kBAAC,MAAD;IAEE,WAAWsB,MAAOtB,EAAM,OAAO,GAAGN,EAAE,KAAK,GAAGA,EAAE,aAAaA,EAAE;IAE5D,UAAA4B;GACC,GAJGA,CAIH,CACL;EACC,CAAA,CAEH;MApBY;AAsBrB"}
1
+ {"version":3,"file":"PickHud.js","names":["s","hud_module_default","PickHud","toWorldRef","useLatest","toWorld","state","setState","useState","useHostAnchor","anchorRef","canvasRef","offset","useEffect","onMove","canvas","view","viewRef","rect","e","worldX","worldY","clientToWorld","ids","pickEvery","best","pickBest","style","id"],"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,SAAgBE,EAAQ,EAAE,cAAW,cAAW,YAAS,YAAS,cAAW,aAAU,aAAwB;CAC7G,IAAMC,IAAaC,EAAUC,CAAO,GAC9B,CAACC,GAAOC,KAAYC,EAAmB;EAC3C,KAAK,CAAC;EAAG,MAAM;EAAM,UAAU;CACjC,CAAC,GACK,EAAE,QAAK,aAAUC,QACfC,GAAW,WAAWC,EAAU,SAAS,iBAAiBA,EAAU,SAC1E;EACE,OAAO;GAAE,GAAG;GAAO,GAAG;EAAQ;EAC9B,QAAQ;GAAE,GAAGC,GAAQ,SAAS;GAAG,GAAGA,GAAQ,OAAO;EAAG;CACxD,CACF;CA0CA,OAxCAC,QAAgB;EACd,IAAMC,KAAU,MAAoB;GAClC,IAAMC,IAASJ,EAAU,SACnBK,IAAOC,EAAQ;GACrB,IAAI,CAACF,KAAU,CAACC,GAAM;IACpB,EAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,IAAME,IAAOH,EAAO,sBAAsB;GAI1C,IAAI,EAFFI,EAAE,WAAWD,EAAK,QAAQC,EAAE,WAAWD,EAAK,SAC5CC,EAAE,WAAWD,EAAK,OAAQC,EAAE,WAAWD,EAAK,SAC/B;IACb,EAAS;KAAE,KAAK,CAAC;KAAG,MAAM;KAAM,UAAU;IAAM,CAAC;IACjD;GACF;GACA,IAAM,CAACE,GAAQC,KAAUlB,EAAW,UAAUgB,EAAE,SAASA,EAAE,OAAO,KAC7DG,EAAcH,EAAE,SAASA,EAAE,SAASD,GAAMF,CAAI,GAC/CO,IAAyB,CAAC;GAC9B,IAAI;IACF,IAAMC,EAAUJ,GAAQC,CAAM;GAChC,QAAQ;IACN,IAAM,CAAC;GACT;GACA,IAAII,IAAsB;GAC1B,IAAIC,GACF,IAAI;IAAE,IAAOA,EAASN,GAAQC,CAAM;GAAG,QAAQ;IAAE,IAAO;GAAM;GAEhE,EAAS;IAAE;IAAK;IAAM,UAAU;GAAK,CAAC;EACxC;EAIA,OAFA,SAAS,iBAAiB,eAAeP,CAAM,SAElC;GACX,SAAS,oBAAoB,eAAeA,CAAM;EACpD;CACF,GAAG;EAACH;EAAWM;EAASO;EAAWE;EAAUvB;CAAU,CAAC,GAEnDwB,IAGH,kBAAC,OAAD;EAAU;EAAK,WAAW,GAAG3B,EAAE,IAAI,GAAGA,EAAE;EAAgB;EAAxD,UAAA,CACE,kBAAC,OAAD;GAAK,WAAW,GAAGA,EAAE,OAAO,GAAGA,EAAE;GAAjC,UAAA;IAA0C;IAAYM,EAAM,IAAI;IAAO;GAAM;EAC5E,CAAA,GAAAA,EAAM,IAAI,WAAW,IACpB,kBAAC,OAAD;GAAK,WAAWN,EAAE;GAAS,UAAAM,EAAM,WAAW,MAAM;EAAkB,CAAA,IAEpE,kBAAC,MAAD;GAAI,WAAWN,EAAE;GAEd,UAAAM,EAAM,IAAI,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,MAChC,kBAAC,MAAD;IAEE,WAAWsB,MAAOtB,EAAM,OAAO,GAAGN,EAAE,KAAK,GAAGA,EAAE,aAAaA,EAAE;IAE5D,UAAA4B;GACC,GAJGA,CAIH,CACL;EACC,CAAA,CAEH;MApBY;AAsBrB"}