@weasel-js/core 1.11.0 → 1.12.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 (586) hide show
  1. package/CHANGELOG.md +611 -0
  2. package/README.md +1 -1
  3. package/dist/WeaselProvider.js +1 -1
  4. package/dist/affordances/pathAnchors.js +10 -6
  5. package/dist/affordances/pathAnchors.js.map +1 -1
  6. package/dist/animation/index.js +3 -3
  7. package/dist/animation/rig/bindRig.js +1 -1
  8. package/dist/animation/rig/rigNode.js.map +1 -1
  9. package/dist/barrel/canvas.js +9 -3
  10. package/dist/barrel/interactions.js +5 -4
  11. package/dist/barrel/paint.js +4 -4
  12. package/dist/barrel/paths.js +10 -6
  13. package/dist/barrel/renderer.js +5 -3
  14. package/dist/barrel/routing.js +7 -12
  15. package/dist/barrel/scene.js +9 -5
  16. package/dist/barrel/text.js +2 -2
  17. package/dist/barrel/viewport.js +9 -4
  18. package/dist/canvas/Canvas.js +5 -2
  19. package/dist/canvas/Canvas.js.map +1 -1
  20. package/dist/canvas/CanvasView.js +23 -34
  21. package/dist/canvas/CanvasView.js.map +1 -1
  22. package/dist/canvas/ModalityHud.js +1 -1
  23. package/dist/canvas/NodeShape.js +4 -1
  24. package/dist/canvas/NodeShape.js.map +1 -1
  25. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +1 -1
  26. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +1 -1
  27. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +1 -1
  28. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +17 -3
  29. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
  30. package/dist/canvas/SceneCanvas/SurfaceDeclarations.js +23 -0
  31. package/dist/canvas/SceneCanvas/SurfaceDeclarations.js.map +1 -0
  32. package/dist/canvas/SceneCanvas/builtinToolSets.js +30 -0
  33. package/dist/canvas/SceneCanvas/builtinToolSets.js.map +1 -0
  34. package/dist/canvas/SceneCanvas/canvasPassThrough.js +2 -0
  35. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
  36. package/dist/canvas/SceneCanvas/coordTrace.js +5 -16
  37. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  38. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +5 -0
  39. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  40. package/dist/canvas/SceneCanvas/features.js +45 -5
  41. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  42. package/dist/canvas/SceneCanvas/props.js +1 -11
  43. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  44. package/dist/canvas/SceneCanvas/scenePointQuery.js +7 -3
  45. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
  46. package/dist/canvas/SceneCanvas/toolRegistry.js +8 -4
  47. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -1
  48. package/dist/canvas/SceneCanvas/useActionTunings.js +6 -1
  49. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -1
  50. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +1 -11
  51. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  52. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  53. package/dist/canvas/SceneCanvas/useBuiltinTools.js +2 -9
  54. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -1
  55. package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js +94 -0
  56. package/dist/canvas/SceneCanvas/useCanvasDevtoolsRoot.js.map +1 -0
  57. package/dist/canvas/SceneCanvas/useCanvasSelection.js +7 -2
  58. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/useCanvasTools.js +15 -10
  60. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  61. package/dist/canvas/SceneCanvas/useNodeKinds.js +1 -1
  62. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -1
  63. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +9 -3
  64. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -1
  65. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +23 -4
  66. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  67. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +2 -3
  68. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
  69. package/dist/canvas/SceneCanvas/useSceneChrome.js +6 -7
  70. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -1
  71. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js +24 -7
  72. package/dist/canvas/SceneCanvas/useSceneGestureDispatcher.js.map +1 -1
  73. package/dist/canvas/SceneCanvas/useScenePicking.js +2 -3
  74. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
  75. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +2 -1
  76. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  77. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -5
  78. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
  79. package/dist/canvas/SceneCanvas.js +27 -24
  80. package/dist/canvas/SceneCanvas.js.map +1 -1
  81. package/dist/canvas/SurfaceCanvas.js +5 -22
  82. package/dist/canvas/SurfaceCanvas.js.map +1 -1
  83. package/dist/canvas/ViewMarker.js +35 -0
  84. package/dist/canvas/ViewMarker.js.map +1 -0
  85. package/dist/canvas/canvasRenderer.js +9 -5
  86. package/dist/canvas/canvasRenderer.js.map +1 -1
  87. package/dist/canvas/contextAttributes.js +14 -0
  88. package/dist/canvas/contextAttributes.js.map +1 -0
  89. package/dist/canvas/defaultDrawOne.js +2 -0
  90. package/dist/canvas/defaultDrawOne.js.map +1 -1
  91. package/dist/canvas/deps/booleans.js +2 -1
  92. package/dist/canvas/deps/booleans.js.map +1 -1
  93. package/dist/canvas/deps/editAnchors.js +9 -113
  94. package/dist/canvas/deps/editAnchors.js.map +1 -1
  95. package/dist/canvas/deps/hitTestArea.js +2 -2
  96. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  97. package/dist/canvas/deps/insert.js +10 -4
  98. package/dist/canvas/deps/insert.js.map +1 -1
  99. package/dist/canvas/deps/pathEditCommits.js +189 -0
  100. package/dist/canvas/deps/pathEditCommits.js.map +1 -0
  101. package/dist/canvas/deps/snap.js +12 -9
  102. package/dist/canvas/deps/snap.js.map +1 -1
  103. package/dist/canvas/deps/transformFollowers.js +20 -0
  104. package/dist/canvas/deps/transformFollowers.js.map +1 -0
  105. package/dist/canvas/derivedPath.js +20 -1
  106. package/dist/canvas/derivedPath.js.map +1 -1
  107. package/dist/canvas/drawnBounds.js +38 -4
  108. package/dist/canvas/drawnBounds.js.map +1 -1
  109. package/dist/canvas/inheritedPaints.js +44 -0
  110. package/dist/canvas/inheritedPaints.js.map +1 -0
  111. package/dist/canvas/nodeShapes/derivedPainter.js +23 -16
  112. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  113. package/dist/canvas/nodeShapes/nodePaint.js +13 -34
  114. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  115. package/dist/canvas/nodeShapes/pathPainter.js +12 -10
  116. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  117. package/dist/canvas/nodeShapes/rectFallbackPainter.js +4 -5
  118. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  119. package/dist/canvas/nodeShapes/shapePainter.js +12 -11
  120. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  121. package/dist/canvas/nodeShapes/textPainter.js +13 -12
  122. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  123. package/dist/canvas/overlayRoleStrokes.js +12 -0
  124. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  125. package/dist/canvas/pathOverlay.js +27 -7
  126. package/dist/canvas/pathOverlay.js.map +1 -1
  127. package/dist/canvas/pickReach.js +3 -3
  128. package/dist/canvas/pickReach.js.map +1 -1
  129. package/dist/canvas/pickWalk.js +3 -1
  130. package/dist/canvas/pickWalk.js.map +1 -1
  131. package/dist/canvas/renderDebugSnapshot.js +1 -0
  132. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  133. package/dist/canvas/renderSceneToPixels.js +7 -6
  134. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  135. package/dist/canvas/sceneAdapter.js.map +1 -1
  136. package/dist/canvas/sceneSlotWiring.js +2 -1
  137. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  138. package/dist/canvas/sceneViewRender.js +2 -1
  139. package/dist/canvas/sceneViewRender.js.map +1 -1
  140. package/dist/canvas/surfaceContribution.js +12 -8
  141. package/dist/canvas/surfaceContribution.js.map +1 -1
  142. package/dist/canvas/useCanvasPaint.js +2 -1
  143. package/dist/canvas/useCanvasPaint.js.map +1 -1
  144. package/dist/canvas/useCanvasView.js +4 -2
  145. package/dist/canvas/useCanvasView.js.map +1 -1
  146. package/dist/canvas/useInFlightBounds.js +52 -0
  147. package/dist/canvas/useInFlightBounds.js.map +1 -0
  148. package/dist/canvas/useLayerStack.js +6 -2
  149. package/dist/canvas/useLayerStack.js.map +1 -1
  150. package/dist/canvas/useViewAim.js +121 -0
  151. package/dist/canvas/useViewAim.js.map +1 -0
  152. package/dist/canvas/useViewHelpers.js +7 -9
  153. package/dist/canvas/useViewHelpers.js.map +1 -1
  154. package/dist/canvas/useViewNesting.js +3 -2
  155. package/dist/canvas/useViewNesting.js.map +1 -1
  156. package/dist/canvas/useViewRegistrySurface.js +4 -2
  157. package/dist/canvas/useViewRegistrySurface.js.map +1 -1
  158. package/dist/canvas/viewMarkers.js +63 -0
  159. package/dist/canvas/viewMarkers.js.map +1 -0
  160. package/dist/canvas/viewRegistry.js +27 -1
  161. package/dist/canvas/viewRegistry.js.map +1 -1
  162. package/dist/clipboard.d.ts +3 -2
  163. package/dist/{clone-DZDrfIlU.d.ts → clone-C3e0OTuF.d.ts} +8 -21
  164. package/dist/clone.d.ts +4 -3
  165. package/dist/core/geometry/autoPoseDescriptor.js +1 -1
  166. package/dist/core/ops/setDependsOn.js +37 -0
  167. package/dist/core/ops/setDependsOn.js.map +1 -0
  168. package/dist/core/ops/writtenBy.js +53 -0
  169. package/dist/core/ops/writtenBy.js.map +1 -0
  170. package/dist/core/pages/fitViewToPage.js +12 -1
  171. package/dist/core/pages/fitViewToPage.js.map +1 -1
  172. package/dist/core/pages/pageEdits.js +163 -0
  173. package/dist/core/pages/pageEdits.js.map +1 -0
  174. package/dist/core/pages/pages.js +30 -1
  175. package/dist/core/pages/pages.js.map +1 -1
  176. package/dist/core/paint/meshKindLazy.js +59 -2
  177. package/dist/core/paint/meshKindLazy.js.map +1 -1
  178. package/dist/core/scene/NodeRouting.js +8 -3
  179. package/dist/core/scene/NodeRouting.js.map +1 -1
  180. package/dist/core/scene/arrivalWindow.js.map +1 -1
  181. package/dist/core/scene/carryDescendants.js +51 -0
  182. package/dist/core/scene/carryDescendants.js.map +1 -0
  183. package/dist/core/scene/clipNothing.js +13 -0
  184. package/dist/core/scene/clipNothing.js.map +1 -0
  185. package/dist/core/scene/depMemo.js +11 -3
  186. package/dist/core/scene/depMemo.js.map +1 -1
  187. package/dist/core/scene/dependents.js +7 -1
  188. package/dist/core/scene/dependents.js.map +1 -1
  189. package/dist/core/scene/derivedParts.js +10 -11
  190. package/dist/core/scene/derivedParts.js.map +1 -1
  191. package/dist/core/scene/docValues.js +57 -0
  192. package/dist/core/scene/docValues.js.map +1 -0
  193. package/dist/core/scene/editPass.js +111 -0
  194. package/dist/core/scene/editPass.js.map +1 -0
  195. package/dist/core/scene/effectivePose.js +13 -2
  196. package/dist/core/scene/effectivePose.js.map +1 -1
  197. package/dist/core/scene/fieldEdits.js +4 -1
  198. package/dist/core/scene/fieldEdits.js.map +1 -1
  199. package/dist/core/scene/fontReads.js +37 -0
  200. package/dist/core/scene/fontReads.js.map +1 -0
  201. package/dist/core/scene/historyFacade.js +1 -0
  202. package/dist/core/scene/historyFacade.js.map +1 -1
  203. package/dist/core/scene/inheritedPaint.js +75 -0
  204. package/dist/core/scene/inheritedPaint.js.map +1 -0
  205. package/dist/core/scene/kitRegistry.js +5 -0
  206. package/dist/core/scene/kitRegistry.js.map +1 -1
  207. package/dist/core/scene/layoutPass.js +28 -3
  208. package/dist/core/scene/layoutPass.js.map +1 -1
  209. package/dist/core/scene/nodeMemo.js +15 -7
  210. package/dist/core/scene/nodeMemo.js.map +1 -1
  211. package/dist/core/scene/pathEffects/blend.js.map +1 -1
  212. package/dist/core/scene/pathEffects/derive.js +7 -2
  213. package/dist/core/scene/pathEffects/derive.js.map +1 -1
  214. package/dist/core/scene/pathEffects/effects.js +3 -1
  215. package/dist/core/scene/pathEffects/effects.js.map +1 -1
  216. package/dist/core/scene/pathEffects/textAlong.js +95 -0
  217. package/dist/core/scene/pathEffects/textAlong.js.map +1 -0
  218. package/dist/core/scene/recorder.js +28 -19
  219. package/dist/core/scene/recorder.js.map +1 -1
  220. package/dist/core/scene/scene.js +15 -9
  221. package/dist/core/scene/scene.js.map +1 -1
  222. package/dist/core/scene/sceneChanges.js +13 -0
  223. package/dist/core/scene/sceneChanges.js.map +1 -0
  224. package/dist/core/scene/sceneEdits.js +8 -1
  225. package/dist/core/scene/sceneEdits.js.map +1 -1
  226. package/dist/core/scene/sceneMutators.js +1 -0
  227. package/dist/core/scene/sceneMutators.js.map +1 -1
  228. package/dist/core/scene/sceneRecording.js +20 -3
  229. package/dist/core/scene/sceneRecording.js.map +1 -1
  230. package/dist/core/scene/sceneSelection.js +4 -1
  231. package/dist/core/scene/sceneSelection.js.map +1 -1
  232. package/dist/core/scene/sceneState.js +11 -5
  233. package/dist/core/scene/sceneState.js.map +1 -1
  234. package/dist/core/scene/serialization.js +5 -3
  235. package/dist/core/scene/serialization.js.map +1 -1
  236. package/dist/core/scene/types.js.map +1 -1
  237. package/dist/core/scene/unitScopes.js +19 -1
  238. package/dist/core/scene/unitScopes.js.map +1 -1
  239. package/dist/core/selection/usePublishSceneSelection.js +6 -12
  240. package/dist/core/selection/usePublishSceneSelection.js.map +1 -1
  241. package/dist/core/shapeKinds.js +25 -11
  242. package/dist/core/shapeKinds.js.map +1 -1
  243. package/dist/{cornerHandles-Camw_yeu.d.ts → cornerHandles-p8fDIAKt.d.ts} +3 -2
  244. package/dist/debug/createDebugOverlayLayer.js +16 -111
  245. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  246. package/dist/debug/createDebugSink.js +2 -1
  247. package/dist/debug/createDebugSink.js.map +1 -1
  248. package/dist/debug/defaultTheme.js +4 -2
  249. package/dist/debug/defaultTheme.js.map +1 -1
  250. package/dist/debug/features.js +17 -0
  251. package/dist/debug/features.js.map +1 -0
  252. package/dist/debug/overlayPanels.js +117 -0
  253. package/dist/debug/overlayPanels.js.map +1 -0
  254. package/dist/debug/parseDebugFlags.js +4 -13
  255. package/dist/debug/parseDebugFlags.js.map +1 -1
  256. package/dist/{depSchema-Cgfu_G9s.d.ts → depSchema-mG19aEdD.d.ts} +174 -904
  257. package/dist/devtools/handlers.js +112 -0
  258. package/dist/devtools/handlers.js.map +1 -0
  259. package/dist/devtools/history.js +71 -0
  260. package/dist/devtools/history.js.map +1 -0
  261. package/dist/devtools/hook.js +74 -0
  262. package/dist/devtools/hook.js.map +1 -0
  263. package/dist/devtools/label.js +25 -0
  264. package/dist/devtools/label.js.map +1 -0
  265. package/dist/devtools/notices.js +58 -0
  266. package/dist/devtools/notices.js.map +1 -0
  267. package/dist/devtools/protocol.js +7 -0
  268. package/dist/devtools/protocol.js.map +1 -0
  269. package/dist/devtools/registry.js +90 -0
  270. package/dist/devtools/registry.js.map +1 -0
  271. package/dist/devtools/root.js +80 -0
  272. package/dist/devtools/root.js.map +1 -0
  273. package/dist/devtools/serialize.js +86 -0
  274. package/dist/devtools/serialize.js.map +1 -0
  275. package/dist/devtools/session.js +111 -0
  276. package/dist/devtools/session.js.map +1 -0
  277. package/dist/devtools/transport.js +67 -0
  278. package/dist/devtools/transport.js.map +1 -0
  279. package/dist/devtools/useDevtoolsRoot.js +81 -0
  280. package/dist/devtools/useDevtoolsRoot.js.map +1 -0
  281. package/dist/devtools-protocol.d.ts +435 -0
  282. package/dist/devtools-protocol.js +7 -0
  283. package/dist/devtools.d.ts +8 -0
  284. package/dist/devtools.js +12 -0
  285. package/dist/devtools.js.map +1 -0
  286. package/dist/features/chrome-caps/useHoverTracking.js +16 -10
  287. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  288. package/dist/features/ingestion/contentHandlers.js +25 -2
  289. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  290. package/dist/features/measure/measureCommands.js +7 -5
  291. package/dist/features/measure/measureCommands.js.map +1 -1
  292. package/dist/features/measure/measureContribution.js +4 -2
  293. package/dist/features/measure/measureContribution.js.map +1 -1
  294. package/dist/features/modes/modeTriggers.js +7 -3
  295. package/dist/features/modes/modeTriggers.js.map +1 -1
  296. package/dist/features/pathEffects/effectSources.js +60 -0
  297. package/dist/features/pathEffects/effectSources.js.map +1 -0
  298. package/dist/features/pathEffects/readSource.js +17 -1
  299. package/dist/features/pathEffects/readSource.js.map +1 -1
  300. package/dist/features/pathEffects/textItems.js +53 -0
  301. package/dist/features/pathEffects/textItems.js.map +1 -0
  302. package/dist/features/pathEffects/useEffectSourcesLayer.js +57 -0
  303. package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -0
  304. package/dist/features/paths/index.js +2 -2
  305. package/dist/features/paths/pathEditExtension.js.map +1 -1
  306. package/dist/features/paths/pathEditState.js +5 -2
  307. package/dist/features/paths/pathEditState.js.map +1 -1
  308. package/dist/features/paths/pathSnap/pathSnapSource.js +5 -5
  309. package/dist/features/paths/pathSnap/pathSnapSource.js.map +1 -1
  310. package/dist/features/paths/pathSnap/sceneIndex.js +10 -3
  311. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
  312. package/dist/features/selection/selectionPose.js +4 -1
  313. package/dist/features/selection/selectionPose.js.map +1 -1
  314. package/dist/features/snap/gather.js +9 -1
  315. package/dist/features/snap/gather.js.map +1 -1
  316. package/dist/features/snap/lazySession.js +17 -0
  317. package/dist/features/snap/lazySession.js.map +1 -0
  318. package/dist/features/snap/marks.js.map +1 -1
  319. package/dist/features/snap/probes2d.js +27 -19
  320. package/dist/features/snap/probes2d.js.map +1 -1
  321. package/dist/features/snap/readoutLayer.js.map +1 -1
  322. package/dist/features/snap/roles.js +2 -1
  323. package/dist/features/snap/roles.js.map +1 -1
  324. package/dist/features/snap/rotationSource.js +25 -8
  325. package/dist/features/snap/rotationSource.js.map +1 -1
  326. package/dist/features/snap/sceneSession2d.js +6 -4
  327. package/dist/features/snap/sceneSession2d.js.map +1 -1
  328. package/dist/features/snap/session2d.js +37 -23
  329. package/dist/features/snap/session2d.js.map +1 -1
  330. package/dist/features/snap/spanSnap.js +5 -2
  331. package/dist/features/snap/spanSnap.js.map +1 -1
  332. package/dist/features/text/sceneTextDrafts.js +65 -0
  333. package/dist/features/text/sceneTextDrafts.js.map +1 -0
  334. package/dist/features/text/textHitAt.js +31 -2
  335. package/dist/features/text/textHitAt.js.map +1 -1
  336. package/dist/features/text/useSceneTextEdit.js +22 -18
  337. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  338. package/dist/features/viewports/aim.js +105 -0
  339. package/dist/features/viewports/aim.js.map +1 -0
  340. package/dist/features/viewports/viewMarker.js +82 -0
  341. package/dist/features/viewports/viewMarker.js.map +1 -0
  342. package/dist/features/viewports/viewMarkerDrag.js +55 -0
  343. package/dist/features/viewports/viewMarkerDrag.js.map +1 -0
  344. package/dist/icons.table.js +1 -1
  345. package/dist/icons.table.js.map +1 -1
  346. package/dist/icons.table.json +0 -10
  347. package/dist/index.d.ts +1198 -894
  348. package/dist/index.js +55 -38
  349. package/dist/interactions/actions/align/action.js +6 -4
  350. package/dist/interactions/actions/align/action.js.map +1 -1
  351. package/dist/interactions/actions/align/align.js.map +1 -1
  352. package/dist/interactions/actions/booleans/action.js +7 -1
  353. package/dist/interactions/actions/booleans/action.js.map +1 -1
  354. package/dist/interactions/actions/booleans/booleans.js +2 -1
  355. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  356. package/dist/interactions/actions/booleans/operands.js +6 -5
  357. package/dist/interactions/actions/booleans/operands.js.map +1 -1
  358. package/dist/interactions/actions/clipboard/action.js +27 -17
  359. package/dist/interactions/actions/clipboard/action.js.map +1 -1
  360. package/dist/interactions/actions/clone/action.js +1 -1
  361. package/dist/interactions/actions/clone/behaviors.js +4 -4
  362. package/dist/interactions/actions/clone/behaviors.js.map +1 -1
  363. package/dist/interactions/actions/defaults/anchorEditing.js +44 -23
  364. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  365. package/dist/interactions/actions/defaults/anchorJoin.js +12 -6
  366. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -1
  367. package/dist/interactions/actions/defaults/bendSegment.js +8 -5
  368. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -1
  369. package/dist/interactions/actions/defaults/cancelGesture.js +11 -8
  370. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  371. package/dist/interactions/actions/defaults/contextMenu.js +17 -8
  372. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
  373. package/dist/interactions/actions/defaults/createPaintAction.js +2 -2
  374. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  375. package/dist/interactions/actions/defaults/delete.js +64 -41
  376. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  377. package/dist/interactions/actions/defaults/duplicate.js +12 -9
  378. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  379. package/dist/interactions/actions/defaults/enterPathEdit.js +19 -9
  380. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  381. package/dist/interactions/actions/defaults/escape.js +11 -8
  382. package/dist/interactions/actions/defaults/escape.js.map +1 -1
  383. package/dist/interactions/actions/defaults/exitPathEdit.js +7 -4
  384. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -1
  385. package/dist/interactions/actions/defaults/group.js +21 -15
  386. package/dist/interactions/actions/defaults/group.js.map +1 -1
  387. package/dist/interactions/actions/defaults/ingest.js +17 -9
  388. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  389. package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -4
  390. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  391. package/dist/interactions/actions/defaults/nudge.js +21 -40
  392. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  393. package/dist/interactions/actions/defaults/pathEditTools.js +11 -8
  394. package/dist/interactions/actions/defaults/pathEditTools.js.map +1 -1
  395. package/dist/interactions/actions/defaults/pinchZoom.js +7 -4
  396. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  397. package/dist/interactions/actions/defaults/reorder.js +24 -6
  398. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  399. package/dist/interactions/actions/defaults/selectAll.js +8 -5
  400. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  401. package/dist/interactions/actions/defaults/setFill.js +7 -3
  402. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  403. package/dist/interactions/actions/defaults/setFillOpacity.js +1 -1
  404. package/dist/interactions/actions/defaults/setStroke.js +12 -11
  405. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  406. package/dist/interactions/actions/defaults/setStrokeOpacity.js +1 -1
  407. package/dist/interactions/actions/defaults/toolActivate.js +7 -1
  408. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  409. package/dist/interactions/actions/defaults/toolResetToDefault.js +7 -4
  410. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  411. package/dist/interactions/actions/defaults/undoRedo.js +19 -13
  412. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -1
  413. package/dist/interactions/actions/defaults/viewportWheelPan.js +16 -7
  414. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  415. package/dist/interactions/actions/defaults/viewportZoom.js +24 -6
  416. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  417. package/dist/interactions/actions/distribute/action.js +6 -4
  418. package/dist/interactions/actions/distribute/action.js.map +1 -1
  419. package/dist/interactions/actions/drawnBoxes.js +2 -1
  420. package/dist/interactions/actions/drawnBoxes.js.map +1 -1
  421. package/dist/interactions/actions/edit-anchors/action.js +10 -10
  422. package/dist/interactions/actions/edit-anchors/action.js.map +1 -1
  423. package/dist/interactions/actions/edit-anchors/preview.js +41 -8
  424. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -1
  425. package/dist/interactions/actions/flip/action.js +14 -6
  426. package/dist/interactions/actions/flip/action.js.map +1 -1
  427. package/dist/interactions/actions/gestureLifecycle.js +5 -2
  428. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  429. package/dist/interactions/actions/insert/action.js +1 -2
  430. package/dist/interactions/actions/insert/action.js.map +1 -1
  431. package/dist/interactions/actions/insert/commit.js +1 -1
  432. package/dist/interactions/actions/insert/parent.js +11 -0
  433. package/dist/interactions/actions/insert/parent.js.map +1 -0
  434. package/dist/interactions/actions/insert/placeAction.js +7 -2
  435. package/dist/interactions/actions/insert/placeAction.js.map +1 -1
  436. package/dist/interactions/actions/insert/repositionAction.js +2 -1
  437. package/dist/interactions/actions/insert/repositionAction.js.map +1 -1
  438. package/dist/interactions/actions/insert/session.js +5 -1
  439. package/dist/interactions/actions/insert/session.js.map +1 -1
  440. package/dist/interactions/actions/move/action.js +15 -8
  441. package/dist/interactions/actions/move/action.js.map +1 -1
  442. package/dist/interactions/actions/move/behaviors/layoutDrop.js +0 -1
  443. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -1
  444. package/dist/interactions/actions/move/behaviors/snapToContainer.js +1 -1
  445. package/dist/interactions/actions/move/capture.js +1 -1
  446. package/dist/interactions/actions/move/commit/index.js +0 -2
  447. package/dist/interactions/actions/move/commit/index.js.map +1 -1
  448. package/dist/interactions/actions/move/commit/layoutDrop.js +2 -2
  449. package/dist/interactions/actions/move/commit/layoutRelease.js +2 -2
  450. package/dist/interactions/actions/move/commit/reparent.js +11 -5
  451. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  452. package/dist/interactions/actions/move/frame.js +4 -10
  453. package/dist/interactions/actions/move/frame.js.map +1 -1
  454. package/dist/interactions/actions/move/landedDescendants.js +20 -17
  455. package/dist/interactions/actions/move/landedDescendants.js.map +1 -1
  456. package/dist/interactions/actions/move/layout/container.js +2 -1
  457. package/dist/interactions/actions/move/layout/container.js.map +1 -1
  458. package/dist/interactions/actions/move/layout/dragged.js +1 -1
  459. package/dist/interactions/actions/move/layout/dropPass.js +18 -1
  460. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -1
  461. package/dist/interactions/actions/move/layout/exits.js +5 -5
  462. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  463. package/dist/interactions/actions/move/session.js +14 -3
  464. package/dist/interactions/actions/move/session.js.map +1 -1
  465. package/dist/interactions/actions/move/translate.js +8 -37
  466. package/dist/interactions/actions/move/translate.js.map +1 -1
  467. package/dist/interactions/actions/moveNodes.js +87 -0
  468. package/dist/interactions/actions/moveNodes.js.map +1 -0
  469. package/dist/interactions/actions/outlines/createOutlinesAction.js +8 -5
  470. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -1
  471. package/dist/interactions/actions/outlines/outlineStroke.js +5 -3
  472. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -1
  473. package/dist/interactions/actions/pathCommands/cutJoin.js +8 -5
  474. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -1
  475. package/dist/interactions/actions/planeInput.js.map +1 -1
  476. package/dist/interactions/actions/resize/action.js +83 -72
  477. package/dist/interactions/actions/resize/action.js.map +1 -1
  478. package/dist/interactions/actions/resize/commit.js +2 -1
  479. package/dist/interactions/actions/resize/commit.js.map +1 -1
  480. package/dist/interactions/actions/resize/cornerHandles.js +2 -1
  481. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -1
  482. package/dist/interactions/actions/resize/session.js +2 -0
  483. package/dist/interactions/actions/resize/session.js.map +1 -1
  484. package/dist/interactions/actions/resolvePreviews.js +3 -3
  485. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  486. package/dist/interactions/actions/rotate/action.js +7 -4
  487. package/dist/interactions/actions/rotate/action.js.map +1 -1
  488. package/dist/interactions/actions/rotate/commit.js +2 -1
  489. package/dist/interactions/actions/rotate/commit.js.map +1 -1
  490. package/dist/interactions/actions/rotate/session.js +2 -0
  491. package/dist/interactions/actions/rotate/session.js.map +1 -1
  492. package/dist/interactions/actions/selectionSubtree.js +25 -9
  493. package/dist/interactions/actions/selectionSubtree.js.map +1 -1
  494. package/dist/interactions/actions/testUtils.js.map +1 -1
  495. package/dist/interactions/actions/transform-again/action.js +13 -11
  496. package/dist/interactions/actions/transform-again/action.js.map +1 -1
  497. package/dist/interactions/actions/transformFinish.js +106 -0
  498. package/dist/interactions/actions/transformFinish.js.map +1 -0
  499. package/dist/json.d.ts +4 -0
  500. package/dist/json.js +3 -0
  501. package/dist/kitSettingsSchema.js +8 -5
  502. package/dist/kitSettingsSchema.js.map +1 -1
  503. package/dist/{math-CrJULaZI.d.ts → math-B56zxVs5.d.ts} +10 -1
  504. package/dist/math.d.ts +1 -1
  505. package/dist/math.js +2 -1
  506. package/dist/move.d.ts +5 -4
  507. package/dist/{options-p9GZMXbY.d.ts → options-DBxEryYq.d.ts} +1 -1
  508. package/dist/resize.d.ts +4 -3
  509. package/dist/routing.d.ts +1 -1
  510. package/dist/routing.js +2 -2
  511. package/dist/test-hook/createTestHook.js +1 -1
  512. package/dist/test-hook/createTestHook.js.map +1 -1
  513. package/dist/test-hook/useTestHook.js +2 -1
  514. package/dist/test-hook/useTestHook.js.map +1 -1
  515. package/dist/test-seams.d.ts +9 -5
  516. package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
  517. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  518. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +2 -1
  519. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  520. package/dist/tools/builtin/hand/dragPanContribution.js +4 -1
  521. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -1
  522. package/dist/tools/builtin/hand/useHandTool.js +7 -4
  523. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  524. package/dist/tools/builtin/image/useImageTool.js +1 -0
  525. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  526. package/dist/tools/builtin/lasso/useLassoTool.js +1 -0
  527. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  528. package/dist/tools/builtin/line/useLineTool.js +1 -0
  529. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  530. package/dist/tools/builtin/measure/useMeasureTool.js +12 -5
  531. package/dist/tools/builtin/measure/useMeasureTool.js.map +1 -1
  532. package/dist/tools/builtin/pen/penHandle.js +3 -5
  533. package/dist/tools/builtin/pen/penHandle.js.map +1 -1
  534. package/dist/tools/builtin/pen/usePenTool.js +14 -6
  535. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  536. package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
  537. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  538. package/dist/tools/builtin/polygon/usePolygonTool.js +13 -4
  539. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  540. package/dist/tools/builtin/rect/useRectTool.js +1 -0
  541. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  542. package/dist/tools/builtin/select/adapterPointQuery.js +3 -2
  543. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  544. package/dist/tools/builtin/select/pressDecision.js +32 -0
  545. package/dist/tools/builtin/select/pressDecision.js.map +1 -0
  546. package/dist/tools/builtin/select/selectionContributions.js +22 -13
  547. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  548. package/dist/tools/builtin/select/useSelectTool.js +13 -10
  549. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  550. package/dist/tools/builtin/slice/useSliceTool.js +22 -8
  551. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  552. package/dist/tools/builtin/star/useStarTool.js +13 -4
  553. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  554. package/dist/tools/builtin/sticky/stickyNode.js +4 -1
  555. package/dist/tools/builtin/sticky/stickyNode.js.map +1 -1
  556. package/dist/tools/builtin/sticky/useStickyTool.js +10 -5
  557. package/dist/tools/builtin/sticky/useStickyTool.js.map +1 -1
  558. package/dist/tools/builtin/text/useTextTool.js +3 -1
  559. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  560. package/dist/tools/index.js +26 -0
  561. package/dist/{types-CHVXGfYm.d.ts → types-7puAuVD2.d.ts} +3 -262
  562. package/dist/types-BN9hbdMI.d.ts +184 -0
  563. package/dist/types-CniVctmk.d.ts +949 -0
  564. package/dist/types-oFeQ5VjV.d.ts +264 -0
  565. package/dist/util/paint.js +1 -3
  566. package/dist/util/paint.js.map +1 -1
  567. package/dist/version.js +1 -1
  568. package/package.json +39 -25
  569. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js +0 -65
  570. package/dist/canvas/SceneCanvas/useBuiltinRigTools.js.map +0 -1
  571. package/dist/tools/builtin/bone/boneActions.js +0 -156
  572. package/dist/tools/builtin/bone/boneActions.js.map +0 -1
  573. package/dist/tools/builtin/bone/boneOverlay.js +0 -71
  574. package/dist/tools/builtin/bone/boneOverlay.js.map +0 -1
  575. package/dist/tools/builtin/bone/placedRig.js +0 -28
  576. package/dist/tools/builtin/bone/placedRig.js.map +0 -1
  577. package/dist/tools/builtin/bone/rigEditState.js +0 -30
  578. package/dist/tools/builtin/bone/rigEditState.js.map +0 -1
  579. package/dist/tools/builtin/bone/useBoneTool.js +0 -125
  580. package/dist/tools/builtin/bone/useBoneTool.js.map +0 -1
  581. package/dist/tools/builtin/weight/useWeightTool.js +0 -101
  582. package/dist/tools/builtin/weight/useWeightTool.js.map +0 -1
  583. package/dist/tools/builtin/weight/weightActions.js +0 -140
  584. package/dist/tools/builtin/weight/weightActions.js.map +0 -1
  585. package/dist/tools/builtin/weight/weightOverlay.js +0 -78
  586. package/dist/tools/builtin/weight/weightOverlay.js.map +0 -1
@@ -0,0 +1,435 @@
1
+ import { e as DebugFeature, a as DebugConfig } from './types-BN9hbdMI.js';
2
+ import { DispatchTrace, TraceRing } from '@weasel-js/routing';
3
+ import { S as Scene } from './types-CniVctmk.js';
4
+ import '@weasel-js/history';
5
+ import './types-7puAuVD2.js';
6
+ import '@weasel-js/geom';
7
+ import '@weasel-js/quantity';
8
+
9
+ /**
10
+ * Turn any value into plain data a panel can display. A node's `data` is the
11
+ * app's own type, so nothing here assumes it is JSON-safe.
12
+ */
13
+ /** What {@link serialize} produces: JSON-safe apart from `undefined`, which structured clone carries. */
14
+ type SerializedValue = string | number | boolean | null | undefined | SerializedValue[] | {
15
+ [key: string]: SerializedValue;
16
+ };
17
+ /** How much of a value {@link serialize} writes out. */
18
+ interface SerializeLimits {
19
+ /** Nesting below this depth is written as `'…'`. */
20
+ depth?: number;
21
+ /** Array, map, set and object entries past this many are cut, with a note of how many. */
22
+ items?: number;
23
+ /** Strings longer than this are cut. */
24
+ chars?: number;
25
+ }
26
+ /** `value` as plain data: functions as `ƒ name`, typed arrays as their type and
27
+ * length, maps and sets tagged, cycles marked, and every size capped. */
28
+ declare function serialize(value: unknown, limits?: SerializeLimits): SerializedValue;
29
+
30
+ /**
31
+ * The messages a devtools panel and a page running weasel exchange. Plain
32
+ * data only, so the same messages cross a direct call or `window.postMessage`.
33
+ */
34
+
35
+ /** Bumped on any change a panel built against the previous number would misread. */
36
+ declare const DEVTOOLS_PROTOCOL = 1;
37
+ /** The areas of a root a `changed` notice reports. */
38
+ type DevtoolsArea = 'scene' | 'selection' | 'view' | 'tool' | 'trace' | 'registry' | 'history';
39
+ /** One mounted `<SceneCanvas>`. */
40
+ interface DevtoolsRootInfo {
41
+ id: string;
42
+ /** The canvas's `aria-label`, else its DOM id, else its root id. */
43
+ label: string;
44
+ dimension: '2d' | '3d';
45
+ }
46
+ /** Debug overlay features a panel turns on or off over the canvas's own `debug` prop. */
47
+ type DevtoolsOverlays = Partial<Record<DebugFeature, boolean>>;
48
+ /** A request a panel sends about one root. */
49
+ type DevtoolsRequest = {
50
+ protocol: number;
51
+ requestId: number;
52
+ rootId: string;
53
+ } & ({
54
+ type: 'get-children';
55
+ nodeId?: string;
56
+ } | {
57
+ type: 'get-node';
58
+ nodeId: string;
59
+ } | {
60
+ type: 'get-state';
61
+ }
62
+ /** Coord records come back only when `coordCursor` is given. */
63
+ | {
64
+ type: 'get-trace';
65
+ cursor: number;
66
+ coordCursor?: number;
67
+ } | {
68
+ type: 'get-frame';
69
+ } | {
70
+ type: 'get-registry';
71
+ }
72
+ /** The stack's entry labels come back only when `checkpoints` is true. */
73
+ | {
74
+ type: 'get-history';
75
+ cursor: number;
76
+ checkpoints?: boolean;
77
+ } | {
78
+ type: 'select';
79
+ ids: string[];
80
+ } | {
81
+ type: 'highlight';
82
+ ids: string[];
83
+ } | {
84
+ type: 'set-tool';
85
+ toolId: string | null;
86
+ } | {
87
+ type: 'set-overlays';
88
+ overlays: DevtoolsOverlays;
89
+ });
90
+ /** Every message a panel sends the page. */
91
+ type PanelMessage = {
92
+ type: 'yo';
93
+ protocol: number;
94
+ }
95
+ /** The panel is closing: drop its overlays and highlight, and stop tracing for it. */
96
+ | {
97
+ type: 'bye';
98
+ protocol: number;
99
+ } | DevtoolsRequest;
100
+ /** Every message the page sends a panel. */
101
+ type PageMessage = {
102
+ type: 'sup';
103
+ protocol: number;
104
+ kitVersion: string;
105
+ roots: DevtoolsRootInfo[];
106
+ } | {
107
+ type: 'root-added';
108
+ protocol: number;
109
+ root: DevtoolsRootInfo;
110
+ } | {
111
+ type: 'root-removed';
112
+ protocol: number;
113
+ rootId: string;
114
+ }
115
+ /** Each changed area with its new version. At most one per root per frame. */
116
+ | {
117
+ type: 'changed';
118
+ protocol: number;
119
+ rootId: string;
120
+ areas: Partial<Record<DevtoolsArea, number>>;
121
+ } | {
122
+ type: 'result';
123
+ protocol: number;
124
+ requestId: number;
125
+ result: DevtoolsResult;
126
+ }
127
+ /** `requestId` is null for a message that was not a request. */
128
+ | {
129
+ type: 'error';
130
+ protocol: number;
131
+ requestId: number | null;
132
+ message: string;
133
+ };
134
+ /** One child row of the scene tree. `nodeId` absent asks for the top level. */
135
+ interface DevtoolsNodeSummary {
136
+ id: string;
137
+ kind: 'leaf' | 'container';
138
+ layer: string;
139
+ childCount: number;
140
+ hidden: boolean;
141
+ locked: boolean;
142
+ pickable: boolean;
143
+ }
144
+ /** A node as `get-node` returns it: its row in the tree, plus its parent, pose and data. */
145
+ interface DevtoolsNodeDetail extends DevtoolsNodeSummary {
146
+ parent: string | null;
147
+ pose: SerializedValue;
148
+ data: SerializedValue;
149
+ }
150
+ /** What `get-state` returns about a root. */
151
+ interface DevtoolsRootState {
152
+ selection: string[];
153
+ view: SerializedValue;
154
+ activeTool: string | null;
155
+ tools: string[];
156
+ /** The debug overlay features in effect: the canvas's own, with the panel's over them. */
157
+ overlays: DevtoolsOverlays;
158
+ /** Probes registered through the test hook, by name. */
159
+ probes: Record<string, SerializedValue>;
160
+ }
161
+ /** What `get-trace` returns: the records after the cursor, and the cursor to send next. */
162
+ interface DevtoolsTraceSlice {
163
+ entries: SerializedValue[];
164
+ cursor: number;
165
+ /** What a press at the pointer would do, or null when the pointer is off the canvas. */
166
+ live: SerializedValue;
167
+ coords?: {
168
+ entries: SerializedValue[];
169
+ cursor: number;
170
+ };
171
+ }
172
+ /** One gesture-to-action binding, as a tool, an always-on entry or an action declares it. */
173
+ interface DevtoolsBinding {
174
+ actionId: string;
175
+ /** The `GestureSpec` as written. */
176
+ spec: SerializedValue;
177
+ /** The spec in the route grammar, one string per route it expands to. */
178
+ routes: string[];
179
+ /** The binding's `BindingOpts`: params, roles, views. */
180
+ opts: SerializedValue;
181
+ }
182
+ /** A tool or other contribution the canvas's dispatcher assembles bindings from. */
183
+ interface DevtoolsToolEntry {
184
+ id: string;
185
+ /** A switchable tool, an always-on entry, or one a `features` preset brought. */
186
+ slot: 'tool' | 'ambient' | 'contribution';
187
+ label: string;
188
+ /** The icon's qualified name. */
189
+ icon: string | null;
190
+ group: string | null;
191
+ shortcut: string | null;
192
+ /** The key that holds it engaged while pressed. */
193
+ hotkey: string | null;
194
+ hidden: boolean;
195
+ cursor: SerializedValue;
196
+ eligibility: SerializedValue;
197
+ bindings: DevtoolsBinding[];
198
+ /** Ids of the actions it brings with it. */
199
+ actions: string[];
200
+ /** Names of the deps it registers. */
201
+ deps: string[];
202
+ hasOverlay: boolean;
203
+ }
204
+ /** A registered action. `enabled` and `active` are asked when the registry is read. */
205
+ interface DevtoolsActionEntry {
206
+ id: string;
207
+ label: string;
208
+ icon: string | null;
209
+ group: string | null;
210
+ tags: string[];
211
+ shortcut: string | null;
212
+ /** Which binding scope its own bindings ride. */
213
+ scope: 'hotkey' | 'ambient';
214
+ invoker: 'immediate' | 'ongoing' | null;
215
+ requires: string[];
216
+ variants: {
217
+ key: string;
218
+ label: string;
219
+ icon: string | null;
220
+ params: SerializedValue;
221
+ }[];
222
+ /** `true`, or the reason it is disabled. */
223
+ enabled: true | string;
224
+ /** Null for an action with no pressed state. */
225
+ active: boolean | null;
226
+ hasPreview: boolean;
227
+ /** The eligibility rule, or null for always eligible. */
228
+ eligible: SerializedValue;
229
+ bindings: DevtoolsBinding[];
230
+ }
231
+ /** A dep name the canvas's registry answers. */
232
+ interface DevtoolsDepEntry {
233
+ name: string;
234
+ /** How many scopes above the canvas's own its live source sits: 0 for the canvas's. */
235
+ depth: number;
236
+ /** How many sources are stacked under the name there, the live one included. */
237
+ stacked: number;
238
+ }
239
+ /** What `get-registry` returns: what one canvas has registered. */
240
+ interface DevtoolsRegistry {
241
+ tools: DevtoolsToolEntry[];
242
+ actions: DevtoolsActionEntry[];
243
+ deps: DevtoolsDepEntry[];
244
+ /** The node routing kinds a binding's `kind:` target can name, in classify order. */
245
+ routingKinds: string[];
246
+ }
247
+ /** One op of a recorded history step. */
248
+ interface DevtoolsHistoryOp {
249
+ /** The op's registered name, `'kit:setPose'` and the like; `'?'` for an op with none. */
250
+ kind: string;
251
+ /** The node ids its args address. */
252
+ targets: string[];
253
+ summary: SerializedValue;
254
+ }
255
+ /** One change to a scene's history: an edit recorded, merged, undone, redone or jumped across. */
256
+ interface DevtoolsHistoryRecord {
257
+ ts: number;
258
+ step: 'push' | 'coalesce' | 'undo' | 'redo' | 'goto' | 'branch' | 'prune' | 'clear' | 'restore';
259
+ /** The entries the step pushed, merged into or walked across, in the order it touched them. */
260
+ entries: {
261
+ id: number;
262
+ label: string;
263
+ opCount: number;
264
+ ops: DevtoolsHistoryOp[];
265
+ }[];
266
+ /** Where the history stood after the step: entries applied, and entries in all. */
267
+ position: {
268
+ index: number;
269
+ total: number;
270
+ };
271
+ }
272
+ /** What `get-history` returns: the steps after the cursor, the cursor to send next, and where the history stands. */
273
+ interface DevtoolsHistorySlice {
274
+ entries: DevtoolsHistoryRecord[];
275
+ cursor: number;
276
+ position: {
277
+ index: number;
278
+ total: number;
279
+ canUndo: boolean;
280
+ canRedo: boolean;
281
+ };
282
+ /** Every entry on the stacks, oldest applied first, then the redoable ones. */
283
+ checkpoints?: {
284
+ id: string;
285
+ label: string;
286
+ }[];
287
+ }
288
+ /** The body of a `result` reply; which one depends on the request it answers. */
289
+ type DevtoolsResult = DevtoolsNodeSummary[] | DevtoolsNodeDetail | DevtoolsRootState | DevtoolsTraceSlice | DevtoolsRegistry | DevtoolsHistorySlice | SerializedValue | null;
290
+
291
+ /** One `clientToWorld` call, so a cursor position can be reconciled with the
292
+ * world point it became. A canvas keeps these beside its dispatch trace, and
293
+ * the devtools hook's `get-trace` reads them. */
294
+ interface CoordTraceEntry {
295
+ ts: number;
296
+ clientX: number;
297
+ clientY: number;
298
+ rect: {
299
+ left: number;
300
+ top: number;
301
+ width: number;
302
+ height: number;
303
+ } | null;
304
+ view: {
305
+ x: number;
306
+ y: number;
307
+ scaleX: number;
308
+ scaleY: number;
309
+ } | null;
310
+ world: {
311
+ x: number;
312
+ y: number;
313
+ };
314
+ /** True when canvas/view weren't available and we returned identity. */
315
+ fallback: boolean;
316
+ }
317
+
318
+ /**
319
+ * A root: what one mounted `<SceneCanvas>` exposes to the devtools hook and to
320
+ * the test hook. The canvas supplies live getters; the root adds change
321
+ * versions and the probe registry.
322
+ */
323
+
324
+ /** What a canvas hands {@link createDevtoolsRoot}. Every getter reads the latest committed value. */
325
+ interface DevtoolsRootSource {
326
+ label(): string;
327
+ readonly dimension: '2d' | '3d';
328
+ scene(): Scene<unknown, string, unknown> | null;
329
+ selection(): readonly string[];
330
+ select(ids: readonly string[]): void;
331
+ view(): unknown;
332
+ activeTool(): string | null;
333
+ tools(): readonly string[];
334
+ setTool(id: string | null): void;
335
+ trace: DispatchTrace;
336
+ coords: TraceRing<CoordTraceEntry>;
337
+ /** The debug sink's stats for the last paint, or null while the frame panel is off. */
338
+ frame(): unknown;
339
+ /** The debug overlay config in effect, or null when the overlay is off. */
340
+ overlays(): DebugConfig | null;
341
+ /** Lay the panel's overlay flags and highlight over the canvas's own `debug`; null drops them. */
342
+ setOverride(override: {
343
+ overlays: DevtoolsOverlays;
344
+ highlight: readonly string[];
345
+ } | null): void;
346
+ /** What the canvas has registered, described when asked. Absent, `get-registry` is refused. */
347
+ registry?(): DevtoolsRegistry;
348
+ /** Hear that what {@link DevtoolsRootSource.registry} describes may have changed. Returns the unsubscribe. */
349
+ subscribeRegistry?(listener: () => void): () => void;
350
+ /** The scene's history steps. Absent, `get-history` is refused. */
351
+ history?: TraceRing<DevtoolsHistoryRecord>;
352
+ }
353
+ /** One canvas as the devtools hook holds it. */
354
+ interface DevtoolsRoot {
355
+ readonly id: string;
356
+ readonly source: DevtoolsRootSource;
357
+ info(): DevtoolsRootInfo;
358
+ /** Name-keyed probes; the test hook's `registerProbe` writes here. */
359
+ readonly probes: Map<string, () => unknown>;
360
+ version(area: DevtoolsArea): number;
361
+ /** Say that `area` changed. The scene and the trace say so themselves while anything listens. */
362
+ notify(area: DevtoolsArea): void;
363
+ /** Hear each change, with the area. Returns the unsubscribe. */
364
+ subscribe(listener: (area: DevtoolsArea) => void): () => void;
365
+ }
366
+ /** A root over `source`, with a fresh page-unique id. */
367
+ declare function createDevtoolsRoot(source: DevtoolsRootSource): DevtoolsRoot;
368
+
369
+ /** A session's change notices: the roots it follows, and what changed in each since the last flush. */
370
+
371
+ /** Run `flush` once, soon. The hook's default waits for the next animation frame. */
372
+ type DevtoolsSchedule = (flush: () => void) => void;
373
+
374
+ /**
375
+ * How devtools messages travel. A transport sends one side's messages and
376
+ * hears the other side's; the session neither knows nor cares which kind it has.
377
+ */
378
+
379
+ /** One end of a connection: it sends `Out` and hears `In`. */
380
+ interface DevtoolsTransport<Out, In> {
381
+ send(message: Out): void;
382
+ /** Hear the other side. Returns the unsubscribe. */
383
+ onMessage(listener: (message: In) => void): () => void;
384
+ }
385
+ /** The page's end of a connection. */
386
+ type PageTransport = DevtoolsTransport<PageMessage, PanelMessage>;
387
+ /** The panel's end of a connection. */
388
+ type PanelTransport = DevtoolsTransport<PanelMessage, PageMessage>;
389
+ /** Marks devtools traffic among whatever else a page posts to its window. */
390
+ declare const DEVTOOLS_ENVELOPE = "weasel-devtools";
391
+ /** A devtools message as posted to a window. */
392
+ interface DevtoolsEnvelope {
393
+ source: typeof DEVTOOLS_ENVELOPE;
394
+ side: 'page' | 'panel';
395
+ message: PageMessage | PanelMessage;
396
+ }
397
+ /** Whether a posted message's `data` is devtools traffic. */
398
+ declare function isDevtoolsEnvelope(data: unknown): data is DevtoolsEnvelope;
399
+ /** Both ends of a connection within one page: delivery is a direct, synchronous call. */
400
+ declare function createInPageTransports(): {
401
+ page: PageTransport;
402
+ panel: PanelTransport;
403
+ };
404
+ /** The page's end over `window.postMessage`, for an extension's content script. */
405
+ declare function createWindowPageTransport(target?: Window): PageTransport;
406
+ /** The panel's end over `window.postMessage`: what a content script uses to reach the page. */
407
+ declare function createWindowPanelTransport(target?: Window): PanelTransport;
408
+
409
+ /** What `window.__weaselDevtools__` holds: the page's canvases, and the way a panel connects to them. */
410
+ interface WeaselDevtoolsHook {
411
+ readonly protocol: number;
412
+ readonly kitVersion: string;
413
+ roots(): DevtoolsRootInfo[];
414
+ /** The root registered under `id`, for in-page readers such as the test hook. */
415
+ root(id: string): DevtoolsRoot | undefined;
416
+ /** Add a canvas's root. Returns its removal. */
417
+ register(root: DevtoolsRoot): () => void;
418
+ /** Serve a panel over `transport` until the panel says `bye` or the returned close is called.
419
+ * `opening` is a message that arrived before the transport was listened to — the `yo` that
420
+ * prompted the connection. */
421
+ connect(transport: PageTransport, opening?: PanelMessage): () => void;
422
+ }
423
+ declare global {
424
+ interface Window {
425
+ __weaselDevtools__?: WeaselDevtoolsHook;
426
+ }
427
+ }
428
+ /** A hook not published anywhere: what {@link installDevtoolsHook} publishes, and what tests build. */
429
+ declare function createDevtoolsHook(opts?: {
430
+ schedule?: DevtoolsSchedule;
431
+ }): WeaselDevtoolsHook;
432
+ /** Publish the hook on `window.__weaselDevtools__`, once; later calls return the same hook. */
433
+ declare function installDevtoolsHook(): WeaselDevtoolsHook | null;
434
+
435
+ export { DEVTOOLS_ENVELOPE, DEVTOOLS_PROTOCOL, type DevtoolsActionEntry, type DevtoolsArea, type DevtoolsBinding, type DevtoolsDepEntry, type DevtoolsEnvelope, type DevtoolsHistoryOp, type DevtoolsHistoryRecord, type DevtoolsHistorySlice, type DevtoolsNodeDetail, type DevtoolsNodeSummary, type DevtoolsOverlays, type DevtoolsRegistry, type DevtoolsRequest, type DevtoolsResult, type DevtoolsRoot, type DevtoolsRootInfo, type DevtoolsRootSource, type DevtoolsRootState, type DevtoolsSchedule, type DevtoolsToolEntry, type DevtoolsTraceSlice, type DevtoolsTransport, type PageMessage, type PageTransport, type PanelMessage, type PanelTransport, type SerializeLimits, type SerializedValue, type WeaselDevtoolsHook, createDevtoolsHook, createDevtoolsRoot, createInPageTransports, createWindowPageTransport, createWindowPanelTransport, installDevtoolsHook, isDevtoolsEnvelope, serialize };
@@ -0,0 +1,7 @@
1
+ import { serialize } from "./devtools/serialize.js";
2
+ import { DEVTOOLS_PROTOCOL } from "./devtools/protocol.js";
3
+ import { DEVTOOLS_ENVELOPE, createInPageTransports, createWindowPageTransport, createWindowPanelTransport, isDevtoolsEnvelope } from "./devtools/transport.js";
4
+ import { createDevtoolsHook, installDevtoolsHook } from "./devtools/hook.js";
5
+ import { createDevtoolsRoot } from "./devtools/root.js";
6
+
7
+ export { DEVTOOLS_ENVELOPE, DEVTOOLS_PROTOCOL, createDevtoolsHook, createDevtoolsRoot, createInPageTransports, createWindowPageTransport, createWindowPanelTransport, installDevtoolsHook, isDevtoolsEnvelope, serialize };
@@ -0,0 +1,8 @@
1
+ export { DEVTOOLS_ENVELOPE, DEVTOOLS_PROTOCOL, DevtoolsActionEntry, DevtoolsArea, DevtoolsBinding, DevtoolsDepEntry, DevtoolsEnvelope, DevtoolsHistoryOp, DevtoolsHistoryRecord, DevtoolsHistorySlice, DevtoolsNodeDetail, DevtoolsNodeSummary, DevtoolsOverlays, DevtoolsRegistry, DevtoolsRequest, DevtoolsResult, DevtoolsRoot, DevtoolsRootInfo, DevtoolsRootSource, DevtoolsRootState, DevtoolsSchedule, DevtoolsToolEntry, DevtoolsTraceSlice, DevtoolsTransport, PageMessage, PageTransport, PanelMessage, PanelTransport, SerializeLimits, SerializedValue, WeaselDevtoolsHook, createDevtoolsHook, createDevtoolsRoot, createInPageTransports, createWindowPageTransport, createWindowPanelTransport, installDevtoolsHook, isDevtoolsEnvelope, serialize } from './devtools-protocol.js';
2
+ import './types-BN9hbdMI.js';
3
+ import '@weasel-js/routing';
4
+ import './types-CniVctmk.js';
5
+ import '@weasel-js/history';
6
+ import './types-7puAuVD2.js';
7
+ import '@weasel-js/geom';
8
+ import '@weasel-js/quantity';
@@ -0,0 +1,12 @@
1
+ import { serialize } from "./devtools/serialize.js";
2
+ import { DEVTOOLS_PROTOCOL } from "./devtools/protocol.js";
3
+ import { DEVTOOLS_ENVELOPE, createInPageTransports, createWindowPageTransport, createWindowPanelTransport, isDevtoolsEnvelope } from "./devtools/transport.js";
4
+ import { createDevtoolsHook, installDevtoolsHook } from "./devtools/hook.js";
5
+ import { createDevtoolsRoot } from "./devtools/root.js";
6
+
7
+ //#region src/import-shims/devtools.ts
8
+ installDevtoolsHook();
9
+
10
+ //#endregion
11
+ export { DEVTOOLS_ENVELOPE, DEVTOOLS_PROTOCOL, createDevtoolsHook, createDevtoolsRoot, createInPageTransports, createWindowPageTransport, createWindowPanelTransport, installDevtoolsHook, isDevtoolsEnvelope, serialize };
12
+ //# sourceMappingURL=devtools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools.js","names":[],"sources":["../src/import-shims/devtools.ts"],"sourcesContent":["// `@weasel-js/core/devtools` — importing it publishes the devtools hook on\n// `window.__weaselDevtools__`. A dev build does that by itself; a production\n// build does it only for an app that imports this. Its exports are\n// `@weasel-js/core/devtools-protocol`'s, which installs nothing.\nimport { installDevtoolsHook } from '../devtools/hook';\n\ninstallDevtoolsHook();\n\nexport * from './devtools-protocol';\n"],"mappings":";;;;;;;AAMA,oBAAoB"}
@@ -10,37 +10,43 @@ function useHoverTracking(args) {
10
10
  const { nodeAtClientPoint, enabled = true } = args;
11
11
  const hoverRef = useRef(null);
12
12
  const nodeAtRef = useLatest(nodeAtClientPoint);
13
+ const onChangeRef = useLatest(args.onChange);
13
14
  const elementRef = useRef(null);
14
15
  const enabledRef = useRef(enabled);
15
16
  const detachRef = useRef(null);
17
+ const hover = useCallback((id) => {
18
+ if (hoverRef.current === id) return;
19
+ hoverRef.current = id;
20
+ onChangeRef.current?.(id);
21
+ }, [onChangeRef]);
16
22
  const sync = useCallback(() => {
17
23
  detachRef.current?.();
18
24
  detachRef.current = null;
19
- hoverRef.current = null;
25
+ hover(null);
20
26
  const el = elementRef.current;
21
27
  if (!el || !enabledRef.current) return;
22
- const onMove = (e) => {
23
- hoverRef.current = nodeAtRef.current(e.clientX, e.clientY)?.id ?? null;
24
- };
25
- const onLeave = () => {
26
- hoverRef.current = null;
27
- };
28
+ const onMove = (e) => hover(nodeAtRef.current(e.clientX, e.clientY)?.id ?? null);
29
+ const onLeave = () => hover(null);
28
30
  el.addEventListener("pointermove", onMove);
29
31
  el.addEventListener("pointerleave", onLeave);
30
32
  detachRef.current = () => {
31
33
  el.removeEventListener("pointermove", onMove);
32
34
  el.removeEventListener("pointerleave", onLeave);
33
35
  };
34
- }, [nodeAtRef]);
36
+ }, [nodeAtRef, hover]);
35
37
  useEffect(() => {
36
38
  enabledRef.current = enabled;
37
39
  sync();
38
40
  return () => {
39
41
  detachRef.current?.();
40
42
  detachRef.current = null;
41
- hoverRef.current = null;
43
+ hover(null);
42
44
  };
43
- }, [enabled, sync]);
45
+ }, [
46
+ enabled,
47
+ sync,
48
+ hover
49
+ ]);
44
50
  const canvasRef = useCallback((element) => {
45
51
  if (elementRef.current === element) return;
46
52
  elementRef.current = element;
@@ -1 +1 @@
1
- {"version":3,"file":"useHoverTracking.js","names":[],"sources":["../../../src/features/chrome-caps/useHoverTracking.ts"],"sourcesContent":["/** Last-hovered NodeId for chrome-caps rules. */\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { NodeId } from '../../core/scene/types';\n\n/** Options for `useHoverTracking`. */\nexport interface UseHoverTrackingArgs {\n /** Topmost id under a client point, or null. */\n nodeAtClientPoint: (clientX: number, clientY: number) => { id: NodeId } | null;\n enabled?: boolean;\n}\n\n/** What `useHoverTracking` returns. Both members keep their identity. */\nexport interface HoverTracking {\n /** The node the pointer is over, or null. */\n getHover: () => NodeId | null;\n /** Hand it the element to track, or null to stop: a callback ref, so an\n * element that mounts after the hook is tracked from the moment it arrives. */\n canvasRef: (element: HTMLElement | null) => void;\n}\n\n/** Track which node the pointer is over. Returns a getter rather than state,\n * so a pointer move does not re-render the component. Cleared on\n * `pointerleave`. */\nexport function useHoverTracking(args: UseHoverTrackingArgs): HoverTracking {\n const { nodeAtClientPoint, enabled = true } = args;\n const hoverRef = useRef<NodeId | null>(null);\n const nodeAtRef = useLatest(nodeAtClientPoint);\n const elementRef = useRef<HTMLElement | null>(null);\n const enabledRef = useRef(enabled);\n const detachRef = useRef<(() => void) | null>(null);\n\n const sync = useCallback(() => {\n detachRef.current?.();\n detachRef.current = null;\n hoverRef.current = null;\n const el = elementRef.current;\n if (!el || !enabledRef.current) return;\n const onMove = (e: PointerEvent) => {\n hoverRef.current = nodeAtRef.current(e.clientX, e.clientY)?.id ?? null;\n };\n const onLeave = () => { hoverRef.current = null; };\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerleave', onLeave);\n detachRef.current = () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerleave', onLeave);\n };\n }, [nodeAtRef]);\n\n useEffect(() => {\n enabledRef.current = enabled;\n sync();\n return () => {\n detachRef.current?.();\n detachRef.current = null;\n hoverRef.current = null;\n };\n }, [enabled, sync]);\n\n const canvasRef = useCallback((element: HTMLElement | null) => {\n if (elementRef.current === element) return;\n elementRef.current = element;\n sync();\n }, [sync]);\n const getHover = useCallback(() => hoverRef.current, []);\n\n return useMemo(() => ({ getHover, canvasRef }), [getHover, canvasRef]);\n}\n"],"mappings":";;;;;;;;AAyBA,SAAgB,iBAAiB,MAA2C;CAC1E,MAAM,EAAE,mBAAmB,UAAU,SAAS;CAC9C,MAAM,WAAW,OAAsB,IAAI;CAC3C,MAAM,YAAY,UAAU,iBAAiB;CAC7C,MAAM,aAAa,OAA2B,IAAI;CAClD,MAAM,aAAa,OAAO,OAAO;CACjC,MAAM,YAAY,OAA4B,IAAI;CAElD,MAAM,OAAO,kBAAkB;EAC7B,UAAU,UAAU;EACpB,UAAU,UAAU;EACpB,SAAS,UAAU;EACnB,MAAM,KAAK,WAAW;EACtB,IAAI,CAAC,MAAM,CAAC,WAAW,SAAS;EAChC,MAAM,UAAU,MAAoB;GAClC,SAAS,UAAU,UAAU,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM;EACpE;EACA,MAAM,gBAAgB;GAAE,SAAS,UAAU;EAAM;EACjD,GAAG,iBAAiB,eAAe,MAAM;EACzC,GAAG,iBAAiB,gBAAgB,OAAO;EAC3C,UAAU,gBAAgB;GACxB,GAAG,oBAAoB,eAAe,MAAM;GAC5C,GAAG,oBAAoB,gBAAgB,OAAO;EAChD;CACF,GAAG,CAAC,SAAS,CAAC;CAEd,gBAAgB;EACd,WAAW,UAAU;EACrB,KAAK;EACL,aAAa;GACX,UAAU,UAAU;GACpB,UAAU,UAAU;GACpB,SAAS,UAAU;EACrB;CACF,GAAG,CAAC,SAAS,IAAI,CAAC;CAElB,MAAM,YAAY,aAAa,YAAgC;EAC7D,IAAI,WAAW,YAAY,SAAS;EACpC,WAAW,UAAU;EACrB,KAAK;CACP,GAAG,CAAC,IAAI,CAAC;CACT,MAAM,WAAW,kBAAkB,SAAS,SAAS,CAAC,CAAC;CAEvD,OAAO,eAAe;EAAE;EAAU;CAAU,IAAI,CAAC,UAAU,SAAS,CAAC;AACvE"}
1
+ {"version":3,"file":"useHoverTracking.js","names":[],"sources":["../../../src/features/chrome-caps/useHoverTracking.ts"],"sourcesContent":["/** Last-hovered NodeId for chrome-caps rules. */\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { NodeId } from '../../core/scene/types';\n\n/** Options for `useHoverTracking`. */\nexport interface UseHoverTrackingArgs {\n /** Topmost id under a client point, or null. */\n nodeAtClientPoint: (clientX: number, clientY: number) => { id: NodeId } | null;\n enabled?: boolean;\n /** Called when the hovered id changes, `null` once the pointer is over no node or has left. */\n onChange?: (id: NodeId | null) => void;\n}\n\n/** What `useHoverTracking` returns. Both members keep their identity. */\nexport interface HoverTracking {\n /** The node the pointer is over, or null. */\n getHover: () => NodeId | null;\n /** Hand it the element to track, or null to stop: a callback ref, so an\n * element that mounts after the hook is tracked from the moment it arrives. */\n canvasRef: (element: HTMLElement | null) => void;\n}\n\n/** Track which node the pointer is over. Returns a getter rather than state,\n * so a pointer move does not re-render the component. Cleared on\n * `pointerleave`. */\nexport function useHoverTracking(args: UseHoverTrackingArgs): HoverTracking {\n const { nodeAtClientPoint, enabled = true } = args;\n const hoverRef = useRef<NodeId | null>(null);\n const nodeAtRef = useLatest(nodeAtClientPoint);\n const onChangeRef = useLatest(args.onChange);\n const elementRef = useRef<HTMLElement | null>(null);\n const enabledRef = useRef(enabled);\n const detachRef = useRef<(() => void) | null>(null);\n\n const hover = useCallback((id: NodeId | null) => {\n if (hoverRef.current === id) return;\n hoverRef.current = id;\n onChangeRef.current?.(id);\n }, [onChangeRef]);\n\n const sync = useCallback(() => {\n detachRef.current?.();\n detachRef.current = null;\n hover(null);\n const el = elementRef.current;\n if (!el || !enabledRef.current) return;\n const onMove = (e: PointerEvent) => hover(nodeAtRef.current(e.clientX, e.clientY)?.id ?? null);\n const onLeave = () => hover(null);\n el.addEventListener('pointermove', onMove);\n el.addEventListener('pointerleave', onLeave);\n detachRef.current = () => {\n el.removeEventListener('pointermove', onMove);\n el.removeEventListener('pointerleave', onLeave);\n };\n }, [nodeAtRef, hover]);\n\n useEffect(() => {\n enabledRef.current = enabled;\n sync();\n return () => {\n detachRef.current?.();\n detachRef.current = null;\n hover(null);\n };\n }, [enabled, sync, hover]);\n\n const canvasRef = useCallback((element: HTMLElement | null) => {\n if (elementRef.current === element) return;\n elementRef.current = element;\n sync();\n }, [sync]);\n const getHover = useCallback(() => hoverRef.current, []);\n\n return useMemo(() => ({ getHover, canvasRef }), [getHover, canvasRef]);\n}\n"],"mappings":";;;;;;;;AA2BA,SAAgB,iBAAiB,MAA2C;CAC1E,MAAM,EAAE,mBAAmB,UAAU,SAAS;CAC9C,MAAM,WAAW,OAAsB,IAAI;CAC3C,MAAM,YAAY,UAAU,iBAAiB;CAC7C,MAAM,cAAc,UAAU,KAAK,QAAQ;CAC3C,MAAM,aAAa,OAA2B,IAAI;CAClD,MAAM,aAAa,OAAO,OAAO;CACjC,MAAM,YAAY,OAA4B,IAAI;CAElD,MAAM,QAAQ,aAAa,OAAsB;EAC/C,IAAI,SAAS,YAAY,IAAI;EAC7B,SAAS,UAAU;EACnB,YAAY,UAAU,EAAE;CAC1B,GAAG,CAAC,WAAW,CAAC;CAEhB,MAAM,OAAO,kBAAkB;EAC7B,UAAU,UAAU;EACpB,UAAU,UAAU;EACpB,MAAM,IAAI;EACV,MAAM,KAAK,WAAW;EACtB,IAAI,CAAC,MAAM,CAAC,WAAW,SAAS;EAChC,MAAM,UAAU,MAAoB,MAAM,UAAU,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI;EAC7F,MAAM,gBAAgB,MAAM,IAAI;EAChC,GAAG,iBAAiB,eAAe,MAAM;EACzC,GAAG,iBAAiB,gBAAgB,OAAO;EAC3C,UAAU,gBAAgB;GACxB,GAAG,oBAAoB,eAAe,MAAM;GAC5C,GAAG,oBAAoB,gBAAgB,OAAO;EAChD;CACF,GAAG,CAAC,WAAW,KAAK,CAAC;CAErB,gBAAgB;EACd,WAAW,UAAU;EACrB,KAAK;EACL,aAAa;GACX,UAAU,UAAU;GACpB,UAAU,UAAU;GACpB,MAAM,IAAI;EACZ;CACF,GAAG;EAAC;EAAS;EAAM;CAAK,CAAC;CAEzB,MAAM,YAAY,aAAa,YAAgC;EAC7D,IAAI,WAAW,YAAY,SAAS;EACpC,WAAW,UAAU;EACrB,KAAK;CACP,GAAG,CAAC,IAAI,CAAC;CACT,MAAM,WAAW,kBAAkB,SAAS,SAAS,CAAC,CAAC;CAEvD,OAAO,eAAe;EAAE;EAAU;CAAU,IAAI,CAAC,UAAU,SAAS,CAAC;AACvE"}
@@ -1,4 +1,5 @@
1
1
  import { dwarn } from "../../debug/flag.js";
2
+ import { admitIngestMime } from "@weasel-js/routing";
2
3
  import { UNKNOWN_MIME, mimeMatchesGlob } from "@weasel-js/gestures";
3
4
 
4
5
  //#region src/features/ingestion/contentHandlers.ts
@@ -16,12 +17,34 @@ import { UNKNOWN_MIME, mimeMatchesGlob } from "@weasel-js/gestures";
16
17
  * matched can never disagree with the registry about what a glob means.
17
18
  */
18
19
  var HANDLERS = [];
20
+ var RELEASES = /* @__PURE__ */ new Map();
21
+ /** The exact MIMEs a handler names, for string flavors to be kept. A glob
22
+ * names no one flavor, and `application/octet-stream` is what an untyped
23
+ * file reports, never a string flavor anyone meant. */
24
+ function namedMimes(entry) {
25
+ const named = [...typeof entry.match === "function" ? [] : [entry.match].flat(), ...entry.types ?? []];
26
+ return [...new Set(named)].filter((m) => !m.includes("*") && m !== "application/octet-stream");
27
+ }
28
+ function unregister(entry) {
29
+ const i = HANDLERS.indexOf(entry);
30
+ if (i < 0) return;
31
+ HANDLERS.splice(i, 1);
32
+ const releases = RELEASES.get(entry);
33
+ releases?.pop()?.();
34
+ if (releases?.length === 0) RELEASES.delete(entry);
35
+ }
19
36
  /** Register a content handler. Returns a disposer that removes it. */
20
37
  function registerContentHandler(entry) {
21
38
  HANDLERS.push(entry);
39
+ const admits = namedMimes(entry).map(admitIngestMime);
40
+ const releases = RELEASES.get(entry) ?? [];
41
+ releases.push(() => admits.forEach((release) => release()));
42
+ RELEASES.set(entry, releases);
43
+ let removed = false;
22
44
  return () => {
23
- const i = HANDLERS.indexOf(entry);
24
- if (i >= 0) HANDLERS.splice(i, 1);
45
+ if (removed) return;
46
+ removed = true;
47
+ unregister(entry);
25
48
  };
26
49
  }
27
50
  function byPriority(handlers) {
@@ -1 +1 @@
1
- {"version":3,"file":"contentHandlers.js","names":[],"sources":["../../../src/features/ingestion/contentHandlers.ts"],"sourcesContent":["/**\n * Content-handler registry for external-content ingestion.\n *\n * All three arrival paths (OS drop, clipboard paste, file picker /\n * `CanvasExtensionApi.ingest`) converge here: `runIngest(items, ctx)`\n * partitions the items across registered handlers in priority order — the\n * first matching handler takes every item it matches; leftovers continue\n * down the list.\n *\n * MIME matching delegates to `mimeMatchesGlob` from `@weasel-js/gestures` —\n * the SAME matcher the binding-level `types` filter uses, so a binding that\n * matched can never disagree with the registry about what a glob means.\n */\nimport { mimeMatchesGlob, UNKNOWN_MIME } from '@weasel-js/gestures';\nimport { dwarn } from '../../debug';\nimport type { Scene } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Op } from 'core/ops/types';\nimport type { ClipboardIngestCtx, InsertDep, SvgIngestOptions } from 'interactions/actions/depSchema';\nimport type { ActionDeps } from '@weasel-js/routing';\nimport type { IngestItem } from '@weasel-js/routing';\n\n/** Context handed to every content handler for one ingest event. */\nexport interface IngestCtx {\n /** World-space arrival point (drop / pointed imperative ingest); `null`\n * for paste and point-less calls — handlers pick their own policy\n * (the kit image handler centers on the viewport). */\n point: { x: number; y: number } | null;\n /** Visible canvas area in world coordinates. */\n viewportWorldRect(): { x: number; y: number; width: number; height: number };\n /** The kit insert dep — id/layer/undoable-op supplied; the canonical way\n * for a handler to mint a node (`insert.commit(bounds, { kind, ... })`). */\n insert: InsertDep;\n /** Raw op commit for handlers that build their own ops. */\n applyOps(ops: Op[], label?: string): void;\n scene: Scene<unknown, string, unknown>;\n selection: SelectionApi;\n /** Consumer file→src resolver (SceneCanvas `ingestion.resolveSrc`).\n * When absent, the kit image handler embeds as a `data:` URI. */\n resolveSrc?: (file: File) => Promise<string>;\n /** Kit SVG-handler options (SceneCanvas `ingestion.svg`) — e.g.\n * `{ unpack: unpackSvgFiles }` (from `@weasel-js/svg`) to parse SVG files\n * into scene nodes. */\n svg?: SvgIngestOptions;\n /** Clipboard-paste seam — present when the hosting `SceneCanvas` supplied\n * an adapter with `commitPaste`. `reviver` comes from\n * `SceneCanvasProps.ingestion.clipboard`. Absent ⇒ the kit weasel-JSON\n * handler declines inert (dwarn, nothing ingested) — its matched items\n * were already consumed at match time, so they do NOT fall through;\n * only match-level misses flow on to other handlers. */\n clipboard?: ClipboardIngestCtx;\n /** Set to `true` by the kit weasel-JSON handler when it successfully\n * pastes a payload in this event. `kit:svg`'s `text/plain` SVG fallback\n * reads this to decline the SVG flavor of a copy whose weasel-JSON flavor\n * already ingested (avoids a double-paste when both flavors ride one\n * clipboard event). */\n consumedWeaselPayload?: boolean;\n /** Full action-deps bag, for consumer handlers that need more. */\n deps: ActionDeps;\n}\n\n/** A handler for content arriving by paste, drop or file picker. Handlers are\n * matched by MIME glob or predicate and run highest-priority first; the kit's\n * own register at a low priority so a consumer's handler wins by default. */\nexport interface ContentHandlerEntry {\n /** Stable identifier — used for unregistration and debugging\n * (`'kit:image'`, `'app:csv'`). */\n id: string;\n /** MIME glob(s) (`'image/*'`, `'text/csv'`) or an item predicate. */\n match: string | string[] | ((item: IngestItem) => boolean);\n /** For a predicate `match`: the MIME globs it could say yes to. A drag\n * still in flight shows its MIMEs and no contents, so a predicate cannot be\n * asked about it; this is what it is asked instead. Without it, no drag\n * can be refused while this handler is registered. */\n types?: readonly string[];\n /** Higher runs earlier. Kit defaults register at -100 so any consumer\n * handler (default 0) beats them. */\n priority?: number;\n handle(items: IngestItem[], ctx: IngestCtx): void | Promise<void>;\n}\n\nconst HANDLERS: ContentHandlerEntry[] = [];\n\n/** Register a content handler. Returns a disposer that removes it. */\nexport function registerContentHandler(entry: ContentHandlerEntry): () => void {\n HANDLERS.push(entry);\n return () => {\n const i = HANDLERS.indexOf(entry);\n if (i >= 0) HANDLERS.splice(i, 1);\n };\n}\n\nfunction byPriority(handlers: readonly ContentHandlerEntry[]): ContentHandlerEntry[] {\n return [...handlers].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n}\n\n/** Snapshot of registered handlers, priority-ordered (stable within ties —\n * registration order; Array.prototype.sort is stable per ES2019). */\nexport function getContentHandlers(): readonly ContentHandlerEntry[] {\n return byPriority(HANDLERS);\n}\n\n/** Options for {@link runIngest}. */\nexport interface RunIngestOptions {\n /**\n * The handlers to route through, in place of the registry. The registry is\n * shared by every canvas on the page, so this is how one arrival path\n * accepts a narrower set of content than the page has handlers for.\n * Ordered by `priority` like registered handlers; an item none of them\n * matches is ignored.\n */\n handlers?: readonly ContentHandlerEntry[];\n}\n\nfunction entryMatches(entry: ContentHandlerEntry, item: IngestItem): boolean {\n const { match } = entry;\n if (typeof match === 'function') {\n try {\n return match(item);\n } catch (err) {\n console.warn(`weasel ingest: handler \"${entry.id}\" match predicate threw`, err);\n return false;\n }\n }\n const globs = Array.isArray(match) ? match : [match];\n return globs.some((g) => mimeMatchesGlob(item.mime, g));\n}\n\n/**\n * Whether some handler could claim one of `items`: the registry's, or\n * `handlers`. An item with contents is put to each handler's `match`. One\n * with a MIME alone, from a drag still in flight, is answered from the globs\n * and a predicate's declared `types`; it is never refused when its MIME is\n * `UNKNOWN_MIME`, or while a predicate handler declares no types.\n */\nexport function couldClaim(\n items: readonly IngestItem[],\n handlers: readonly ContentHandlerEntry[] = HANDLERS,\n): boolean {\n return items.some((item) => {\n if ((item as { kind?: string }).kind !== undefined) return handlers.some((h) => entryMatches(h, item));\n if (item.mime === UNKNOWN_MIME) return true;\n return handlers.some((h) => {\n const globs = typeof h.match === 'function' ? h.types : [h.match].flat();\n return globs === undefined || globs.some((g) => mimeMatchesGlob(item.mime, g));\n });\n });\n}\n\n/**\n * Route one ingest event's items through the registry. Handlers are queued\n * as microtasks in priority order and their async work then overlaps (each\n * already owns a disjoint item set); a throwing or rejecting handler\n * `console.warn`s and doesn't block the others. The queue order is a real\n * invariant: a higher-priority handler's `handle` body runs before lower\n * ones start, so ctx-flag coordination (e.g. `consumedWeaselPayload`)\n * works — but only while the writing handler stays synchronous up to the\n * write and the reading handler reads before its first `await`.\n * Unmatched items are ignored with a debug-gated `dwarn('ingest', ...)`.\n */\nexport async function runIngest(\n items: IngestItem[],\n ctx: IngestCtx,\n opts: RunIngestOptions = {},\n): Promise<void> {\n let remaining = items;\n const runs: Promise<void>[] = [];\n const handlers = opts.handlers ? byPriority(opts.handlers) : getContentHandlers();\n\n for (const entry of handlers) {\n if (remaining.length === 0) break;\n const mine = remaining.filter((it) => entryMatches(entry, it));\n if (mine.length === 0) continue;\n remaining = remaining.filter((it) => !mine.includes(it));\n runs.push(\n Promise.resolve()\n .then(() => entry.handle(mine, ctx))\n .catch((err) => {\n console.warn(`weasel ingest: handler \"${entry.id}\" threw`, err);\n }),\n );\n }\n\n if (remaining.length > 0) {\n dwarn(\n 'ingest',\n `no content handler matched ${remaining.length} item(s):`,\n remaining.map((it) => it.mime).join(', '),\n );\n }\n\n await Promise.all(runs);\n}\n\n/** @internal test seam — clear the registry. Not part of the public barrel. */\nexport function _resetContentHandlersForTests(): void {\n HANDLERS.length = 0;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAiFA,IAAM,WAAkC,CAAC;;AAGzC,SAAgB,uBAAuB,OAAwC;CAC7E,SAAS,KAAK,KAAK;CACnB,aAAa;EACX,MAAM,IAAI,SAAS,QAAQ,KAAK;EAChC,IAAI,KAAK,GAAG,SAAS,OAAO,GAAG,CAAC;CAClC;AACF;AAEA,SAAS,WAAW,UAAiE;CACnF,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,GAAG,OAAO,EAAE,YAAY,MAAM,EAAE,YAAY,EAAE;AAC3E;;;AAIA,SAAgB,qBAAqD;CACnE,OAAO,WAAW,QAAQ;AAC5B;AAcA,SAAS,aAAa,OAA4B,MAA2B;CAC3E,MAAM,EAAE,UAAU;CAClB,IAAI,OAAO,UAAU,YACnB,IAAI;EACF,OAAO,MAAM,IAAI;CACnB,SAAS,KAAK;EACZ,QAAQ,KAAK,2BAA2B,MAAM,GAAG,0BAA0B,GAAG;EAC9E,OAAO;CACT;CAGF,QADc,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK,EAC5C,CAAM,MAAM,MAAM,gBAAgB,KAAK,MAAM,CAAC,CAAC;AACxD;;;;;;;;AASA,SAAgB,WACd,OACA,WAA2C,UAClC;CACT,OAAO,MAAM,MAAM,SAAS;EAC1B,IAAK,KAA2B,SAAS,QAAW,OAAO,SAAS,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC;EACrG,IAAI,KAAK,SAAS,cAAc,OAAO;EACvC,OAAO,SAAS,MAAM,MAAM;GAC1B,MAAM,QAAQ,OAAO,EAAE,UAAU,aAAa,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK;GACvE,OAAO,UAAU,UAAa,MAAM,MAAM,MAAM,gBAAgB,KAAK,MAAM,CAAC,CAAC;EAC/E,CAAC;CACH,CAAC;AACH;;;;;;;;;;;;AAaA,eAAsB,UACpB,OACA,KACA,OAAyB,CAAC,GACX;CACf,IAAI,YAAY;CAChB,MAAM,OAAwB,CAAC;CAC/B,MAAM,WAAW,KAAK,WAAW,WAAW,KAAK,QAAQ,IAAI,mBAAmB;CAEhF,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,UAAU,WAAW,GAAG;EAC5B,MAAM,OAAO,UAAU,QAAQ,OAAO,aAAa,OAAO,EAAE,CAAC;EAC7D,IAAI,KAAK,WAAW,GAAG;EACvB,YAAY,UAAU,QAAQ,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;EACvD,KAAK,KACH,QAAQ,QAAQ,CAAC,CACd,WAAW,MAAM,OAAO,MAAM,GAAG,CAAC,CAAC,CACnC,OAAO,QAAQ;GACd,QAAQ,KAAK,2BAA2B,MAAM,GAAG,UAAU,GAAG;EAChE,CAAC,CACL;CACF;CAEA,IAAI,UAAU,SAAS,GACrB,MACE,UACA,8BAA8B,UAAU,OAAO,YAC/C,UAAU,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAC1C;CAGF,MAAM,QAAQ,IAAI,IAAI;AACxB"}
1
+ {"version":3,"file":"contentHandlers.js","names":[],"sources":["../../../src/features/ingestion/contentHandlers.ts"],"sourcesContent":["/**\n * Content-handler registry for external-content ingestion.\n *\n * All three arrival paths (OS drop, clipboard paste, file picker /\n * `CanvasExtensionApi.ingest`) converge here: `runIngest(items, ctx)`\n * partitions the items across registered handlers in priority order — the\n * first matching handler takes every item it matches; leftovers continue\n * down the list.\n *\n * MIME matching delegates to `mimeMatchesGlob` from `@weasel-js/gestures` —\n * the SAME matcher the binding-level `types` filter uses, so a binding that\n * matched can never disagree with the registry about what a glob means.\n */\nimport { mimeMatchesGlob, UNKNOWN_MIME } from '@weasel-js/gestures';\nimport { dwarn } from '../../debug';\nimport type { Scene } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Op } from 'core/ops/types';\nimport type { ClipboardIngestCtx, InsertDep, SnapDep, SvgIngestOptions } from 'interactions/actions/depSchema';\nimport { admitIngestMime, type ActionDeps, type IngestItem } from '@weasel-js/routing';\n\n/** Context handed to every content handler for one ingest event. */\nexport interface IngestCtx {\n /** World-space arrival point (drop / pointed imperative ingest); `null`\n * for paste and point-less calls — handlers pick their own policy\n * (the kit image handler centers on the viewport). */\n point: { x: number; y: number } | null;\n /** Visible canvas area in world coordinates. */\n viewportWorldRect(): { x: number; y: number; width: number; height: number };\n /** The kit insert dep — id/layer/undoable-op supplied; the canonical way\n * for a handler to mint a node (`insert.commit(bounds, { kind, ... })`). */\n insert: InsertDep;\n /** The canvas's snap dep, for a handler that places what it inserts where a\n * gesture would: begin a session, take `at()`, `end()`. Its points are ctx\n * coordinates: world on a 2D canvas, screen in a 3D host. */\n snap?: SnapDep;\n /** Raw op commit for handlers that build their own ops. */\n applyOps(ops: Op[], label?: string): void;\n scene: Scene<unknown, string, unknown>;\n selection: SelectionApi;\n /** Consumer file→src resolver (SceneCanvas `ingestion.resolveSrc`).\n * When absent, the kit image handler embeds as a `data:` URI. */\n resolveSrc?: (file: File) => Promise<string>;\n /** Kit SVG-handler options (SceneCanvas `ingestion.svg`) — e.g.\n * `{ unpack: unpackSvgFiles }` (from `@weasel-js/svg`) to parse SVG files\n * into scene nodes. */\n svg?: SvgIngestOptions;\n /** Clipboard-paste seam — present when the hosting `SceneCanvas` supplied\n * an adapter with `commitPaste`. `reviver` comes from\n * `SceneCanvasProps.ingestion.clipboard`. Absent ⇒ the kit weasel-JSON\n * handler declines inert (dwarn, nothing ingested) — its matched items\n * were already consumed at match time, so they do NOT fall through;\n * only match-level misses flow on to other handlers. */\n clipboard?: ClipboardIngestCtx;\n /** Set to `true` by the kit weasel-JSON handler when it successfully\n * pastes a payload in this event. `kit:svg`'s `text/plain` SVG fallback\n * reads this to decline the SVG flavor of a copy whose weasel-JSON flavor\n * already ingested (avoids a double-paste when both flavors ride one\n * clipboard event). */\n consumedWeaselPayload?: boolean;\n /** Full action-deps bag, for consumer handlers that need more. */\n deps: ActionDeps;\n}\n\n/** A handler for content arriving by paste, drop or file picker. Handlers are\n * matched by MIME glob or predicate and run highest-priority first; the kit's\n * own register at a low priority so a consumer's handler wins by default. */\nexport interface ContentHandlerEntry {\n /** Stable identifier — used for unregistration and debugging\n * (`'kit:image'`, `'app:csv'`). */\n id: string;\n /** MIME glob(s) (`'image/*'`, `'text/csv'`) or an item predicate. A drop\n * or paste keeps string flavors of any exact MIME named here or in\n * `types` while the handler is registered, so a handler can claim a drag\n * from the app's own UI by a type of its own. */\n match: string | string[] | ((item: IngestItem) => boolean);\n /** For a predicate `match`: the MIME globs it could say yes to. A drag\n * still in flight shows its MIMEs and no contents, so a predicate cannot be\n * asked about it; this is what it is asked instead. Without it, no drag\n * can be refused while this handler is registered. */\n types?: readonly string[];\n /** Higher runs earlier. Kit defaults register at -100 so any consumer\n * handler (default 0) beats them. */\n priority?: number;\n handle(items: IngestItem[], ctx: IngestCtx): void | Promise<void>;\n}\n\nconst HANDLERS: ContentHandlerEntry[] = [];\nconst RELEASES = new Map<ContentHandlerEntry, (() => void)[]>();\n\n/** The exact MIMEs a handler names, for string flavors to be kept. A glob\n * names no one flavor, and `application/octet-stream` is what an untyped\n * file reports, never a string flavor anyone meant. */\nfunction namedMimes(entry: ContentHandlerEntry): string[] {\n const named = [...(typeof entry.match === 'function' ? [] : [entry.match].flat()), ...(entry.types ?? [])];\n return [...new Set(named)].filter((m) => !m.includes('*') && m !== 'application/octet-stream');\n}\n\nfunction unregister(entry: ContentHandlerEntry): void {\n const i = HANDLERS.indexOf(entry);\n if (i < 0) return;\n HANDLERS.splice(i, 1);\n // The same entry may be registered more than once; each registration admitted once.\n const releases = RELEASES.get(entry);\n releases?.pop()?.();\n if (releases?.length === 0) RELEASES.delete(entry);\n}\n\n/** Register a content handler. Returns a disposer that removes it. */\nexport function registerContentHandler(entry: ContentHandlerEntry): () => void {\n HANDLERS.push(entry);\n const admits = namedMimes(entry).map(admitIngestMime);\n const releases = RELEASES.get(entry) ?? [];\n releases.push(() => admits.forEach((release) => release()));\n RELEASES.set(entry, releases);\n let removed = false;\n return () => {\n if (removed) return;\n removed = true;\n unregister(entry);\n };\n}\n\nfunction byPriority(handlers: readonly ContentHandlerEntry[]): ContentHandlerEntry[] {\n return [...handlers].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n}\n\n/** Snapshot of registered handlers, priority-ordered (stable within ties —\n * registration order; Array.prototype.sort is stable per ES2019). */\nexport function getContentHandlers(): readonly ContentHandlerEntry[] {\n return byPriority(HANDLERS);\n}\n\n/** Options for {@link runIngest}. */\nexport interface RunIngestOptions {\n /**\n * The handlers to route through, in place of the registry. The registry is\n * shared by every canvas on the page, so this is how one arrival path\n * accepts a narrower set of content than the page has handlers for.\n * Ordered by `priority` like registered handlers; an item none of them\n * matches is ignored.\n */\n handlers?: readonly ContentHandlerEntry[];\n}\n\nfunction entryMatches(entry: ContentHandlerEntry, item: IngestItem): boolean {\n const { match } = entry;\n if (typeof match === 'function') {\n try {\n return match(item);\n } catch (err) {\n console.warn(`weasel ingest: handler \"${entry.id}\" match predicate threw`, err);\n return false;\n }\n }\n const globs = Array.isArray(match) ? match : [match];\n return globs.some((g) => mimeMatchesGlob(item.mime, g));\n}\n\n/**\n * Whether some handler could claim one of `items`: the registry's, or\n * `handlers`. An item with contents is put to each handler's `match`. One\n * with a MIME alone, from a drag still in flight, is answered from the globs\n * and a predicate's declared `types`; it is never refused when its MIME is\n * `UNKNOWN_MIME`, or while a predicate handler declares no types.\n */\nexport function couldClaim(\n items: readonly IngestItem[],\n handlers: readonly ContentHandlerEntry[] = HANDLERS,\n): boolean {\n return items.some((item) => {\n if ((item as { kind?: string }).kind !== undefined) return handlers.some((h) => entryMatches(h, item));\n if (item.mime === UNKNOWN_MIME) return true;\n return handlers.some((h) => {\n const globs = typeof h.match === 'function' ? h.types : [h.match].flat();\n return globs === undefined || globs.some((g) => mimeMatchesGlob(item.mime, g));\n });\n });\n}\n\n/**\n * Route one ingest event's items through the registry. Handlers are queued\n * as microtasks in priority order and their async work then overlaps (each\n * already owns a disjoint item set); a throwing or rejecting handler\n * `console.warn`s and doesn't block the others. The queue order is a real\n * invariant: a higher-priority handler's `handle` body runs before lower\n * ones start, so ctx-flag coordination (e.g. `consumedWeaselPayload`)\n * works — but only while the writing handler stays synchronous up to the\n * write and the reading handler reads before its first `await`.\n * Unmatched items are ignored with a debug-gated `dwarn('ingest', ...)`.\n */\nexport async function runIngest(\n items: IngestItem[],\n ctx: IngestCtx,\n opts: RunIngestOptions = {},\n): Promise<void> {\n let remaining = items;\n const runs: Promise<void>[] = [];\n const handlers = opts.handlers ? byPriority(opts.handlers) : getContentHandlers();\n\n for (const entry of handlers) {\n if (remaining.length === 0) break;\n const mine = remaining.filter((it) => entryMatches(entry, it));\n if (mine.length === 0) continue;\n remaining = remaining.filter((it) => !mine.includes(it));\n runs.push(\n Promise.resolve()\n .then(() => entry.handle(mine, ctx))\n .catch((err) => {\n console.warn(`weasel ingest: handler \"${entry.id}\" threw`, err);\n }),\n );\n }\n\n if (remaining.length > 0) {\n dwarn(\n 'ingest',\n `no content handler matched ${remaining.length} item(s):`,\n remaining.map((it) => it.mime).join(', '),\n );\n }\n\n await Promise.all(runs);\n}\n\n/** @internal test seam — clear the registry. Not part of the public barrel. */\nexport function _resetContentHandlersForTests(): void {\n while (HANDLERS.length > 0) unregister(HANDLERS[0]!);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAuFA,IAAM,WAAkC,CAAC;AACzC,IAAM,2BAAW,IAAI,IAAyC;;;;AAK9D,SAAS,WAAW,OAAsC;CACxD,MAAM,QAAQ,CAAC,GAAI,OAAO,MAAM,UAAU,aAAa,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,KAAK,GAAI,GAAI,MAAM,SAAS,CAAC,CAAE;CACzG,OAAO,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,EAAE,SAAS,GAAG,KAAK,MAAM,0BAA0B;AAC/F;AAEA,SAAS,WAAW,OAAkC;CACpD,MAAM,IAAI,SAAS,QAAQ,KAAK;CAChC,IAAI,IAAI,GAAG;CACX,SAAS,OAAO,GAAG,CAAC;CAEpB,MAAM,WAAW,SAAS,IAAI,KAAK;CACnC,UAAU,IAAI,CAAC,GAAG;CAClB,IAAI,UAAU,WAAW,GAAG,SAAS,OAAO,KAAK;AACnD;;AAGA,SAAgB,uBAAuB,OAAwC;CAC7E,SAAS,KAAK,KAAK;CACnB,MAAM,SAAS,WAAW,KAAK,CAAC,CAAC,IAAI,eAAe;CACpD,MAAM,WAAW,SAAS,IAAI,KAAK,KAAK,CAAC;CACzC,SAAS,WAAW,OAAO,SAAS,YAAY,QAAQ,CAAC,CAAC;CAC1D,SAAS,IAAI,OAAO,QAAQ;CAC5B,IAAI,UAAU;CACd,aAAa;EACX,IAAI,SAAS;EACb,UAAU;EACV,WAAW,KAAK;CAClB;AACF;AAEA,SAAS,WAAW,UAAiE;CACnF,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,MAAM,GAAG,OAAO,EAAE,YAAY,MAAM,EAAE,YAAY,EAAE;AAC3E;;;AAIA,SAAgB,qBAAqD;CACnE,OAAO,WAAW,QAAQ;AAC5B;AAcA,SAAS,aAAa,OAA4B,MAA2B;CAC3E,MAAM,EAAE,UAAU;CAClB,IAAI,OAAO,UAAU,YACnB,IAAI;EACF,OAAO,MAAM,IAAI;CACnB,SAAS,KAAK;EACZ,QAAQ,KAAK,2BAA2B,MAAM,GAAG,0BAA0B,GAAG;EAC9E,OAAO;CACT;CAGF,QADc,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK,EAC5C,CAAM,MAAM,MAAM,gBAAgB,KAAK,MAAM,CAAC,CAAC;AACxD;;;;;;;;AASA,SAAgB,WACd,OACA,WAA2C,UAClC;CACT,OAAO,MAAM,MAAM,SAAS;EAC1B,IAAK,KAA2B,SAAS,QAAW,OAAO,SAAS,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC;EACrG,IAAI,KAAK,SAAS,cAAc,OAAO;EACvC,OAAO,SAAS,MAAM,MAAM;GAC1B,MAAM,QAAQ,OAAO,EAAE,UAAU,aAAa,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK;GACvE,OAAO,UAAU,UAAa,MAAM,MAAM,MAAM,gBAAgB,KAAK,MAAM,CAAC,CAAC;EAC/E,CAAC;CACH,CAAC;AACH;;;;;;;;;;;;AAaA,eAAsB,UACpB,OACA,KACA,OAAyB,CAAC,GACX;CACf,IAAI,YAAY;CAChB,MAAM,OAAwB,CAAC;CAC/B,MAAM,WAAW,KAAK,WAAW,WAAW,KAAK,QAAQ,IAAI,mBAAmB;CAEhF,KAAK,MAAM,SAAS,UAAU;EAC5B,IAAI,UAAU,WAAW,GAAG;EAC5B,MAAM,OAAO,UAAU,QAAQ,OAAO,aAAa,OAAO,EAAE,CAAC;EAC7D,IAAI,KAAK,WAAW,GAAG;EACvB,YAAY,UAAU,QAAQ,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;EACvD,KAAK,KACH,QAAQ,QAAQ,CAAC,CACd,WAAW,MAAM,OAAO,MAAM,GAAG,CAAC,CAAC,CACnC,OAAO,QAAQ;GACd,QAAQ,KAAK,2BAA2B,MAAM,GAAG,UAAU,GAAG;EAChE,CAAC,CACL;CACF;CAEA,IAAI,UAAU,SAAS,GACrB,MACE,UACA,8BAA8B,UAAU,OAAO,YAC/C,UAAU,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAC1C;CAGF,MAAM,QAAQ,IAAI,IAAI;AACxB"}