@weasel-js/core 1.9.3 → 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 (1139) hide show
  1. package/CHANGELOG.md +1106 -0
  2. package/README.md +7 -5
  3. package/dist/WeaselProvider.js +5 -7
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +91 -93
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +27 -18
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +65 -104
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js.map +1 -1
  12. package/dist/affordances/rotationHandle.js +22 -21
  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 +38 -88
  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 +32 -24
  44. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  45. package/dist/animation/wrappers/animateOnSetPose.js +31 -29
  46. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  47. package/dist/animation/wrappers/instantPose.js +13 -0
  48. package/dist/animation/wrappers/instantPose.js.map +1 -0
  49. package/dist/animation/writtenPoseTarget.js +33 -0
  50. package/dist/animation/writtenPoseTarget.js.map +1 -0
  51. package/dist/{autoPoseDescriptor-vCdt55xm.d.ts → autoPoseDescriptor-DHg5KqaJ.d.ts} +1 -1
  52. package/dist/barrel/canvas.js +31 -0
  53. package/dist/barrel/chrome.js +16 -0
  54. package/dist/barrel/input.js +18 -0
  55. package/dist/barrel/interactions.js +38 -0
  56. package/dist/barrel/paint.js +11 -0
  57. package/dist/barrel/paths.js +12 -0
  58. package/dist/barrel/renderer.js +14 -0
  59. package/dist/barrel/routing.js +57 -0
  60. package/dist/barrel/scene.js +37 -0
  61. package/dist/barrel/text.js +9 -0
  62. package/dist/barrel/viewport.js +42 -0
  63. package/dist/canvas/Canvas.js +280 -559
  64. package/dist/canvas/Canvas.js.map +1 -1
  65. package/dist/canvas/CanvasView.js +147 -167
  66. package/dist/canvas/CanvasView.js.map +1 -1
  67. package/dist/canvas/CursorCoordsHud.js +53 -49
  68. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  69. package/dist/canvas/DrawCanvas.js +40 -51
  70. package/dist/canvas/DrawCanvas.js.map +1 -1
  71. package/dist/canvas/ModalityHud.js.map +1 -1
  72. package/dist/canvas/NodeShape.js +55 -374
  73. package/dist/canvas/NodeShape.js.map +1 -1
  74. package/dist/canvas/PickHud.js +50 -47
  75. package/dist/canvas/PickHud.js.map +1 -1
  76. package/dist/canvas/SceneCanvas/DevHuds.js +40 -0
  77. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -0
  78. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +126 -0
  79. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -0
  80. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +27 -31
  81. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  82. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +64 -0
  83. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -0
  84. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +16 -0
  85. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -0
  86. package/dist/canvas/SceneCanvas/coordTrace.js +46 -0
  87. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -0
  88. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +138 -85
  89. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  90. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +9 -8
  91. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  92. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/features.js +74 -43
  94. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  95. package/dist/canvas/SceneCanvas/isDev.js +12 -0
  96. package/dist/canvas/SceneCanvas/isDev.js.map +1 -0
  97. package/dist/canvas/SceneCanvas/poseGeometry.js +31 -34
  98. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  99. package/dist/canvas/SceneCanvas/poseRegistrars.js +13 -0
  100. package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -0
  101. package/dist/canvas/SceneCanvas/props.js +39 -0
  102. package/dist/canvas/SceneCanvas/props.js.map +1 -0
  103. package/dist/canvas/SceneCanvas/toolRegistry.js +23 -0
  104. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -0
  105. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +6 -1
  106. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  107. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +21 -62
  108. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  109. package/dist/canvas/SceneCanvas/useBuiltinTools.js +21 -0
  110. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -0
  111. package/dist/canvas/SceneCanvas/useCanvasCamera.js +38 -0
  112. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -0
  113. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +20 -0
  114. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -0
  115. package/dist/canvas/SceneCanvas/useCanvasSelection.js +16 -0
  116. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -0
  117. package/dist/canvas/SceneCanvas/useCanvasTools.js +67 -0
  118. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -0
  119. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +29 -29
  120. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  121. package/dist/canvas/SceneCanvas/useHeldModifiers.js +20 -0
  122. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -0
  123. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +26 -0
  124. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -0
  125. package/dist/canvas/SceneCanvas/useNodeKinds.js +26 -0
  126. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -0
  127. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +48 -48
  128. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  129. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +47 -0
  130. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -0
  131. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +66 -0
  132. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -0
  133. package/dist/canvas/SceneCanvas/useSceneChrome.js +59 -0
  134. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -0
  135. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +23 -0
  136. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -0
  137. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +74 -78
  138. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  139. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +37 -0
  140. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -0
  141. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +38 -0
  142. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -0
  143. package/dist/canvas/SceneCanvas/useViewLayerGate.js +20 -0
  144. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +1 -0
  145. package/dist/canvas/SceneCanvas/useViewportActions.js +9 -1
  146. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  147. package/dist/canvas/SceneCanvas/worldPointAt.js +9 -0
  148. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -0
  149. package/dist/canvas/SceneCanvas.js +311 -969
  150. package/dist/canvas/SceneCanvas.js.map +1 -1
  151. package/dist/canvas/SceneViewCanvas.js +42 -46
  152. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  153. package/dist/canvas/adapterDerivedPath.js +26 -0
  154. package/dist/canvas/adapterDerivedPath.js.map +1 -0
  155. package/dist/canvas/affordanceAt.js +11 -1
  156. package/dist/canvas/affordanceAt.js.map +1 -1
  157. package/dist/canvas/buildSceneLayer.js +111 -0
  158. package/dist/canvas/buildSceneLayer.js.map +1 -0
  159. package/dist/canvas/buildSceneTree.js +16 -19
  160. package/dist/canvas/buildSceneTree.js.map +1 -1
  161. package/dist/canvas/canvasRenderer.js +67 -55
  162. package/dist/canvas/canvasRenderer.js.map +1 -1
  163. package/dist/canvas/colorOverrides.js.map +1 -1
  164. package/dist/canvas/defaultDrawOne.js +12 -12
  165. package/dist/canvas/defaultDrawOne.js.map +1 -1
  166. package/dist/canvas/deps/areaSelect.js +4 -4
  167. package/dist/canvas/deps/areaSelect.js.map +1 -1
  168. package/dist/canvas/deps/changes.js +13 -0
  169. package/dist/canvas/deps/changes.js.map +1 -0
  170. package/dist/canvas/deps/debug.js.map +1 -1
  171. package/dist/canvas/deps/editAnchors.js +38 -57
  172. package/dist/canvas/deps/editAnchors.js.map +1 -1
  173. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  174. package/dist/canvas/deps/hitTestArea.js +31 -26
  175. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  176. package/dist/canvas/deps/insert.js +130 -91
  177. package/dist/canvas/deps/insert.js.map +1 -1
  178. package/dist/canvas/deps/lassoSelect.js +5 -5
  179. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  180. package/dist/canvas/deps/poseDescriptor.js +1 -1
  181. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  182. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  183. package/dist/canvas/deps/slice.js +26 -26
  184. package/dist/canvas/deps/slice.js.map +1 -1
  185. package/dist/canvas/deps/textEdit.js +6 -5
  186. package/dist/canvas/deps/textEdit.js.map +1 -1
  187. package/dist/canvas/deps/view.js.map +1 -1
  188. package/dist/canvas/derivedPath.js +47 -22
  189. package/dist/canvas/derivedPath.js.map +1 -1
  190. package/dist/canvas/drawEnvelope.js +8 -4
  191. package/dist/canvas/drawEnvelope.js.map +1 -1
  192. package/dist/canvas/getNodeAtPoint.js +4 -8
  193. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  194. package/dist/canvas/hud.module.js +1 -1
  195. package/dist/canvas/hud.module.js.map +1 -1
  196. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  197. package/dist/canvas/kitRequirements.js +2 -2
  198. package/dist/canvas/kitRequirements.js.map +1 -1
  199. package/dist/canvas/layerOrder.js +13 -6
  200. package/dist/canvas/layerOrder.js.map +1 -1
  201. package/dist/canvas/layerSlots.js +6 -1
  202. package/dist/canvas/layerSlots.js.map +1 -1
  203. package/dist/canvas/nodeShapes/derivedPainter.js +34 -0
  204. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -0
  205. package/dist/canvas/nodeShapes/imagePainter.js +87 -0
  206. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -0
  207. package/dist/canvas/nodeShapes/memo.js +9 -0
  208. package/dist/canvas/nodeShapes/memo.js.map +1 -0
  209. package/dist/canvas/nodeShapes/nodePaint.js +68 -0
  210. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -0
  211. package/dist/canvas/nodeShapes/pathPainter.js +39 -0
  212. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -0
  213. package/dist/canvas/nodeShapes/poseBox.js +20 -0
  214. package/dist/canvas/nodeShapes/poseBox.js.map +1 -0
  215. package/dist/canvas/nodeShapes/rectFallbackPainter.js +38 -0
  216. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -0
  217. package/dist/canvas/nodeShapes/shapePainter.js +72 -0
  218. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -0
  219. package/dist/canvas/nodeShapes/textPainter.js +55 -0
  220. package/dist/canvas/nodeShapes/textPainter.js.map +1 -0
  221. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  222. package/dist/canvas/paintCull.js +11 -14
  223. package/dist/canvas/paintCull.js.map +1 -1
  224. package/dist/{features/cursor → canvas}/paintedCursorLayer.js +2 -2
  225. package/dist/canvas/paintedCursorLayer.js.map +1 -0
  226. package/dist/canvas/pickWalk.js +59 -68
  227. package/dist/canvas/pickWalk.js.map +1 -1
  228. package/dist/canvas/planeClips.js +18 -19
  229. package/dist/canvas/planeClips.js.map +1 -1
  230. package/dist/canvas/poseCascade.js +41 -0
  231. package/dist/canvas/poseCascade.js.map +1 -0
  232. package/dist/canvas/poseRotation.js +9 -23
  233. package/dist/canvas/poseRotation.js.map +1 -1
  234. package/dist/canvas/rasterReadback.js +22 -0
  235. package/dist/canvas/rasterReadback.js.map +1 -0
  236. package/dist/canvas/renderDebugSnapshot.js +11 -11
  237. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  238. package/dist/canvas/renderNeeds.js +3 -3
  239. package/dist/canvas/renderNeeds.js.map +1 -1
  240. package/dist/canvas/renderSceneToPixels.js +64 -81
  241. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  242. package/dist/canvas/sceneAdapter.js +68 -214
  243. package/dist/canvas/sceneAdapter.js.map +1 -1
  244. package/dist/canvas/sceneClipboard.js +112 -0
  245. package/dist/canvas/sceneClipboard.js.map +1 -0
  246. package/dist/canvas/sceneLayerPaint.js +4 -4
  247. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  248. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  249. package/dist/canvas/sceneViewRender.js +39 -39
  250. package/dist/canvas/sceneViewRender.js.map +1 -1
  251. package/dist/canvas/slopsDebugLayer.js +4 -4
  252. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  253. package/dist/canvas/surface.module.js +6 -0
  254. package/dist/canvas/surface.module.js.map +1 -0
  255. package/dist/canvas/surfaceBox.js +16 -0
  256. package/dist/canvas/surfaceBox.js.map +1 -0
  257. package/dist/canvas/useCanvasRenderer.js +26 -6
  258. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  259. package/dist/canvas/useCanvasSurface.js +31 -0
  260. package/dist/canvas/useCanvasSurface.js.map +1 -0
  261. package/dist/canvas/useCanvasView.js +67 -0
  262. package/dist/canvas/useCanvasView.js.map +1 -0
  263. package/dist/canvas/useFrameLoop.js +39 -31
  264. package/dist/canvas/useFrameLoop.js.map +1 -1
  265. package/dist/canvas/useHostAnchor.js +35 -33
  266. package/dist/canvas/useHostAnchor.js.map +1 -1
  267. package/dist/canvas/useLateContentRedraw.js +8 -8
  268. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  269. package/dist/canvas/useSceneLayerList.js +11 -0
  270. package/dist/canvas/useSceneLayerList.js.map +1 -0
  271. package/dist/canvas/useSurfaceInput.js +42 -0
  272. package/dist/canvas/useSurfaceInput.js.map +1 -0
  273. package/dist/canvas/useToolCursor.js +29 -0
  274. package/dist/canvas/useToolCursor.js.map +1 -0
  275. package/dist/canvas/useViewHelpers.js +46 -85
  276. package/dist/canvas/useViewHelpers.js.map +1 -1
  277. package/dist/canvas/viewInputs.js.map +1 -1
  278. package/dist/canvas/viewRegistry.js +25 -27
  279. package/dist/canvas/viewRegistry.js.map +1 -1
  280. package/dist/canvas/watchElementMove.js +43 -0
  281. package/dist/canvas/watchElementMove.js.map +1 -0
  282. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  283. package/dist/clipboard.d.ts +16 -19
  284. package/dist/{types-B_9g6hMM.d.ts → clone-2a5hVbBd.d.ts} +123 -74
  285. package/dist/clone.d.ts +4 -7
  286. package/dist/clone.js +0 -2
  287. package/dist/core/device/index.js +5 -4
  288. package/dist/core/device/targets.js.map +1 -1
  289. package/dist/core/device/useDeviceProfile.js +38 -44
  290. package/dist/core/device/useDeviceProfile.js.map +1 -1
  291. package/dist/core/device/watchDevicePixelRatio.js +17 -0
  292. package/dist/core/device/watchDevicePixelRatio.js.map +1 -0
  293. package/dist/{interactions/actions/resize → core/geometry}/autoPoseDescriptor.js +8 -7
  294. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -0
  295. package/dist/core/geometry/pathPoseDescriptor.js +88 -0
  296. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -0
  297. package/dist/core/geometry/poseDescriptor.js +68 -19
  298. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  299. package/dist/core/geometry/regionHit.js +31 -34
  300. package/dist/core/geometry/regionHit.js.map +1 -1
  301. package/dist/core/geometry/targetFrame.js +94 -0
  302. package/dist/core/geometry/targetFrame.js.map +1 -0
  303. package/dist/core/geometry/unionBounds.js +30 -29
  304. package/dist/core/geometry/unionBounds.js.map +1 -1
  305. package/dist/core/isPlainObject.js +2 -11
  306. package/dist/core/layers/backgroundFill.js +31 -0
  307. package/dist/core/layers/backgroundFill.js.map +1 -0
  308. package/dist/{features/groups → core/layers}/children.js +1 -1
  309. package/dist/core/layers/children.js.map +1 -0
  310. package/dist/core/layers/gateLayer.js +13 -0
  311. package/dist/core/layers/gateLayer.js.map +1 -0
  312. package/dist/core/layers/layerGroup.js +40 -0
  313. package/dist/core/layers/layerGroup.js.map +1 -0
  314. package/dist/core/layers/render.js +50 -76
  315. package/dist/core/layers/render.js.map +1 -1
  316. package/dist/core/ops/arrange.js +1 -0
  317. package/dist/core/ops/arrange.js.map +1 -1
  318. package/dist/core/ops/create.js +10 -5
  319. package/dist/core/ops/create.js.map +1 -1
  320. package/dist/core/ops/createHistory.js +9 -9
  321. package/dist/core/ops/createHistory.js.map +1 -1
  322. package/dist/core/ops/delete.js +12 -24
  323. package/dist/core/ops/delete.js.map +1 -1
  324. package/dist/core/ops/reorder/index.js +43 -40
  325. package/dist/core/ops/reorder/index.js.map +1 -1
  326. package/dist/core/ops/reorder/setChildOrder.js +34 -0
  327. package/dist/core/ops/reorder/setChildOrder.js.map +1 -0
  328. package/dist/core/paint/meshKind.js +16 -0
  329. package/dist/core/paint/meshKind.js.map +1 -0
  330. package/dist/{features/meshPaint/lazyKind.js → core/paint/meshKindLazy.js} +282 -105
  331. package/dist/core/paint/meshKindLazy.js.map +1 -0
  332. package/dist/core/paint/paintKindEntry.js +8 -0
  333. package/dist/core/paint/paintKindEntry.js.map +1 -0
  334. package/dist/core/paint/paintKinds.js +144 -0
  335. package/dist/core/paint/paintKinds.js.map +1 -0
  336. package/dist/core/paint/registerMesh.js +7 -0
  337. package/dist/core/paint/registerMesh.js.map +1 -0
  338. package/dist/core/scene/NodeProperties.js.map +1 -1
  339. package/dist/core/scene/NodeRouting.js.map +1 -1
  340. package/dist/core/scene/appliedLog.js +37 -0
  341. package/dist/core/scene/appliedLog.js.map +1 -0
  342. package/dist/core/scene/arrivalWindow.js +102 -0
  343. package/dist/core/scene/arrivalWindow.js.map +1 -0
  344. package/dist/core/scene/boundOps.js +40 -0
  345. package/dist/core/scene/boundOps.js.map +1 -0
  346. package/dist/core/scene/composeFrame.js +9 -6
  347. package/dist/core/scene/composeFrame.js.map +1 -1
  348. package/dist/{features/groups → core/scene}/composePose.js +18 -18
  349. package/dist/core/scene/composePose.js.map +1 -0
  350. package/dist/core/scene/depMemo.js +31 -6
  351. package/dist/core/scene/depMemo.js.map +1 -1
  352. package/dist/core/scene/derivedPath.js +19 -20
  353. package/dist/core/scene/derivedPath.js.map +1 -1
  354. package/dist/core/scene/editMode.js +26 -0
  355. package/dist/core/scene/editMode.js.map +1 -0
  356. package/dist/core/scene/effectivePose.js +38 -39
  357. package/dist/core/scene/effectivePose.js.map +1 -1
  358. package/dist/core/scene/fieldEdits.js +98 -0
  359. package/dist/core/scene/fieldEdits.js.map +1 -0
  360. package/dist/core/scene/historyFacade.js +130 -0
  361. package/dist/core/scene/historyFacade.js.map +1 -0
  362. package/dist/core/scene/historyForm.js +6 -0
  363. package/dist/core/scene/historyForm.js.map +1 -0
  364. package/dist/core/scene/kitOps.js +185 -0
  365. package/dist/core/scene/kitOps.js.map +1 -0
  366. package/dist/core/scene/kitRegistry.js.map +1 -1
  367. package/dist/core/scene/layerStack.js +131 -0
  368. package/dist/core/scene/layerStack.js.map +1 -0
  369. package/dist/core/scene/layoutPass.js +58 -59
  370. package/dist/core/scene/layoutPass.js.map +1 -1
  371. package/dist/core/scene/lockGuard.js +37 -0
  372. package/dist/core/scene/lockGuard.js.map +1 -0
  373. package/dist/{features/groups → core/scene}/nestedHit.js +3 -3
  374. package/dist/core/scene/nestedHit.js.map +1 -0
  375. package/dist/core/scene/nodeFnFields.js +10 -11
  376. package/dist/core/scene/nodeFnFields.js.map +1 -1
  377. package/dist/core/scene/nodeMemo.js +45 -19
  378. package/dist/core/scene/nodeMemo.js.map +1 -1
  379. package/dist/core/scene/nodeStore.js +127 -0
  380. package/dist/core/scene/nodeStore.js.map +1 -0
  381. package/dist/core/scene/notifier.js +37 -0
  382. package/dist/core/scene/notifier.js.map +1 -0
  383. package/dist/core/scene/opTable.js +50 -0
  384. package/dist/core/scene/opTable.js.map +1 -0
  385. package/dist/core/scene/outerOps.js +66 -0
  386. package/dist/core/scene/outerOps.js.map +1 -0
  387. package/dist/core/scene/poseFeed.js +38 -38
  388. package/dist/core/scene/poseFeed.js.map +1 -1
  389. package/dist/core/scene/poseHold.js +39 -0
  390. package/dist/core/scene/poseHold.js.map +1 -0
  391. package/dist/core/scene/poseOverrides.js +44 -40
  392. package/dist/core/scene/poseOverrides.js.map +1 -1
  393. package/dist/core/scene/poseSnapshot.js.map +1 -1
  394. package/dist/core/scene/reconcileSpecs.js +3 -2
  395. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  396. package/dist/core/scene/recorder.js +86 -0
  397. package/dist/core/scene/recorder.js.map +1 -0
  398. package/dist/core/scene/renderOrder.js +84 -0
  399. package/dist/core/scene/renderOrder.js.map +1 -0
  400. package/dist/core/scene/scene.js +80 -1266
  401. package/dist/core/scene/scene.js.map +1 -1
  402. package/dist/core/scene/sceneEdits.js +58 -0
  403. package/dist/core/scene/sceneEdits.js.map +1 -0
  404. package/dist/core/scene/sceneMutators.js +49 -0
  405. package/dist/core/scene/sceneMutators.js.map +1 -0
  406. package/dist/core/scene/scenePoseAdapter.js +16 -0
  407. package/dist/core/scene/scenePoseAdapter.js.map +1 -0
  408. package/dist/core/scene/sceneRecording.js +90 -0
  409. package/dist/core/scene/sceneRecording.js.map +1 -0
  410. package/dist/core/scene/sceneSelection.js +28 -0
  411. package/dist/core/scene/sceneSelection.js.map +1 -0
  412. package/dist/core/scene/sceneState.js +49 -0
  413. package/dist/core/scene/sceneState.js.map +1 -0
  414. package/dist/core/scene/serialization.js +71 -0
  415. package/dist/core/scene/serialization.js.map +1 -0
  416. package/dist/core/scene/staleReplay.js +51 -0
  417. package/dist/core/scene/staleReplay.js.map +1 -0
  418. package/dist/core/scene/statedFields.js +9 -0
  419. package/dist/core/scene/statedFields.js.map +1 -0
  420. package/dist/core/scene/treeEdits.js +127 -0
  421. package/dist/core/scene/treeEdits.js.map +1 -0
  422. package/dist/core/scene/treeOrder.js +13 -0
  423. package/dist/core/scene/treeOrder.js.map +1 -0
  424. package/dist/core/scene/treeReads.js +26 -0
  425. package/dist/core/scene/treeReads.js.map +1 -0
  426. package/dist/core/scene/types.js.map +1 -1
  427. package/dist/{features/groups → core/scene}/unionOfChildren.js +3 -3
  428. package/dist/core/scene/unionOfChildren.js.map +1 -0
  429. package/dist/core/scene/unitScopes.js +13 -0
  430. package/dist/core/scene/unitScopes.js.map +1 -0
  431. package/dist/core/scene/useScene.js.map +1 -1
  432. package/dist/core/selection/readOnlySelection.js +32 -0
  433. package/dist/core/selection/readOnlySelection.js.map +1 -0
  434. package/dist/core/selection/usePublishSceneSelection.js +26 -0
  435. package/dist/core/selection/usePublishSceneSelection.js.map +1 -0
  436. package/dist/core/selection/useSelection.js +34 -25
  437. package/dist/core/selection/useSelection.js.map +1 -1
  438. package/dist/core/shapeKinds.js.map +1 -1
  439. package/dist/core/stylus/stylus.js.map +1 -1
  440. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  441. package/dist/core/usePaintKinds.js +1 -1
  442. package/dist/core/usePaintKinds.js.map +1 -1
  443. package/dist/core/viewport/clientToWorld.js.map +1 -1
  444. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  445. package/dist/core/viewport/parallax.js.map +1 -1
  446. package/dist/core/viewport/screenSlop.js +11 -11
  447. package/dist/core/viewport/screenSlop.js.map +1 -1
  448. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  449. package/dist/core/viewport/useDecayLoop.js +8 -8
  450. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  451. package/dist/core/viewport/useNodeOverlayFrame.js +84 -0
  452. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -0
  453. package/dist/core/viewport/useViewAnimation.js +102 -43
  454. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  455. package/dist/core/viewport/view.js +9 -9
  456. package/dist/core/viewport/view.js.map +1 -1
  457. package/dist/core/viewport/wheelHandler.js.map +1 -1
  458. package/dist/core/viewport/zoomBounds.js +10 -8
  459. package/dist/core/viewport/zoomBounds.js.map +1 -1
  460. package/dist/{cornerHandles-BCrDp_mH.d.ts → cornerHandles-BEshc4z3.d.ts} +11 -24
  461. package/dist/debug/createDebugOverlayLayer.js +97 -97
  462. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  463. package/dist/debug/createDebugSink.js.map +1 -1
  464. package/dist/debug/flag.js +2 -41
  465. package/dist/debug/frameStats.js.map +1 -1
  466. package/dist/debug/useDebugSink.js +52 -0
  467. package/dist/debug/useDebugSink.js.map +1 -0
  468. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  469. package/dist/features/chrome-caps/conditions.js.map +1 -1
  470. package/dist/features/chrome-caps/defaults.js.map +1 -1
  471. package/dist/features/chrome-caps/resolve.js.map +1 -1
  472. package/dist/features/chrome-caps/useChromeCaps.js +54 -0
  473. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -0
  474. package/dist/features/chrome-caps/useHoverTracking.js +22 -17
  475. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  476. package/dist/features/ingestion/contentHandlers.js +28 -19
  477. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  478. package/dist/features/ingestion/imageHandler.js +21 -24
  479. package/dist/features/ingestion/imageHandler.js.map +1 -1
  480. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  481. package/dist/features/ingestion/placement.js +16 -0
  482. package/dist/features/ingestion/placement.js.map +1 -0
  483. package/dist/features/ingestion/registerKitHandlers.js +7 -7
  484. package/dist/features/ingestion/svgHandler.js +5 -0
  485. package/dist/features/ingestion/svgHandler.js.map +1 -1
  486. package/dist/features/ingestion/textHandler.js +28 -0
  487. package/dist/features/ingestion/textHandler.js.map +1 -0
  488. package/dist/features/ingestion/useCanvasIngestion.js +48 -0
  489. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -0
  490. package/dist/features/ingestion/weaselJsonHandler.js +22 -14
  491. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  492. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  493. package/dist/features/modes/modeLayers.js +7 -7
  494. package/dist/features/modes/modeLayers.js.map +1 -1
  495. package/dist/features/paths/editablePath.js +47 -0
  496. package/dist/features/paths/editablePath.js.map +1 -0
  497. package/dist/features/paths/index.js +9 -14
  498. package/dist/features/paths/pathEditState.js +41 -0
  499. package/dist/features/paths/pathEditState.js.map +1 -0
  500. package/dist/features/paths/pathEditingOverlayLayer.js +36 -38
  501. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  502. package/dist/features/paths/pathLayer.js +3 -2
  503. package/dist/features/paths/pathLayer.js.map +1 -1
  504. package/dist/features/paths/penPreviewLayer.js +86 -88
  505. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  506. package/dist/features/paths/usePathEdit.js +34 -0
  507. package/dist/features/paths/usePathEdit.js.map +1 -0
  508. package/dist/features/poseRun/usePoseRun.js +44 -52
  509. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  510. package/dist/features/selection/overlay.js +171 -179
  511. package/dist/features/selection/overlay.js.map +1 -1
  512. package/dist/features/text/index.js +6 -0
  513. package/dist/features/text/textLayer.js +1 -1
  514. package/dist/features/text/textLayer.js.map +1 -1
  515. package/dist/features/text/useSceneTextEdit.js +100 -93
  516. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  517. package/dist/features/viewports/viewportLayer.js +25 -36
  518. package/dist/features/viewports/viewportLayer.js.map +1 -1
  519. package/dist/index.d.ts +8473 -9141
  520. package/dist/index.js +269 -307
  521. package/dist/input/keyState.js +38 -39
  522. package/dist/input/keyState.js.map +1 -1
  523. package/dist/input/useKeyModifiers.js +11 -0
  524. package/dist/input/useKeyModifiers.js.map +1 -0
  525. package/dist/interactions/actions/actionShortcuts.js.map +1 -1
  526. package/dist/interactions/actions/{defaults/align.js → align/action.js} +18 -20
  527. package/dist/interactions/actions/align/action.js.map +1 -0
  528. package/dist/interactions/actions/align/align.js +20 -20
  529. package/dist/interactions/actions/align/align.js.map +1 -1
  530. package/dist/interactions/actions/booleans/action.js +65 -0
  531. package/dist/interactions/actions/booleans/action.js.map +1 -0
  532. package/dist/interactions/actions/booleans/booleans.js +69 -78
  533. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  534. package/dist/interactions/actions/booleans/operands.js +40 -0
  535. package/dist/interactions/actions/booleans/operands.js.map +1 -0
  536. package/dist/interactions/actions/booleans/pieces.js +45 -0
  537. package/dist/interactions/actions/booleans/pieces.js.map +1 -0
  538. package/dist/interactions/actions/booleans/placement.js +24 -0
  539. package/dist/interactions/actions/booleans/placement.js.map +1 -0
  540. package/dist/interactions/actions/booleans/useBooleans.js +11 -9
  541. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  542. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  543. package/dist/interactions/actions/{defaults/clipboard.js → clipboard/action.js} +31 -15
  544. package/dist/interactions/actions/clipboard/action.js.map +1 -0
  545. package/dist/interactions/actions/clipboard/clipboardOps.js +44 -42
  546. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  547. package/dist/interactions/actions/clipboard/materializePaste.js +10 -7
  548. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  549. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  550. package/dist/interactions/actions/clone/action.js +98 -0
  551. package/dist/interactions/actions/clone/action.js.map +1 -0
  552. package/dist/interactions/actions/clone/behaviors.js +52 -0
  553. package/dist/interactions/actions/clone/behaviors.js.map +1 -0
  554. package/dist/interactions/actions/defaultCommitAdapter.js +7 -32
  555. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  556. package/dist/interactions/actions/defaults/anchorEditing.js +60 -84
  557. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  558. package/dist/interactions/actions/defaults/areaSelect.js +35 -38
  559. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  560. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  561. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  562. package/dist/interactions/actions/defaults/copySubtree.js +40 -0
  563. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -0
  564. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  565. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  566. package/dist/interactions/actions/defaults/duplicate.js +13 -53
  567. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  568. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  569. package/dist/interactions/actions/defaults/group.js +40 -50
  570. package/dist/interactions/actions/defaults/group.js.map +1 -1
  571. package/dist/interactions/actions/defaults/icons/booleanIcons.js +24 -1
  572. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -1
  573. package/dist/interactions/actions/defaults/icons/outlineIcons.js +39 -1
  574. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -1
  575. package/dist/interactions/actions/defaults/ingest.js +44 -38
  576. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  577. package/dist/interactions/actions/defaults/insertPathAnchor.js +11 -12
  578. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  579. package/dist/interactions/actions/defaults/nudge.js +40 -69
  580. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  581. package/dist/interactions/actions/defaults/nudgeSteps.js +37 -0
  582. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -0
  583. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  584. package/dist/interactions/actions/defaults/reorder.js +2 -0
  585. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  586. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  587. package/dist/interactions/actions/defaults/setFill.js +14 -8
  588. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  589. package/dist/interactions/actions/defaults/setFillOpacity.js +7 -4
  590. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  591. package/dist/interactions/actions/defaults/setStroke.js +12 -12
  592. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  593. package/dist/interactions/actions/defaults/setStrokeOpacity.js +6 -6
  594. package/dist/interactions/actions/defaults/sliceOps.js +8 -10
  595. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  596. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  597. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  598. package/dist/interactions/actions/defaults/viewportDragPan.js +37 -26
  599. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  600. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  601. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  602. package/dist/interactions/actions/distribute/action.js +66 -0
  603. package/dist/interactions/actions/distribute/action.js.map +1 -0
  604. package/dist/interactions/actions/distribute/distribute.js +11 -11
  605. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  606. package/dist/interactions/actions/{defaults/editAnchors.js → edit-anchors/action.js} +7 -9
  607. package/dist/interactions/actions/edit-anchors/action.js.map +1 -0
  608. package/dist/interactions/actions/edit-anchors/geometry.js +30 -27
  609. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  610. package/dist/interactions/actions/flip/action.js +124 -0
  611. package/dist/interactions/actions/flip/action.js.map +1 -0
  612. package/dist/interactions/actions/flip/helpers.js +30 -17
  613. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  614. package/dist/interactions/actions/gestureFrames.js +18 -0
  615. package/dist/interactions/actions/gestureFrames.js.map +1 -0
  616. package/dist/interactions/actions/gestureLifecycle.js +47 -20
  617. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  618. package/dist/interactions/actions/hitSelection.js +8 -0
  619. package/dist/interactions/actions/hitSelection.js.map +1 -0
  620. package/dist/interactions/actions/insert/action.js +72 -0
  621. package/dist/interactions/actions/insert/action.js.map +1 -0
  622. package/dist/interactions/actions/insert/commit.js +28 -0
  623. package/dist/interactions/actions/insert/commit.js.map +1 -0
  624. package/dist/interactions/actions/insert/extras.js +65 -0
  625. package/dist/interactions/actions/insert/extras.js.map +1 -0
  626. package/dist/interactions/actions/insert/frame.js +48 -0
  627. package/dist/interactions/actions/insert/frame.js.map +1 -0
  628. package/dist/interactions/actions/insert/geometry.js +35 -0
  629. package/dist/interactions/actions/insert/geometry.js.map +1 -0
  630. package/dist/interactions/actions/insert/rotateAction.js +21 -0
  631. package/dist/interactions/actions/insert/rotateAction.js.map +1 -0
  632. package/dist/interactions/actions/insert/session.js +59 -0
  633. package/dist/interactions/actions/insert/session.js.map +1 -0
  634. package/dist/interactions/actions/insert/shape.js +34 -0
  635. package/dist/interactions/actions/insert/shape.js.map +1 -0
  636. package/dist/interactions/actions/lasso-select/action.js +143 -0
  637. package/dist/interactions/actions/lasso-select/action.js.map +1 -0
  638. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +14 -18
  639. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
  640. package/dist/interactions/actions/move/action.js +87 -0
  641. package/dist/interactions/actions/move/action.js.map +1 -0
  642. package/dist/interactions/actions/move/behaviors/layoutDrop.js +51 -0
  643. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -0
  644. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +15 -0
  645. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -0
  646. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +5 -5
  647. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
  648. package/dist/interactions/actions/move/behaviors/snapToContainer.js +39 -27
  649. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  650. package/dist/interactions/actions/move/capture.js +99 -0
  651. package/dist/interactions/actions/move/capture.js.map +1 -0
  652. package/dist/interactions/actions/move/commit/index.js +41 -0
  653. package/dist/interactions/actions/move/commit/index.js.map +1 -0
  654. package/dist/interactions/actions/move/commit/layoutDrop.js +44 -0
  655. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -0
  656. package/dist/interactions/actions/move/commit/layoutRelease.js +100 -0
  657. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -0
  658. package/dist/interactions/actions/move/commit/rebase.js +18 -0
  659. package/dist/interactions/actions/move/commit/rebase.js.map +1 -0
  660. package/dist/interactions/actions/move/commit/reparent.js +65 -0
  661. package/dist/interactions/actions/move/commit/reparent.js.map +1 -0
  662. package/dist/interactions/actions/move/delta.js +51 -0
  663. package/dist/interactions/actions/move/delta.js.map +1 -0
  664. package/dist/interactions/actions/move/frame.js +59 -0
  665. package/dist/interactions/actions/move/frame.js.map +1 -0
  666. package/dist/interactions/actions/move/gestureAdapter.js +22 -30
  667. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  668. package/dist/interactions/actions/move/landedDescendants.js +33 -0
  669. package/dist/interactions/actions/move/landedDescendants.js.map +1 -0
  670. package/dist/interactions/actions/move/layout/container.js +94 -0
  671. package/dist/interactions/actions/move/layout/container.js.map +1 -0
  672. package/dist/interactions/actions/move/layout/dragged.js +58 -0
  673. package/dist/interactions/actions/move/layout/dragged.js.map +1 -0
  674. package/dist/interactions/actions/move/layout/dropPass.js +122 -0
  675. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -0
  676. package/dist/interactions/actions/move/layout/exits.js +38 -0
  677. package/dist/interactions/actions/move/layout/exits.js.map +1 -0
  678. package/dist/interactions/actions/move/layout/glide.js +48 -0
  679. package/dist/interactions/actions/move/layout/glide.js.map +1 -0
  680. package/dist/interactions/actions/move/session.js +63 -0
  681. package/dist/interactions/actions/move/session.js.map +1 -0
  682. package/dist/interactions/actions/move/translate.js +61 -0
  683. package/dist/interactions/actions/move/translate.js.map +1 -0
  684. package/dist/interactions/actions/outlines/createOutlines.js +16 -63
  685. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  686. package/dist/interactions/actions/outlines/createOutlinesAction.js +51 -0
  687. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -0
  688. package/dist/interactions/actions/outlines/outlineStroke.js +72 -0
  689. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -0
  690. package/dist/interactions/actions/outlines/outlineStrokeAction.js +37 -0
  691. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -0
  692. package/dist/interactions/actions/outlines/replaceWithPaths.js +54 -0
  693. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -0
  694. package/dist/interactions/actions/outlines/strokeRegion.js +27 -0
  695. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -0
  696. package/dist/interactions/actions/planeInput.js.map +1 -1
  697. package/dist/interactions/actions/pointerState.js +12 -0
  698. package/dist/interactions/actions/pointerState.js.map +1 -0
  699. package/dist/interactions/actions/poseDescriptorDep.js +16 -4
  700. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  701. package/dist/interactions/actions/poseFrame.js +25 -20
  702. package/dist/interactions/actions/poseFrame.js.map +1 -1
  703. package/dist/interactions/actions/resize/action.js +55 -0
  704. package/dist/interactions/actions/resize/action.js.map +1 -0
  705. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -1
  706. package/dist/interactions/actions/resize/boxFrame.js +16 -0
  707. package/dist/interactions/actions/resize/boxFrame.js.map +1 -0
  708. package/dist/interactions/actions/resize/capture.js +85 -0
  709. package/dist/interactions/actions/resize/capture.js.map +1 -0
  710. package/dist/interactions/actions/resize/commit.js +69 -0
  711. package/dist/interactions/actions/resize/commit.js.map +1 -0
  712. package/dist/interactions/actions/resize/frame.js +74 -0
  713. package/dist/interactions/actions/resize/frame.js.map +1 -0
  714. package/dist/interactions/actions/resize/pointSnap.js +111 -0
  715. package/dist/interactions/actions/resize/pointSnap.js.map +1 -0
  716. package/dist/interactions/actions/resize/ruleBounds.js +9 -0
  717. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -0
  718. package/dist/interactions/actions/resize/session.js +49 -0
  719. package/dist/interactions/actions/resize/session.js.map +1 -0
  720. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  721. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  722. package/dist/interactions/actions/rotate/action.js +56 -0
  723. package/dist/interactions/actions/rotate/action.js.map +1 -0
  724. package/dist/interactions/actions/rotate/behaviors/index.js +7 -0
  725. package/dist/interactions/actions/rotate/behaviors/index.js.map +1 -0
  726. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +12 -0
  727. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +1 -0
  728. package/dist/interactions/actions/rotate/commit.js +40 -0
  729. package/dist/interactions/actions/rotate/commit.js.map +1 -0
  730. package/dist/interactions/actions/rotate/frame.js +65 -0
  731. package/dist/interactions/actions/rotate/frame.js.map +1 -0
  732. package/dist/interactions/actions/rotate/handle.js +12 -12
  733. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  734. package/dist/interactions/actions/rotate/session.js +92 -0
  735. package/dist/interactions/actions/rotate/session.js.map +1 -0
  736. package/dist/interactions/actions/selectionSubtree.js +69 -0
  737. package/dist/interactions/actions/selectionSubtree.js.map +1 -0
  738. package/dist/interactions/actions/spatialReference.js.map +1 -1
  739. package/dist/interactions/actions/useStandardActions.js +87 -78
  740. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  741. package/dist/interactions/gestures/dragGesture/dragGesture.js +4 -7
  742. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
  743. package/dist/interactions/gestures/dragGesture/dragPointOf.js +23 -0
  744. package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -0
  745. package/dist/interactions/gestures/handleDrag/handleDrag.js +21 -26
  746. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
  747. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +62 -41
  748. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  749. package/dist/interactions/gestures/shared/originProjection.js +1 -1
  750. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  751. package/dist/interactions/gestures/shared/screenTolerance.js +8 -2
  752. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  753. package/dist/interactions/gestures/shared/snap.js.map +1 -1
  754. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +8 -4
  755. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  756. package/dist/layout/arrivals.js +20 -23
  757. package/dist/layout/arrivals.js.map +1 -1
  758. package/dist/math-CYUjoyyU.d.ts +33 -0
  759. package/dist/math.d.ts +5 -3
  760. package/dist/math.js +6 -6
  761. package/dist/mesh.d.ts +4 -268
  762. package/dist/mesh.js +3 -7
  763. package/dist/move.d.ts +14 -11
  764. package/dist/{originProjection-DEklpDc_.d.ts → originProjection-PPT88jZv.d.ts} +1 -1
  765. package/dist/patterns-builtin.d.ts +1 -118
  766. package/dist/patterns-builtin.js +2 -3
  767. package/dist/{poseDescriptor-D-OH-tu5.d.ts → poseDescriptor-Bqk-11Rl.d.ts} +26 -36
  768. package/dist/renderer.d.ts +1 -91
  769. package/dist/renderer.js +2 -18
  770. package/dist/resize.d.ts +10 -22
  771. package/dist/resize.js +6 -6
  772. package/dist/style.css +1 -1
  773. package/dist/test-hook/install.js +12 -6
  774. package/dist/test-hook/install.js.map +1 -1
  775. package/dist/test-hook/useTestHook.js +22 -0
  776. package/dist/test-hook/useTestHook.js.map +1 -0
  777. package/dist/test-seams-D0pyV3pR.d.ts +149 -0
  778. package/dist/test-seams.d.ts +4 -4
  779. package/dist/test-seams.js +2 -2
  780. package/dist/tools/builtin/bone/boneActions.js +130 -0
  781. package/dist/tools/builtin/bone/boneActions.js.map +1 -0
  782. package/dist/tools/builtin/bone/boneOverlay.js +58 -0
  783. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -0
  784. package/dist/tools/builtin/bone/placedRig.js +24 -0
  785. package/dist/tools/builtin/bone/placedRig.js.map +1 -0
  786. package/dist/tools/builtin/bone/rigEditState.js +21 -0
  787. package/dist/tools/builtin/bone/rigEditState.js.map +1 -0
  788. package/dist/tools/builtin/bone/useBoneTool.js +98 -0
  789. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -0
  790. package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
  791. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  792. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  793. package/dist/tools/builtin/hand/useHandTool.js +1 -0
  794. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  795. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  796. package/dist/tools/builtin/lasso/useLassoTool.js +11 -11
  797. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  798. package/dist/tools/builtin/line/useLineTool.js +1 -0
  799. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  800. package/dist/tools/builtin/pen/usePenTool.js +198 -150
  801. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  802. package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
  803. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  804. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  805. package/dist/tools/builtin/polygon/usePolygonTool.js +13 -8
  806. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  807. package/dist/tools/builtin/rect/useRectTool.js +1 -0
  808. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  809. package/dist/tools/builtin/select/adapterPointQuery.js +36 -0
  810. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -0
  811. package/dist/tools/builtin/select/selectionContributions.js +25 -24
  812. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  813. package/dist/tools/builtin/select/useSelectTool.js +42 -67
  814. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  815. package/dist/tools/builtin/shared/pointerFollower.js +17 -0
  816. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -0
  817. package/dist/tools/builtin/slice/useSliceTool.js +72 -82
  818. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  819. package/dist/tools/builtin/star/useStarTool.js +22 -16
  820. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  821. package/dist/tools/builtin/text/useTextTool.js +9 -0
  822. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  823. package/dist/tools/builtin/weight/useWeightTool.js +77 -0
  824. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -0
  825. package/dist/tools/builtin/weight/weightActions.js +112 -0
  826. package/dist/tools/builtin/weight/weightActions.js.map +1 -0
  827. package/dist/tools/builtin/weight/weightOverlay.js +61 -0
  828. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -0
  829. package/dist/tools/overlayBinding.js.map +1 -1
  830. package/dist/tools/useKeybindings.js +12 -22
  831. package/dist/tools/useKeybindings.js.map +1 -1
  832. package/dist/{types-A37hYkeR.d.ts → types-CIKDwlsP.d.ts} +113 -169
  833. package/dist/util/color.js +3 -3
  834. package/dist/util/color.js.map +1 -1
  835. package/dist/util/paint.js +1 -1
  836. package/dist/util/paint.js.map +1 -1
  837. package/dist/version.js +1 -1
  838. package/package.json +28 -21
  839. package/dist/animation/colorHelpers.js +0 -135
  840. package/dist/animation/colorHelpers.js.map +0 -1
  841. package/dist/animation/colorRegistry.js +0 -37
  842. package/dist/animation/colorRegistry.js.map +0 -1
  843. package/dist/animation/engine/axes.js +0 -36
  844. package/dist/animation/engine/axes.js.map +0 -1
  845. package/dist/animation/engine/codec.js +0 -170
  846. package/dist/animation/engine/codec.js.map +0 -1
  847. package/dist/animation/engine/integrator.js +0 -12
  848. package/dist/animation/engine/integrator.js.map +0 -1
  849. package/dist/animation/loop.js +0 -62
  850. package/dist/animation/loop.js.map +0 -1
  851. package/dist/animation/observe.js +0 -23
  852. package/dist/animation/observe.js.map +0 -1
  853. package/dist/animation/rig/blendPoses.js +0 -43
  854. package/dist/animation/rig/blendPoses.js.map +0 -1
  855. package/dist/animation/rig/mirrorPose.js +0 -19
  856. package/dist/animation/rig/mirrorPose.js.map +0 -1
  857. package/dist/animation/rig/resolveSkeleton.js +0 -33
  858. package/dist/animation/rig/resolveSkeleton.js.map +0 -1
  859. package/dist/animation/rig/solveIk.js +0 -103
  860. package/dist/animation/rig/solveIk.js.map +0 -1
  861. package/dist/animation/rig/types.js +0 -12
  862. package/dist/animation/rig/types.js.map +0 -1
  863. package/dist/animation/slew.js +0 -27
  864. package/dist/animation/slew.js.map +0 -1
  865. package/dist/animation/stagger.js +0 -138
  866. package/dist/animation/stagger.js.map +0 -1
  867. package/dist/animation/timeline/booking.js +0 -106
  868. package/dist/animation/timeline/booking.js.map +0 -1
  869. package/dist/animation/timeline/createTimeline.js +0 -116
  870. package/dist/animation/timeline/createTimeline.js.map +0 -1
  871. package/dist/animation/timeline/sampleTrack.js +0 -71
  872. package/dist/animation/timeline/sampleTrack.js.map +0 -1
  873. package/dist/animation/useAnimator.js +0 -378
  874. package/dist/animation/useAnimator.js.map +0 -1
  875. package/dist/builtins-C-VgUlWI.d.ts +0 -4514
  876. package/dist/canvas/MinimapCanvas.js +0 -139
  877. package/dist/canvas/MinimapCanvas.js.map +0 -1
  878. package/dist/canvas/deps/poseComposition.js +0 -11
  879. package/dist/canvas/deps/poseComposition.js.map +0 -1
  880. package/dist/canvas/minimapMath.js +0 -80
  881. package/dist/canvas/minimapMath.js.map +0 -1
  882. package/dist/canvas/toolPreview.js +0 -39
  883. package/dist/canvas/toolPreview.js.map +0 -1
  884. package/dist/core/adapters/arrayAdapter.js +0 -85
  885. package/dist/core/adapters/arrayAdapter.js.map +0 -1
  886. package/dist/core/adapters/useArrayAdapter.js +0 -13
  887. package/dist/core/adapters/useArrayAdapter.js.map +0 -1
  888. package/dist/core/fillInPoseFrame.js +0 -102
  889. package/dist/core/fillInPoseFrame.js.map +0 -1
  890. package/dist/core/geometry/poseRotation.js +0 -58
  891. package/dist/core/geometry/poseRotation.js.map +0 -1
  892. package/dist/core/gradient.js +0 -136
  893. package/dist/core/gradient.js.map +0 -1
  894. package/dist/core/isPlainObject.js.map +0 -1
  895. package/dist/core/markerInset.js +0 -24
  896. package/dist/core/markerInset.js.map +0 -1
  897. package/dist/core/mixed.js +0 -6
  898. package/dist/core/mixed.js.map +0 -1
  899. package/dist/core/paintKinds.js +0 -156
  900. package/dist/core/paintKinds.js.map +0 -1
  901. package/dist/core/strokeMarkerShapes.js +0 -139
  902. package/dist/core/strokeMarkerShapes.js.map +0 -1
  903. package/dist/core/strokeMarkers.js +0 -28
  904. package/dist/core/strokeMarkers.js.map +0 -1
  905. package/dist/core/viewport/meanScale.js +0 -8
  906. package/dist/core/viewport/meanScale.js.map +0 -1
  907. package/dist/core/viewport/pxExtent.js +0 -42
  908. package/dist/core/viewport/pxExtent.js.map +0 -1
  909. package/dist/debug/flag.js.map +0 -1
  910. package/dist/features/cursor/paintedCursorLayer.js.map +0 -1
  911. package/dist/features/focus/gateLayer.js +0 -14
  912. package/dist/features/focus/gateLayer.js.map +0 -1
  913. package/dist/features/focus/useCanvasFocus.js +0 -29
  914. package/dist/features/focus/useCanvasFocus.js.map +0 -1
  915. package/dist/features/groups/children.js.map +0 -1
  916. package/dist/features/groups/composePose.js.map +0 -1
  917. package/dist/features/groups/nestedHit.js.map +0 -1
  918. package/dist/features/groups/unionOfChildren.js.map +0 -1
  919. package/dist/features/images/imageCache.js +0 -94
  920. package/dist/features/images/imageCache.js.map +0 -1
  921. package/dist/features/ingestion/index.js +0 -8
  922. package/dist/features/meshPaint/bake.js +0 -79
  923. package/dist/features/meshPaint/bake.js.map +0 -1
  924. package/dist/features/meshPaint/bakeCache.js +0 -59
  925. package/dist/features/meshPaint/bakeCache.js.map +0 -1
  926. package/dist/features/meshPaint/handles.js +0 -86
  927. package/dist/features/meshPaint/handles.js.map +0 -1
  928. package/dist/features/meshPaint/lazyKind.js.map +0 -1
  929. package/dist/features/meshPaint/meshPaint.js +0 -236
  930. package/dist/features/meshPaint/meshPaint.js.map +0 -1
  931. package/dist/features/meshPaint/meshShader.js +0 -6
  932. package/dist/features/meshPaint/meshShader.js.map +0 -1
  933. package/dist/features/meshPaint/register.js +0 -7
  934. package/dist/features/meshPaint/register.js.map +0 -1
  935. package/dist/features/meshPaint/surface.js +0 -110
  936. package/dist/features/meshPaint/surface.js.map +0 -1
  937. package/dist/features/minimap/actions.js +0 -53
  938. package/dist/features/minimap/actions.js.map +0 -1
  939. package/dist/features/minimap/createMinimapContribution.js +0 -96
  940. package/dist/features/minimap/createMinimapContribution.js.map +0 -1
  941. package/dist/features/minimap/layers.js +0 -103
  942. package/dist/features/minimap/layers.js.map +0 -1
  943. package/dist/features/overlays/useNodeOverlayFrame.js +0 -103
  944. package/dist/features/overlays/useNodeOverlayFrame.js.map +0 -1
  945. package/dist/features/parallax/createParallaxLayer.js +0 -26
  946. package/dist/features/parallax/createParallaxLayer.js.map +0 -1
  947. package/dist/features/parallax/createParallaxPlane.js +0 -26
  948. package/dist/features/parallax/createParallaxPlane.js.map +0 -1
  949. package/dist/features/paths/anchorEdits.js +0 -156
  950. package/dist/features/paths/anchorEdits.js.map +0 -1
  951. package/dist/features/paths/anchors.js +0 -154
  952. package/dist/features/paths/anchors.js.map +0 -1
  953. package/dist/features/paths/booleans.js +0 -2
  954. package/dist/features/paths/markerCommands.js +0 -148
  955. package/dist/features/paths/markerCommands.js.map +0 -1
  956. package/dist/features/paths/markerSites.js +0 -59
  957. package/dist/features/paths/markerSites.js.map +0 -1
  958. package/dist/features/paths/markers.js +0 -95
  959. package/dist/features/paths/markers.js.map +0 -1
  960. package/dist/features/paths/nearestAnchor.js +0 -36
  961. package/dist/features/paths/nearestAnchor.js.map +0 -1
  962. package/dist/features/paths/pathInWorld.js +0 -41
  963. package/dist/features/paths/pathInWorld.js.map +0 -1
  964. package/dist/features/paths/poseDescriptor.js +0 -39
  965. package/dist/features/paths/poseDescriptor.js.map +0 -1
  966. package/dist/features/paths/tessellate/dash.js +0 -52
  967. package/dist/features/paths/tessellate/dash.js.map +0 -1
  968. package/dist/features/paths/tessellate/insets.js +0 -32
  969. package/dist/features/paths/tessellate/insets.js.map +0 -1
  970. package/dist/features/paths/tessellate/metric.js +0 -72
  971. package/dist/features/paths/tessellate/metric.js.map +0 -1
  972. package/dist/features/paths/tessellate/stroke.js +0 -170
  973. package/dist/features/paths/tessellate/stroke.js.map +0 -1
  974. package/dist/features/paths/tessellate/vertexWidths.js +0 -32
  975. package/dist/features/paths/tessellate/vertexWidths.js.map +0 -1
  976. package/dist/features/patterns/index.js +0 -23
  977. package/dist/features/patterns/index.js.map +0 -1
  978. package/dist/features/patterns/patterns-builtin.js +0 -38
  979. package/dist/features/patterns/patterns-builtin.js.map +0 -1
  980. package/dist/features/patterns/resolveSpec.js +0 -57
  981. package/dist/features/patterns/resolveSpec.js.map +0 -1
  982. package/dist/features/patterns/tileGeometry.js +0 -158
  983. package/dist/features/patterns/tileGeometry.js.map +0 -1
  984. package/dist/features/pointer/PointerContext.js +0 -45
  985. package/dist/features/pointer/PointerContext.js.map +0 -1
  986. package/dist/features/selection/SelectionContext.js +0 -46
  987. package/dist/features/selection/SelectionContext.js.map +0 -1
  988. package/dist/features/simulation/createSimulation.js +0 -61
  989. package/dist/features/simulation/createSimulation.js.map +0 -1
  990. package/dist/features/simulation/types.js +0 -6
  991. package/dist/features/simulation/types.js.map +0 -1
  992. package/dist/features/simulation/useSimulation.js +0 -74
  993. package/dist/features/simulation/useSimulation.js.map +0 -1
  994. package/dist/features/text/domRuns.js +0 -258
  995. package/dist/features/text/domRuns.js.map +0 -1
  996. package/dist/features/text/fitTextPose.js +0 -38
  997. package/dist/features/text/fitTextPose.js.map +0 -1
  998. package/dist/features/text/hitTest.js +0 -45
  999. package/dist/features/text/hitTest.js.map +0 -1
  1000. package/dist/features/text/renderLabel.js +0 -14
  1001. package/dist/features/text/renderLabel.js.map +0 -1
  1002. package/dist/features/text/runs/effectiveRangeStyle.js +0 -66
  1003. package/dist/features/text/runs/effectiveRangeStyle.js.map +0 -1
  1004. package/dist/features/text/runs/flagRange.js +0 -53
  1005. package/dist/features/text/runs/flagRange.js.map +0 -1
  1006. package/dist/features/text/runs/rangeStyle.js +0 -135
  1007. package/dist/features/text/runs/rangeStyle.js.map +0 -1
  1008. package/dist/features/text/textCommand.js +0 -59
  1009. package/dist/features/text/textCommand.js.map +0 -1
  1010. package/dist/features/text/textToPath.js +0 -181
  1011. package/dist/features/text/textToPath.js.map +0 -1
  1012. package/dist/features/text/useTextEdit.js +0 -467
  1013. package/dist/features/text/useTextEdit.js.map +0 -1
  1014. package/dist/features/tiling/createTiledLayer.js +0 -63
  1015. package/dist/features/tiling/createTiledLayer.js.map +0 -1
  1016. package/dist/features/tiling/tiledProject.js +0 -14
  1017. package/dist/features/tiling/tiledProject.js.map +0 -1
  1018. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +0 -26
  1019. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +0 -1
  1020. package/dist/interactions/actions/defaults/align.js.map +0 -1
  1021. package/dist/interactions/actions/defaults/booleans.js +0 -52
  1022. package/dist/interactions/actions/defaults/booleans.js.map +0 -1
  1023. package/dist/interactions/actions/defaults/clipboard.js.map +0 -1
  1024. package/dist/interactions/actions/defaults/clone.js +0 -107
  1025. package/dist/interactions/actions/defaults/clone.js.map +0 -1
  1026. package/dist/interactions/actions/defaults/createOutlines.js +0 -47
  1027. package/dist/interactions/actions/defaults/createOutlines.js.map +0 -1
  1028. package/dist/interactions/actions/defaults/distribute.js +0 -66
  1029. package/dist/interactions/actions/defaults/distribute.js.map +0 -1
  1030. package/dist/interactions/actions/defaults/editAnchors.js.map +0 -1
  1031. package/dist/interactions/actions/defaults/flip.js +0 -119
  1032. package/dist/interactions/actions/defaults/flip.js.map +0 -1
  1033. package/dist/interactions/actions/defaults/freshNodeId.js +0 -10
  1034. package/dist/interactions/actions/defaults/freshNodeId.js.map +0 -1
  1035. package/dist/interactions/actions/defaults/insert.js +0 -288
  1036. package/dist/interactions/actions/defaults/insert.js.map +0 -1
  1037. package/dist/interactions/actions/defaults/lassoSelect.js +0 -156
  1038. package/dist/interactions/actions/defaults/lassoSelect.js.map +0 -1
  1039. package/dist/interactions/actions/defaults/move.js +0 -760
  1040. package/dist/interactions/actions/defaults/move.js.map +0 -1
  1041. package/dist/interactions/actions/defaults/resize.js +0 -335
  1042. package/dist/interactions/actions/defaults/resize.js.map +0 -1
  1043. package/dist/interactions/actions/defaults/rotate.js +0 -184
  1044. package/dist/interactions/actions/defaults/rotate.js.map +0 -1
  1045. package/dist/interactions/actions/previewOverrides.js +0 -25
  1046. package/dist/interactions/actions/previewOverrides.js.map +0 -1
  1047. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +0 -1
  1048. package/dist/math-Drrw4ewZ.d.ts +0 -160
  1049. package/dist/registerProgram-BMZRDgrh.d.ts +0 -197
  1050. package/dist/renderer/DrawCommand.js +0 -6
  1051. package/dist/renderer/DrawCommand.js.map +0 -1
  1052. package/dist/renderer/WeaselRenderer.js +0 -331
  1053. package/dist/renderer/WeaselRenderer.js.map +0 -1
  1054. package/dist/renderer/batchClip.js +0 -46
  1055. package/dist/renderer/batchClip.js.map +0 -1
  1056. package/dist/renderer/cache/GLImageCache.js +0 -64
  1057. package/dist/renderer/cache/GLImageCache.js.map +0 -1
  1058. package/dist/renderer/cache/GLMeshCache.js +0 -102
  1059. package/dist/renderer/cache/GLMeshCache.js.map +0 -1
  1060. package/dist/renderer/cache/GLTextureCache.js +0 -51
  1061. package/dist/renderer/cache/GLTextureCache.js.map +0 -1
  1062. package/dist/renderer/cache/GradientRampAtlas.js +0 -82
  1063. package/dist/renderer/cache/GradientRampAtlas.js.map +0 -1
  1064. package/dist/renderer/cache/cache.js +0 -13
  1065. package/dist/renderer/cache/cache.js.map +0 -1
  1066. package/dist/renderer/cache/markerCommandCache.js +0 -63
  1067. package/dist/renderer/cache/markerCommandCache.js.map +0 -1
  1068. package/dist/renderer/cache/outlineMeshCache.js +0 -15
  1069. package/dist/renderer/cache/outlineMeshCache.js.map +0 -1
  1070. package/dist/renderer/cache/outlineStrokeMeshCache.js +0 -36
  1071. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +0 -1
  1072. package/dist/renderer/cache/strokeMeshCache.js +0 -55
  1073. package/dist/renderer/cache/strokeMeshCache.js.map +0 -1
  1074. package/dist/renderer/cullDrawCommands.js +0 -90
  1075. package/dist/renderer/cullDrawCommands.js.map +0 -1
  1076. package/dist/renderer/draw.js +0 -1135
  1077. package/dist/renderer/draw.js.map +0 -1
  1078. package/dist/renderer/drawBatch.js +0 -198
  1079. package/dist/renderer/drawBatch.js.map +0 -1
  1080. package/dist/renderer/effects/EffectTargets.js +0 -45
  1081. package/dist/renderer/effects/EffectTargets.js.map +0 -1
  1082. package/dist/renderer/effects/builtins.js +0 -31
  1083. package/dist/renderer/effects/builtins.js.map +0 -1
  1084. package/dist/renderer/effects/composite.js +0 -9
  1085. package/dist/renderer/effects/composite.js.map +0 -1
  1086. package/dist/renderer/effects/effectPrelude.js +0 -10
  1087. package/dist/renderer/effects/effectPrelude.js.map +0 -1
  1088. package/dist/renderer/effects/types.js +0 -10
  1089. package/dist/renderer/effects/types.js.map +0 -1
  1090. package/dist/renderer/glyphOutlineMesh.js +0 -67
  1091. package/dist/renderer/glyphOutlineMesh.js.map +0 -1
  1092. package/dist/renderer/index.js +0 -19
  1093. package/dist/renderer/math/color.js +0 -341
  1094. package/dist/renderer/math/color.js.map +0 -1
  1095. package/dist/renderer/math/mat3.js +0 -76
  1096. package/dist/renderer/math/mat3.js.map +0 -1
  1097. package/dist/renderer/math/patternSpace.js +0 -22
  1098. package/dist/renderer/math/patternSpace.js.map +0 -1
  1099. package/dist/renderer/math/viewToMat3.js +0 -19
  1100. package/dist/renderer/math/viewToMat3.js.map +0 -1
  1101. package/dist/renderer/paintResources.js +0 -18
  1102. package/dist/renderer/paintResources.js.map +0 -1
  1103. package/dist/renderer/paintScratch.js +0 -37
  1104. package/dist/renderer/paintScratch.js.map +0 -1
  1105. package/dist/renderer/shaders/ShaderProgram.js +0 -74
  1106. package/dist/renderer/shaders/ShaderProgram.js.map +0 -1
  1107. package/dist/renderer/shaders/batchFill.js +0 -119
  1108. package/dist/renderer/shaders/batchFill.js.map +0 -1
  1109. package/dist/renderer/shaders/customPrelude.js +0 -34
  1110. package/dist/renderer/shaders/customPrelude.js.map +0 -1
  1111. package/dist/renderer/shaders/extractUniformNames.js +0 -184
  1112. package/dist/renderer/shaders/extractUniformNames.js.map +0 -1
  1113. package/dist/renderer/shaders/glyphPaint.js +0 -61
  1114. package/dist/renderer/shaders/glyphPaint.js.map +0 -1
  1115. package/dist/renderer/shaders/gradFill.js +0 -30
  1116. package/dist/renderer/shaders/gradFill.js.map +0 -1
  1117. package/dist/renderer/shaders/imageFill.js +0 -14
  1118. package/dist/renderer/shaders/imageFill.js.map +0 -1
  1119. package/dist/renderer/shaders/pathFill.js +0 -13
  1120. package/dist/renderer/shaders/pathFill.js.map +0 -1
  1121. package/dist/renderer/shaders/patternFill.js +0 -24
  1122. package/dist/renderer/shaders/patternFill.js.map +0 -1
  1123. package/dist/renderer/shaders/registerProgram.js +0 -18
  1124. package/dist/renderer/shaders/registerProgram.js.map +0 -1
  1125. package/dist/renderer/spriteSheet.js +0 -14
  1126. package/dist/renderer/spriteSheet.js.map +0 -1
  1127. package/dist/renderer/state/GroupState.js +0 -77
  1128. package/dist/renderer/state/GroupState.js.map +0 -1
  1129. package/dist/renderer/strokeLengths.js +0 -50
  1130. package/dist/renderer/strokeLengths.js.map +0 -1
  1131. package/dist/renderer/syntheticItalic.js +0 -6
  1132. package/dist/renderer/syntheticItalic.js.map +0 -1
  1133. package/dist/renderer/textures/registerTexture.js +0 -14
  1134. package/dist/renderer/textures/registerTexture.js.map +0 -1
  1135. package/dist/scheduling/useVisibleRaf.js +0 -69
  1136. package/dist/scheduling/useVisibleRaf.js.map +0 -1
  1137. package/dist/test-seams-CuIxe0xY.d.ts +0 -356
  1138. package/dist/tools/prefs.js +0 -62
  1139. package/dist/tools/prefs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"contentHandlers.js","names":["HANDLERS","registerContentHandler","entry","i","getContentHandlers","b","a","entryMatches","match","item","err","mimeMatchesGlob","g","runIngest","remaining","items","runs","mine","it","ctx","dwarn"],"sources":["../../../src/features/ingestion/contentHandlers.ts"],"sourcesContent":["/**\n * Content-handler registry — the \"registry out\" half of external-content\n * ingestion (spec: docs/superpowers/specs/2026-07-03-content-ingestion-design.md).\n *\n * All three arrival paths (OS drop, clipboard paste, file picker /\n * `CanvasExtensionApi.ingest`) converge here: the `ingest` action calls\n * `runIngest(items, ctx)`, which partitions the items across registered\n * handlers in priority order — the first matching handler takes every item\n * it matches; leftovers continue down the list. Same per-trait registry\n * idiom as `NodeShape` / `NodeRouting`.\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 } 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. The `ctx` object is shared across all\n * handlers in one `runIngest` call, and higher-priority handlers' `handle`\n * bodies run (synchronously) before lower ones — so `kit:svg`'s\n * `text/plain` SVG fallback reads this to decline the SVG flavor of a copy\n * whose canonical weasel-JSON flavor already ingested (avoids a\n * double-paste when both flavors ride one 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 /** 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\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 [...HANDLERS].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\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 * 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(items: IngestItem[], ctx: IngestCtx): Promise<void> {\n let remaining = items;\n const runs: Promise<void>[] = [];\n\n for (const entry of getContentHandlers()) {\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":";;;AAgFA,IAAMA,IAAkC,CAAC;AAGzC,SAAgBC,EAAuB,GAAwC;CAE7E,OADAD,EAAS,KAAKE,CAAK,SACN;EACX,IAAMC,IAAIH,EAAS,QAAQE,CAAK;EAChC,AAAIC,KAAK,KAAGH,EAAS,OAAOG,GAAG,CAAC;CAClC;AACF;AAIA,SAAgBC,IAAqD;CACnE,OAAO,CAAC,GAAGJ,CAAQ,CAAC,CAAC,MAAM,GAAG,OAAOK,EAAE,YAAY,MAAMC,EAAE,YAAY,EAAE;AAC3E;AAEA,SAASC,EAAa,GAA4B,GAA2B;CAC3E,IAAM,EAAE,aAAUL;CAClB,IAAI,OAAOM,KAAU,YACnB,IAAI;EACF,OAAOA,EAAMC,CAAI;CACnB,SAASC,GAAK;EAEZ,OADA,QAAQ,KAAK,2BAA2BR,EAAM,GAAG,0BAA0BQ,CAAG,GACvE;CACT;CAGF,QADc,MAAM,QAAQF,CAAK,IAAIA,IAAQ,CAACA,CAAK,EAAA,CACtC,MAAM,MAAMG,EAAgBF,EAAK,MAAMG,CAAC,CAAC;AACxD;AAaA,eAAsBC,EAAU,GAAqB,GAA+B;CAClF,IAAIC,IAAYC,GACVC,IAAwB,CAAC;CAE/B,KAAK,IAAMd,KAASE,EAAmB,GAAG;EACxC,IAAIU,EAAU,WAAW,GAAG;EAC5B,IAAMG,IAAOH,EAAU,QAAQ,MAAOP,EAAaL,GAAOgB,CAAE,CAAC;EAC7D,AAAID,EAAK,WAAW,MACpB,IAAYH,EAAU,QAAQ,MAAO,CAACG,EAAK,SAASC,CAAE,CAAC,GACvDF,EAAK,KACH,QAAQ,QAAQ,CAAC,CACd,WAAWd,EAAM,OAAOe,GAAME,CAAG,CAAC,CAAC,CACnC,OAAO,MAAQ;GACd,QAAQ,KAAK,2BAA2BjB,EAAM,GAAG,UAAUQ,CAAG;EAChE,CAAC,CACL;CACF;CAUA,AARII,EAAU,SAAS,KACrBM,EACE,UACA,8BAA8BN,EAAU,OAAO,YAC/CA,EAAU,KAAK,MAAOI,EAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAC1C,GAGF,MAAM,QAAQ,IAAIF,CAAI;AACxB"}
1
+ {"version":3,"file":"contentHandlers.js","names":["HANDLERS","registerContentHandler","entry","i","byPriority","handlers","b","a","getContentHandlers","entryMatches","match","item","err","mimeMatchesGlob","g","couldClaim","items","UNKNOWN_MIME","globs","h","runIngest","remaining","runs","opts","mine","it","ctx","dwarn"],"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,IAAMA,IAAkC,CAAC;AAGzC,SAAgBC,EAAuB,GAAwC;CAE7E,OADAD,EAAS,KAAKE,CAAK,SACN;EACX,IAAMC,IAAIH,EAAS,QAAQE,CAAK;EAChC,AAAIC,KAAK,KAAGH,EAAS,OAAOG,GAAG,CAAC;CAClC;AACF;AAEA,SAASC,EAAW,GAAiE;CACnF,OAAO,CAAC,GAAGC,CAAQ,CAAC,CAAC,MAAM,GAAG,OAAOC,EAAE,YAAY,MAAMC,EAAE,YAAY,EAAE;AAC3E;AAIA,SAAgBC,IAAqD;CACnE,OAAOJ,EAAWJ,CAAQ;AAC5B;AAcA,SAASS,EAAa,GAA4B,GAA2B;CAC3E,IAAM,EAAE,aAAUP;CAClB,IAAI,OAAOQ,KAAU,YACnB,IAAI;EACF,OAAOA,EAAMC,CAAI;CACnB,SAASC,GAAK;EAEZ,OADA,QAAQ,KAAK,2BAA2BV,EAAM,GAAG,0BAA0BU,CAAG,GACvE;CACT;CAGF,QADc,MAAM,QAAQF,CAAK,IAAIA,IAAQ,CAACA,CAAK,EAAA,CACtC,MAAM,MAAMG,EAAgBF,EAAK,MAAMG,CAAC,CAAC;AACxD;AASA,SAAgBC,EACd,GACA,IAA2Cf,GAClC;CACT,OAAOgB,EAAM,MAAM,MACZL,EAA2B,SAAS,KAAA,IACrCA,EAAK,SAASM,KACXZ,EAAS,MAAM,MAAM;EAC1B,IAAMa,IAAQ,OAAOC,EAAE,SAAU,aAAaA,EAAE,QAAQ,CAACA,EAAE,KAAK,CAAC,CAAC,KAAK;EACvE,OAAOD,MAAU,KAAA,KAAaA,EAAM,MAAM,MAAML,EAAgBF,EAAK,MAAMG,CAAC,CAAC;CAC/E,CAAC,IAL0DT,EAAS,MAAM,MAAMI,EAAaU,GAAGR,CAAI,CAAC,CAMtG;AACH;AAaA,eAAsBS,EACpB,GACA,GACA,IAAyB,CAAC,GACX;CACf,IAAIC,IAAYL,GACVM,IAAwB,CAAC,GACzBjB,IAAWkB,EAAK,WAAWnB,EAAWmB,EAAK,QAAQ,IAAIf,EAAmB;CAEhF,KAAK,IAAMN,KAASG,GAAU;EAC5B,IAAIgB,EAAU,WAAW,GAAG;EAC5B,IAAMG,IAAOH,EAAU,QAAQ,MAAOZ,EAAaP,GAAOuB,CAAE,CAAC;EAC7D,AAAID,EAAK,WAAW,MACpB,IAAYH,EAAU,QAAQ,MAAO,CAACG,EAAK,SAASC,CAAE,CAAC,GACvDH,EAAK,KACH,QAAQ,QAAQ,CAAC,CACd,WAAWpB,EAAM,OAAOsB,GAAME,CAAG,CAAC,CAAC,CACnC,OAAO,MAAQ;GACd,QAAQ,KAAK,2BAA2BxB,EAAM,GAAG,UAAUU,CAAG;EAChE,CAAC,CACL;CACF;CAUA,AARIS,EAAU,SAAS,KACrBM,EACE,UACA,8BAA8BN,EAAU,OAAO,YAC/CA,EAAU,KAAK,MAAOI,EAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAC1C,GAGF,MAAM,QAAQ,IAAIH,CAAI;AACxB"}
@@ -1,45 +1,42 @@
1
+ import { arrivalBounds as e } from "./placement.js";
1
2
  //#region src/features/ingestion/imageHandler.ts
2
- var e = .9, t = async (e) => {
3
+ var t = .9, n = async (e) => {
3
4
  let t = await createImageBitmap(e), n = {
4
5
  width: t.width,
5
6
  height: t.height
6
7
  };
7
8
  return t.close(), n;
8
- }, n = (e) => new Promise((t, n) => {
9
+ }, r = (e) => new Promise((t, n) => {
9
10
  let r = new FileReader();
10
11
  r.onload = () => t(r.result), r.onerror = () => n(r.error), r.readAsDataURL(e);
11
- }), r = t, i = n;
12
- async function a(t, n, a = {}) {
13
- let o = 0;
14
- for (let s of t) try {
15
- let t = await (a.measure ?? r)(s), c = n.resolveSrc ? await n.resolveSrc(s) : await i(s);
16
- !n.resolveSrc && a.mimeOverride && (c = c.replace(/^data:[^;,]*/, `data:${a.mimeOverride}`));
17
- let l = n.viewportWorldRect(), u = Math.min(1, l.width * e / t.width, l.height * e / t.height), d = t.width * u, f = t.height * u, p = n.point ?? {
18
- x: l.x + l.width / 2,
19
- y: l.y + l.height / 2
20
- }, m = o * 24;
21
- n.insert.commit({
22
- x: p.x - d / 2 + m,
23
- y: p.y - f / 2 + m,
24
- width: d,
25
- height: f
26
- }, {
12
+ }), i = n, a = r;
13
+ async function o(n, r, o = {}) {
14
+ let s = 0;
15
+ for (let c of n) try {
16
+ let n = await (o.measure ?? i)(c), l = r.resolveSrc ? await r.resolveSrc(c) : await a(c);
17
+ !r.resolveSrc && o.mimeOverride && (l = l.replace(/^data:[^;,]*/, `data:${o.mimeOverride}`));
18
+ let u = r.viewportWorldRect(), d = Math.min(1, u.width * t / n.width, u.height * t / n.height), f = {
19
+ width: n.width * d,
20
+ height: n.height * d
21
+ };
22
+ r.insert.commit(e(r, f, s), {
27
23
  kind: "image",
28
- src: c
29
- }), o++;
24
+ src: l
25
+ }), s++;
30
26
  } catch (e) {
31
- console.warn(`weasel ingest: image "${s.name}" failed to load`, e);
27
+ console.warn(`weasel ingest: image "${c.name}" failed to load`, e);
32
28
  }
33
29
  }
34
- var o = {
30
+ var s = {
35
31
  id: "kit:image",
36
32
  match: (e) => e.kind === "file" && e.mime.startsWith("image/"),
33
+ types: ["image/*"],
37
34
  priority: -100,
38
35
  handle(e, t) {
39
- return a(e.flatMap((e) => e.kind === "file" ? [e.file] : []), t);
36
+ return o(e.flatMap((e) => e.kind === "file" ? [e.file] : []), t);
40
37
  }
41
38
  };
42
39
  //#endregion
43
- export { a as embedFilesAsImageNodes, o as kitImageHandler };
40
+ export { o as embedFilesAsImageNodes, s as kitImageHandler };
44
41
 
45
42
  //# sourceMappingURL=imageHandler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"imageHandler.js","names":["VIEWPORT_FIT","defaultMeasure","bitmap","file","size","defaultToDataUri","reader","resolve","reject","measure","toDataUri","embedFilesAsImageNodes","index","files","natural","opts","src","ctx","view","scale","width","height","center","offset","err","kitImageHandler","item","items","it"],"sources":["../../../src/features/ingestion/imageHandler.ts"],"sourcesContent":["/**\n * The kit's `image/*` content handler — the one handler shipped by default.\n *\n * For each image file: resolve a `src` (consumer `resolveSrc` when provided,\n * else embed as a `data:` URI so the scene stays serializable), measure the\n * natural pixel size, fit-clamp to 90% of the visible viewport, and insert a\n * leaf node with `data.image = { src }` via the insert dep (id/layer/undoable\n * op supplied there — same contract as `useImageTool`).\n *\n * Placement: centered on `ctx.point` (drop / pointed ingest) or the viewport\n * center (paste / point-less). Multi-file ingests cascade by a fixed offset.\n *\n * Registered at priority -100 so any consumer handler (default 0) can take\n * image files first.\n */\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\nimport type { IngestItem } from '@weasel-js/routing';\n\nconst CASCADE_OFFSET_PX = 24;\nconst VIEWPORT_FIT = 0.9;\n\nexport type Measure = (file: File) => Promise<{ width: number; height: number }>;\ntype ToDataUri = (file: File) => Promise<string>;\n\nconst defaultMeasure: Measure = async (file) => {\n const bitmap = await createImageBitmap(file);\n const size = { width: bitmap.width, height: bitmap.height };\n bitmap.close();\n return size;\n};\n\nconst defaultToDataUri: ToDataUri = (file) =>\n new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n\nlet measure: Measure = defaultMeasure;\nlet toDataUri: ToDataUri = defaultToDataUri;\n\n/** @internal Options for {@link embedFilesAsImageNodes} — used by the kit\n * SVG handler, whose files can't go through `createImageBitmap`. */\nexport interface EmbedImageOptions {\n /** Replace the raster measurer for these files (the SVG handler supplies\n * an `Image`-element one). Defaults to the module measurer (seam-aware). */\n measure?: Measure;\n /** Force the data-URI MIME. A sniffed `.svg` whose `File.type` was empty\n * would otherwise embed as `data:application/octet-stream;…`, which\n * browsers refuse to rasterize. No effect on `resolveSrc` output. */\n mimeOverride?: string;\n}\n\n/**\n * @internal The shared embed engine: for each file, measure → resolve a\n * `src` → fit-clamp to 90% of the visible viewport → insert one image node\n * centered on `ctx.point` (or the viewport center), cascading multi-file\n * batches by a fixed offset. A file that fails to measure or resolve is\n * skipped with a `console.warn`; the rest proceed.\n */\nexport async function embedFilesAsImageNodes(\n files: File[],\n ctx: IngestCtx,\n opts: EmbedImageOptions = {},\n): Promise<void> {\n let index = 0;\n for (const file of files) {\n try {\n // Measure first: a corrupt file should fail cheaply here, not after\n // a consumer `resolveSrc` has already uploaded it somewhere.\n const natural = await (opts.measure ?? measure)(file);\n let src = ctx.resolveSrc ? await ctx.resolveSrc(file) : await toDataUri(file);\n if (!ctx.resolveSrc && opts.mimeOverride) {\n src = src.replace(/^data:[^;,]*/, `data:${opts.mimeOverride}`);\n }\n const view = ctx.viewportWorldRect();\n const scale = Math.min(\n 1,\n (view.width * VIEWPORT_FIT) / natural.width,\n (view.height * VIEWPORT_FIT) / natural.height,\n );\n const width = natural.width * scale;\n const height = natural.height * scale;\n const center = ctx.point ?? {\n x: view.x + view.width / 2,\n y: view.y + view.height / 2,\n };\n const offset = index * CASCADE_OFFSET_PX;\n ctx.insert.commit(\n {\n x: center.x - width / 2 + offset,\n y: center.y - height / 2 + offset,\n width,\n height,\n },\n { kind: 'image', src },\n );\n index++;\n } catch (err) {\n console.warn(`weasel ingest: image \"${file.name}\" failed to load`, err);\n }\n }\n}\n\nexport const kitImageHandler: ContentHandlerEntry = {\n id: 'kit:image',\n match: (item: IngestItem) => item.kind === 'file' && item.mime.startsWith('image/'),\n priority: -100,\n handle(items, ctx: IngestCtx) {\n const files = items.flatMap((it) => (it.kind === 'file' ? [it.file] : []));\n return embedFilesAsImageNodes(files, ctx);\n },\n};\n\n/** @internal test seam — override the bitmap measurer (jsdom has no\n * `createImageBitmap`). Not part of the public barrel. */\nexport function __setImageMeasureForTests(fn: Measure): void {\n measure = fn;\n}\n\n/** @internal test seam — override the FileReader embed. */\nexport function __setFileToDataUriForTests(fn: ToDataUri): void {\n toDataUri = fn;\n}\n\n/** @internal test seam — restore default seams. */\nexport function _resetImageHandlerSeamsForTests(): void {\n measure = defaultMeasure;\n toDataUri = defaultToDataUri;\n}\n"],"mappings":";AAkBA,IACMA,IAAe,IAKfC,IAA0B,OAAO,MAAS;CAC9C,IAAMC,IAAS,MAAM,kBAAkBC,CAAI,GACrCC,IAAO;EAAE,OAAOF,EAAO;EAAO,QAAQA,EAAO;CAAO;CAE1D,OADAA,EAAO,MAAM,GACNE;AACT,GAEMC,KAA+B,MACnC,IAAI,SAAS,GAAS,MAAW;CAC/B,IAAMC,IAAS,IAAI,WAAW;CAG9B,AAFA,EAAO,eAAeC,EAAQD,EAAO,MAAgB,GACrD,EAAO,gBAAgBE,EAAOF,EAAO,KAAK,GAC1CA,EAAO,cAAcH,CAAI;AAC3B,CAAC,GAECM,IAAmBR,GACnBS,IAAuBL;AAqB3B,eAAsBM,EACpB,GACA,GACA,IAA0B,CAAC,GACZ;CACf,IAAIC,IAAQ;CACZ,KAAK,IAAMT,KAAQU,GACjB,IAAI;EAGF,IAAMC,IAAU,OAAOC,EAAK,WAAWN,EAAA,CAASN,CAAI,GAChDa,IAAMC,EAAI,aAAa,MAAMA,EAAI,WAAWd,CAAI,IAAI,MAAMO,EAAUP,CAAI;EAC5E,AAAI,CAACc,EAAI,cAAcF,EAAK,iBAC1B,IAAMC,EAAI,QAAQ,gBAAgB,QAAQD,EAAK,cAAc;EAE/D,IAAMG,IAAOD,EAAI,kBAAkB,GAC7BE,IAAQ,KAAK,IACjB,GACCD,EAAK,QAAQlB,IAAgBc,EAAQ,OACrCI,EAAK,SAASlB,IAAgBc,EAAQ,MACzC,GACMM,IAAQN,EAAQ,QAAQK,GACxBE,IAASP,EAAQ,SAASK,GAC1BG,IAASL,EAAI,SAAS;GAC1B,GAAGC,EAAK,IAAIA,EAAK,QAAQ;GACzB,GAAGA,EAAK,IAAIA,EAAK,SAAS;EAC5B,GACMK,IAASX,IAAQ;EAUvB,AATAK,EAAI,OAAO,OACT;GACE,GAAGK,EAAO,IAAIF,IAAQ,IAAIG;GAC1B,GAAGD,EAAO,IAAID,IAAS,IAAIE;GAC3B;GACA;EACF,GACA;GAAE,MAAM;GAAS;EAAI,CACvB,GACA;CACF,SAASC,GAAK;EACZ,QAAQ,KAAK,yBAAyBrB,EAAK,KAAK,mBAAmBqB,CAAG;CACxE;AAEJ;AAEA,IAAaC,IAAuC;CAClD,IAAI;CACJ,QAAQ,MAAqBC,EAAK,SAAS,UAAUA,EAAK,KAAK,WAAW,QAAQ;CAClF,UAAU;CACV,OAAO,GAAO,GAAgB;EAE5B,OAAOf,EADOgB,EAAM,SAAS,MAAQC,EAAG,SAAS,SAAS,CAACA,EAAG,IAAI,IAAI,CAAC,CACzC,GAAOX,CAAG;CAC1C;AACF"}
1
+ {"version":3,"file":"imageHandler.js","names":["VIEWPORT_FIT","defaultMeasure","bitmap","file","size","defaultToDataUri","reader","resolve","reject","measure","toDataUri","embedFilesAsImageNodes","index","files","natural","opts","src","ctx","view","scale","arrivalBounds","err","kitImageHandler","item","items","it"],"sources":["../../../src/features/ingestion/imageHandler.ts"],"sourcesContent":["/**\n * The kit's `image/*` content handler. With no consumer `resolveSrc`, a file\n * embeds as a `data:` URI so the scene stays serializable.\n *\n * Registered at priority -100 so any consumer handler (default 0) can take\n * image files first.\n */\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\nimport type { IngestItem } from '@weasel-js/routing';\nimport { arrivalBounds } from './placement';\n\nconst VIEWPORT_FIT = 0.9;\n\nexport type Measure = (file: File) => Promise<{ width: number; height: number }>;\ntype ToDataUri = (file: File) => Promise<string>;\n\nconst defaultMeasure: Measure = async (file) => {\n const bitmap = await createImageBitmap(file);\n const size = { width: bitmap.width, height: bitmap.height };\n bitmap.close();\n return size;\n};\n\nconst defaultToDataUri: ToDataUri = (file) =>\n new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => resolve(reader.result as string);\n reader.onerror = () => reject(reader.error);\n reader.readAsDataURL(file);\n });\n\nlet measure: Measure = defaultMeasure;\nlet toDataUri: ToDataUri = defaultToDataUri;\n\n/** @internal Options for {@link embedFilesAsImageNodes} — used by the kit\n * SVG handler, whose files can't go through `createImageBitmap`. */\nexport interface EmbedImageOptions {\n /** Replace the raster measurer for these files (the SVG handler supplies\n * an `Image`-element one). Defaults to the module measurer (seam-aware). */\n measure?: Measure;\n /** Force the data-URI MIME. A sniffed `.svg` whose `File.type` was empty\n * would otherwise embed as `data:application/octet-stream;…`, which\n * browsers refuse to rasterize. No effect on `resolveSrc` output. */\n mimeOverride?: string;\n}\n\n/**\n * @internal The shared embed engine: for each file, measure → resolve a\n * `src` → fit-clamp to 90% of the visible viewport → insert one image node\n * centered on `ctx.point` (or the viewport center), cascading multi-file\n * batches by a fixed offset. A file that fails to measure or resolve is\n * skipped with a `console.warn`; the rest proceed.\n */\nexport async function embedFilesAsImageNodes(\n files: File[],\n ctx: IngestCtx,\n opts: EmbedImageOptions = {},\n): Promise<void> {\n let index = 0;\n for (const file of files) {\n try {\n // Measure first: a corrupt file should fail cheaply here, not after\n // a consumer `resolveSrc` has already uploaded it somewhere.\n const natural = await (opts.measure ?? measure)(file);\n let src = ctx.resolveSrc ? await ctx.resolveSrc(file) : await toDataUri(file);\n if (!ctx.resolveSrc && opts.mimeOverride) {\n src = src.replace(/^data:[^;,]*/, `data:${opts.mimeOverride}`);\n }\n const view = ctx.viewportWorldRect();\n const scale = Math.min(\n 1,\n (view.width * VIEWPORT_FIT) / natural.width,\n (view.height * VIEWPORT_FIT) / natural.height,\n );\n const size = { width: natural.width * scale, height: natural.height * scale };\n ctx.insert.commit(arrivalBounds(ctx, size, index), { kind: 'image', src });\n index++;\n } catch (err) {\n console.warn(`weasel ingest: image \"${file.name}\" failed to load`, err);\n }\n }\n}\n\nexport const kitImageHandler: ContentHandlerEntry = {\n id: 'kit:image',\n match: (item: IngestItem) => item.kind === 'file' && item.mime.startsWith('image/'),\n types: ['image/*'],\n priority: -100,\n handle(items, ctx: IngestCtx) {\n const files = items.flatMap((it) => (it.kind === 'file' ? [it.file] : []));\n return embedFilesAsImageNodes(files, ctx);\n },\n};\n\n/** @internal test seam — override the bitmap measurer (jsdom has no\n * `createImageBitmap`). Not part of the public barrel. */\nexport function __setImageMeasureForTests(fn: Measure): void {\n measure = fn;\n}\n\n/** @internal test seam — override the FileReader embed. */\nexport function __setFileToDataUriForTests(fn: ToDataUri): void {\n toDataUri = fn;\n}\n\n/** @internal test seam — restore default seams. */\nexport function _resetImageHandlerSeamsForTests(): void {\n measure = defaultMeasure;\n toDataUri = defaultToDataUri;\n}\n"],"mappings":";;AAWA,IAAMA,IAAe,IAKfC,IAA0B,OAAO,MAAS;CAC9C,IAAMC,IAAS,MAAM,kBAAkBC,CAAI,GACrCC,IAAO;EAAE,OAAOF,EAAO;EAAO,QAAQA,EAAO;CAAO;CAE1D,OADAA,EAAO,MAAM,GACNE;AACT,GAEMC,KAA+B,MACnC,IAAI,SAAS,GAAS,MAAW;CAC/B,IAAMC,IAAS,IAAI,WAAW;CAG9B,AAFA,EAAO,eAAeC,EAAQD,EAAO,MAAgB,GACrD,EAAO,gBAAgBE,EAAOF,EAAO,KAAK,GAC1CA,EAAO,cAAcH,CAAI;AAC3B,CAAC,GAECM,IAAmBR,GACnBS,IAAuBL;AAqB3B,eAAsBM,EACpB,GACA,GACA,IAA0B,CAAC,GACZ;CACf,IAAIC,IAAQ;CACZ,KAAK,IAAMT,KAAQU,GACjB,IAAI;EAGF,IAAMC,IAAU,OAAOC,EAAK,WAAWN,EAAA,CAASN,CAAI,GAChDa,IAAMC,EAAI,aAAa,MAAMA,EAAI,WAAWd,CAAI,IAAI,MAAMO,EAAUP,CAAI;EAC5E,AAAI,CAACc,EAAI,cAAcF,EAAK,iBAC1B,IAAMC,EAAI,QAAQ,gBAAgB,QAAQD,EAAK,cAAc;EAE/D,IAAMG,IAAOD,EAAI,kBAAkB,GAC7BE,IAAQ,KAAK,IACjB,GACCD,EAAK,QAAQlB,IAAgBc,EAAQ,OACrCI,EAAK,SAASlB,IAAgBc,EAAQ,MACzC,GACMV,IAAO;GAAE,OAAOU,EAAQ,QAAQK;GAAO,QAAQL,EAAQ,SAASK;EAAM;EAE5E,AADAF,EAAI,OAAO,OAAOG,EAAcH,GAAKb,GAAMQ,CAAK,GAAG;GAAE,MAAM;GAAS;EAAI,CAAC,GACzE;CACF,SAASS,GAAK;EACZ,QAAQ,KAAK,yBAAyBlB,EAAK,KAAK,mBAAmBkB,CAAG;CACxE;AAEJ;AAEA,IAAaC,IAAuC;CAClD,IAAI;CACJ,QAAQ,MAAqBC,EAAK,SAAS,UAAUA,EAAK,KAAK,WAAW,QAAQ;CAClF,OAAO,CAAC,SAAS;CACjB,UAAU;CACV,OAAO,GAAO,GAAgB;EAE5B,OAAOZ,EADOa,EAAM,SAAS,MAAQC,EAAG,SAAS,SAAS,CAACA,EAAG,IAAI,IAAI,CAAC,CACzC,GAAOR,CAAG;CAC1C;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"openFilePicker.js","names":["openFilePicker","input","opts","finish","resolve","files"],"sources":["../../../src/features/ingestion/openFilePicker.ts"],"sourcesContent":["/**\n * `openFilePicker` — tiny DOM helper opening the OS file dialog and resolving\n * the chosen `File[]` ([] on cancel). Pairs with `CanvasExtensionApi.ingest`:\n *\n * ```ts\n * const files = await openFilePicker({ accept: 'image/*', multiple: true });\n * canvasRef.current?.ingest(files);\n * ```\n *\n * Must be called from a user-activation context (a click handler) — browsers\n * block programmatic `input.click()` otherwise.\n */\nexport interface OpenFilePickerOptions {\n /** `<input accept>` filter, e.g. `'image/*'` or `'.csv,text/csv'`. */\n accept?: string;\n /** Allow multi-select. Default false. */\n multiple?: boolean;\n}\n\n/** Show the browser's file picker and resolve with what the user chose —\n * empty when they cancel. Must be called from a user gesture. */\nexport function openFilePicker(opts: OpenFilePickerOptions = {}): Promise<File[]> {\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.hidden = true;\n if (opts.accept) input.accept = opts.accept;\n if (opts.multiple) input.multiple = true;\n document.body.appendChild(input);\n const finish = (files: File[]) => {\n input.remove();\n resolve(files);\n };\n input.addEventListener('change', () => finish(Array.from(input.files ?? [])), { once: true });\n // Fired by browsers that support it when the dialog is dismissed. When\n // unsupported, the input simply leaks until the page unloads — acceptable\n // for a hidden element; no timer heuristics.\n input.addEventListener('cancel', () => finish([]), { once: true });\n input.click();\n });\n}\n"],"mappings":";AAqBA,SAAgBA,EAAe,IAA8B,CAAC,GAAoB;CAChF,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAMC,IAAQ,SAAS,cAAc,OAAO;EAK5C,AAJA,EAAM,OAAO,QACb,EAAM,SAAS,IACXC,EAAK,WAAQ,EAAM,SAASA,EAAK,SACjCA,EAAK,aAAU,EAAM,WAAW,KACpC,SAAS,KAAK,YAAYD,CAAK;EAC/B,IAAME,KAAU,MAAkB;GAEhC,AADAF,EAAM,OAAO,GACbG,EAAQC,CAAK;EACf;EAMA,AALAJ,EAAM,iBAAiB,gBAAgBE,EAAO,MAAM,KAAKF,EAAM,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,GAAK,CAAC,GAI5FA,EAAM,iBAAiB,gBAAgBE,EAAO,CAAC,CAAC,GAAG,EAAE,MAAM,GAAK,CAAC,GACjEF,EAAM,MAAM;CACd,CAAC;AACH"}
1
+ {"version":3,"file":"openFilePicker.js","names":["openFilePicker","input","opts","finish","resolve","files"],"sources":["../../../src/features/ingestion/openFilePicker.ts"],"sourcesContent":["/** Options for {@link openFilePicker}. */\nexport interface OpenFilePickerOptions {\n /** `<input accept>` filter, e.g. `'image/*'` or `'.csv,text/csv'`. */\n accept?: string;\n /** Allow multi-select. Default false. */\n multiple?: boolean;\n}\n\n/**\n * Show the browser's file picker and resolve with what the user chose —\n * empty when they cancel. Must be called from a user gesture (a click\n * handler): browsers block programmatic `input.click()` otherwise. Pairs\n * with `CanvasExtensionApi.ingest`:\n *\n * ```ts\n * const files = await openFilePicker({ accept: 'image/*', multiple: true });\n * canvasRef.current?.ingest(files);\n * ```\n */\nexport function openFilePicker(opts: OpenFilePickerOptions = {}): Promise<File[]> {\n return new Promise((resolve) => {\n const input = document.createElement('input');\n input.type = 'file';\n input.hidden = true;\n if (opts.accept) input.accept = opts.accept;\n if (opts.multiple) input.multiple = true;\n document.body.appendChild(input);\n const finish = (files: File[]) => {\n input.remove();\n resolve(files);\n };\n input.addEventListener('change', () => finish(Array.from(input.files ?? [])), { once: true });\n // Where `cancel` is unsupported, the hidden input leaks until the page\n // unloads.\n input.addEventListener('cancel', () => finish([]), { once: true });\n input.click();\n });\n}\n"],"mappings":";AAmBA,SAAgBA,EAAe,IAA8B,CAAC,GAAoB;CAChF,OAAO,IAAI,SAAS,MAAY;EAC9B,IAAMC,IAAQ,SAAS,cAAc,OAAO;EAK5C,AAJA,EAAM,OAAO,QACb,EAAM,SAAS,IACXC,EAAK,WAAQ,EAAM,SAASA,EAAK,SACjCA,EAAK,aAAU,EAAM,WAAW,KACpC,SAAS,KAAK,YAAYD,CAAK;EAC/B,IAAME,KAAU,MAAkB;GAEhC,AADAF,EAAM,OAAO,GACbG,EAAQC,CAAK;EACf;EAKA,AAJAJ,EAAM,iBAAiB,gBAAgBE,EAAO,MAAM,KAAKF,EAAM,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,GAAK,CAAC,GAG5FA,EAAM,iBAAiB,gBAAgBE,EAAO,CAAC,CAAC,GAAG,EAAE,MAAM,GAAK,CAAC,GACjEF,EAAM,MAAM;CACd,CAAC;AACH"}
@@ -0,0 +1,16 @@
1
+ function e(e, t, n) {
2
+ let r = e.viewportWorldRect(), i = e.point ?? {
3
+ x: r.x + r.width / 2,
4
+ y: r.y + r.height / 2
5
+ }, a = n * 24;
6
+ return {
7
+ x: i.x - t.width / 2 + a,
8
+ y: i.y - t.height / 2 + a,
9
+ width: t.width,
10
+ height: t.height
11
+ };
12
+ }
13
+ //#endregion
14
+ export { e as arrivalBounds };
15
+
16
+ //# sourceMappingURL=placement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement.js","names":["arrivalBounds","view","ctx","center","offset","index","size"],"sources":["../../../src/features/ingestion/placement.ts"],"sourcesContent":["import type { IngestCtx } from './contentHandlers';\n\nconst CASCADE_OFFSET_PX = 24;\n\n/**\n * Where the kit's handlers put arriving content of a given size: centered on\n * `ctx.point` (a drop, a pointed ingest) or on the viewport (a paste), with the\n * `index`-th item of one arrival stepped down and right of the first.\n */\nexport function arrivalBounds(\n ctx: IngestCtx,\n size: { width: number; height: number },\n index: number,\n): { x: number; y: number; width: number; height: number } {\n const view = ctx.viewportWorldRect();\n const center = ctx.point ?? { x: view.x + view.width / 2, y: view.y + view.height / 2 };\n const offset = index * CASCADE_OFFSET_PX;\n return {\n x: center.x - size.width / 2 + offset,\n y: center.y - size.height / 2 + offset,\n width: size.width,\n height: size.height,\n };\n}\n"],"mappings":"AASA,SAAgBA,EACd,GACA,GACA,GACyD;CACzD,IAAMC,IAAOC,EAAI,kBAAkB,GAC7BC,IAASD,EAAI,SAAS;EAAE,GAAGD,EAAK,IAAIA,EAAK,QAAQ;EAAG,GAAGA,EAAK,IAAIA,EAAK,SAAS;CAAE,GAChFG,IAASC,IAAQ;CACvB,OAAO;EACL,GAAGF,EAAO,IAAIG,EAAK,QAAQ,IAAIF;EAC/B,GAAGD,EAAO,IAAIG,EAAK,SAAS,IAAIF;EAChC,OAAOE,EAAK;EACZ,QAAQA,EAAK;CACf;AACF"}
@@ -1,16 +1,16 @@
1
- import { registerContentHandler as e } from "./contentHandlers.js";
2
- import { kitImageHandler as t } from "./imageHandler.js";
3
- import { kitSvgHandler as n } from "./svgHandler.js";
4
- import { kitWeaselJsonHandler as r } from "./weaselJsonHandler.js";
1
+ import { kitImageHandler as e } from "./imageHandler.js";
2
+ import { kitSvgHandler as t } from "./svgHandler.js";
3
+ import { kitWeaselJsonHandler as n } from "./weaselJsonHandler.js";
4
+ import { registerContentHandler as r } from "./contentHandlers.js";
5
5
  //#region src/features/ingestion/registerKitHandlers.ts
6
6
  var i = 0, a = null;
7
7
  function o() {
8
8
  if (i++, i === 1) {
9
9
  let i = [
10
+ e,
10
11
  t,
11
- n,
12
- r
13
- ].map(e);
12
+ n
13
+ ].map(r);
14
14
  a = () => {
15
15
  for (let e of i) e();
16
16
  };
@@ -42,6 +42,11 @@ var o = async (e) => {
42
42
  }, s = {
43
43
  id: "kit:svg",
44
44
  match: (e) => i(e) || e.kind === "string" && e.mime === "text/plain" && a(e.text),
45
+ types: [
46
+ t,
47
+ "application/octet-stream",
48
+ "text/plain"
49
+ ],
45
50
  priority: -90,
46
51
  handle(n, r) {
47
52
  let i = n.flatMap((e) => e.kind === "file" ? [e.file] : []);
@@ -1 +1 @@
1
- {"version":3,"file":"svgHandler.js","names":["SVG_MIME","FALLBACK_WIDTH","FALLBACK_HEIGHT","isSvgFileItem","item","sniffSvgText","text","end","measure","url","file","img","kitSvgHandler","files","items","it","ctx","embedFilesAsImageNodes","f"],"sources":["../../../src/features/ingestion/svgHandler.ts"],"sourcesContent":["/**\n * The kit's `image/svg+xml` content handler.\n *\n * Default: a dropped SVG stays **one scene node** — the standard\n * embedded-image contract (`data.image.src` as a `data:image/svg+xml;…`\n * URI, source bytes preserved verbatim). Rendering rides the normal\n * `imageCache` path: browsers rasterize SVG in an `<img>`, so only the\n * ingest-time measurement needs special handling — Chromium's\n * `createImageBitmap` rejects raw SVG blobs, so this handler measures via\n * an `Image` element instead, falling back to 300×150 (the CSS default\n * object size) when the file declares no intrinsic dimensions.\n *\n * `<SceneCanvas ingestion={{ svg: { unpack: unpackSvgFiles } }}>` switches to\n * parsing the file into native scene nodes. The unpacker is injected (see\n * `SvgIngestOptions.unpack`) because the SVG parser lives in\n * `@weasel-js/svg`, which depends on this package.\n *\n * Registered at priority -90: ahead of `kit:image` (-100) so SVG files\n * never hit the raster measure path, still behind any consumer handler\n * (default 0).\n */\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\nimport type { IngestItem } from '@weasel-js/routing';\nimport { embedFilesAsImageNodes, type Measure } from './imageHandler';\n\nexport const SVG_MIME = 'image/svg+xml';\n\n// CSS default object size — what browsers use for replaced content with no\n// intrinsic dimensions (e.g. a viewBox-only SVG in an <img>).\nconst FALLBACK_WIDTH = 300;\nconst FALLBACK_HEIGHT = 150;\n\n/**\n * True for file items that are SVG by MIME — or by `.svg` extension when\n * the source offered no usable type (an empty `File.type` normalizes to\n * `application/octet-stream` at materialization).\n */\nexport function isSvgFileItem(item: IngestItem): boolean {\n if (item.kind !== 'file') return false;\n if (item.mime === SVG_MIME) return true;\n return item.mime === 'application/octet-stream' && /\\.svg$/i.test(item.file.name);\n}\n\n/**\n * Strict-prefix sniff: could this text be an SVG document? `<svg` (or an XML\n * declaration, then optional whitespace/comments/DOCTYPE, then `<svg`) must\n * open the document — no mid-document substring scans, same discipline as\n * `sniffWeaselClipboardText`. Exists because Safari drops both custom MIMEs\n * and `image/svg+xml` from async clipboard writes, leaving `text/plain` as\n * the only surviving flavor of an SVG copy.\n */\nexport function sniffSvgText(text: string): boolean {\n let t = text.trimStart();\n if (t.startsWith('<?xml')) {\n const end = t.indexOf('?>');\n if (end < 0) return false;\n t = t.slice(end + 2);\n }\n for (;;) {\n t = t.trimStart();\n if (t.startsWith('<!--')) {\n const end = t.indexOf('-->');\n if (end < 0) return false;\n t = t.slice(end + 3);\n continue;\n }\n // Illustrator-style preamble: <!DOCTYPE svg PUBLIC \"...\" \"...\">. Skipping\n // ANY doctype is safe — a non-SVG doctype's root element fails the final\n // `<svg` check anyway. (No internal-subset handling; clipboard SVG\n // preambles don't carry `[...]` blocks.)\n if (/^<!doctype/i.test(t)) {\n const end = t.indexOf('>');\n if (end < 0) return false;\n t = t.slice(end + 1);\n continue;\n }\n break;\n }\n return /^<svg[\\s>/]/i.test(t);\n}\n\nconst defaultMeasure: Measure = async (file) => {\n const url = URL.createObjectURL(file);\n try {\n const img = new Image();\n img.src = url;\n await img.decode();\n return {\n width: img.naturalWidth || FALLBACK_WIDTH,\n height: img.naturalHeight || FALLBACK_HEIGHT,\n };\n } finally {\n URL.revokeObjectURL(url);\n }\n};\n\nlet measure: Measure = defaultMeasure;\n\nexport const kitSvgHandler: ContentHandlerEntry = {\n id: 'kit:svg',\n // Files by MIME/extension, plus the text/plain fallback flavor: SVG markup\n // pasted as plain text (the only flavor Safari lets an SVG copy keep).\n match: (item) =>\n isSvgFileItem(item)\n || (item.kind === 'string' && item.mime === 'text/plain' && sniffSvgText(item.text)),\n priority: -90,\n handle(items, ctx: IngestCtx) {\n const files = items.flatMap((it) => (it.kind === 'file' ? [it.file] : []));\n // String items (the text/plain SVG fallback flavor) enter the same file\n // path — wrap the markup in a File so unpack/embed stays one code path.\n // BUT skip them when the weasel-JSON handler already pasted this event's\n // copy: draw writes weasel-JSON + SVG together, so ingesting both would\n // double-paste. (ctx is shared per event; the weasel handler runs first.)\n // WARNING: this read must stay before any `await` in this handle — the\n // sync-ordering of handler microtasks is what makes the flag visible.\n if (!ctx.consumedWeaselPayload) {\n for (const it of items) {\n if (it.kind === 'string') files.push(new File([it.text], 'pasted.svg', { type: SVG_MIME }));\n }\n }\n if (files.length === 0) return;\n if (ctx.svg?.unpack) return ctx.svg.unpack(files, ctx);\n // Thunk (not the variable) so the test seam is read at call time.\n return embedFilesAsImageNodes(files, ctx, {\n measure: (f) => measure(f),\n mimeOverride: SVG_MIME,\n });\n },\n};\n\n/** @internal test seam — override the Image-element measurer (jsdom can't\n * decode SVG). Not part of the public barrel. */\nexport function __setSvgMeasureForTests(fn: Measure): void {\n measure = fn;\n}\n\n/** @internal test seam — restore the default measurer. */\nexport function _resetSvgHandlerSeamsForTests(): void {\n measure = defaultMeasure;\n}\n"],"mappings":";;AAyBA,IAAaA,IAAW,iBAIlBC,IAAiB,KACjBC,IAAkB;AAOxB,SAAgBC,EAAc,GAA2B;CAGvD,OAFIC,EAAK,SAAS,SACdA,EAAK,SAASJ,KACXI,EAAK,SAAS,8BAA8B,UAAU,KAAKA,EAAK,KAAK,IAAI,IAF/C;AAGnC;AAUA,SAAgBC,EAAa,GAAuB;CAClD,IAAI,IAAIC,EAAK,UAAU;CACvB,IAAI,EAAE,WAAW,OAAO,GAAG;EACzB,IAAMC,IAAM,EAAE,QAAQ,IAAI;EAC1B,IAAIA,IAAM,GAAG,OAAO;EACpB,IAAI,EAAE,MAAMA,IAAM,CAAC;CACrB;CACA,SAAS;EAEP,IADA,IAAI,EAAE,UAAU,GACZ,EAAE,WAAW,MAAM,GAAG;GACxB,IAAMA,IAAM,EAAE,QAAQ,KAAK;GAC3B,IAAIA,IAAM,GAAG,OAAO;GACpB,IAAI,EAAE,MAAMA,IAAM,CAAC;GACnB;EACF;EAKA,IAAI,cAAc,KAAK,CAAC,GAAG;GACzB,IAAMA,IAAM,EAAE,QAAQ,GAAG;GACzB,IAAIA,IAAM,GAAG,OAAO;GACpB,IAAI,EAAE,MAAMA,IAAM,CAAC;GACnB;EACF;EACA;CACF;CACA,OAAO,eAAe,KAAK,CAAC;AAC9B;AAiBA,IAAIC,IAAmB,OAfgB,MAAS;CAC9C,IAAMC,IAAM,IAAI,gBAAgBC,CAAI;CACpC,IAAI;EACF,IAAMC,IAAM,IAAI,MAAM;EAGtB,OAFA,EAAI,MAAMF,GACV,MAAME,EAAI,OAAO,GACV;GACL,OAAOA,EAAI,gBAAgBV;GAC3B,QAAQU,EAAI,iBAAiBT;EAC/B;CACF,UAAU;EACR,IAAI,gBAAgBO,CAAG;CACzB;AACF,GAIaG,IAAqC;CAChD,IAAI;CAGJ,QAAQ,MACNT,EAAcC,CAAI,KACdA,EAAK,SAAS,YAAYA,EAAK,SAAS,gBAAgBC,EAAaD,EAAK,IAAI;CACpF,UAAU;CACV,OAAO,GAAO,GAAgB;EAC5B,IAAMS,IAAQC,EAAM,SAAS,MAAQC,EAAG,SAAS,SAAS,CAACA,EAAG,IAAI,IAAI,CAAC,CAAE;EAQzE,IAAI,CAACC,EAAI,uBACF,KAAA,IAAMD,KAAMD,GACf,AAAIC,EAAG,SAAS,YAAUF,EAAM,KAAK,IAAI,KAAK,CAACE,EAAG,IAAI,GAAG,cAAc,EAAE,MAAMf,EAAS,CAAC,CAAC;EAG9F,IAAIa,EAAM,WAAW,GAGrB,OAFIG,EAAI,KAAK,SAAeA,EAAI,IAAI,OAAOH,GAAOG,CAAG,IAE9CC,EAAuBJ,GAAOG,GAAK;GACxC,UAAU,MAAMR,EAAQU,CAAC;GACzB,cAAclB;EAChB,CAAC;CACH;AACF"}
1
+ {"version":3,"file":"svgHandler.js","names":["SVG_MIME","FALLBACK_WIDTH","FALLBACK_HEIGHT","isSvgFileItem","item","sniffSvgText","text","end","measure","url","file","img","kitSvgHandler","files","items","it","ctx","embedFilesAsImageNodes","f"],"sources":["../../../src/features/ingestion/svgHandler.ts"],"sourcesContent":["/**\n * The kit's `image/svg+xml` content handler.\n *\n * Default: a dropped SVG stays **one scene node** — an embedded image\n * (`data.image.src` as a `data:image/svg+xml;…` URI, source bytes preserved\n * verbatim). Chromium's `createImageBitmap` rejects raw SVG blobs, so this\n * handler measures via an `Image` element instead, falling back to 300×150\n * (the CSS default object size) when the file declares no intrinsic\n * dimensions.\n *\n * `<SceneCanvas ingestion={{ svg: { unpack: unpackSvgFiles } }}>` switches to\n * parsing the file into native scene nodes. The unpacker is injected because\n * the SVG parser lives in `@weasel-js/svg`, which depends on this package.\n *\n * Registered at priority -90: ahead of `kit:image` (-100) so SVG files\n * never hit the raster measure path, still behind any consumer handler\n * (default 0).\n */\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\nimport type { IngestItem } from '@weasel-js/routing';\nimport { embedFilesAsImageNodes, type Measure } from './imageHandler';\n\nexport const SVG_MIME = 'image/svg+xml';\n\n// CSS default object size — what browsers use for replaced content with no\n// intrinsic dimensions (e.g. a viewBox-only SVG in an <img>).\nconst FALLBACK_WIDTH = 300;\nconst FALLBACK_HEIGHT = 150;\n\n/**\n * True for file items that are SVG by MIME — or by `.svg` extension when\n * the source offered no usable type (an empty `File.type` normalizes to\n * `application/octet-stream` at materialization).\n */\nexport function isSvgFileItem(item: IngestItem): boolean {\n if (item.kind !== 'file') return false;\n if (item.mime === SVG_MIME) return true;\n return item.mime === 'application/octet-stream' && /\\.svg$/i.test(item.file.name);\n}\n\n/**\n * Strict-prefix sniff: could this text be an SVG document? `<svg` (or an XML\n * declaration, then optional whitespace/comments/DOCTYPE, then `<svg`) must\n * open the document — no mid-document substring scans. Exists because Safari drops both custom MIMEs\n * and `image/svg+xml` from async clipboard writes, leaving `text/plain` as\n * the only surviving flavor of an SVG copy.\n */\nexport function sniffSvgText(text: string): boolean {\n let t = text.trimStart();\n if (t.startsWith('<?xml')) {\n const end = t.indexOf('?>');\n if (end < 0) return false;\n t = t.slice(end + 2);\n }\n for (;;) {\n t = t.trimStart();\n if (t.startsWith('<!--')) {\n const end = t.indexOf('-->');\n if (end < 0) return false;\n t = t.slice(end + 3);\n continue;\n }\n // Skipping ANY doctype is safe — a non-SVG doctype's root element fails\n // the final `<svg` check anyway. No internal-subset (`[...]`) handling.\n if (/^<!doctype/i.test(t)) {\n const end = t.indexOf('>');\n if (end < 0) return false;\n t = t.slice(end + 1);\n continue;\n }\n break;\n }\n return /^<svg[\\s>/]/i.test(t);\n}\n\nconst defaultMeasure: Measure = async (file) => {\n const url = URL.createObjectURL(file);\n try {\n const img = new Image();\n img.src = url;\n await img.decode();\n return {\n width: img.naturalWidth || FALLBACK_WIDTH,\n height: img.naturalHeight || FALLBACK_HEIGHT,\n };\n } finally {\n URL.revokeObjectURL(url);\n }\n};\n\nlet measure: Measure = defaultMeasure;\n\nexport const kitSvgHandler: ContentHandlerEntry = {\n id: 'kit:svg',\n // Files by MIME/extension, plus the text/plain fallback flavor: SVG markup\n // pasted as plain text (the only flavor Safari lets an SVG copy keep).\n match: (item) =>\n isSvgFileItem(item)\n || (item.kind === 'string' && item.mime === 'text/plain' && sniffSvgText(item.text)),\n types: [SVG_MIME, 'application/octet-stream', 'text/plain'],\n priority: -90,\n handle(items, ctx: IngestCtx) {\n const files = items.flatMap((it) => (it.kind === 'file' ? [it.file] : []));\n // String items are skipped when the weasel-JSON handler already pasted\n // this event's copy: ingesting both flavors would double-paste.\n // WARNING: this read must stay before any `await` in this handle — the\n // sync-ordering of handler microtasks is what makes the flag visible.\n if (!ctx.consumedWeaselPayload) {\n for (const it of items) {\n if (it.kind === 'string') files.push(new File([it.text], 'pasted.svg', { type: SVG_MIME }));\n }\n }\n if (files.length === 0) return;\n if (ctx.svg?.unpack) return ctx.svg.unpack(files, ctx);\n // Thunk (not the variable) so the test seam is read at call time.\n return embedFilesAsImageNodes(files, ctx, {\n measure: (f) => measure(f),\n mimeOverride: SVG_MIME,\n });\n },\n};\n\n/** @internal test seam — override the Image-element measurer (jsdom can't\n * decode SVG). Not part of the public barrel. */\nexport function __setSvgMeasureForTests(fn: Measure): void {\n measure = fn;\n}\n\n/** @internal test seam — restore the default measurer. */\nexport function _resetSvgHandlerSeamsForTests(): void {\n measure = defaultMeasure;\n}\n"],"mappings":";;AAsBA,IAAaA,IAAW,iBAIlBC,IAAiB,KACjBC,IAAkB;AAOxB,SAAgBC,EAAc,GAA2B;CAGvD,OAFIC,EAAK,SAAS,SACdA,EAAK,SAASJ,KACXI,EAAK,SAAS,8BAA8B,UAAU,KAAKA,EAAK,KAAK,IAAI,IAF/C;AAGnC;AASA,SAAgBC,EAAa,GAAuB;CAClD,IAAI,IAAIC,EAAK,UAAU;CACvB,IAAI,EAAE,WAAW,OAAO,GAAG;EACzB,IAAMC,IAAM,EAAE,QAAQ,IAAI;EAC1B,IAAIA,IAAM,GAAG,OAAO;EACpB,IAAI,EAAE,MAAMA,IAAM,CAAC;CACrB;CACA,SAAS;EAEP,IADA,IAAI,EAAE,UAAU,GACZ,EAAE,WAAW,MAAM,GAAG;GACxB,IAAMA,IAAM,EAAE,QAAQ,KAAK;GAC3B,IAAIA,IAAM,GAAG,OAAO;GACpB,IAAI,EAAE,MAAMA,IAAM,CAAC;GACnB;EACF;EAGA,IAAI,cAAc,KAAK,CAAC,GAAG;GACzB,IAAMA,IAAM,EAAE,QAAQ,GAAG;GACzB,IAAIA,IAAM,GAAG,OAAO;GACpB,IAAI,EAAE,MAAMA,IAAM,CAAC;GACnB;EACF;EACA;CACF;CACA,OAAO,eAAe,KAAK,CAAC;AAC9B;AAiBA,IAAIC,IAAmB,OAfgB,MAAS;CAC9C,IAAMC,IAAM,IAAI,gBAAgBC,CAAI;CACpC,IAAI;EACF,IAAMC,IAAM,IAAI,MAAM;EAGtB,OAFA,EAAI,MAAMF,GACV,MAAME,EAAI,OAAO,GACV;GACL,OAAOA,EAAI,gBAAgBV;GAC3B,QAAQU,EAAI,iBAAiBT;EAC/B;CACF,UAAU;EACR,IAAI,gBAAgBO,CAAG;CACzB;AACF,GAIaG,IAAqC;CAChD,IAAI;CAGJ,QAAQ,MACNT,EAAcC,CAAI,KACdA,EAAK,SAAS,YAAYA,EAAK,SAAS,gBAAgBC,EAAaD,EAAK,IAAI;CACpF,OAAO;EAACJ;EAAU;EAA4B;CAAY;CAC1D,UAAU;CACV,OAAO,GAAO,GAAgB;EAC5B,IAAMa,IAAQC,EAAM,SAAS,MAAQC,EAAG,SAAS,SAAS,CAACA,EAAG,IAAI,IAAI,CAAC,CAAE;EAKzE,IAAI,CAACC,EAAI,uBACF,KAAA,IAAMD,KAAMD,GACf,AAAIC,EAAG,SAAS,YAAUF,EAAM,KAAK,IAAI,KAAK,CAACE,EAAG,IAAI,GAAG,cAAc,EAAE,MAAMf,EAAS,CAAC,CAAC;EAG9F,IAAIa,EAAM,WAAW,GAGrB,OAFIG,EAAI,KAAK,SAAeA,EAAI,IAAI,OAAOH,GAAOG,CAAG,IAE9CC,EAAuBJ,GAAOG,GAAK;GACxC,UAAU,MAAMR,EAAQU,CAAC;GACzB,cAAclB;EAChB,CAAC;CACH;AACF"}
@@ -0,0 +1,28 @@
1
+ import { arrivalBounds as e } from "./placement.js";
2
+ import { measureTextBounds as t } from "@weasel-js/text";
3
+ //#region src/features/ingestion/textHandler.ts
4
+ function n(n = {}) {
5
+ let r = n.measure ?? ((e) => t(e));
6
+ return {
7
+ id: "kit:text",
8
+ match: (e) => e.kind === "string" && e.mime === "text/plain",
9
+ types: ["text/plain"],
10
+ priority: -110,
11
+ handle(t, n) {
12
+ let i = 0;
13
+ for (let a of t) {
14
+ if (a.kind !== "string") continue;
15
+ let t = a.text.replace(/\r\n?/g, "\n").replace(/\n+$/, "");
16
+ t.trim() !== "" && (n.insert.commit(e(n, r(t), i), {
17
+ kind: "text",
18
+ text: t
19
+ }), i++);
20
+ }
21
+ }
22
+ };
23
+ }
24
+ var r = n();
25
+ //#endregion
26
+ export { n as createTextHandler, r as kitTextHandler };
27
+
28
+ //# sourceMappingURL=textHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textHandler.js","names":["createTextHandler","measure","opts","measureTextBounds","text","item","index","items","ctx","arrivalBounds","kitTextHandler"],"sources":["../../../src/features/ingestion/textHandler.ts"],"sourcesContent":["/**\n * The kit's `text/plain` content handler: a pasted or dropped string becomes\n * a text node. Not registered by default; a canvas takes it through\n * `ingestion.handlers`.\n *\n * The node's box is the string's own laid-out size at the default text style,\n * so it holds the text exactly and wraps nowhere the string does not break.\n * Placement is the image handler's: on the point, or centered in the viewport.\n *\n * Priority -110, below every kit handler, so SVG markup and a copied node\n * payload arriving as plain text go to the handlers that read them.\n */\nimport { measureTextBounds } from '@weasel-js/text';\nimport type { IngestItem } from '@weasel-js/routing';\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\nimport { arrivalBounds } from './placement';\n\n/** Options for {@link createTextHandler}. */\nexport interface TextHandlerOptions {\n /** Size of a string's layout box in world units. Default\n * `measureTextBounds`, which reads the registered font. */\n measure?: (text: string) => { width: number; height: number };\n}\n\n/** Build the plain-text content handler; {@link kitTextHandler} is the one\n * with the default measurer. */\nexport function createTextHandler(opts: TextHandlerOptions = {}): ContentHandlerEntry {\n const measure = opts.measure ?? ((text: string) => measureTextBounds(text));\n return {\n id: 'kit:text',\n match: (item: IngestItem) => item.kind === 'string' && item.mime === 'text/plain',\n types: ['text/plain'],\n priority: -110,\n handle(items, ctx: IngestCtx) {\n let index = 0;\n for (const item of items) {\n if (item.kind !== 'string') continue;\n const text = item.text.replace(/\\r\\n?/g, '\\n').replace(/\\n+$/, '');\n if (text.trim() === '') continue;\n ctx.insert.commit(arrivalBounds(ctx, measure(text), index), { kind: 'text', text });\n index++;\n }\n },\n };\n}\n\n/**\n * Turns pasted or dropped plain text into a text node sized to the string. Registered nowhere by\n * default: a canvas opts in with `ingestion={{ handlers: [kitTextHandler] }}`.\n */\nexport const kitTextHandler: ContentHandlerEntry = createTextHandler();\n"],"mappings":";;;AA0BA,SAAgBA,EAAkB,IAA2B,CAAC,GAAwB;CACpF,IAAMC,IAAUC,EAAK,aAAa,MAAiBC,EAAkBC,CAAI;CACzE,OAAO;EACL,IAAI;EACJ,QAAQ,MAAqBC,EAAK,SAAS,YAAYA,EAAK,SAAS;EACrE,OAAO,CAAC,YAAY;EACpB,UAAU;EACV,OAAO,GAAO,GAAgB;GAC5B,IAAIC,IAAQ;GACZ,KAAK,IAAMD,KAAQE,GAAO;IACxB,IAAIF,EAAK,SAAS,UAAU;IAC5B,IAAMD,IAAOC,EAAK,KAAK,QAAQ,UAAU,IAAI,CAAC,CAAC,QAAQ,QAAQ,EAAE;IACjE,AAAID,EAAK,KAAK,MAAM,OACpBI,EAAI,OAAO,OAAOC,EAAcD,GAAKP,EAAQG,CAAI,GAAGE,CAAK,GAAG;KAAE,MAAM;KAAQ;IAAK,CAAC,GAClF;GACF;EACF;CACF;AACF;AAMA,IAAaI,IAAsCV,EAAkB"}
@@ -0,0 +1,48 @@
1
+ import { dwarn as e } from "../../debug/flag.js";
2
+ import { registerContentHandler as t } from "./contentHandlers.js";
3
+ import { acquireKitContentHandlers as n } from "./registerKitHandlers.js";
4
+ import { useCallback as r, useEffect as i, useMemo as a } from "react";
5
+ import { useLatest as o } from "@weasel-js/react";
6
+ import { itemsFromFiles as s } from "@weasel-js/routing";
7
+ //#region src/features/ingestion/useCanvasIngestion.ts
8
+ function c(c, l, u) {
9
+ let d = u?.handlers;
10
+ i(() => {
11
+ let e = [n()];
12
+ for (let n of d ?? []) e.push(t(n));
13
+ return () => e.forEach((e) => e());
14
+ }, [d]);
15
+ let f = u?.clipboard?.reviver, p = u?.clipboard?.enabled !== !1, m = o(u?.clipboard?.onOmitted), h = a(() => {
16
+ if (p && c.commitPaste) return {
17
+ adapter: c,
18
+ ...f ? { reviver: f } : {},
19
+ onOmitted: (e) => m.current?.(e)
20
+ };
21
+ }, [
22
+ c,
23
+ p,
24
+ f,
25
+ m
26
+ ]), g = o(l);
27
+ return {
28
+ ingest: r((t, n) => {
29
+ let r = t.map((e) => e instanceof File ? s([e])[0] : e);
30
+ if (r.length === 0) return !1;
31
+ let i = g.current();
32
+ if (!i) return e("ingest", "CanvasExtensionApi.ingest called before the action registry mounted — call ignored. Defer to an effect or event handler."), !1;
33
+ let a = {
34
+ items: r,
35
+ ...n ? {
36
+ worldX: n.x,
37
+ worldY: n.y
38
+ } : {}
39
+ }, o = i.trigger("ingest", a);
40
+ return o || e("ingest", "CanvasExtensionApi.ingest ran nothing: this canvas has no `ingest` action. Add `ingest` to `features`."), o;
41
+ }, [g]),
42
+ clipboard: h
43
+ };
44
+ }
45
+ //#endregion
46
+ export { c as useCanvasIngestion };
47
+
48
+ //# sourceMappingURL=useCanvasIngestion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCanvasIngestion.js","names":["useCanvasIngestion","handlers","options","disposers","acquireKitContentHandlers","h","registerContentHandler","d","reviver","enabled","onOmitted","useLatest","clipboard","useMemo","adapter","omitted","registryOf","getRegistry","useCallback","items","input","entry","itemsFromFiles","registry","dwarn","params","point","ran"],"sources":["../../../src/features/ingestion/useCanvasIngestion.ts"],"sourcesContent":["import { useLatest } from '@weasel-js/react';\nimport { itemsFromFiles, type ActionsRegistry, type IngestItem } from '@weasel-js/routing';\nimport type { InsertAdapter } from 'core/adapters/types';\nimport type { ClipboardIngestCtx } from 'interactions/actions/depSchema';\nimport { useCallback, useEffect, useMemo } from 'react';\nimport { dwarn } from '../../debug';\nimport { registerContentHandler, type ContentHandlerEntry } from './contentHandlers';\nimport { acquireKitContentHandlers } from './registerKitHandlers';\n\n/** What `useCanvasIngestion` reads of `<SceneCanvas ingestion>`. */\nexport interface CanvasIngestionOptions {\n handlers?: ContentHandlerEntry[];\n clipboard?: {\n reviver?: ClipboardIngestCtx['reviver'];\n enabled?: boolean;\n onOmitted?: ClipboardIngestCtx['onOmitted'];\n };\n}\n\nexport interface CanvasIngestion {\n /** `SceneCanvasApi.ingest`. */\n ingest(input: File[] | IngestItem[], point?: { x: number; y: number }): boolean;\n /** For the `ingestion` dep. Absent, so the kit weasel-JSON handler declines, when\n * `clipboard.enabled` is false or the adapter cannot `commitPaste`. */\n clipboard: ClipboardIngestCtx | undefined;\n}\n\n/**\n * One canvas's share of ingestion: its content handlers for as long as it is mounted, the\n * clipboard seam pastes re-materialize through, and the imperative `ingest`, which triggers\n * the `ingest` action so its deps resolve as they do on the dispatcher path.\n *\n * `getRegistry` answers null until the canvas's action registry is reachable.\n */\nexport function useCanvasIngestion(\n adapter: InsertAdapter<{ id: string }>,\n getRegistry: () => ActionsRegistry | null,\n options: CanvasIngestionOptions | undefined,\n): CanvasIngestion {\n // The kit's default handlers are refcounted across mounted canvases.\n const handlers = options?.handlers;\n useEffect(() => {\n const disposers = [acquireKitContentHandlers()];\n for (const h of handlers ?? []) disposers.push(registerContentHandler(h));\n return () => disposers.forEach((d) => d());\n }, [handlers]);\n\n const reviver = options?.clipboard?.reviver;\n const enabled = options?.clipboard?.enabled !== false;\n const onOmitted = useLatest(options?.clipboard?.onOmitted);\n const clipboard = useMemo<ClipboardIngestCtx | undefined>(() => {\n if (!enabled || !adapter.commitPaste) return undefined;\n return {\n adapter,\n ...(reviver ? { reviver } : {}),\n onOmitted: (omitted) => onOmitted.current?.(omitted),\n };\n }, [adapter, enabled, reviver, onOmitted]);\n\n const registryOf = useLatest(getRegistry);\n const ingest = useCallback<CanvasIngestion['ingest']>((input, point) => {\n const items: IngestItem[] = (input as (File | IngestItem)[]).map((entry) =>\n entry instanceof File ? itemsFromFiles([entry])[0] : entry,\n );\n if (items.length === 0) return false;\n const registry = registryOf.current();\n if (!registry) {\n dwarn('ingest', 'CanvasExtensionApi.ingest called before the action registry mounted — call ignored. Defer to an effect or event handler.');\n return false;\n }\n const params = { items, ...(point ? { worldX: point.x, worldY: point.y } : {}) };\n const ran = registry.trigger('ingest', params);\n if (!ran) dwarn('ingest', 'CanvasExtensionApi.ingest ran nothing: this canvas has no `ingest` action. Add `ingest` to `features`.');\n return ran;\n }, [registryOf]);\n\n return { ingest, clipboard };\n}\n"],"mappings":";;;;;;;AAkCA,SAAgBA,EACd,GACA,GACA,GACiB;CAEjB,IAAMC,IAAWC,GAAS;CAC1B,QAAgB;EACd,IAAMC,IAAY,CAACC,EAA0B,CAAC;EAC9C,KAAK,IAAMC,KAAKJ,KAAY,CAAC,GAAG,EAAU,KAAKK,EAAuBD,CAAC,CAAC;EACxE,aAAaF,EAAU,SAAS,MAAMI,EAAE,CAAC;CAC3C,GAAG,CAACN,CAAQ,CAAC;CAEb,IAAMO,IAAUN,GAAS,WAAW,SAC9BO,IAAUP,GAAS,WAAW,YAAY,IAC1CQ,IAAYC,EAAUT,GAAS,WAAW,SAAS,GACnDU,IAAYC,QAA8C;EAC9D,IAAKJ,KAAYK,EAAQ,aACzB,OAAO;GACL;GACA,GAAIN,IAAU,EAAE,WAAQ,IAAI,CAAC;GAC7B,YAAY,MAAYE,EAAU,UAAUK,CAAO;EACrD;CACF,GAAG;EAACD;EAASL;EAASD;EAASE;CAAS,CAAC,GAEnCM,IAAaL,EAAUM,CAAW;CAiBxC,OAAO;EAAE,QAhBMC,GAAwC,GAAO,MAAU;GACtE,IAAMC,IAAuBC,EAAgC,KAAK,MAChEC,aAAiB,OAAOC,EAAe,CAACD,CAAK,CAAC,CAAC,CAAC,KAAKA,CACvD;GACA,IAAIF,EAAM,WAAW,GAAG,OAAO;GAC/B,IAAMI,IAAWP,EAAW,QAAQ;GACpC,IAAI,CAACO,GAEH,OADAC,EAAM,UAAU,0HAA0H,GACnI;GAET,IAAMC,IAAS;IAAE;IAAO,GAAIC,IAAQ;KAAE,QAAQA,EAAM;KAAG,QAAQA,EAAM;IAAE,IAAI,CAAC;GAAG,GACzEC,IAAMJ,EAAS,QAAQ,UAAUE,CAAM;GAE7C,OADKE,KAAKH,EAAM,UAAU,wGAAwG,GAC3HG;EACT,GAAG,CAACX,CAAU,CAEL;EAAQ;CAAU;AAC7B"}
@@ -1,36 +1,44 @@
1
1
  import { dwarn as e } from "../../debug/flag.js";
2
- import { sniffSvgText as t } from "./svgHandler.js";
3
- import { materializePaste as n } from "../../interactions/actions/clipboard/materializePaste.js";
4
- import { WEASEL_CLIPBOARD_MIME as r, WEASEL_CLIPBOARD_MIME_WEB as i, extractWeaselClipboardFromSvg as a, parseWeaselClipboardText as o, sniffWeaselClipboardText as s } from "../../interactions/actions/clipboard/wireFormat.js";
2
+ import { materializePaste as t } from "../../interactions/actions/clipboard/materializePaste.js";
3
+ import { WEASEL_CLIPBOARD_MIME as n, WEASEL_CLIPBOARD_MIME_WEB as r, extractWeaselClipboardFromSvg as i, parseWeaselClipboardText as a, sniffWeaselClipboardText as o } from "../../interactions/actions/clipboard/wireFormat.js";
4
+ import { sniffSvgText as s } from "./svgHandler.js";
5
5
  //#region src/features/ingestion/weaselJsonHandler.ts
6
- var c = (e) => e.includes("\"weaselClipboard\"") && t(e) && a(e) !== null, l = {
6
+ var c = (e) => e.includes("\"weaselClipboard\"") && s(e) && i(e) !== null, l = {
7
7
  id: "kit:weasel-json",
8
8
  priority: -50,
9
- match: (e) => e.kind === "string" && (e.mime === r || e.mime === i || e.mime === "text/plain" && (s(e.text) || c(e.text))),
10
- handle(r, i) {
11
- let s = i.clipboard;
12
- if (!s) {
9
+ match: (e) => e.kind === "string" && (e.mime === n || e.mime === r || e.mime === "text/plain" && (o(e.text) || c(e.text))),
10
+ types: [
11
+ n,
12
+ r,
13
+ "text/plain"
14
+ ],
15
+ handle(n, r) {
16
+ let o = r.clipboard;
17
+ if (!o) {
13
18
  e("clipboard", "weasel payload arrived but ctx.clipboard is not wired (ingestion.clipboard disabled or absent) — declining");
14
19
  return;
15
20
  }
16
- if (!s.adapter.commitPaste) {
21
+ if (!o.adapter.commitPaste) {
17
22
  e("clipboard", "weasel payload arrived but the clipboard adapter lacks commitPaste — declining");
18
23
  return;
19
24
  }
20
- let c = r.find((e) => e.kind === "string");
25
+ let c = n.find((e) => e.kind === "string");
21
26
  if (!c || c.kind !== "string") return;
22
- let l = t(c.text) ? a(c.text) : c.text;
27
+ let l = s(c.text) ? i(c.text) : c.text;
23
28
  if (l === null) {
24
29
  e("clipboard", "weasel payload vanished from the SVG metadata between match and handle — declining");
25
30
  return;
26
31
  }
27
- let u = o(l, s.reviver);
32
+ let u = a(l, o.reviver);
28
33
  if (u === null) {
29
34
  e("clipboard", "weasel payload unusable — declining (see prior warning if the parse threw)");
30
35
  return;
31
36
  }
32
- let d = { items: u }, f = n(s.adapter, d, { currentSelection: i.selection.get() });
33
- f && (i.applyOps(f.ops, "Paste"), i.selection.set(f.newIds), i.consumedWeaselPayload = !0);
37
+ let d = { items: u }, f = t(o.adapter, d, {
38
+ currentSelection: r.selection.get(),
39
+ onOmitted: o.onOmitted
40
+ });
41
+ f && (r.applyOps(f.ops, "Paste"), r.selection.set(f.newIds), r.consumedWeaselPayload = !0);
34
42
  }
35
43
  };
36
44
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"weaselJsonHandler.js","names":["isMetadataBearingSvg","text","sniffSvgText","extractWeaselClipboardFromSvg","kitWeaselJsonHandler","item","WEASEL_CLIPBOARD_MIME","WEASEL_CLIPBOARD_MIME_WEB","sniffWeaselClipboardText","clipboard","ctx","items","it","nodes","parseWeaselClipboardText","snapshot","result","materializePaste"],"sources":["../../../src/features/ingestion/weaselJsonHandler.ts"],"sourcesContent":["/**\n * The kit's weasel-JSON clipboard content handler.\n *\n * Consumes `application/x-weasel-clipboard+json` payloads (either MIME\n * spelling — Chromium's async-clipboard API round-trips custom formats with\n * a `web ` prefix — plus `text/plain` that sniffs as the wire format, plus\n * `text/plain` SVG carrying the wire format embedded in a `<metadata>`\n * element: Chromium's DOM paste event exposes ONLY `text/plain`, and draw\n * puts metadata-bearing SVG there so draw→draw paste keeps full JSON\n * fidelity) and replays them as a paste through the hosting canvas's\n * adapter: parse →\n * `commitPaste` (fresh ids, cascade offset) → one undoable batch of\n * `InsertOp`s + a selection op. Mirrors `useClipboardOps.paste`'s op\n * construction exactly so OS-arriving pastes and in-memory pastes are\n * indistinguishable in history.\n *\n * Declines (leaving the event un-acted-on) when `ctx.clipboard` is absent\n * (consumer disabled it, or the adapter lacks `commitPaste`) or the payload\n * fails to parse. Note `runIngest` consumes items at *match* time, so\n * \"leave it for other handlers\" is the sniff's job: non-weasel `text/plain`\n * never matches and flows on to lower-priority handlers untouched.\n */\nimport type { NodeId } from 'core/scene/types';\nimport type { ClipboardSnapshot } from 'core/adapters/types';\nimport { materializePaste } from 'interactions/actions/clipboard/materializePaste';\nimport {\n WEASEL_CLIPBOARD_MIME,\n WEASEL_CLIPBOARD_MIME_WEB,\n sniffWeaselClipboardText,\n parseWeaselClipboardText,\n extractWeaselClipboardFromSvg,\n} from 'interactions/actions/clipboard/wireFormat';\nimport { dwarn } from '../../debug';\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\n// Direct module import (not the ./index barrel) to avoid a cycle — the\n// barrel re-exports this handler.\nimport { sniffSvgText } from './svgHandler';\n\n/** text/plain SVG whose `<metadata>` carries a verified weasel payload —\n * the draw→draw DOM-paste flavor (Chromium exposes only text/plain there).\n * The `\"weaselClipboard\"` substring guard keeps match cheap on arbitrary\n * external SVG pastes before the extraction regex runs. */\nconst isMetadataBearingSvg = (text: string): boolean =>\n text.includes('\"weaselClipboard\"')\n && sniffSvgText(text)\n && extractWeaselClipboardFromSvg(text) !== null;\n\nexport const kitWeaselJsonHandler: ContentHandlerEntry = {\n id: 'kit:weasel-json',\n // Above the other kit handlers (-100/-90) so weasel payloads never fall\n // through to the SVG/text paths; still below consumer handlers (default 0).\n priority: -50,\n match: (item) =>\n item.kind === 'string'\n && (item.mime === WEASEL_CLIPBOARD_MIME\n || item.mime === WEASEL_CLIPBOARD_MIME_WEB\n || (item.mime === 'text/plain'\n && (sniffWeaselClipboardText(item.text) || isMetadataBearingSvg(item.text)))),\n handle(items, ctx: IngestCtx) {\n const clipboard = ctx.clipboard;\n if (!clipboard) {\n dwarn('clipboard', 'weasel payload arrived but ctx.clipboard is not wired (ingestion.clipboard disabled or absent) — declining');\n return;\n }\n if (!clipboard.adapter.commitPaste) {\n dwarn('clipboard', 'weasel payload arrived but the clipboard adapter lacks commitPaste — declining');\n return;\n }\n const item = items.find((it) => it.kind === 'string');\n if (!item || item.kind !== 'string') return;\n // The metadata-bearing-SVG flavor: unwrap the embedded payload before\n // parsing. Extraction was already verified at match time, so a null here\n // is the same inert-decline class as a corrupt custom-MIME payload.\n const text = sniffSvgText(item.text)\n ? extractWeaselClipboardFromSvg(item.text)\n : item.text;\n if (text === null) {\n dwarn('clipboard', 'weasel payload vanished from the SVG metadata between match and handle — declining');\n return;\n }\n const nodes = parseWeaselClipboardText(text, clipboard.reviver);\n if (nodes === null) {\n dwarn('clipboard', 'weasel payload unusable — declining (see prior warning if the parse threw)');\n return;\n }\n // Shared paste recipe (offset → commitPaste → InsertOps + selection op)\n // so OS-arriving pastes match useClipboardOps.paste exactly. `ctx.point`\n // is null for paste, so no dropPoint is threaded — the cascade offset is\n // the placement.\n const snapshot: ClipboardSnapshot = { items: nodes };\n const result = materializePaste(clipboard.adapter, snapshot, {\n currentSelection: ctx.selection.get(),\n });\n if (!result) return;\n ctx.applyOps(result.ops, 'Paste');\n ctx.selection.set(result.newIds as NodeId[]);\n // Flag the shared event ctx so kit:svg's text/plain fallback declines the\n // SVG flavor of this same copy (draw writes weasel-JSON + SVG together).\n // WARNING: do not add an `await` earlier in this handle — the flag must\n // be written before lower-priority handlers' microtasks run.\n ctx.consumedWeaselPayload = true;\n },\n};\n"],"mappings":";;;;;AA0CA,IAAMA,KAAwB,MAC5BC,EAAK,SAAS,qBAAmB,KAC9BC,EAAaD,CAAI,KACjBE,EAA8BF,CAAI,MAAM,MAEhCG,IAA4C;CACvD,IAAI;CAGJ,UAAU;CACV,QAAQ,MACNC,EAAK,SAAS,aACVA,EAAK,SAASC,KACbD,EAAK,SAASE,KACbF,EAAK,SAAS,iBACZG,EAAyBH,EAAK,IAAI,KAAKL,EAAqBK,EAAK,IAAI;CAC/E,OAAO,GAAO,GAAgB;EAC5B,IAAMI,IAAYC,EAAI;EACtB,IAAI,CAACD,GAAW;GACd,EAAM,aAAa,4GAA4G;GAC/H;EACF;EACA,IAAI,CAACA,EAAU,QAAQ,aAAa;GAClC,EAAM,aAAa,gFAAgF;GACnG;EACF;EACA,IAAMJ,IAAOM,EAAM,MAAM,MAAOC,EAAG,SAAS,QAAQ;EACpD,IAAI,CAACP,KAAQA,EAAK,SAAS,UAAU;EAIrC,IAAMJ,IAAOC,EAAaG,EAAK,IAAI,IAC/BF,EAA8BE,EAAK,IAAI,IACvCA,EAAK;EACT,IAAIJ,MAAS,MAAM;GACjB,EAAM,aAAa,oFAAoF;GACvG;EACF;EACA,IAAMY,IAAQC,EAAyBb,GAAMQ,EAAU,OAAO;EAC9D,IAAII,MAAU,MAAM;GAClB,EAAM,aAAa,4EAA4E;GAC/F;EACF;EAKA,IAAME,IAA8B,EAAE,OAAOF,EAAM,GAC7CG,IAASC,EAAiBR,EAAU,SAASM,GAAU,EAC3D,kBAAkBL,EAAI,UAAU,IAAI,EACtC,CAAC;EACD,AAAKM,MACLN,EAAI,SAASM,EAAO,KAAK,OAAO,GAChCN,EAAI,UAAU,IAAIM,EAAO,MAAkB,GAK3C,EAAI,wBAAwB;CAC9B;AACF"}
1
+ {"version":3,"file":"weaselJsonHandler.js","names":["isMetadataBearingSvg","text","sniffSvgText","extractWeaselClipboardFromSvg","kitWeaselJsonHandler","item","WEASEL_CLIPBOARD_MIME","WEASEL_CLIPBOARD_MIME_WEB","sniffWeaselClipboardText","clipboard","ctx","items","it","nodes","parseWeaselClipboardText","snapshot","result","materializePaste"],"sources":["../../../src/features/ingestion/weaselJsonHandler.ts"],"sourcesContent":["/**\n * The kit's weasel-JSON clipboard content handler.\n *\n * Consumes `application/x-weasel-clipboard+json` payloads in either MIME\n * spelling (Chromium's async-clipboard API round-trips custom formats with\n * a `web ` prefix), `text/plain` that sniffs as the wire format, and\n * `text/plain` SVG carrying the wire format embedded in a `<metadata>`\n * element (Chromium's DOM paste event exposes ONLY `text/plain`). It replays\n * them as a paste through the hosting canvas's adapter, mirroring\n * `useClipboardOps.paste`'s op construction exactly so OS-arriving pastes\n * and in-memory pastes are indistinguishable in history.\n *\n * Declines when `ctx.clipboard` is absent or the payload fails to parse.\n * `runIngest` consumes items at *match* time, so \"leave it for other\n * handlers\" is the sniff's job: non-weasel `text/plain` never matches.\n */\nimport type { NodeId } from 'core/scene/types';\nimport type { ClipboardSnapshot } from 'core/adapters/types';\nimport { materializePaste } from 'interactions/actions/clipboard/materializePaste';\nimport {\n WEASEL_CLIPBOARD_MIME,\n WEASEL_CLIPBOARD_MIME_WEB,\n sniffWeaselClipboardText,\n parseWeaselClipboardText,\n extractWeaselClipboardFromSvg,\n} from 'interactions/actions/clipboard/wireFormat';\nimport { dwarn } from '../../debug';\nimport type { ContentHandlerEntry, IngestCtx } from './contentHandlers';\n// Direct module import (not the ./index barrel) to avoid a cycle — the\n// barrel re-exports this handler.\nimport { sniffSvgText } from './svgHandler';\n\n/** text/plain SVG whose `<metadata>` carries a verified weasel payload —\n * the draw→draw DOM-paste flavor (Chromium exposes only text/plain there).\n * The `\"weaselClipboard\"` substring guard keeps match cheap on arbitrary\n * external SVG pastes before the extraction regex runs. */\nconst isMetadataBearingSvg = (text: string): boolean =>\n text.includes('\"weaselClipboard\"')\n && sniffSvgText(text)\n && extractWeaselClipboardFromSvg(text) !== null;\n\nexport const kitWeaselJsonHandler: ContentHandlerEntry = {\n id: 'kit:weasel-json',\n // Above the other kit handlers (-100/-90) so weasel payloads never fall\n // through to the SVG/text paths; still below consumer handlers (default 0).\n priority: -50,\n match: (item) =>\n item.kind === 'string'\n && (item.mime === WEASEL_CLIPBOARD_MIME\n || item.mime === WEASEL_CLIPBOARD_MIME_WEB\n || (item.mime === 'text/plain'\n && (sniffWeaselClipboardText(item.text) || isMetadataBearingSvg(item.text)))),\n types: [WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, 'text/plain'],\n handle(items, ctx: IngestCtx) {\n const clipboard = ctx.clipboard;\n if (!clipboard) {\n dwarn('clipboard', 'weasel payload arrived but ctx.clipboard is not wired (ingestion.clipboard disabled or absent) — declining');\n return;\n }\n if (!clipboard.adapter.commitPaste) {\n dwarn('clipboard', 'weasel payload arrived but the clipboard adapter lacks commitPaste — declining');\n return;\n }\n const item = items.find((it) => it.kind === 'string');\n if (!item || item.kind !== 'string') return;\n // The metadata-bearing-SVG flavor: unwrap the embedded payload before\n // parsing. Extraction was already verified at match time, so a null here\n // is the same inert-decline class as a corrupt custom-MIME payload.\n const text = sniffSvgText(item.text)\n ? extractWeaselClipboardFromSvg(item.text)\n : item.text;\n if (text === null) {\n dwarn('clipboard', 'weasel payload vanished from the SVG metadata between match and handle — declining');\n return;\n }\n const nodes = parseWeaselClipboardText(text, clipboard.reviver);\n if (nodes === null) {\n dwarn('clipboard', 'weasel payload unusable — declining (see prior warning if the parse threw)');\n return;\n }\n // `ctx.point` is null for paste, so no dropPoint is threaded — the\n // cascade offset is the placement.\n const snapshot: ClipboardSnapshot = { items: nodes };\n const result = materializePaste(clipboard.adapter, snapshot, {\n currentSelection: ctx.selection.get(),\n onOmitted: clipboard.onOmitted,\n });\n if (!result) return;\n ctx.applyOps(result.ops, 'Paste');\n ctx.selection.set(result.newIds as NodeId[]);\n // So kit:svg's text/plain fallback declines the SVG flavor of this copy.\n // WARNING: do not add an `await` earlier in this handle — the flag must\n // be written before lower-priority handlers' microtasks run.\n ctx.consumedWeaselPayload = true;\n },\n};\n"],"mappings":";;;;;AAoCA,IAAMA,KAAwB,MAC5BC,EAAK,SAAS,qBAAmB,KAC9BC,EAAaD,CAAI,KACjBE,EAA8BF,CAAI,MAAM,MAEhCG,IAA4C;CACvD,IAAI;CAGJ,UAAU;CACV,QAAQ,MACNC,EAAK,SAAS,aACVA,EAAK,SAASC,KACbD,EAAK,SAASE,KACbF,EAAK,SAAS,iBACZG,EAAyBH,EAAK,IAAI,KAAKL,EAAqBK,EAAK,IAAI;CAC/E,OAAO;EAACC;EAAuBC;EAA2B;CAAY;CACtE,OAAO,GAAO,GAAgB;EAC5B,IAAME,IAAYC,EAAI;EACtB,IAAI,CAACD,GAAW;GACd,EAAM,aAAa,4GAA4G;GAC/H;EACF;EACA,IAAI,CAACA,EAAU,QAAQ,aAAa;GAClC,EAAM,aAAa,gFAAgF;GACnG;EACF;EACA,IAAMJ,IAAOM,EAAM,MAAM,MAAOC,EAAG,SAAS,QAAQ;EACpD,IAAI,CAACP,KAAQA,EAAK,SAAS,UAAU;EAIrC,IAAMJ,IAAOC,EAAaG,EAAK,IAAI,IAC/BF,EAA8BE,EAAK,IAAI,IACvCA,EAAK;EACT,IAAIJ,MAAS,MAAM;GACjB,EAAM,aAAa,oFAAoF;GACvG;EACF;EACA,IAAMY,IAAQC,EAAyBb,GAAMQ,EAAU,OAAO;EAC9D,IAAII,MAAU,MAAM;GAClB,EAAM,aAAa,4EAA4E;GAC/F;EACF;EAGA,IAAME,IAA8B,EAAE,OAAOF,EAAM,GAC7CG,IAASC,EAAiBR,EAAU,SAASM,GAAU;GAC3D,kBAAkBL,EAAI,UAAU,IAAI;GACpC,WAAWD,EAAU;EACvB,CAAC;EACD,AAAKO,MACLN,EAAI,SAASM,EAAO,KAAK,OAAO,GAChCN,EAAI,UAAU,IAAIM,EAAO,MAAkB,GAI3C,EAAI,wBAAwB;CAC9B;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"longPressFeedback.js","names":["LONG_PRESS_FEEDBACK_ID","RING_SEGMENTS","TRACK_OPACITY","nowMs","prefersReducedMotion","arcPath","n","t","pts","i","a","cx","cy","polylineFromPoints","circlePath","ellipsePath","viewIdOf","data","createLongPressFeedbackContribution","id","opts","radius","width","delay","state","color","reduced","showing","p","now","stroke","opacity","x","y","store","deps","appear","onChange","accentColorOf","api","wait","offStore","ctx"],"sources":["../../../src/features/longPress/longPressFeedback.ts"],"sourcesContent":["/**\n * The default \"press is registering\" feedback for a touch or pen long-press: a\n * ring around the press point that fills over the hold. It reads the `longPress`\n * dep the gesture dispatcher publishes, so it shows only for a press some\n * binding would fire on, and disappears when the press fires, moves past the\n * drag threshold, lifts, or is canceled.\n */\nimport type { LongPressState } from '@weasel-js/routing';\nimport type { RenderLayer } from 'core/layers/render';\nimport { ellipsePath, polylineFromPoints, type Path } from '@weasel-js/geom';\nimport type { DrawCommand } from '../../renderer';\nimport type { CanvasExtensionApi } from '../../canvas/canvasExtension';\nimport type { ContributionDepReader, SurfaceContribution } from '../../canvas/surfaceContribution';\nimport { accentColorOf } from '../../canvas/accentColor';\n\n/** Entry and layer id of the default feedback, so a host can find or order it. */\nexport const LONG_PRESS_FEEDBACK_ID = 'long-press-feedback';\n\n/** Options for {@link createLongPressFeedbackContribution}. */\nexport interface LongPressFeedbackOptions {\n /** Entry and layer id. Default {@link LONG_PRESS_FEEDBACK_ID}. */\n id?: string;\n /** Ring radius in CSS pixels. Default 22 — clear of a fingertip. */\n radius?: number;\n /** Ring stroke width in CSS pixels. Default 3. */\n width?: number;\n /** Ring color. Default the theme's `--wzl-accent`, read off the canvas\n * element when each press starts. */\n color?: string | (() => string);\n /** How long a press is held before the ring appears, in ms, so an ordinary\n * tap shows nothing. Default 120. */\n delay?: number;\n /** `true` shows a static full ring instead of one that fills, and runs no\n * frame loop. Default `'auto'`: follow `prefers-reduced-motion`, read when\n * each press starts. */\n reducedMotion?: boolean | 'auto';\n}\n\nconst RING_SEGMENTS = 64;\nconst TRACK_OPACITY = 0.3;\n\nconst nowMs = (): number => performance.now();\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function'\n && matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/** An open arc from 12 o'clock, clockwise on a y-down screen, through `t` of a turn. */\nfunction arcPath(cx: number, cy: number, r: number, t: number): Path {\n const n = Math.max(1, Math.ceil(RING_SEGMENTS * t));\n const pts: { x: number; y: number }[] = [];\n for (let i = 0; i <= n; i++) {\n const a = (i / n) * t * Math.PI * 2;\n pts.push({ x: cx + r * Math.sin(a), y: cy - r * Math.cos(a) });\n }\n return polylineFromPoints(pts);\n}\n\nfunction circlePath(cx: number, cy: number, r: number): Path {\n return ellipsePath({ x: cx - r, y: cy - r, width: 2 * r, height: 2 * r });\n}\n\nconst viewIdOf = (data: unknown): string | null =>\n (data as { viewId?: string | null } | null)?.viewId ?? null;\n\n/**\n * The default long-press feedback, as one entry. `<SceneCanvas>` installs it\n * unless `longPress={{ feedback: false }}`; pass a contribution of your own there to\n * replace it — it reads the same `longPress` dep this one does.\n */\nexport function createLongPressFeedbackContribution(\n opts: LongPressFeedbackOptions = {},\n): SurfaceContribution {\n const id = opts.id ?? LONG_PRESS_FEEDBACK_ID;\n const radius = opts.radius ?? 22;\n const width = opts.width ?? 3;\n const delay = opts.delay ?? 120;\n\n let state: LongPressState | undefined;\n let color = '';\n let reduced = false;\n\n const showing = (): boolean => {\n const p = state?.get();\n return !!p && p.armed;\n };\n\n const layer: RenderLayer<unknown> = {\n id,\n label: 'Long-press feedback',\n space: 'screen',\n draw: (data): DrawCommand[] => {\n const p = state?.get();\n // Screen space is the whole canvas, so the root pass draws the ring\n // wherever the press routed; a view pass drawing it too would double it.\n if (!state || !p || !p.armed || viewIdOf(data) !== null) return [];\n const now = nowMs();\n if (now - p.startedAt < delay) return [];\n const { x, y } = p.local;\n const stroke = (opacity?: number) => ({\n paint: { color, ...(opacity !== undefined ? { opacity } : {}) },\n width: { px: width },\n cap: 'round' as const,\n });\n if (reduced) return [{ kind: 'path', path: circlePath(x, y, radius), stroke: stroke() }];\n return [\n { kind: 'path', path: circlePath(x, y, radius), stroke: stroke(TRACK_OPACITY) },\n { kind: 'path', path: arcPath(x, y, radius, state.progress(now)), stroke: stroke() },\n ];\n },\n };\n\n const attach = (api: CanvasExtensionApi, deps: ContributionDepReader): (() => void) => {\n const store = deps.get('longPress');\n if (!store) return () => {};\n state = store;\n let appear: ReturnType<typeof setTimeout> | undefined;\n\n const onChange = (): void => {\n clearTimeout(appear);\n appear = undefined;\n const p = store.get();\n if (p?.armed) {\n color = typeof opts.color === 'function' ? opts.color() : (opts.color ?? accentColorOf(api.element));\n reduced = opts.reducedMotion === 'auto' || opts.reducedMotion === undefined\n ? prefersReducedMotion()\n : opts.reducedMotion;\n // A static ring changes once, when it appears; nothing needs frames.\n const wait = delay - (nowMs() - p.startedAt);\n if (reduced && wait > 0) appear = setTimeout(() => { api.requestRedraw(); }, wait);\n }\n api.requestRedraw();\n };\n\n const offStore = store.subscribe(onChange);\n onChange();\n return () => {\n offStore();\n clearTimeout(appear);\n state = undefined;\n api.requestRedraw();\n };\n };\n\n return {\n id,\n eligibility: { always: true },\n overlay: layer,\n attach,\n // The filling ring asks for the next frame from each painted one while it shows.\n afterPaint: (ctx) => {\n if (!reduced && showing()) ctx.requestFrame();\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"longPressFeedback.js","names":["circlePath","LONG_PRESS_FEEDBACK_ID","RING_SEGMENTS","TRACK_OPACITY","nowMs","prefersReducedMotion","arcPath","n","t","pts","i","a","cx","cy","polylineFromPoints","circlePath$1","ellipsePath","viewIdOf","data","createLongPressFeedbackContribution","id","opts","radius","width","delay","state","color","reduced","showing","p","now","stroke","opacity","x","y","store","deps","appear","onChange","accentColorOf","api","wait","offStore","ctx"],"sources":["../../../src/features/longPress/longPressFeedback.ts"],"sourcesContent":["/**\n * The default \"press is registering\" feedback for a touch or pen long-press: a\n * ring around the press point that fills over the hold. It reads the `longPress`\n * dep the gesture dispatcher publishes, so it shows only for a press some\n * binding would fire on, and disappears when the press fires, moves past the\n * drag threshold, lifts, or is canceled.\n */\nimport type { LongPressState } from '@weasel-js/routing';\nimport type { RenderLayer } from 'core/layers/render';\nimport { ellipsePath, polylineFromPoints, type Path } from '@weasel-js/geom';\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport type { CanvasExtensionApi } from '../../canvas/canvasExtension';\nimport type { ContributionDepReader, SurfaceContribution } from '../../canvas/surfaceContribution';\nimport { accentColorOf } from '../../canvas/accentColor';\n\n/** Entry and layer id of the default feedback, so a host can find or order it. */\nexport const LONG_PRESS_FEEDBACK_ID = 'long-press-feedback';\n\n/** Options for {@link createLongPressFeedbackContribution}. */\nexport interface LongPressFeedbackOptions {\n /** Entry and layer id. Default {@link LONG_PRESS_FEEDBACK_ID}. */\n id?: string;\n /** Ring radius in CSS pixels. Default 22 — clear of a fingertip. */\n radius?: number;\n /** Ring stroke width in CSS pixels. Default 3. */\n width?: number;\n /** Ring color. Default the theme's `--wzl-accent`, read off the canvas\n * element when each press starts. */\n color?: string | (() => string);\n /** How long a press is held before the ring appears, in ms, so an ordinary\n * tap shows nothing. Default 120. */\n delay?: number;\n /** `true` shows a static full ring instead of one that fills, and runs no\n * frame loop. Default `'auto'`: follow `prefers-reduced-motion`, read when\n * each press starts. */\n reducedMotion?: boolean | 'auto';\n}\n\nconst RING_SEGMENTS = 64;\nconst TRACK_OPACITY = 0.3;\n\nconst nowMs = (): number => performance.now();\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function'\n && matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\n/** An open arc from 12 o'clock, clockwise on a y-down screen, through `t` of a turn. */\nfunction arcPath(cx: number, cy: number, r: number, t: number): Path {\n const n = Math.max(1, Math.ceil(RING_SEGMENTS * t));\n const pts: { x: number; y: number }[] = [];\n for (let i = 0; i <= n; i++) {\n const a = (i / n) * t * Math.PI * 2;\n pts.push({ x: cx + r * Math.sin(a), y: cy - r * Math.cos(a) });\n }\n return polylineFromPoints(pts);\n}\n\nfunction circlePath(cx: number, cy: number, r: number): Path {\n return ellipsePath({ x: cx - r, y: cy - r, width: 2 * r, height: 2 * r });\n}\n\nconst viewIdOf = (data: unknown): string | null =>\n (data as { viewId?: string | null } | null)?.viewId ?? null;\n\n/**\n * The default long-press feedback, as one entry. `<SceneCanvas>` installs it\n * unless `longPress={{ feedback: false }}`; pass a contribution of your own there to\n * replace it — it reads the same `longPress` dep this one does.\n */\nexport function createLongPressFeedbackContribution(\n opts: LongPressFeedbackOptions = {},\n): SurfaceContribution {\n const id = opts.id ?? LONG_PRESS_FEEDBACK_ID;\n const radius = opts.radius ?? 22;\n const width = opts.width ?? 3;\n const delay = opts.delay ?? 120;\n\n let state: LongPressState | undefined;\n let color = '';\n let reduced = false;\n\n const showing = (): boolean => {\n const p = state?.get();\n return !!p && p.armed;\n };\n\n const layer: RenderLayer<unknown> = {\n id,\n label: 'Long-press feedback',\n space: 'screen',\n draw: (data): DrawCommand[] => {\n const p = state?.get();\n // Screen space is the whole canvas, so the root pass draws the ring\n // wherever the press routed; a view pass drawing it too would double it.\n if (!state || !p || !p.armed || viewIdOf(data) !== null) return [];\n const now = nowMs();\n if (now - p.startedAt < delay) return [];\n const { x, y } = p.local;\n const stroke = (opacity?: number) => ({\n paint: { color, ...(opacity !== undefined ? { opacity } : {}) },\n width: { px: width },\n cap: 'round' as const,\n });\n if (reduced) return [{ kind: 'path', path: circlePath(x, y, radius), stroke: stroke() }];\n return [\n { kind: 'path', path: circlePath(x, y, radius), stroke: stroke(TRACK_OPACITY) },\n { kind: 'path', path: arcPath(x, y, radius, state.progress(now)), stroke: stroke() },\n ];\n },\n };\n\n const attach = (api: CanvasExtensionApi, deps: ContributionDepReader): (() => void) => {\n const store = deps.get('longPress');\n if (!store) return () => {};\n state = store;\n let appear: ReturnType<typeof setTimeout> | undefined;\n\n const onChange = (): void => {\n clearTimeout(appear);\n appear = undefined;\n const p = store.get();\n if (p?.armed) {\n color = typeof opts.color === 'function' ? opts.color() : (opts.color ?? accentColorOf(api.element));\n reduced = opts.reducedMotion === 'auto' || opts.reducedMotion === undefined\n ? prefersReducedMotion()\n : opts.reducedMotion;\n // A static ring changes once, when it appears; nothing needs frames.\n const wait = delay - (nowMs() - p.startedAt);\n if (reduced && wait > 0) appear = setTimeout(() => { api.requestRedraw(); }, wait);\n }\n api.requestRedraw();\n };\n\n const offStore = store.subscribe(onChange);\n onChange();\n return () => {\n offStore();\n clearTimeout(appear);\n state = undefined;\n api.requestRedraw();\n };\n };\n\n return {\n id,\n eligibility: { always: true },\n overlay: layer,\n attach,\n // The filling ring asks for the next frame from each painted one while it shows.\n afterPaint: (ctx) => {\n if (!reduced && showing()) ctx.requestFrame();\n },\n };\n}\n"],"mappings":"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"}
@@ -21,8 +21,8 @@ function r(r) {
21
21
  width: n,
22
22
  height: r
23
23
  },
24
- fill: c.gradient ? {
25
- fill: "linear-gradient",
24
+ fill: { paint: c.gradient ? {
25
+ kind: "linear-gradient",
26
26
  from: i,
27
27
  to: a,
28
28
  stops: [{
@@ -34,10 +34,10 @@ function r(r) {
34
34
  }],
35
35
  opacity: u
36
36
  } : {
37
- fill: "solid",
37
+ kind: "solid",
38
38
  color: l,
39
39
  opacity: u
40
- }
40
+ } }
41
41
  }), m = () => [c.gradient === "top-down" ? p(0, 0, d, f, {
42
42
  x: 0,
43
43
  y: 0
@@ -62,11 +62,11 @@ function r(r) {
62
62
  width: d,
63
63
  height: f
64
64
  },
65
- fill: {
66
- fill: "solid",
65
+ fill: { paint: {
66
+ kind: "solid",
67
67
  color: l,
68
68
  opacity: u
69
- }
69
+ } }
70
70
  }];
71
71
  let T = [], E = (e, t, n, r, i, a) => {
72
72
  n > 0 && r > 0 && T.push(p(e, t, n, r, i, a));
@@ -1 +1 @@
1
- {"version":3,"file":"modeLayers.js","names":["DEFAULT_INTENSITY","workspaceTintLayer","opts","registry","ws","tint","opacity","W","H","dims","strip","whole","page","t","viewToTransform","view","sx0","sy0","worldToScreen","sx1","sy1","pl","pt","pr","pb","cmds","push","w","h","x","y","from","to","modeDecorationLayer","decorations"],"sources":["../../../src/features/modes/modeLayers.ts"],"sourcesContent":["import type { Rect } from '@weasel-js/geom';\nimport type { ModeDecorations, ModeRegistry } from '@weasel-js/modes';\nimport type { DrawCommand } from '../../renderer';\nimport type { RenderLayer } from 'core/layers/render';\nimport { viewToTransform } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\n\n/** Options for {@link workspaceTintLayer}. */\nexport interface WorkspaceTintLayerOptions {\n registry: ModeRegistry;\n /** The page, in world coordinates. When given, the tint covers only the\n * workspace around it, each strip fading toward the page edge if the mode\n * names a gradient. Without it the tint covers the whole canvas. */\n page?: () => Rect | null;\n /** Opacity for every mode's tint, in place of its `workspace.intensity`. */\n intensity?: number;\n id?: string;\n label?: string;\n}\n\nconst DEFAULT_INTENSITY = 0.12;\n\n/**\n * A screen-space layer painting the active mode's `WorkspaceVisual`: nothing in\n * a mode without a tint, otherwise a wash at the mode's intensity, bottom-up or\n * top-down when the mode names a gradient. It subscribes to the registry, so a\n * mode switch repaints it.\n */\nexport function workspaceTintLayer(opts: WorkspaceTintLayerOptions): RenderLayer<unknown> {\n const { registry } = opts;\n return {\n id: opts.id ?? 'mode-tint',\n label: opts.label ?? 'Mode tint',\n space: 'screen',\n subscribe: registry.subscribe,\n draw: (_data, view, dims) => {\n const ws = registry.current().workspace;\n const tint = ws?.tint;\n if (!tint || tint === 'transparent') return [];\n const opacity = opts.intensity ?? ws.intensity ?? DEFAULT_INTENSITY;\n const { width: W, height: H } = dims;\n\n const strip = (\n x: number, y: number, width: number, height: number,\n from: { x: number; y: number }, to: { x: number; y: number },\n ): DrawCommand => ({\n kind: 'path',\n path: { kind: 'rect', x, y, width, height },\n fill: ws.gradient\n ? { fill: 'linear-gradient', from, to, stops: [{ offset: 0, color: tint }, { offset: 1, color: 'transparent' }], opacity }\n : { fill: 'solid', color: tint, opacity },\n });\n\n const whole = (): DrawCommand[] => [\n ws.gradient === 'top-down'\n ? strip(0, 0, W, H, { x: 0, y: 0 }, { x: 0, y: H })\n : strip(0, 0, W, H, { x: 0, y: H }, { x: 0, y: 0 }),\n ];\n\n const page = opts.page?.();\n if (!page) return whole();\n\n const t = viewToTransform(view);\n const [sx0, sy0] = worldToScreen(page.x, page.y, t);\n const [sx1, sy1] = worldToScreen(page.x + page.width, page.y + page.height, t);\n const pl = Math.max(0, Math.min(sx0, sx1));\n const pt = Math.max(0, Math.min(sy0, sy1));\n const pr = Math.min(W, Math.max(sx0, sx1));\n const pb = Math.min(H, Math.max(sy0, sy1));\n if (pr <= pl || pb <= pt) {\n return [{ kind: 'path', path: { kind: 'rect', x: 0, y: 0, width: W, height: H }, fill: { fill: 'solid', color: tint, opacity } }];\n }\n\n const cmds: DrawCommand[] = [];\n const push = (\n x: number, y: number, w: number, h: number,\n from: { x: number; y: number }, to: { x: number; y: number },\n ): void => { if (w > 0 && h > 0) cmds.push(strip(x, y, w, h, from, to)); };\n push(0, 0, W, pt, { x: 0, y: 0 }, { x: 0, y: pt });\n push(0, pb, W, H - pb, { x: 0, y: H }, { x: 0, y: pb });\n push(0, pt, pl, pb - pt, { x: 0, y: 0 }, { x: pl, y: 0 });\n push(pr, pt, W - pr, pb - pt, { x: W, y: 0 }, { x: pr, y: 0 });\n return cmds;\n },\n };\n}\n\n/** A world-space layer drawing a `ModeDecorations`' active painter. It\n * subscribes to the decorations, so a mode switch or a new painter repaints\n * it. */\nexport function modeDecorationLayer(\n decorations: ModeDecorations,\n opts: { id?: string; label?: string } = {},\n): RenderLayer<unknown> {\n return {\n id: opts.id ?? 'mode-decorations',\n label: opts.label ?? 'Mode decorations',\n subscribe: decorations.subscribe,\n draw: () => decorations.paint() as DrawCommand[],\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"modeLayers.js","names":["DEFAULT_INTENSITY","workspaceTintLayer","opts","registry","ws","tint","opacity","W","H","dims","strip","whole","page","t","viewToTransform","view","sx0","sy0","worldToScreen","sx1","sy1","pl","pt","pr","pb","cmds","push","w","h","x","y","from","to","modeDecorationLayer","decorations"],"sources":["../../../src/features/modes/modeLayers.ts"],"sourcesContent":["import type { Rect } from '@weasel-js/geom';\nimport type { ModeDecorations, ModeRegistry } from '@weasel-js/modes';\nimport type { DrawCommand } from '@weasel-js/renderer';\nimport type { RenderLayer } from 'core/layers/render';\nimport { viewToTransform } from 'core/viewport/view';\nimport { worldToScreen } from 'core/viewport/viewTransform';\n\n/** Options for {@link workspaceTintLayer}. */\nexport interface WorkspaceTintLayerOptions {\n registry: ModeRegistry;\n /** The page, in world coordinates. When given, the tint covers only the\n * workspace around it, each strip fading toward the page edge if the mode\n * names a gradient. Without it the tint covers the whole canvas. */\n page?: () => Rect | null;\n /** Opacity for every mode's tint, in place of its `workspace.intensity`. */\n intensity?: number;\n id?: string;\n label?: string;\n}\n\nconst DEFAULT_INTENSITY = 0.12;\n\n/**\n * A screen-space layer painting the active mode's `WorkspaceVisual`: nothing in\n * a mode without a tint, otherwise a wash at the mode's intensity, bottom-up or\n * top-down when the mode names a gradient. It subscribes to the registry, so a\n * mode switch repaints it.\n */\nexport function workspaceTintLayer(opts: WorkspaceTintLayerOptions): RenderLayer<unknown> {\n const { registry } = opts;\n return {\n id: opts.id ?? 'mode-tint',\n label: opts.label ?? 'Mode tint',\n space: 'screen',\n subscribe: registry.subscribe,\n draw: (_data, view, dims) => {\n const ws = registry.current().workspace;\n const tint = ws?.tint;\n if (!tint || tint === 'transparent') return [];\n const opacity = opts.intensity ?? ws.intensity ?? DEFAULT_INTENSITY;\n const { width: W, height: H } = dims;\n\n const strip = (\n x: number, y: number, width: number, height: number,\n from: { x: number; y: number }, to: { x: number; y: number },\n ): DrawCommand => ({\n kind: 'path',\n path: { kind: 'rect', x, y, width, height },\n fill: { paint: ws.gradient\n ? { kind: 'linear-gradient', from, to, stops: [{ offset: 0, color: tint }, { offset: 1, color: 'transparent' }], opacity }\n : { kind: 'solid', color: tint, opacity } },\n });\n\n const whole = (): DrawCommand[] => [\n ws.gradient === 'top-down'\n ? strip(0, 0, W, H, { x: 0, y: 0 }, { x: 0, y: H })\n : strip(0, 0, W, H, { x: 0, y: H }, { x: 0, y: 0 }),\n ];\n\n const page = opts.page?.();\n if (!page) return whole();\n\n const t = viewToTransform(view);\n const [sx0, sy0] = worldToScreen(page.x, page.y, t);\n const [sx1, sy1] = worldToScreen(page.x + page.width, page.y + page.height, t);\n const pl = Math.max(0, Math.min(sx0, sx1));\n const pt = Math.max(0, Math.min(sy0, sy1));\n const pr = Math.min(W, Math.max(sx0, sx1));\n const pb = Math.min(H, Math.max(sy0, sy1));\n if (pr <= pl || pb <= pt) {\n return [{ kind: 'path', path: { kind: 'rect', x: 0, y: 0, width: W, height: H }, fill: { paint: { kind: 'solid', color: tint, opacity } } }];\n }\n\n const cmds: DrawCommand[] = [];\n const push = (\n x: number, y: number, w: number, h: number,\n from: { x: number; y: number }, to: { x: number; y: number },\n ): void => { if (w > 0 && h > 0) cmds.push(strip(x, y, w, h, from, to)); };\n push(0, 0, W, pt, { x: 0, y: 0 }, { x: 0, y: pt });\n push(0, pb, W, H - pb, { x: 0, y: H }, { x: 0, y: pb });\n push(0, pt, pl, pb - pt, { x: 0, y: 0 }, { x: pl, y: 0 });\n push(pr, pt, W - pr, pb - pt, { x: W, y: 0 }, { x: pr, y: 0 });\n return cmds;\n },\n };\n}\n\n/** A world-space layer drawing a `ModeDecorations`' active painter. It\n * subscribes to the decorations, so a mode switch or a new painter repaints\n * it. */\nexport function modeDecorationLayer(\n decorations: ModeDecorations,\n opts: { id?: string; label?: string } = {},\n): RenderLayer<unknown> {\n return {\n id: opts.id ?? 'mode-decorations',\n label: opts.label ?? 'Mode decorations',\n subscribe: decorations.subscribe,\n draw: () => decorations.paint() as DrawCommand[],\n };\n}\n"],"mappings":";;;AAoBA,IAAMA,IAAoB;AAQ1B,SAAgBC,EAAmB,GAAuD;CACxF,IAAM,EAAE,gBAAaC;CACrB,OAAO;EACL,IAAIA,EAAK,MAAM;EACf,OAAOA,EAAK,SAAS;EACrB,OAAO;EACP,WAAWC,EAAS;EACpB,OAAO,GAAO,GAAM,MAAS;GAC3B,IAAMC,IAAKD,EAAS,QAAQ,CAAC,CAAC,WACxBE,IAAOD,GAAI;GACjB,IAAI,CAACC,KAAQA,MAAS,eAAe,OAAO,CAAC;GAC7C,IAAMC,IAAUJ,EAAK,aAAaE,EAAG,aAAaJ,GAC5C,EAAE,OAAOO,GAAG,QAAQC,MAAMC,GAE1BC,KACJ,GAAW,GAAW,GAAe,GACrC,GAAgC,OACf;IACjB,MAAM;IACN,MAAM;KAAE,MAAM;KAAQ;KAAG;KAAG;KAAO;IAAO;IAC1C,MAAM,EAAE,OAAON,EAAG,WACd;KAAE,MAAM;KAAmB;KAAM;KAAI,OAAO,CAAC;MAAE,QAAQ;MAAG,OAAOC;KAAK,GAAG;MAAE,QAAQ;MAAG,OAAO;KAAc,CAAC;KAAG;IAAQ,IACvH;KAAE,MAAM;KAAS,OAAOA;KAAM;IAAQ,EAAE;GAC9C,IAEMM,UAA6B,CACjCP,EAAG,aAAa,aACZM,EAAM,GAAG,GAAGH,GAAGC,GAAG;IAAE,GAAG;IAAG,GAAG;GAAE,GAAG;IAAE,GAAG;IAAG,GAAGA;GAAE,CAAC,IAChDE,EAAM,GAAG,GAAGH,GAAGC,GAAG;IAAE,GAAG;IAAG,GAAGA;GAAE,GAAG;IAAE,GAAG;IAAG,GAAG;GAAE,CAAC,CACtD,GAEMI,IAAOV,EAAK,OAAO;GACzB,IAAI,CAACU,GAAM,OAAOD,EAAM;GAExB,IAAME,IAAIC,EAAgBC,CAAI,GACxB,CAACC,GAAKC,KAAOC,EAAcN,EAAK,GAAGA,EAAK,GAAGC,CAAC,GAC5C,CAACM,GAAKC,KAAOF,EAAcN,EAAK,IAAIA,EAAK,OAAOA,EAAK,IAAIA,EAAK,QAAQC,CAAC,GACvEQ,IAAK,KAAK,IAAI,GAAG,KAAK,IAAIL,GAAKG,CAAG,CAAC,GACnCG,IAAK,KAAK,IAAI,GAAG,KAAK,IAAIL,GAAKG,CAAG,CAAC,GACnCG,IAAK,KAAK,IAAIhB,GAAG,KAAK,IAAIS,GAAKG,CAAG,CAAC,GACnCK,IAAK,KAAK,IAAIhB,GAAG,KAAK,IAAIS,GAAKG,CAAG,CAAC;GACzC,IAAIG,KAAMF,KAAMG,KAAMF,GACpB,OAAO,CAAC;IAAE,MAAM;IAAQ,MAAM;KAAE,MAAM;KAAQ,GAAG;KAAG,GAAG;KAAG,OAAOf;KAAG,QAAQC;IAAE;IAAG,MAAM,EAAE,OAAO;KAAE,MAAM;KAAS,OAAOH;KAAM;IAAQ,EAAE;GAAE,CAAC;GAG7I,IAAMoB,IAAsB,CAAC,GACvBC,KACJ,GAAW,GAAW,GAAW,GACjC,GAAgC,MACvB;IAAE,AAAIC,IAAI,KAAKC,IAAI,KAAGH,EAAK,KAAKf,EAAMmB,GAAGC,GAAGH,GAAGC,GAAGG,GAAMC,CAAE,CAAC;GAAG;GAKzE,OAJAN,EAAK,GAAG,GAAGnB,GAAGe,GAAI;IAAE,GAAG;IAAG,GAAG;GAAE,GAAG;IAAE,GAAG;IAAG,GAAGA;GAAG,CAAC,GACjDI,EAAK,GAAGF,GAAIjB,GAAGC,IAAIgB,GAAI;IAAE,GAAG;IAAG,GAAGhB;GAAE,GAAG;IAAE,GAAG;IAAG,GAAGgB;GAAG,CAAC,GACtDE,EAAK,GAAGJ,GAAID,GAAIG,IAAKF,GAAI;IAAE,GAAG;IAAG,GAAG;GAAE,GAAG;IAAKD;IAAI,GAAG;GAAE,CAAC,GACxDK,EAAKH,GAAID,GAAIf,IAAIgB,GAAIC,IAAKF,GAAI;IAAE,GAAGf;IAAG,GAAG;GAAE,GAAG;IAAE,GAAGgB;IAAI,GAAG;GAAE,CAAC,GACtDE;EACT;CACF;AACF;AAKA,SAAgBQ,EACd,GACA,IAAwC,CAAC,GACnB;CACtB,OAAO;EACL,IAAI/B,EAAK,MAAM;EACf,OAAOA,EAAK,SAAS;EACrB,WAAWgC,EAAY;EACvB,YAAYA,EAAY,MAAM;CAChC;AACF"}