@weasel-js/core 1.9.4 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1191) hide show
  1. package/CHANGELOG.md +918 -0
  2. package/README.md +38 -3
  3. package/dist/WeaselProvider.js +5 -7
  4. package/dist/WeaselProvider.js.map +1 -1
  5. package/dist/affordances/composeAffordanceLayer.js +92 -84
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  7. package/dist/affordances/cornerResize.js +3 -2
  8. package/dist/affordances/cornerResize.js.map +1 -1
  9. package/dist/affordances/hitAffordanceRegions.js +71 -101
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  11. package/dist/affordances/pathAnchors.js +50 -28
  12. package/dist/affordances/pathAnchors.js.map +1 -1
  13. package/dist/affordances/rotateCursor.js +12 -0
  14. package/dist/affordances/rotateCursor.js.map +1 -0
  15. package/dist/affordances/rotationHandle.js +44 -46
  16. package/dist/affordances/rotationHandle.js.map +1 -1
  17. package/dist/animation/behaviors/coast.js +21 -0
  18. package/dist/animation/behaviors/coast.js.map +1 -0
  19. package/dist/animation/behaviors/coastByWrite.js +107 -0
  20. package/dist/animation/behaviors/coastByWrite.js.map +1 -0
  21. package/dist/animation/behaviors/coastOnTargets.js +94 -0
  22. package/dist/animation/behaviors/coastOnTargets.js.map +1 -0
  23. package/dist/animation/behaviors/momentum.js +48 -136
  24. package/dist/animation/behaviors/momentum.js.map +1 -1
  25. package/dist/animation/clipTargets.js +12 -0
  26. package/dist/animation/clipTargets.js.map +1 -0
  27. package/dist/animation/index.js +15 -20
  28. package/dist/animation/poseHelpers.js +112 -33
  29. package/dist/animation/poseHelpers.js.map +1 -1
  30. package/dist/animation/poseTarget.js +115 -0
  31. package/dist/animation/poseTarget.js.map +1 -0
  32. package/dist/animation/reflow.js +113 -83
  33. package/dist/animation/reflow.js.map +1 -1
  34. package/dist/animation/rewind.js +66 -0
  35. package/dist/animation/rewind.js.map +1 -0
  36. package/dist/animation/rig/bindRig.js +85 -53
  37. package/dist/animation/rig/bindRig.js.map +1 -1
  38. package/dist/animation/rig/rigNode.js +99 -0
  39. package/dist/animation/rig/rigNode.js.map +1 -0
  40. package/dist/animation/rig/rigSeat.js +59 -0
  41. package/dist/animation/rig/rigSeat.js.map +1 -0
  42. package/dist/animation/rig/skinBinding.js +64 -0
  43. package/dist/animation/rig/skinBinding.js.map +1 -0
  44. package/dist/animation/rig/useRig.js +31 -16
  45. package/dist/animation/rig/useRig.js.map +1 -1
  46. package/dist/animation/wrappers/animateLifecycle.js +8 -7
  47. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  48. package/dist/animation/wrappers/animateOnSetPose.js +31 -31
  49. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  50. package/dist/animation/wrappers/instantPose.js.map +1 -1
  51. package/dist/animation/writtenPoseTarget.js +33 -0
  52. package/dist/animation/writtenPoseTarget.js.map +1 -0
  53. package/dist/autoPoseDescriptor-DHg5KqaJ.d.ts +27 -0
  54. package/dist/barrel/canvas.js +32 -0
  55. package/dist/barrel/chrome.js +10 -10
  56. package/dist/barrel/input.js +16 -17
  57. package/dist/barrel/interactions.js +34 -37
  58. package/dist/barrel/paint.js +11 -18
  59. package/dist/barrel/paths.js +13 -19
  60. package/dist/barrel/renderer.js +14 -20
  61. package/dist/barrel/routing.js +54 -47
  62. package/dist/barrel/scene.js +37 -0
  63. package/dist/barrel/text.js +9 -18
  64. package/dist/barrel/viewport.js +44 -51
  65. package/dist/canvas/Canvas.js +270 -475
  66. package/dist/canvas/Canvas.js.map +1 -1
  67. package/dist/canvas/CanvasView.js +168 -190
  68. package/dist/canvas/CanvasView.js.map +1 -1
  69. package/dist/canvas/CursorCoordsHud.js +24 -25
  70. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  71. package/dist/canvas/DrawCanvas.js +39 -56
  72. package/dist/canvas/DrawCanvas.js.map +1 -1
  73. package/dist/canvas/ModalityHud.js.map +1 -1
  74. package/dist/canvas/NodeShape.js +28 -29
  75. package/dist/canvas/NodeShape.js.map +1 -1
  76. package/dist/canvas/PickHud.js.map +1 -1
  77. package/dist/canvas/SceneCanvas/DevHuds.js +40 -0
  78. package/dist/canvas/SceneCanvas/DevHuds.js.map +1 -0
  79. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +66 -107
  80. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -1
  81. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +33 -36
  82. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -1
  83. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +38 -50
  84. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -1
  85. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +3 -3
  86. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/coordTrace.js +37 -1
  88. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -1
  89. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +319 -270
  90. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  91. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +1 -1
  92. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  93. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -1
  94. package/dist/canvas/SceneCanvas/features.js +71 -62
  95. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  96. package/dist/canvas/SceneCanvas/insertPreviewCommands.js +97 -0
  97. package/dist/canvas/SceneCanvas/insertPreviewCommands.js.map +1 -0
  98. package/dist/canvas/SceneCanvas/isDev.js.map +1 -1
  99. package/dist/canvas/SceneCanvas/poseGeometry.js +33 -37
  100. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  101. package/dist/canvas/SceneCanvas/props.js +15 -14
  102. package/dist/canvas/SceneCanvas/props.js.map +1 -1
  103. package/dist/canvas/SceneCanvas/scenePointQuery.js +50 -0
  104. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -0
  105. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js +52 -0
  106. package/dist/canvas/SceneCanvas/shapeGeneratorProperties.js.map +1 -0
  107. package/dist/canvas/SceneCanvas/toolRegistry.js +23 -0
  108. package/dist/canvas/SceneCanvas/toolRegistry.js.map +1 -0
  109. package/dist/canvas/SceneCanvas/useActionTunings.js +17 -0
  110. package/dist/canvas/SceneCanvas/useActionTunings.js.map +1 -0
  111. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +6 -1
  112. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -1
  113. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  114. package/dist/canvas/SceneCanvas/useBuiltinTools.js +21 -0
  115. package/dist/canvas/SceneCanvas/useBuiltinTools.js.map +1 -0
  116. package/dist/canvas/SceneCanvas/useCanvasCamera.js +46 -0
  117. package/dist/canvas/SceneCanvas/useCanvasCamera.js.map +1 -0
  118. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js +20 -0
  119. package/dist/canvas/SceneCanvas/useCanvasDispatcher.js.map +1 -0
  120. package/dist/canvas/SceneCanvas/useCanvasSelection.js +16 -0
  121. package/dist/canvas/SceneCanvas/useCanvasSelection.js.map +1 -0
  122. package/dist/canvas/SceneCanvas/useCanvasTools.js +67 -0
  123. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -0
  124. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +49 -113
  125. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  126. package/dist/canvas/SceneCanvas/useHeldModifiers.js +20 -0
  127. package/dist/canvas/SceneCanvas/useHeldModifiers.js.map +1 -0
  128. package/dist/canvas/SceneCanvas/useNodeAtPoint.js +26 -0
  129. package/dist/canvas/SceneCanvas/useNodeAtPoint.js.map +1 -0
  130. package/dist/canvas/SceneCanvas/useNodeKinds.js +26 -0
  131. package/dist/canvas/SceneCanvas/useNodeKinds.js.map +1 -0
  132. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +51 -41
  133. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  134. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js +47 -0
  135. package/dist/canvas/SceneCanvas/useSceneCanvasHandle.js.map +1 -0
  136. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +66 -0
  137. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -0
  138. package/dist/canvas/SceneCanvas/useSceneChrome.js +59 -0
  139. package/dist/canvas/SceneCanvas/useSceneChrome.js.map +1 -0
  140. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js +23 -0
  141. package/dist/canvas/SceneCanvas/useSceneRedrawSources.js.map +1 -0
  142. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +65 -101
  143. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  144. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js +37 -0
  145. package/dist/canvas/SceneCanvas/useSceneSlotLayers.js.map +1 -0
  146. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js +38 -0
  147. package/dist/canvas/SceneCanvas/useSelectionOverlayLayer.js.map +1 -0
  148. package/dist/canvas/SceneCanvas/useViewLayerGate.js +20 -0
  149. package/dist/canvas/SceneCanvas/useViewLayerGate.js.map +1 -0
  150. package/dist/canvas/SceneCanvas/useViewportActions.js +9 -1
  151. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -1
  152. package/dist/canvas/SceneCanvas/worldPointAt.js +8 -0
  153. package/dist/canvas/SceneCanvas/worldPointAt.js.map +1 -0
  154. package/dist/canvas/SceneCanvas.js +301 -708
  155. package/dist/canvas/SceneCanvas.js.map +1 -1
  156. package/dist/canvas/SceneViewCanvas.js +41 -47
  157. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  158. package/dist/canvas/SurfaceCanvas.js +40 -0
  159. package/dist/canvas/SurfaceCanvas.js.map +1 -0
  160. package/dist/canvas/adapterDerivedPath.js +26 -0
  161. package/dist/canvas/adapterDerivedPath.js.map +1 -0
  162. package/dist/canvas/adapterPickSource.js +34 -0
  163. package/dist/canvas/adapterPickSource.js.map +1 -0
  164. package/dist/canvas/affordanceAt.js +12 -2
  165. package/dist/canvas/affordanceAt.js.map +1 -1
  166. package/dist/canvas/buildSceneLayer.js +81 -61
  167. package/dist/canvas/buildSceneLayer.js.map +1 -1
  168. package/dist/canvas/buildSceneTree.js +56 -34
  169. package/dist/canvas/buildSceneTree.js.map +1 -1
  170. package/dist/canvas/canvasRenderer.js +40 -44
  171. package/dist/canvas/canvasRenderer.js.map +1 -1
  172. package/dist/canvas/colorOverrides.js.map +1 -1
  173. package/dist/canvas/copiesAbove.js +27 -0
  174. package/dist/canvas/copiesAbove.js.map +1 -0
  175. package/dist/canvas/defaultDrawOne.js +25 -24
  176. package/dist/canvas/defaultDrawOne.js.map +1 -1
  177. package/dist/canvas/deps/areaSelect.js +4 -4
  178. package/dist/canvas/deps/areaSelect.js.map +1 -1
  179. package/dist/canvas/deps/debug.js.map +1 -1
  180. package/dist/canvas/deps/editAnchors.js +47 -71
  181. package/dist/canvas/deps/editAnchors.js.map +1 -1
  182. package/dist/canvas/deps/geometryProjection.js.map +1 -1
  183. package/dist/canvas/deps/hitTestArea.js +45 -25
  184. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  185. package/dist/canvas/deps/insert.js +149 -104
  186. package/dist/canvas/deps/insert.js.map +1 -1
  187. package/dist/canvas/deps/lassoSelect.js +5 -5
  188. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  189. package/dist/canvas/deps/layout.js +9 -15
  190. package/dist/canvas/deps/layout.js.map +1 -1
  191. package/dist/canvas/deps/poseDescriptor.js +1 -1
  192. package/dist/canvas/deps/poseDescriptor.js.map +1 -1
  193. package/dist/canvas/deps/resizePolicy.js.map +1 -1
  194. package/dist/canvas/deps/slice.js +44 -45
  195. package/dist/canvas/deps/slice.js.map +1 -1
  196. package/dist/canvas/deps/textEdit.js +8 -8
  197. package/dist/canvas/deps/textEdit.js.map +1 -1
  198. package/dist/canvas/deps/view.js.map +1 -1
  199. package/dist/canvas/derivedPath.js +69 -43
  200. package/dist/canvas/derivedPath.js.map +1 -1
  201. package/dist/canvas/drawEnvelope.js +8 -4
  202. package/dist/canvas/drawEnvelope.js.map +1 -1
  203. package/dist/canvas/getNodeAtPoint.js +2 -6
  204. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  205. package/dist/canvas/hud.module.js.map +1 -1
  206. package/dist/canvas/insertPreviewExtent.js +33 -31
  207. package/dist/canvas/insertPreviewExtent.js.map +1 -1
  208. package/dist/canvas/layerOrder.js.map +1 -1
  209. package/dist/canvas/layerSlots.js +6 -1
  210. package/dist/canvas/layerSlots.js.map +1 -1
  211. package/dist/canvas/nodeShapes/derivedPainter.js +12 -12
  212. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -1
  213. package/dist/canvas/nodeShapes/imagePainter.js +10 -10
  214. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -1
  215. package/dist/canvas/nodeShapes/memo.js.map +1 -1
  216. package/dist/canvas/nodeShapes/nodePaint.js +34 -23
  217. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  218. package/dist/canvas/nodeShapes/pathPainter.js +23 -22
  219. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  220. package/dist/canvas/nodeShapes/poseBox.js +6 -6
  221. package/dist/canvas/nodeShapes/poseBox.js.map +1 -1
  222. package/dist/canvas/nodeShapes/rectFallbackPainter.js +8 -8
  223. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  224. package/dist/canvas/nodeShapes/shapePainter.js +16 -16
  225. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  226. package/dist/canvas/nodeShapes/textPainter.js +1 -1
  227. package/dist/canvas/nodeShapes/textPainter.js.map +1 -1
  228. package/dist/canvas/overChildren.js +29 -0
  229. package/dist/canvas/overChildren.js.map +1 -0
  230. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  231. package/dist/canvas/paintCull.js +6 -8
  232. package/dist/canvas/paintCull.js.map +1 -1
  233. package/dist/{features/cursor → canvas}/paintedCursorLayer.js +2 -2
  234. package/dist/canvas/paintedCursorLayer.js.map +1 -0
  235. package/dist/canvas/pickReach.js +23 -0
  236. package/dist/canvas/pickReach.js.map +1 -0
  237. package/dist/canvas/pickWalk.js +43 -70
  238. package/dist/canvas/pickWalk.js.map +1 -1
  239. package/dist/canvas/planeClips.js +18 -19
  240. package/dist/canvas/planeClips.js.map +1 -1
  241. package/dist/canvas/poseCascade.js +41 -0
  242. package/dist/canvas/poseCascade.js.map +1 -0
  243. package/dist/canvas/poseRotation.js +1 -3
  244. package/dist/canvas/poseRotation.js.map +1 -1
  245. package/dist/canvas/rasterReadback.js +22 -0
  246. package/dist/canvas/rasterReadback.js.map +1 -0
  247. package/dist/canvas/renderDebugSnapshot.js +12 -12
  248. package/dist/canvas/renderDebugSnapshot.js.map +1 -1
  249. package/dist/canvas/renderNeeds.js +3 -3
  250. package/dist/canvas/renderNeeds.js.map +1 -1
  251. package/dist/canvas/renderSceneToPixels.js +64 -83
  252. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  253. package/dist/canvas/sceneAdapter.js +59 -144
  254. package/dist/canvas/sceneAdapter.js.map +1 -1
  255. package/dist/canvas/sceneClipboard.js +1 -1
  256. package/dist/canvas/sceneClipboard.js.map +1 -1
  257. package/dist/canvas/sceneLayerPaint.js +4 -4
  258. package/dist/canvas/sceneLayerPaint.js.map +1 -1
  259. package/dist/canvas/sceneSlotWiring.js +10 -9
  260. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  261. package/dist/canvas/sceneViewRender.js +37 -42
  262. package/dist/canvas/sceneViewRender.js.map +1 -1
  263. package/dist/canvas/slopsDebugLayer.js +4 -4
  264. package/dist/canvas/slopsDebugLayer.js.map +1 -1
  265. package/dist/canvas/useCanvasRenderer.js +23 -11
  266. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  267. package/dist/canvas/useCanvasSurface.js +31 -0
  268. package/dist/canvas/useCanvasSurface.js.map +1 -0
  269. package/dist/canvas/useCanvasView.js +51 -44
  270. package/dist/canvas/useCanvasView.js.map +1 -1
  271. package/dist/canvas/useFrameLoop.js +11 -12
  272. package/dist/canvas/useFrameLoop.js.map +1 -1
  273. package/dist/canvas/useHostAnchor.js +35 -33
  274. package/dist/canvas/useHostAnchor.js.map +1 -1
  275. package/dist/canvas/useLateContentRedraw.js +8 -8
  276. package/dist/canvas/useLateContentRedraw.js.map +1 -1
  277. package/dist/canvas/useSceneAdapter.js +22 -0
  278. package/dist/canvas/useSceneAdapter.js.map +1 -0
  279. package/dist/canvas/useSceneLayerList.js +4 -14
  280. package/dist/canvas/useSceneLayerList.js.map +1 -1
  281. package/dist/canvas/useSurfaceInput.js +39 -0
  282. package/dist/canvas/useSurfaceInput.js.map +1 -0
  283. package/dist/canvas/useToolCursor.js +29 -0
  284. package/dist/canvas/useToolCursor.js.map +1 -0
  285. package/dist/canvas/useViewHelpers.js +46 -85
  286. package/dist/canvas/useViewHelpers.js.map +1 -1
  287. package/dist/canvas/viewInputs.js.map +1 -1
  288. package/dist/canvas/viewRegistry.js +40 -34
  289. package/dist/canvas/viewRegistry.js.map +1 -1
  290. package/dist/canvas/watchElementMove.js +43 -0
  291. package/dist/canvas/watchElementMove.js.map +1 -0
  292. package/dist/canvas/wrapNodeOutput.js +7 -2
  293. package/dist/canvas/wrapNodeOutput.js.map +1 -1
  294. package/dist/clipboard.d.ts +7 -14
  295. package/dist/{types-B4iJRHC3.d.ts → clone-C0eADtS0.d.ts} +129 -84
  296. package/dist/clone.d.ts +4 -8
  297. package/dist/clone.js +0 -2
  298. package/dist/core/device/targets.js.map +1 -1
  299. package/dist/core/device/useDeviceProfile.js +13 -13
  300. package/dist/core/device/useDeviceProfile.js.map +1 -1
  301. package/dist/{interactions/actions/resize → core/geometry}/autoPoseDescriptor.js +8 -7
  302. package/dist/core/geometry/autoPoseDescriptor.js.map +1 -0
  303. package/dist/core/geometry/pathPoseDescriptor.js +88 -0
  304. package/dist/core/geometry/pathPoseDescriptor.js.map +1 -0
  305. package/dist/core/geometry/poseDescriptor.js +102 -29
  306. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  307. package/dist/core/geometry/regionHit.js +35 -37
  308. package/dist/core/geometry/regionHit.js.map +1 -1
  309. package/dist/core/geometry/targetFrame.js +94 -0
  310. package/dist/core/geometry/targetFrame.js.map +1 -0
  311. package/dist/core/geometry/unionBounds.js +4 -5
  312. package/dist/core/geometry/unionBounds.js.map +1 -1
  313. package/dist/core/layers/backgroundFill.js +31 -0
  314. package/dist/core/layers/backgroundFill.js.map +1 -0
  315. package/dist/{features/groups → core/layers}/children.js +2 -4
  316. package/dist/core/layers/children.js.map +1 -0
  317. package/dist/{features/focus → core/layers}/gateLayer.js +2 -2
  318. package/dist/core/layers/gateLayer.js.map +1 -0
  319. package/dist/core/layers/layerGroup.js +40 -0
  320. package/dist/core/layers/layerGroup.js.map +1 -0
  321. package/dist/core/layers/render.js +50 -76
  322. package/dist/core/layers/render.js.map +1 -1
  323. package/dist/core/ops/create.js +2 -2
  324. package/dist/core/ops/create.js.map +1 -1
  325. package/dist/core/ops/createHistory.js +9 -9
  326. package/dist/core/ops/createHistory.js.map +1 -1
  327. package/dist/core/ops/delete.js +19 -23
  328. package/dist/core/ops/delete.js.map +1 -1
  329. package/dist/core/ops/reorder/index.js +3 -7
  330. package/dist/core/ops/reorder/index.js.map +1 -1
  331. package/dist/core/ops/reorder/setChildOrder.js +2 -4
  332. package/dist/core/ops/reorder/setChildOrder.js.map +1 -1
  333. package/dist/core/ops/reparent.js +0 -1
  334. package/dist/core/ops/reparent.js.map +1 -1
  335. package/dist/core/ops/slot.js +3 -6
  336. package/dist/core/ops/slot.js.map +1 -1
  337. package/dist/core/pages/fitViewToPage.js +15 -0
  338. package/dist/core/pages/fitViewToPage.js.map +1 -0
  339. package/dist/core/pages/pages.js +65 -0
  340. package/dist/core/pages/pages.js.map +1 -0
  341. package/dist/core/pages/pagesLayer.js +27 -0
  342. package/dist/core/pages/pagesLayer.js.map +1 -0
  343. package/dist/core/paint/meshKind.js +16 -0
  344. package/dist/core/paint/meshKind.js.map +1 -0
  345. package/dist/{features/meshPaint/lazyKind.js → core/paint/meshKindLazy.js} +104 -93
  346. package/dist/core/paint/meshKindLazy.js.map +1 -0
  347. package/dist/core/paint/paintKindEntry.js +8 -0
  348. package/dist/core/paint/paintKindEntry.js.map +1 -0
  349. package/dist/core/paint/paintKinds.js +144 -0
  350. package/dist/core/paint/paintKinds.js.map +1 -0
  351. package/dist/core/paint/registerMesh.js +7 -0
  352. package/dist/core/paint/registerMesh.js.map +1 -0
  353. package/dist/core/scene/NodeProperties.js.map +1 -1
  354. package/dist/core/scene/NodeRouting.js.map +1 -1
  355. package/dist/core/scene/arrivalWindow.js +65 -64
  356. package/dist/core/scene/arrivalWindow.js.map +1 -1
  357. package/dist/core/scene/boundOps.js +40 -0
  358. package/dist/core/scene/boundOps.js.map +1 -0
  359. package/dist/core/scene/composeFrame.js +9 -6
  360. package/dist/core/scene/composeFrame.js.map +1 -1
  361. package/dist/core/scene/composePose.js +105 -0
  362. package/dist/core/scene/composePose.js.map +1 -0
  363. package/dist/core/scene/depMemo.js +31 -6
  364. package/dist/core/scene/depMemo.js.map +1 -1
  365. package/dist/core/scene/derivedPath.js +19 -20
  366. package/dist/core/scene/derivedPath.js.map +1 -1
  367. package/dist/core/scene/editMode.js +26 -0
  368. package/dist/core/scene/editMode.js.map +1 -0
  369. package/dist/core/scene/effectivePose.js +42 -39
  370. package/dist/core/scene/effectivePose.js.map +1 -1
  371. package/dist/core/scene/fieldEdits.js +98 -0
  372. package/dist/core/scene/fieldEdits.js.map +1 -0
  373. package/dist/core/scene/historyFacade.js +122 -70
  374. package/dist/core/scene/historyFacade.js.map +1 -1
  375. package/dist/core/scene/historyForm.js +6 -0
  376. package/dist/core/scene/historyForm.js.map +1 -0
  377. package/dist/core/scene/kitOps.js +83 -71
  378. package/dist/core/scene/kitOps.js.map +1 -1
  379. package/dist/core/scene/kitRegistry.js.map +1 -1
  380. package/dist/core/scene/layerStack.js +105 -12
  381. package/dist/core/scene/layerStack.js.map +1 -1
  382. package/dist/core/scene/layoutPass.js +58 -59
  383. package/dist/core/scene/layoutPass.js.map +1 -1
  384. package/dist/{features/groups → core/scene}/nestedHit.js +3 -3
  385. package/dist/core/scene/nestedHit.js.map +1 -0
  386. package/dist/core/scene/nodeFnFields.js +16 -9
  387. package/dist/core/scene/nodeFnFields.js.map +1 -1
  388. package/dist/core/scene/nodeMemo.js.map +1 -1
  389. package/dist/core/scene/nodeStore.js +72 -71
  390. package/dist/core/scene/nodeStore.js.map +1 -1
  391. package/dist/core/scene/notifier.js +37 -0
  392. package/dist/core/scene/notifier.js.map +1 -0
  393. package/dist/core/scene/opTable.js +50 -0
  394. package/dist/core/scene/opTable.js.map +1 -0
  395. package/dist/core/scene/outerOps.js +67 -0
  396. package/dist/core/scene/outerOps.js.map +1 -0
  397. package/dist/core/scene/poseHold.js +39 -0
  398. package/dist/core/scene/poseHold.js.map +1 -0
  399. package/dist/core/scene/poseOverrides.js +44 -36
  400. package/dist/core/scene/poseOverrides.js.map +1 -1
  401. package/dist/core/scene/poseSnapshot.js.map +1 -1
  402. package/dist/core/scene/reconcileSpecs.js +4 -3
  403. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  404. package/dist/core/scene/recorder.js +86 -0
  405. package/dist/core/scene/recorder.js.map +1 -0
  406. package/dist/core/scene/renderOrder.js.map +1 -1
  407. package/dist/core/scene/scene.js +81 -690
  408. package/dist/core/scene/scene.js.map +1 -1
  409. package/dist/core/scene/sceneEdits.js +58 -0
  410. package/dist/core/scene/sceneEdits.js.map +1 -0
  411. package/dist/core/scene/sceneMutators.js +49 -0
  412. package/dist/core/scene/sceneMutators.js.map +1 -0
  413. package/dist/core/scene/scenePoseAdapter.js +16 -0
  414. package/dist/core/scene/scenePoseAdapter.js.map +1 -0
  415. package/dist/core/scene/sceneRecording.js +91 -0
  416. package/dist/core/scene/sceneRecording.js.map +1 -0
  417. package/dist/core/scene/sceneSelection.js +28 -0
  418. package/dist/core/scene/sceneSelection.js.map +1 -0
  419. package/dist/core/scene/sceneState.js +49 -0
  420. package/dist/core/scene/sceneState.js.map +1 -0
  421. package/dist/core/scene/serialization.js +8 -5
  422. package/dist/core/scene/serialization.js.map +1 -1
  423. package/dist/core/scene/staleReplay.js +51 -0
  424. package/dist/core/scene/staleReplay.js.map +1 -0
  425. package/dist/core/scene/statedFields.js +9 -0
  426. package/dist/core/scene/statedFields.js.map +1 -0
  427. package/dist/core/scene/treeEdits.js +127 -0
  428. package/dist/core/scene/treeEdits.js.map +1 -0
  429. package/dist/core/scene/treeReads.js +26 -0
  430. package/dist/core/scene/treeReads.js.map +1 -0
  431. package/dist/core/scene/types.js.map +1 -1
  432. package/dist/{features/groups → core/scene}/unionOfChildren.js +3 -3
  433. package/dist/core/scene/unionOfChildren.js.map +1 -0
  434. package/dist/core/scene/unitScopes.js +13 -0
  435. package/dist/core/scene/unitScopes.js.map +1 -0
  436. package/dist/core/scene/useScene.js.map +1 -1
  437. package/dist/core/selection/readOnlySelection.js +32 -0
  438. package/dist/core/selection/readOnlySelection.js.map +1 -0
  439. package/dist/core/selection/usePublishSceneSelection.js +26 -0
  440. package/dist/core/selection/usePublishSceneSelection.js.map +1 -0
  441. package/dist/core/selection/useSelection.js +34 -25
  442. package/dist/core/selection/useSelection.js.map +1 -1
  443. package/dist/core/shapeKinds.js.map +1 -1
  444. package/dist/core/stylus/stylus.js.map +1 -1
  445. package/dist/core/stylus/usePointerStylus.js.map +1 -1
  446. package/dist/core/usePaintKinds.js +1 -1
  447. package/dist/core/usePaintKinds.js.map +1 -1
  448. package/dist/core/viewport/clientToWorld.js.map +1 -1
  449. package/dist/core/viewport/fitViewToBounds.js.map +1 -1
  450. package/dist/core/viewport/parallax.js.map +1 -1
  451. package/dist/core/viewport/screenSlop.js +11 -11
  452. package/dist/core/viewport/screenSlop.js.map +1 -1
  453. package/dist/core/viewport/useCanvasSize.js.map +1 -1
  454. package/dist/core/viewport/useDecayLoop.js +31 -33
  455. package/dist/core/viewport/useDecayLoop.js.map +1 -1
  456. package/dist/core/viewport/useNodeOverlayFrame.js +84 -0
  457. package/dist/core/viewport/useNodeOverlayFrame.js.map +1 -0
  458. package/dist/core/viewport/useViewAnimation.js +113 -53
  459. package/dist/core/viewport/useViewAnimation.js.map +1 -1
  460. package/dist/core/viewport/view.js +14 -11
  461. package/dist/core/viewport/view.js.map +1 -1
  462. package/dist/core/viewport/wheelHandler.js.map +1 -1
  463. package/dist/core/viewport/zoomAt.js +11 -2
  464. package/dist/core/viewport/zoomAt.js.map +1 -1
  465. package/dist/{cornerHandles-CtCb8a3G.d.ts → cornerHandles-BSKbyuvQ.d.ts} +11 -24
  466. package/dist/debug/createDebugOverlayLayer.js +100 -100
  467. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  468. package/dist/debug/createDebugSink.js.map +1 -1
  469. package/dist/debug/frameStats.js.map +1 -1
  470. package/dist/debug/useDebugSink.js +52 -0
  471. package/dist/debug/useDebugSink.js.map +1 -0
  472. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -1
  473. package/dist/features/chrome-caps/conditions.js.map +1 -1
  474. package/dist/features/chrome-caps/defaults.js.map +1 -1
  475. package/dist/features/chrome-caps/resolve.js.map +1 -1
  476. package/dist/features/chrome-caps/useChromeCaps.js +54 -0
  477. package/dist/features/chrome-caps/useChromeCaps.js.map +1 -0
  478. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  479. package/dist/features/ingestion/contentHandlers.js +25 -19
  480. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  481. package/dist/features/ingestion/imageHandler.js +21 -24
  482. package/dist/features/ingestion/imageHandler.js.map +1 -1
  483. package/dist/features/ingestion/openFilePicker.js.map +1 -1
  484. package/dist/features/ingestion/placement.js +16 -0
  485. package/dist/features/ingestion/placement.js.map +1 -0
  486. package/dist/features/ingestion/svgHandler.js +5 -0
  487. package/dist/features/ingestion/svgHandler.js.map +1 -1
  488. package/dist/features/ingestion/textHandler.js +28 -0
  489. package/dist/features/ingestion/textHandler.js.map +1 -0
  490. package/dist/features/ingestion/useCanvasIngestion.js +48 -0
  491. package/dist/features/ingestion/useCanvasIngestion.js.map +1 -0
  492. package/dist/features/ingestion/weaselJsonHandler.js +5 -0
  493. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  494. package/dist/features/longPress/longPressFeedback.js.map +1 -1
  495. package/dist/features/modes/modeLayers.js +7 -7
  496. package/dist/features/modes/modeLayers.js.map +1 -1
  497. package/dist/features/paths/editablePath.js +63 -0
  498. package/dist/features/paths/editablePath.js.map +1 -0
  499. package/dist/features/paths/index.js +9 -16
  500. package/dist/features/paths/pathEditState.js +41 -0
  501. package/dist/features/paths/pathEditState.js.map +1 -0
  502. package/dist/features/paths/pathEditingOverlayLayer.js +36 -38
  503. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -1
  504. package/dist/features/paths/pathLayer.js +3 -2
  505. package/dist/features/paths/pathLayer.js.map +1 -1
  506. package/dist/features/paths/penPreviewLayer.js +86 -88
  507. package/dist/features/paths/penPreviewLayer.js.map +1 -1
  508. package/dist/features/paths/shapeGenerator.js +89 -0
  509. package/dist/features/paths/shapeGenerator.js.map +1 -0
  510. package/dist/features/paths/usePathEdit.js +34 -0
  511. package/dist/features/paths/usePathEdit.js.map +1 -0
  512. package/dist/features/poseRun/usePoseRun.js +44 -57
  513. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  514. package/dist/features/selection/overlay.js +170 -178
  515. package/dist/features/selection/overlay.js.map +1 -1
  516. package/dist/features/text/index.js +6 -0
  517. package/dist/features/text/textLayer.js +1 -1
  518. package/dist/features/text/textLayer.js.map +1 -1
  519. package/dist/features/text/useSceneTextEdit.js +119 -88
  520. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  521. package/dist/features/viewports/viewResolver.js +28 -24
  522. package/dist/features/viewports/viewResolver.js.map +1 -1
  523. package/dist/features/viewports/viewportLayer.js +25 -36
  524. package/dist/features/viewports/viewportLayer.js.map +1 -1
  525. package/dist/icons/SliceIcon.js +24 -0
  526. package/dist/icons/SliceIcon.js.map +1 -0
  527. package/dist/index.d.ts +5200 -8777
  528. package/dist/index.js +284 -320
  529. package/dist/input/keyState.js +14 -14
  530. package/dist/interactions/actions/actionShortcuts.js.map +1 -1
  531. package/dist/interactions/actions/{defaults/align.js → align/action.js} +15 -16
  532. package/dist/interactions/actions/align/action.js.map +1 -0
  533. package/dist/interactions/actions/align/align.js +24 -24
  534. package/dist/interactions/actions/align/align.js.map +1 -1
  535. package/dist/interactions/actions/booleans/action.js +65 -0
  536. package/dist/interactions/actions/booleans/action.js.map +1 -0
  537. package/dist/interactions/actions/booleans/booleans.js +74 -83
  538. package/dist/interactions/actions/booleans/booleans.js.map +1 -1
  539. package/dist/interactions/actions/booleans/operands.js +40 -0
  540. package/dist/interactions/actions/booleans/operands.js.map +1 -0
  541. package/dist/interactions/actions/booleans/pieces.js +45 -0
  542. package/dist/interactions/actions/booleans/pieces.js.map +1 -0
  543. package/dist/interactions/actions/booleans/placement.js +24 -0
  544. package/dist/interactions/actions/booleans/placement.js.map +1 -0
  545. package/dist/interactions/actions/booleans/useBooleans.js +11 -9
  546. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -1
  547. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -1
  548. package/dist/interactions/actions/{defaults/clipboard.js → clipboard/action.js} +19 -19
  549. package/dist/interactions/actions/clipboard/action.js.map +1 -0
  550. package/dist/interactions/actions/clipboard/clipboardOps.js +15 -15
  551. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  552. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  553. package/dist/interactions/actions/clone/action.js +103 -0
  554. package/dist/interactions/actions/clone/action.js.map +1 -0
  555. package/dist/interactions/actions/clone/behaviors.js +52 -0
  556. package/dist/interactions/actions/clone/behaviors.js.map +1 -0
  557. package/dist/interactions/actions/defaultCommitAdapter.js +10 -37
  558. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  559. package/dist/interactions/actions/defaults/anchorEditing.js +69 -74
  560. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  561. package/dist/interactions/actions/defaults/anchorHandles.js +42 -0
  562. package/dist/interactions/actions/defaults/anchorHandles.js.map +1 -0
  563. package/dist/interactions/actions/defaults/anchorJoin.js +92 -0
  564. package/dist/interactions/actions/defaults/anchorJoin.js.map +1 -0
  565. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  566. package/dist/interactions/actions/defaults/bendSegment.js +46 -0
  567. package/dist/interactions/actions/defaults/bendSegment.js.map +1 -0
  568. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -1
  569. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -1
  570. package/dist/interactions/actions/defaults/copySubtree.js +1 -1
  571. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -1
  572. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  573. package/dist/interactions/actions/defaults/delete.js.map +1 -1
  574. package/dist/interactions/actions/defaults/duplicate.js +36 -21
  575. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  576. package/dist/interactions/actions/defaults/enterPathEdit.js +19 -7
  577. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  578. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  579. package/dist/interactions/actions/defaults/group.js +35 -40
  580. package/dist/interactions/actions/defaults/group.js.map +1 -1
  581. package/dist/interactions/actions/defaults/icons/anchorIcons.js +75 -0
  582. package/dist/interactions/actions/defaults/icons/anchorIcons.js.map +1 -0
  583. package/dist/interactions/actions/defaults/icons/booleanIcons.js +24 -1
  584. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -1
  585. package/dist/interactions/actions/defaults/icons/editIcons.js +35 -8
  586. package/dist/interactions/actions/defaults/icons/editIcons.js.map +1 -1
  587. package/dist/interactions/actions/defaults/icons/outlineIcons.js +39 -1
  588. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -1
  589. package/dist/interactions/actions/defaults/ingest.js +19 -15
  590. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  591. package/dist/interactions/actions/defaults/insertPathAnchor.js +18 -34
  592. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -1
  593. package/dist/interactions/actions/defaults/nudge.js +43 -39
  594. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  595. package/dist/interactions/actions/defaults/pinchZoom.js +29 -29
  596. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -1
  597. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -1
  598. package/dist/interactions/actions/defaults/segmentUnder.js +22 -0
  599. package/dist/interactions/actions/defaults/segmentUnder.js.map +1 -0
  600. package/dist/interactions/actions/defaults/setFill.js +9 -3
  601. package/dist/interactions/actions/defaults/setFill.js.map +1 -1
  602. package/dist/interactions/actions/defaults/setFillOpacity.js +4 -1
  603. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -1
  604. package/dist/interactions/actions/defaults/setStroke.js.map +1 -1
  605. package/dist/interactions/actions/defaults/sliceOps.js +20 -22
  606. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -1
  607. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -1
  608. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -1
  609. package/dist/interactions/actions/defaults/viewportDragPan.js +1 -1
  610. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  611. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -1
  612. package/dist/interactions/actions/defaults/viewportZoom.js +82 -79
  613. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -1
  614. package/dist/interactions/actions/{defaults/distribute.js → distribute/action.js} +18 -19
  615. package/dist/interactions/actions/distribute/action.js.map +1 -0
  616. package/dist/interactions/actions/distribute/distribute.js +15 -15
  617. package/dist/interactions/actions/distribute/distribute.js.map +1 -1
  618. package/dist/interactions/actions/edit-anchors/action.js +101 -0
  619. package/dist/interactions/actions/edit-anchors/action.js.map +1 -0
  620. package/dist/interactions/actions/edit-anchors/geometry.js +2 -4
  621. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  622. package/dist/interactions/actions/edit-anchors/preview.js +26 -0
  623. package/dist/interactions/actions/edit-anchors/preview.js.map +1 -0
  624. package/dist/interactions/actions/edit-anchors/symmetry.js +11 -0
  625. package/dist/interactions/actions/edit-anchors/symmetry.js.map +1 -0
  626. package/dist/interactions/actions/flip/action.js +124 -0
  627. package/dist/interactions/actions/flip/action.js.map +1 -0
  628. package/dist/interactions/actions/flip/helpers.js +1 -1
  629. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  630. package/dist/interactions/actions/geometryProjection.js.map +1 -1
  631. package/dist/interactions/actions/gestureFrames.js +18 -0
  632. package/dist/interactions/actions/gestureFrames.js.map +1 -0
  633. package/dist/interactions/actions/gestureLifecycle.js +47 -20
  634. package/dist/interactions/actions/gestureLifecycle.js.map +1 -1
  635. package/dist/interactions/actions/insert/action.js +79 -0
  636. package/dist/interactions/actions/insert/action.js.map +1 -0
  637. package/dist/interactions/actions/insert/commit.js +28 -0
  638. package/dist/interactions/actions/insert/commit.js.map +1 -0
  639. package/dist/interactions/actions/insert/extras.js +65 -0
  640. package/dist/interactions/actions/insert/extras.js.map +1 -0
  641. package/dist/interactions/actions/insert/frame.js +55 -0
  642. package/dist/interactions/actions/insert/frame.js.map +1 -0
  643. package/dist/interactions/actions/insert/geometry.js +35 -0
  644. package/dist/interactions/actions/insert/geometry.js.map +1 -0
  645. package/dist/interactions/actions/insert/repositionAction.js +31 -0
  646. package/dist/interactions/actions/insert/repositionAction.js.map +1 -0
  647. package/dist/interactions/actions/insert/rotateAction.js +21 -0
  648. package/dist/interactions/actions/insert/rotateAction.js.map +1 -0
  649. package/dist/interactions/actions/insert/session.js +59 -0
  650. package/dist/interactions/actions/insert/session.js.map +1 -0
  651. package/dist/interactions/actions/insert/shape.js +34 -0
  652. package/dist/interactions/actions/insert/shape.js.map +1 -0
  653. package/dist/interactions/actions/lasso-select/action.js +143 -0
  654. package/dist/interactions/actions/lasso-select/action.js.map +1 -0
  655. package/dist/interactions/actions/move/action.js +91 -0
  656. package/dist/interactions/actions/move/action.js.map +1 -0
  657. package/dist/interactions/actions/move/behaviors/layoutDrop.js +51 -0
  658. package/dist/interactions/actions/move/behaviors/layoutDrop.js.map +1 -0
  659. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js +15 -0
  660. package/dist/interactions/actions/move/behaviors/reparentOnDrop.js.map +1 -0
  661. package/dist/interactions/actions/move/behaviors/snapToContainer.js +35 -28
  662. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  663. package/dist/interactions/actions/move/capture.js +108 -0
  664. package/dist/interactions/actions/move/capture.js.map +1 -0
  665. package/dist/interactions/actions/move/commit/index.js +41 -0
  666. package/dist/interactions/actions/move/commit/index.js.map +1 -0
  667. package/dist/interactions/actions/move/commit/layoutDrop.js +44 -0
  668. package/dist/interactions/actions/move/commit/layoutDrop.js.map +1 -0
  669. package/dist/interactions/actions/move/commit/layoutRelease.js +100 -0
  670. package/dist/interactions/actions/move/commit/layoutRelease.js.map +1 -0
  671. package/dist/interactions/actions/move/commit/rebase.js +18 -0
  672. package/dist/interactions/actions/move/commit/rebase.js.map +1 -0
  673. package/dist/interactions/actions/move/commit/reparent.js +65 -0
  674. package/dist/interactions/actions/move/commit/reparent.js.map +1 -0
  675. package/dist/interactions/actions/move/delta.js +51 -0
  676. package/dist/interactions/actions/move/delta.js.map +1 -0
  677. package/dist/interactions/actions/move/frame.js +47 -0
  678. package/dist/interactions/actions/move/frame.js.map +1 -0
  679. package/dist/interactions/actions/move/gestureAdapter.js +15 -40
  680. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  681. package/dist/interactions/actions/move/landedDescendants.js +8 -8
  682. package/dist/interactions/actions/move/layout/container.js +94 -0
  683. package/dist/interactions/actions/move/layout/container.js.map +1 -0
  684. package/dist/interactions/actions/move/layout/dragged.js +58 -0
  685. package/dist/interactions/actions/move/layout/dragged.js.map +1 -0
  686. package/dist/interactions/actions/move/layout/dropPass.js +122 -0
  687. package/dist/interactions/actions/move/layout/dropPass.js.map +1 -0
  688. package/dist/interactions/actions/move/layout/exits.js +38 -0
  689. package/dist/interactions/actions/move/layout/exits.js.map +1 -0
  690. package/dist/interactions/actions/move/layout/glide.js +48 -0
  691. package/dist/interactions/actions/move/layout/glide.js.map +1 -0
  692. package/dist/interactions/actions/move/session.js +63 -0
  693. package/dist/interactions/actions/move/session.js.map +1 -0
  694. package/dist/interactions/actions/move/translate.js +61 -0
  695. package/dist/interactions/actions/move/translate.js.map +1 -0
  696. package/dist/interactions/actions/outlines/createOutlines.js +17 -64
  697. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -1
  698. package/dist/interactions/actions/outlines/createOutlinesAction.js +51 -0
  699. package/dist/interactions/actions/outlines/createOutlinesAction.js.map +1 -0
  700. package/dist/interactions/actions/outlines/outlineStroke.js +72 -0
  701. package/dist/interactions/actions/outlines/outlineStroke.js.map +1 -0
  702. package/dist/interactions/actions/outlines/outlineStrokeAction.js +37 -0
  703. package/dist/interactions/actions/outlines/outlineStrokeAction.js.map +1 -0
  704. package/dist/interactions/actions/outlines/replaceWithPaths.js +54 -0
  705. package/dist/interactions/actions/outlines/replaceWithPaths.js.map +1 -0
  706. package/dist/interactions/actions/outlines/strokeRegion.js +27 -0
  707. package/dist/interactions/actions/outlines/strokeRegion.js.map +1 -0
  708. package/dist/interactions/actions/pathCommands/cutJoin.js +102 -0
  709. package/dist/interactions/actions/pathCommands/cutJoin.js.map +1 -0
  710. package/dist/interactions/actions/pathCommands/livePathEdit.js +64 -0
  711. package/dist/interactions/actions/pathCommands/livePathEdit.js.map +1 -0
  712. package/dist/interactions/actions/pathCommands/pathNodes.js +99 -0
  713. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -0
  714. package/dist/interactions/actions/pathCommands/simplifyOffset.js +42 -0
  715. package/dist/interactions/actions/pathCommands/simplifyOffset.js.map +1 -0
  716. package/dist/interactions/actions/planeInput.js.map +1 -1
  717. package/dist/interactions/actions/pointerState.js +12 -0
  718. package/dist/interactions/actions/pointerState.js.map +1 -0
  719. package/dist/interactions/actions/poseDescriptorDep.js +1 -1
  720. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  721. package/dist/interactions/actions/poseFrame.js +26 -26
  722. package/dist/interactions/actions/poseFrame.js.map +1 -1
  723. package/dist/interactions/actions/resize/action.js +66 -0
  724. package/dist/interactions/actions/resize/action.js.map +1 -0
  725. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -1
  726. package/dist/interactions/actions/resize/boxFrame.js +16 -0
  727. package/dist/interactions/actions/resize/boxFrame.js.map +1 -0
  728. package/dist/interactions/actions/resize/capture.js +85 -0
  729. package/dist/interactions/actions/resize/capture.js.map +1 -0
  730. package/dist/interactions/actions/resize/commit.js +69 -0
  731. package/dist/interactions/actions/resize/commit.js.map +1 -0
  732. package/dist/interactions/actions/resize/frame.js +88 -0
  733. package/dist/interactions/actions/resize/frame.js.map +1 -0
  734. package/dist/interactions/actions/resize/pointSnap.js +111 -0
  735. package/dist/interactions/actions/resize/pointSnap.js.map +1 -0
  736. package/dist/interactions/actions/resize/replay.js +47 -0
  737. package/dist/interactions/actions/resize/replay.js.map +1 -0
  738. package/dist/interactions/actions/resize/ruleBounds.js +9 -0
  739. package/dist/interactions/actions/resize/ruleBounds.js.map +1 -0
  740. package/dist/interactions/actions/resize/session.js +63 -0
  741. package/dist/interactions/actions/resize/session.js.map +1 -0
  742. package/dist/interactions/actions/resolveOverlays.js +2 -1
  743. package/dist/interactions/actions/resolveOverlays.js.map +1 -1
  744. package/dist/interactions/actions/resolvePreviews.js.map +1 -1
  745. package/dist/interactions/actions/rotate/action.js +71 -0
  746. package/dist/interactions/actions/rotate/action.js.map +1 -0
  747. package/dist/interactions/actions/rotate/behaviors/index.js +7 -0
  748. package/dist/interactions/actions/rotate/behaviors/index.js.map +1 -0
  749. package/dist/interactions/actions/rotate/behaviors/snapRotation.js +12 -0
  750. package/dist/interactions/actions/rotate/behaviors/snapRotation.js.map +1 -0
  751. package/dist/interactions/actions/rotate/commit.js +40 -0
  752. package/dist/interactions/actions/rotate/commit.js.map +1 -0
  753. package/dist/interactions/actions/rotate/frame.js +65 -0
  754. package/dist/interactions/actions/rotate/frame.js.map +1 -0
  755. package/dist/interactions/actions/rotate/handle.js +12 -12
  756. package/dist/interactions/actions/rotate/handle.js.map +1 -1
  757. package/dist/interactions/actions/rotate/replay.js +22 -0
  758. package/dist/interactions/actions/rotate/replay.js.map +1 -0
  759. package/dist/interactions/actions/rotate/session.js +102 -0
  760. package/dist/interactions/actions/rotate/session.js.map +1 -0
  761. package/dist/interactions/actions/spatialReference.js.map +1 -1
  762. package/dist/interactions/actions/transform-again/action.js +63 -0
  763. package/dist/interactions/actions/transform-again/action.js.map +1 -0
  764. package/dist/interactions/actions/transform-again/memory.js +35 -0
  765. package/dist/interactions/actions/transform-again/memory.js.map +1 -0
  766. package/dist/interactions/actions/useStandardActions.js +84 -61
  767. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  768. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +61 -42
  769. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  770. package/dist/interactions/gestures/shared/originProjection.js +1 -1
  771. package/dist/interactions/gestures/shared/originProjection.js.map +1 -1
  772. package/dist/interactions/gestures/shared/screenTolerance.js +8 -2
  773. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -1
  774. package/dist/interactions/gestures/shared/snap.js.map +1 -1
  775. package/dist/math-CYUjoyyU.d.ts +33 -0
  776. package/dist/math.d.ts +5 -2
  777. package/dist/math.js +6 -6
  778. package/dist/mesh.d.ts +4 -268
  779. package/dist/mesh.js +3 -7
  780. package/dist/move.d.ts +6 -4
  781. package/dist/{originProjection-gHnOup4e.d.ts → originProjection-CoNVpITV.d.ts} +1 -1
  782. package/dist/patterns-builtin.d.ts +1 -118
  783. package/dist/patterns-builtin.js +2 -3
  784. package/dist/poseDescriptor-Bqk-11Rl.d.ts +73 -0
  785. package/dist/renderer.d.ts +1 -92
  786. package/dist/renderer.js +2 -19
  787. package/dist/resize.d.ts +11 -22
  788. package/dist/resize.js +1 -1
  789. package/dist/style.css +1 -1
  790. package/dist/test-hook/install.js.map +1 -1
  791. package/dist/test-hook/useTestHook.js +22 -0
  792. package/dist/test-hook/useTestHook.js.map +1 -0
  793. package/dist/test-seams-D0pyV3pR.d.ts +149 -0
  794. package/dist/test-seams.d.ts +4 -4
  795. package/dist/test-seams.js +2 -2
  796. package/dist/tools/builtin/bone/boneActions.js +130 -0
  797. package/dist/tools/builtin/bone/boneActions.js.map +1 -0
  798. package/dist/tools/builtin/bone/boneOverlay.js +58 -0
  799. package/dist/tools/builtin/bone/boneOverlay.js.map +1 -0
  800. package/dist/tools/builtin/bone/placedRig.js +24 -0
  801. package/dist/tools/builtin/bone/placedRig.js.map +1 -0
  802. package/dist/tools/builtin/bone/rigEditState.js +21 -0
  803. package/dist/tools/builtin/bone/rigEditState.js.map +1 -0
  804. package/dist/tools/builtin/bone/useBoneTool.js +98 -0
  805. package/dist/tools/builtin/bone/useBoneTool.js.map +1 -0
  806. package/dist/tools/builtin/ellipse/useEllipseTool.js +16 -15
  807. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  808. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -1
  809. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  810. package/dist/tools/builtin/image/useImageTool.js.map +1 -1
  811. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  812. package/dist/tools/builtin/line/useLineTool.js +16 -15
  813. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  814. package/dist/tools/builtin/pen/usePenTool.js +162 -164
  815. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  816. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  817. package/dist/tools/builtin/pickTopMostHit.js +11 -14
  818. package/dist/tools/builtin/pickTopMostHit.js.map +1 -1
  819. package/dist/tools/builtin/polygon/usePolygonTool.js +17 -15
  820. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  821. package/dist/tools/builtin/rect/useRectTool.js +15 -14
  822. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  823. package/dist/tools/builtin/select/adapterPointQuery.js +40 -0
  824. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -0
  825. package/dist/tools/builtin/select/selectionContributions.js +5 -5
  826. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  827. package/dist/tools/builtin/select/useSelectTool.js +44 -71
  828. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  829. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -1
  830. package/dist/tools/builtin/slice/useSliceTool.js +69 -72
  831. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  832. package/dist/tools/builtin/star/useStarTool.js +18 -16
  833. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  834. package/dist/tools/builtin/text/useTextTool.js +10 -2
  835. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  836. package/dist/tools/builtin/weight/useWeightTool.js +77 -0
  837. package/dist/tools/builtin/weight/useWeightTool.js.map +1 -0
  838. package/dist/tools/builtin/weight/weightActions.js +112 -0
  839. package/dist/tools/builtin/weight/weightActions.js.map +1 -0
  840. package/dist/tools/builtin/weight/weightOverlay.js +61 -0
  841. package/dist/tools/builtin/weight/weightOverlay.js.map +1 -0
  842. package/dist/tools/overlayBinding.js.map +1 -1
  843. package/dist/tools/useKeybindings.js +20 -14
  844. package/dist/tools/useKeybindings.js.map +1 -1
  845. package/dist/{types-k-5Oqh-U.d.ts → types-DBbbCy0i.d.ts} +103 -176
  846. package/dist/util/paint.js +1 -1
  847. package/dist/util/paint.js.map +1 -1
  848. package/dist/version.js +1 -1
  849. package/package.json +26 -21
  850. package/dist/animation/colorHelpers.js +0 -135
  851. package/dist/animation/colorHelpers.js.map +0 -1
  852. package/dist/animation/colorRegistry.js +0 -37
  853. package/dist/animation/colorRegistry.js.map +0 -1
  854. package/dist/animation/engine/axes.js +0 -36
  855. package/dist/animation/engine/axes.js.map +0 -1
  856. package/dist/animation/engine/codec.js +0 -170
  857. package/dist/animation/engine/codec.js.map +0 -1
  858. package/dist/animation/engine/integrator.js +0 -12
  859. package/dist/animation/engine/integrator.js.map +0 -1
  860. package/dist/animation/loop.js +0 -60
  861. package/dist/animation/loop.js.map +0 -1
  862. package/dist/animation/observe.js +0 -23
  863. package/dist/animation/observe.js.map +0 -1
  864. package/dist/animation/rig/blendPoses.js +0 -43
  865. package/dist/animation/rig/blendPoses.js.map +0 -1
  866. package/dist/animation/rig/mirrorPose.js +0 -19
  867. package/dist/animation/rig/mirrorPose.js.map +0 -1
  868. package/dist/animation/rig/resolveSkeleton.js +0 -33
  869. package/dist/animation/rig/resolveSkeleton.js.map +0 -1
  870. package/dist/animation/rig/solveIk.js +0 -103
  871. package/dist/animation/rig/solveIk.js.map +0 -1
  872. package/dist/animation/rig/types.js +0 -12
  873. package/dist/animation/rig/types.js.map +0 -1
  874. package/dist/animation/slew.js +0 -27
  875. package/dist/animation/slew.js.map +0 -1
  876. package/dist/animation/stagger.js +0 -146
  877. package/dist/animation/stagger.js.map +0 -1
  878. package/dist/animation/timeline/booking.js +0 -114
  879. package/dist/animation/timeline/booking.js.map +0 -1
  880. package/dist/animation/timeline/createTimeline.js +0 -125
  881. package/dist/animation/timeline/createTimeline.js.map +0 -1
  882. package/dist/animation/timeline/sampleTrack.js +0 -79
  883. package/dist/animation/timeline/sampleTrack.js.map +0 -1
  884. package/dist/animation/useAnimator.js +0 -388
  885. package/dist/animation/useAnimator.js.map +0 -1
  886. package/dist/autoPoseDescriptor-Ct7yqivU.d.ts +0 -108
  887. package/dist/builtins-DPcdghtB.d.ts +0 -1223
  888. package/dist/canvas/MinimapCanvas.js +0 -140
  889. package/dist/canvas/MinimapCanvas.js.map +0 -1
  890. package/dist/canvas/deps/poseComposition.js +0 -11
  891. package/dist/canvas/deps/poseComposition.js.map +0 -1
  892. package/dist/canvas/minimapMath.js +0 -82
  893. package/dist/canvas/minimapMath.js.map +0 -1
  894. package/dist/canvas/toolPreview.js +0 -39
  895. package/dist/canvas/toolPreview.js.map +0 -1
  896. package/dist/core/adapters/arrayAdapter.js +0 -94
  897. package/dist/core/adapters/arrayAdapter.js.map +0 -1
  898. package/dist/core/adapters/useArrayAdapter.js +0 -13
  899. package/dist/core/adapters/useArrayAdapter.js.map +0 -1
  900. package/dist/core/fillInPoseFrame.js +0 -102
  901. package/dist/core/fillInPoseFrame.js.map +0 -1
  902. package/dist/core/geometry/poseFrame.js +0 -44
  903. package/dist/core/geometry/poseFrame.js.map +0 -1
  904. package/dist/core/geometry/poseRotation.js +0 -58
  905. package/dist/core/geometry/poseRotation.js.map +0 -1
  906. package/dist/core/gradient.js +0 -136
  907. package/dist/core/gradient.js.map +0 -1
  908. package/dist/core/markerInset.js +0 -24
  909. package/dist/core/markerInset.js.map +0 -1
  910. package/dist/core/mixed.js +0 -6
  911. package/dist/core/mixed.js.map +0 -1
  912. package/dist/core/paintKinds.js +0 -156
  913. package/dist/core/paintKinds.js.map +0 -1
  914. package/dist/core/scene/pickability.js +0 -6
  915. package/dist/core/scene/pickability.js.map +0 -1
  916. package/dist/core/strokeMarkerShapes.js +0 -139
  917. package/dist/core/strokeMarkerShapes.js.map +0 -1
  918. package/dist/core/strokeMarkers.js +0 -28
  919. package/dist/core/strokeMarkers.js.map +0 -1
  920. package/dist/core/viewport/meanScale.js +0 -8
  921. package/dist/core/viewport/meanScale.js.map +0 -1
  922. package/dist/core/viewport/pxExtent.js +0 -42
  923. package/dist/core/viewport/pxExtent.js.map +0 -1
  924. package/dist/features/cursor/paintedCursorLayer.js.map +0 -1
  925. package/dist/features/focus/gateLayer.js.map +0 -1
  926. package/dist/features/focus/useCanvasFocus.js +0 -29
  927. package/dist/features/focus/useCanvasFocus.js.map +0 -1
  928. package/dist/features/groups/children.js.map +0 -1
  929. package/dist/features/groups/composePose.js +0 -67
  930. package/dist/features/groups/composePose.js.map +0 -1
  931. package/dist/features/groups/nestedHit.js.map +0 -1
  932. package/dist/features/groups/unionOfChildren.js.map +0 -1
  933. package/dist/features/images/imageCache.js +0 -104
  934. package/dist/features/images/imageCache.js.map +0 -1
  935. package/dist/features/ingestion/index.js +0 -8
  936. package/dist/features/meshPaint/bake.js +0 -79
  937. package/dist/features/meshPaint/bake.js.map +0 -1
  938. package/dist/features/meshPaint/bakeCache.js +0 -59
  939. package/dist/features/meshPaint/bakeCache.js.map +0 -1
  940. package/dist/features/meshPaint/handles.js +0 -86
  941. package/dist/features/meshPaint/handles.js.map +0 -1
  942. package/dist/features/meshPaint/lazyKind.js.map +0 -1
  943. package/dist/features/meshPaint/meshPaint.js +0 -239
  944. package/dist/features/meshPaint/meshPaint.js.map +0 -1
  945. package/dist/features/meshPaint/meshShader.js +0 -6
  946. package/dist/features/meshPaint/meshShader.js.map +0 -1
  947. package/dist/features/meshPaint/register.js +0 -7
  948. package/dist/features/meshPaint/register.js.map +0 -1
  949. package/dist/features/meshPaint/surface.js +0 -110
  950. package/dist/features/meshPaint/surface.js.map +0 -1
  951. package/dist/features/minimap/actions.js +0 -53
  952. package/dist/features/minimap/actions.js.map +0 -1
  953. package/dist/features/minimap/createMinimapContribution.js +0 -96
  954. package/dist/features/minimap/createMinimapContribution.js.map +0 -1
  955. package/dist/features/minimap/layers.js +0 -85
  956. package/dist/features/minimap/layers.js.map +0 -1
  957. package/dist/features/overlays/useNodeOverlayFrame.js +0 -103
  958. package/dist/features/overlays/useNodeOverlayFrame.js.map +0 -1
  959. package/dist/features/parallax/createParallaxLayer.js +0 -26
  960. package/dist/features/parallax/createParallaxLayer.js.map +0 -1
  961. package/dist/features/parallax/createParallaxPlane.js +0 -22
  962. package/dist/features/parallax/createParallaxPlane.js.map +0 -1
  963. package/dist/features/paths/anchorEdits.js +0 -167
  964. package/dist/features/paths/anchorEdits.js.map +0 -1
  965. package/dist/features/paths/anchors.js +0 -159
  966. package/dist/features/paths/anchors.js.map +0 -1
  967. package/dist/features/paths/booleans.js +0 -2
  968. package/dist/features/paths/markerCommands.js +0 -149
  969. package/dist/features/paths/markerCommands.js.map +0 -1
  970. package/dist/features/paths/markerSites.js +0 -59
  971. package/dist/features/paths/markerSites.js.map +0 -1
  972. package/dist/features/paths/markers.js +0 -95
  973. package/dist/features/paths/markers.js.map +0 -1
  974. package/dist/features/paths/nearestAnchor.js +0 -36
  975. package/dist/features/paths/nearestAnchor.js.map +0 -1
  976. package/dist/features/paths/pathInWorld.js +0 -41
  977. package/dist/features/paths/pathInWorld.js.map +0 -1
  978. package/dist/features/paths/poseDescriptor.js +0 -39
  979. package/dist/features/paths/poseDescriptor.js.map +0 -1
  980. package/dist/features/paths/strokeToPath.js +0 -40
  981. package/dist/features/paths/strokeToPath.js.map +0 -1
  982. package/dist/features/paths/tessellate/dash.js +0 -52
  983. package/dist/features/paths/tessellate/dash.js.map +0 -1
  984. package/dist/features/paths/tessellate/insets.js +0 -32
  985. package/dist/features/paths/tessellate/insets.js.map +0 -1
  986. package/dist/features/paths/tessellate/metric.js +0 -72
  987. package/dist/features/paths/tessellate/metric.js.map +0 -1
  988. package/dist/features/paths/tessellate/stroke.js +0 -170
  989. package/dist/features/paths/tessellate/stroke.js.map +0 -1
  990. package/dist/features/paths/tessellate/vertexWidths.js +0 -32
  991. package/dist/features/paths/tessellate/vertexWidths.js.map +0 -1
  992. package/dist/features/patterns/commandPaint.js +0 -18
  993. package/dist/features/patterns/commandPaint.js.map +0 -1
  994. package/dist/features/patterns/index.js +0 -11
  995. package/dist/features/patterns/index.js.map +0 -1
  996. package/dist/features/patterns/patterns-builtin.js +0 -38
  997. package/dist/features/patterns/patterns-builtin.js.map +0 -1
  998. package/dist/features/patterns/rasterizeTile.js +0 -17
  999. package/dist/features/patterns/rasterizeTile.js.map +0 -1
  1000. package/dist/features/patterns/resolveSpec.js +0 -65
  1001. package/dist/features/patterns/resolveSpec.js.map +0 -1
  1002. package/dist/features/patterns/tileGeometry.js +0 -158
  1003. package/dist/features/patterns/tileGeometry.js.map +0 -1
  1004. package/dist/features/pointer/PointerContext.js +0 -45
  1005. package/dist/features/pointer/PointerContext.js.map +0 -1
  1006. package/dist/features/selection/SelectionContext.js +0 -51
  1007. package/dist/features/selection/SelectionContext.js.map +0 -1
  1008. package/dist/features/simulation/createSimulation.js +0 -61
  1009. package/dist/features/simulation/createSimulation.js.map +0 -1
  1010. package/dist/features/simulation/types.js +0 -6
  1011. package/dist/features/simulation/types.js.map +0 -1
  1012. package/dist/features/simulation/useSimulation.js +0 -74
  1013. package/dist/features/simulation/useSimulation.js.map +0 -1
  1014. package/dist/features/text/domOffsets.js +0 -82
  1015. package/dist/features/text/domOffsets.js.map +0 -1
  1016. package/dist/features/text/domRuns.js +0 -230
  1017. package/dist/features/text/domRuns.js.map +0 -1
  1018. package/dist/features/text/fitTextPose.js +0 -38
  1019. package/dist/features/text/fitTextPose.js.map +0 -1
  1020. package/dist/features/text/hitTest.js +0 -48
  1021. package/dist/features/text/hitTest.js.map +0 -1
  1022. package/dist/features/text/isTextData.js +0 -8
  1023. package/dist/features/text/isTextData.js.map +0 -1
  1024. package/dist/features/text/overlayDirection.js +0 -15
  1025. package/dist/features/text/overlayDirection.js.map +0 -1
  1026. package/dist/features/text/renderLabel.js +0 -14
  1027. package/dist/features/text/renderLabel.js.map +0 -1
  1028. package/dist/features/text/runs/effectiveRangeStyle.js +0 -66
  1029. package/dist/features/text/runs/effectiveRangeStyle.js.map +0 -1
  1030. package/dist/features/text/runs/flagRange.js +0 -53
  1031. package/dist/features/text/runs/flagRange.js.map +0 -1
  1032. package/dist/features/text/runs/rangeStyle.js +0 -133
  1033. package/dist/features/text/runs/rangeStyle.js.map +0 -1
  1034. package/dist/features/text/textCommand.js +0 -60
  1035. package/dist/features/text/textCommand.js.map +0 -1
  1036. package/dist/features/text/textToPath.js +0 -181
  1037. package/dist/features/text/textToPath.js.map +0 -1
  1038. package/dist/features/text/useTextEdit.js +0 -491
  1039. package/dist/features/text/useTextEdit.js.map +0 -1
  1040. package/dist/features/tiling/createTiledLayer.js +0 -65
  1041. package/dist/features/tiling/createTiledLayer.js.map +0 -1
  1042. package/dist/features/tiling/tiledProject.js +0 -14
  1043. package/dist/features/tiling/tiledProject.js.map +0 -1
  1044. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +0 -26
  1045. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +0 -1
  1046. package/dist/interactions/actions/defaults/align.js.map +0 -1
  1047. package/dist/interactions/actions/defaults/booleans.js +0 -52
  1048. package/dist/interactions/actions/defaults/booleans.js.map +0 -1
  1049. package/dist/interactions/actions/defaults/clipboard.js.map +0 -1
  1050. package/dist/interactions/actions/defaults/clone.js +0 -91
  1051. package/dist/interactions/actions/defaults/clone.js.map +0 -1
  1052. package/dist/interactions/actions/defaults/createOutlines.js +0 -47
  1053. package/dist/interactions/actions/defaults/createOutlines.js.map +0 -1
  1054. package/dist/interactions/actions/defaults/distribute.js.map +0 -1
  1055. package/dist/interactions/actions/defaults/editAnchors.js +0 -100
  1056. package/dist/interactions/actions/defaults/editAnchors.js.map +0 -1
  1057. package/dist/interactions/actions/defaults/flip.js +0 -125
  1058. package/dist/interactions/actions/defaults/flip.js.map +0 -1
  1059. package/dist/interactions/actions/defaults/insert.js +0 -287
  1060. package/dist/interactions/actions/defaults/insert.js.map +0 -1
  1061. package/dist/interactions/actions/defaults/lassoSelect.js +0 -153
  1062. package/dist/interactions/actions/defaults/lassoSelect.js.map +0 -1
  1063. package/dist/interactions/actions/defaults/move.js +0 -778
  1064. package/dist/interactions/actions/defaults/move.js.map +0 -1
  1065. package/dist/interactions/actions/defaults/resize.js +0 -341
  1066. package/dist/interactions/actions/defaults/resize.js.map +0 -1
  1067. package/dist/interactions/actions/defaults/rotate.js +0 -185
  1068. package/dist/interactions/actions/defaults/rotate.js.map +0 -1
  1069. package/dist/interactions/actions/previewOverrides.js +0 -25
  1070. package/dist/interactions/actions/previewOverrides.js.map +0 -1
  1071. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +0 -1
  1072. package/dist/layout/arrivals.js +0 -36
  1073. package/dist/layout/arrivals.js.map +0 -1
  1074. package/dist/math-J-ACHyEg.d.ts +0 -159
  1075. package/dist/registerProgram-T9S_PfAX.d.ts +0 -208
  1076. package/dist/renderer/DrawCommand.js +0 -6
  1077. package/dist/renderer/DrawCommand.js.map +0 -1
  1078. package/dist/renderer/WeaselRenderer.js +0 -333
  1079. package/dist/renderer/WeaselRenderer.js.map +0 -1
  1080. package/dist/renderer/batchClip.js +0 -46
  1081. package/dist/renderer/batchClip.js.map +0 -1
  1082. package/dist/renderer/cache/GLImageCache.js +0 -74
  1083. package/dist/renderer/cache/GLImageCache.js.map +0 -1
  1084. package/dist/renderer/cache/GLMeshCache.js +0 -102
  1085. package/dist/renderer/cache/GLMeshCache.js.map +0 -1
  1086. package/dist/renderer/cache/GLTextureCache.js +0 -68
  1087. package/dist/renderer/cache/GLTextureCache.js.map +0 -1
  1088. package/dist/renderer/cache/GradientRampAtlas.js +0 -82
  1089. package/dist/renderer/cache/GradientRampAtlas.js.map +0 -1
  1090. package/dist/renderer/cache/cache.js +0 -13
  1091. package/dist/renderer/cache/cache.js.map +0 -1
  1092. package/dist/renderer/cache/markerCommandCache.js +0 -63
  1093. package/dist/renderer/cache/markerCommandCache.js.map +0 -1
  1094. package/dist/renderer/cache/outlineMeshCache.js +0 -15
  1095. package/dist/renderer/cache/outlineMeshCache.js.map +0 -1
  1096. package/dist/renderer/cache/outlineStrokeMeshCache.js +0 -36
  1097. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +0 -1
  1098. package/dist/renderer/cache/strokeMeshCache.js +0 -55
  1099. package/dist/renderer/cache/strokeMeshCache.js.map +0 -1
  1100. package/dist/renderer/cullDrawCommands.js +0 -90
  1101. package/dist/renderer/cullDrawCommands.js.map +0 -1
  1102. package/dist/renderer/draw/batch.js +0 -133
  1103. package/dist/renderer/draw/batch.js.map +0 -1
  1104. package/dist/renderer/draw/clip.js +0 -89
  1105. package/dist/renderer/draw/clip.js.map +0 -1
  1106. package/dist/renderer/draw/customShader.js +0 -230
  1107. package/dist/renderer/draw/customShader.js.map +0 -1
  1108. package/dist/renderer/draw/drawTriangles.js +0 -8
  1109. package/dist/renderer/draw/drawTriangles.js.map +0 -1
  1110. package/dist/renderer/draw/effects.js +0 -28
  1111. package/dist/renderer/draw/effects.js.map +0 -1
  1112. package/dist/renderer/draw/flushBatch.js +0 -35
  1113. package/dist/renderer/draw/flushBatch.js.map +0 -1
  1114. package/dist/renderer/draw/gradient.js +0 -90
  1115. package/dist/renderer/draw/gradient.js.map +0 -1
  1116. package/dist/renderer/draw/image.js +0 -38
  1117. package/dist/renderer/draw/image.js.map +0 -1
  1118. package/dist/renderer/draw/mesh.js +0 -16
  1119. package/dist/renderer/draw/mesh.js.map +0 -1
  1120. package/dist/renderer/draw/paintBind.js +0 -70
  1121. package/dist/renderer/draw/paintBind.js.map +0 -1
  1122. package/dist/renderer/draw/pathPaint.js +0 -142
  1123. package/dist/renderer/draw/pathPaint.js.map +0 -1
  1124. package/dist/renderer/draw/scratchPass.js +0 -83
  1125. package/dist/renderer/draw/scratchPass.js.map +0 -1
  1126. package/dist/renderer/draw/stencil.js +0 -28
  1127. package/dist/renderer/draw/stencil.js.map +0 -1
  1128. package/dist/renderer/draw/text.js +0 -167
  1129. package/dist/renderer/draw/text.js.map +0 -1
  1130. package/dist/renderer/draw/uniforms.js +0 -77
  1131. package/dist/renderer/draw/uniforms.js.map +0 -1
  1132. package/dist/renderer/draw.js +0 -79
  1133. package/dist/renderer/draw.js.map +0 -1
  1134. package/dist/renderer/drawBatch.js +0 -198
  1135. package/dist/renderer/drawBatch.js.map +0 -1
  1136. package/dist/renderer/effects/EffectTargets.js +0 -48
  1137. package/dist/renderer/effects/EffectTargets.js.map +0 -1
  1138. package/dist/renderer/effects/builtins.js +0 -31
  1139. package/dist/renderer/effects/builtins.js.map +0 -1
  1140. package/dist/renderer/effects/composite.js +0 -11
  1141. package/dist/renderer/effects/composite.js.map +0 -1
  1142. package/dist/renderer/effects/effectPrelude.js +0 -10
  1143. package/dist/renderer/effects/effectPrelude.js.map +0 -1
  1144. package/dist/renderer/effects/types.js +0 -10
  1145. package/dist/renderer/effects/types.js.map +0 -1
  1146. package/dist/renderer/glyphOutlineMesh.js +0 -67
  1147. package/dist/renderer/glyphOutlineMesh.js.map +0 -1
  1148. package/dist/renderer/index.js +0 -20
  1149. package/dist/renderer/math/color.js +0 -321
  1150. package/dist/renderer/math/color.js.map +0 -1
  1151. package/dist/renderer/math/mat3.js +0 -80
  1152. package/dist/renderer/math/mat3.js.map +0 -1
  1153. package/dist/renderer/math/patternSpace.js +0 -22
  1154. package/dist/renderer/math/patternSpace.js.map +0 -1
  1155. package/dist/renderer/math/viewToMat3.js +0 -19
  1156. package/dist/renderer/math/viewToMat3.js.map +0 -1
  1157. package/dist/renderer/paintResources.js +0 -18
  1158. package/dist/renderer/paintResources.js.map +0 -1
  1159. package/dist/renderer/paintScratch.js +0 -37
  1160. package/dist/renderer/paintScratch.js.map +0 -1
  1161. package/dist/renderer/shaders/ShaderProgram.js +0 -74
  1162. package/dist/renderer/shaders/ShaderProgram.js.map +0 -1
  1163. package/dist/renderer/shaders/batchFill.js +0 -119
  1164. package/dist/renderer/shaders/batchFill.js.map +0 -1
  1165. package/dist/renderer/shaders/customPrelude.js +0 -34
  1166. package/dist/renderer/shaders/customPrelude.js.map +0 -1
  1167. package/dist/renderer/shaders/extractUniformNames.js +0 -184
  1168. package/dist/renderer/shaders/extractUniformNames.js.map +0 -1
  1169. package/dist/renderer/shaders/glyphPaint.js +0 -61
  1170. package/dist/renderer/shaders/glyphPaint.js.map +0 -1
  1171. package/dist/renderer/shaders/gradFill.js +0 -31
  1172. package/dist/renderer/shaders/gradFill.js.map +0 -1
  1173. package/dist/renderer/shaders/pathFill.js +0 -14
  1174. package/dist/renderer/shaders/pathFill.js.map +0 -1
  1175. package/dist/renderer/shaders/patternFill.js +0 -25
  1176. package/dist/renderer/shaders/patternFill.js.map +0 -1
  1177. package/dist/renderer/shaders/registerProgram.js +0 -18
  1178. package/dist/renderer/shaders/registerProgram.js.map +0 -1
  1179. package/dist/renderer/spriteSheet.js +0 -14
  1180. package/dist/renderer/spriteSheet.js.map +0 -1
  1181. package/dist/renderer/state/GroupState.js +0 -77
  1182. package/dist/renderer/state/GroupState.js.map +0 -1
  1183. package/dist/renderer/strokeLengths.js +0 -50
  1184. package/dist/renderer/strokeLengths.js.map +0 -1
  1185. package/dist/renderer/syntheticItalic.js +0 -6
  1186. package/dist/renderer/syntheticItalic.js.map +0 -1
  1187. package/dist/renderer/textures/registerTexture.js +0 -34
  1188. package/dist/renderer/textures/registerTexture.js.map +0 -1
  1189. package/dist/scheduling/useVisibleRaf.js +0 -69
  1190. package/dist/scheduling/useVisibleRaf.js.map +0 -1
  1191. package/dist/test-seams-DM2B87-g.d.ts +0 -356
@@ -1 +1 @@
1
- {"version":3,"file":"booleans.js","names":["operandPath","path","adapter","id","text","glyphs","textToPath","LABEL","isEmpty","p","applyBooleanOp","sel","zOrder","locateChild","resolved","err","TextOutlinesError","entries","a","b","op","paths","results","pathUnion","pathIntersect","pathExclude","back","front","pathSubtract","pathDivide","pathCrop","topmostId","topAnchor","targetIndex","shift","i","z","newNodes","ops","captured","node","index","createDeleteOp","n","createInsertOp","createMoveToIndexOp","createSetSelectionOp","dispatchApplyBatch"],"sources":["../../../../src/interactions/actions/booleans/booleans.ts"],"sourcesContent":["/**\n * Pure action core for path boolean operations. Resolves the current\n * selection into z-ordered paths, runs the chosen op, and dispatches a\n * single batch of `Op`s (delete sources + insert results + set selection).\n *\n * The hook (`useBooleans`) wraps this with React glue; testing here is\n * trivial because the function takes a plain adapter.\n */\nimport {\n pathUnion,\n pathIntersect,\n pathSubtract,\n pathExclude,\n pathDivide,\n pathCrop,\n} from 'features/paths/booleans';\nimport type { Path, PolygonPath } from '@weasel-js/geom';\nimport { createInsertOp } from 'core/ops/create';\nimport { createDeleteOp } from 'core/ops/delete';\nimport { createMoveToIndexOp } from 'core/ops/reorder';\nimport { createSetSelectionOp } from 'core/ops/select';\nimport { locateChild } from 'core/ops/slot';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport { dispatchApplyBatch } from 'core/applyOps';\nimport { textToPath, TextOutlinesError, type TextNodeSource } from 'features/text/textToPath';\n\n/** Boolean op identifiers — five Pathfinder primaries plus Crop. */\nexport type BooleanOp = 'union' | 'intersect' | 'subtract' | 'exclude' | 'divide' | 'crop';\n\n/**\n * z-position descriptor for a path node. `parentId` is the direct parent\n * (or `null` for a top-level node); `index` is the position within that\n * parent's child order — never a global render index.\n */\n/** @internal */\nexport interface BooleanZOrder {\n parentId: string | null;\n index: number;\n}\n\n/** Adapter the hook and the pure core both consume. */\nexport interface BooleansAdapter {\n getSelection(): readonly NodeId[] | readonly string[];\n getWorldPath(id: NodeId): Path | undefined;\n /**\n * Optional: the text node behind `id`, for an id `getWorldPath` has no path\n * for. Its glyph outlines (`textToPath`) become the operand, so text can be\n * cut, united or intersected like any shape.\n */\n getTextSource?(id: NodeId): TextNodeSource | undefined;\n compareZ(a: NodeId, b: NodeId): number;\n /**\n * Mint a new node from a boolean-op result `Path`. `producedBy` names the\n * op that synthesized it — adapters that store provenance (e.g. for a\n * layer-panel icon) record it; others ignore the arg. `sourceId` is the\n * topmost source, whose slot the result takes: give the node that source's\n * parent, or the kit's reorder cannot find it there.\n */\n createPathNode(path: Path, producedBy: BooleanOp, sourceId: NodeId): { id: string };\n /**\n * Optional: return the full object for an id, used by the delete ops so\n * their `invert` (an insert) can restore the complete object on undo.\n * If omitted, a `{ id }` stub is captured — undo will reinstate the id\n * but consumers reading other fields (path, fill, etc.) will see them as\n * undefined. Mirrors `DeleteAdapter.getNode`; should be provided whenever\n * undo over boolean ops is expected to be lossless.\n */\n getNode?(id: NodeId): { id: string } | undefined | null;\n /**\n * Optional: the reorder contract. With `getChildren` (and `getParent`, or\n * every node reads as top-level) the kit reads each source's slot among its\n * siblings, and with `setChildOrder` as well it moves the result into the\n * topmost source's slot. Without them the result lands wherever\n * `insertNode` defaults to. `defaultCommitAdapter` supplies all three.\n */\n getParent?(id: string): string | null;\n getChildren?(parentId: string | null): readonly string[];\n setChildOrder?(parentId: string | null, ids: string[]): void;\n /**\n * Optional override for the slot the kit otherwise reads through\n * `getParent` / `getChildren`: `id`'s parent and its index in that\n * parent's child order.\n *\n * @deprecated Supply `getParent` and `getChildren` instead, and the kit\n * derives this.\n */\n getZOrder?(id: NodeId): BooleanZOrder | undefined;\n applyOps?(ops: Op[], label?: string): void;\n setSelection?(ids: NodeId[]): void;\n insertNode?(node: { id: string }): void;\n removeNode?(id: string): void;\n}\n\n/** Outcome reported back to callers (lets the hook surface no-op signals). */\nexport type BooleanOpResult =\n | { kind: 'applied'; resultIds: string[] }\n | { kind: 'noop'; reason: 'no-paths' | 'too-few-for-subtract' | 'empty-result' }\n /** A text operand had no outline geometry. Nothing was changed: an op that\n * quietly dropped the operand would commit a different shape than asked. */\n | { kind: 'failed'; reason: 'text-outlines'; error: TextOutlinesError };\n\nfunction operandPath(adapter: BooleansAdapter, id: NodeId): Path | undefined {\n const path = adapter.getWorldPath(id);\n if (path) return path;\n const text = adapter.getTextSource?.(id);\n if (!text) return undefined;\n // Blank text has no geometry, and is no more an operand than a group is.\n const glyphs = textToPath(text.data, text.pose);\n return glyphs.commands.length > 0 ? glyphs : undefined;\n}\n\nconst LABEL: Record<BooleanOp, string> = {\n union: 'Union',\n intersect: 'Intersect',\n subtract: 'Subtract',\n exclude: 'Exclude',\n divide: 'Divide',\n crop: 'Crop',\n};\n\nfunction isEmpty(p: PolygonPath): boolean {\n return p.commands.length === 0;\n}\n\n/**\n * Run one Boolean operation over the selected paths and commit the result as a\n * single undoable batch.\n *\n * Operands are ordered back-to-front, which is what makes `subtract` mean\n * \"everything in front removed from the backmost shape\". Returns without\n * mutating anything when the selection holds no paths, or too few for the\n * requested operation.\n */\nexport function applyBooleanOp(\n adapter: BooleansAdapter,\n op: BooleanOp,\n): BooleanOpResult {\n const sel = [...adapter.getSelection()] as NodeId[];\n const zOrder = (id: NodeId): BooleanZOrder | undefined =>\n adapter.getZOrder ? adapter.getZOrder(id) : locateChild(adapter, id) ?? undefined;\n // Resolve path nodes only, sorted ascending by `compareZ` so paths[0] is\n // the bottommost (back) member. `subtract` relies on this: it computes\n // `back − union(rest)`, which is Illustrator's \"Minus Front.\" Keep this\n // convention in sync if compareZ semantics ever flip.\n let resolved: { id: NodeId; path: Path | undefined }[];\n try {\n resolved = sel.map((id) => ({ id, path: operandPath(adapter, id) }));\n } catch (err) {\n if (err instanceof TextOutlinesError) return { kind: 'failed', reason: 'text-outlines', error: err };\n throw err;\n }\n const entries = resolved\n .filter((e): e is { id: NodeId; path: Path } => e.path != null)\n .sort((a, b) => adapter.compareZ(a.id, b.id));\n\n if (entries.length === 0) return { kind: 'noop', reason: 'no-paths' };\n if (op === 'subtract' && entries.length < 2) {\n return { kind: 'noop', reason: 'too-few-for-subtract' };\n }\n if (entries.length < 2) return { kind: 'noop', reason: 'no-paths' };\n\n const paths = entries.map((e) => e.path);\n let results: PolygonPath[];\n\n switch (op) {\n case 'union': results = [pathUnion(...paths)]; break;\n case 'intersect': results = [pathIntersect(...paths)]; break;\n case 'exclude': results = [pathExclude(...paths)]; break;\n case 'subtract': {\n // Illustrator \"Minus Front\": back − union(everything in front).\n const back = paths[0];\n const front = paths.length === 2 ? paths[1] : pathUnion(...paths.slice(1));\n results = [pathSubtract(back, front)];\n break;\n }\n case 'divide': {\n results = pathDivide(...paths);\n break;\n }\n case 'crop': {\n // Illustrator \"Crop\": clip every source-below-top to the topmost\n // path; topmost is consumed as the mask. `paths` is back-to-front\n // ascending, so the topmost source is `paths[paths.length-1]`.\n results = pathCrop(...paths);\n break;\n }\n }\n\n results = results.filter((p) => !isEmpty(p));\n if (results.length === 0) return { kind: 'noop', reason: 'empty-result' };\n\n // Capture the topmost source's z-slot before we mutate the scene. The\n // topmost source is the last entry (entries are back-to-front ascending).\n // We adjust for selected members that sit below the topmost in the same\n // parent — their deletions collapse the parent's child list before the\n // reorder runs, so the visual slot the topmost occupied lives at a lower\n // index after the deletes. Members in a different parent don't affect\n // this parent's indexing.\n const topmostId = entries[entries.length - 1].id;\n const topAnchor = zOrder(topmostId);\n let targetIndex = topAnchor?.index;\n if (topAnchor) {\n let shift = 0;\n for (let i = 0; i < entries.length - 1; i++) {\n const z = zOrder(entries[i].id);\n if (z && z.parentId === topAnchor.parentId && z.index < topAnchor.index) {\n shift++;\n }\n }\n targetIndex = topAnchor.index - shift;\n }\n\n const newNodes = results.map((p) => adapter.createPathNode(p, op, topmostId));\n const ops: Op[] = [];\n const captured: { node: { id: string }; index: number }[] = [];\n for (const e of entries) {\n // Capture the full node so the delete's `invert()` (an insert) restores\n // every field on undo. Fallback to a `{ id }` stub matches the legacy\n // behavior for adapters that haven't opted in yet. Index comes from\n // the same slot read used for anchoring; -1 when the adapter doesn't\n // expose order.\n const node = adapter.getNode?.(e.id) ?? { id: e.id };\n const index = zOrder(e.id)?.index ?? -1;\n captured.push({ node, index });\n }\n // Order by index DESC so reverse-then-invert (history's undo path)\n // re-inserts ASC — each splice lands on a correctly-sized array\n // instead of clamping high indices to a still-growing length.\n captured.sort((a, b) => b.index - a.index);\n for (const { node, index } of captured) ops.push(createDeleteOp({ node, index }));\n for (const n of newNodes) ops.push(createInsertOp({ node: n }));\n if (topAnchor && targetIndex !== undefined) {\n // After the deletes, the topmost source's index is no longer occupied;\n // moving the new nodes to the adjusted index drops them into that slot.\n // For divide (N outputs), they form a contiguous block in input order\n // starting at the target index.\n ops.push(createMoveToIndexOp({\n ids: newNodes.map((n) => n.id),\n parentId: topAnchor.parentId,\n index: targetIndex,\n }));\n }\n ops.push(createSetSelectionOp({\n from: sel,\n to: newNodes.map((n) => n.id as NodeId),\n }));\n dispatchApplyBatch(adapter, ops, LABEL[op]);\n\n return { kind: 'applied', resultIds: newNodes.map((n) => n.id) };\n}\n"],"mappings":";;;;;;;;;AAsGA,SAASA,EAAY,GAA0B,GAA8B;CAC3E,IAAMC,IAAOC,EAAQ,aAAaC,CAAE;CACpC,IAAIF,GAAM,OAAOA;CACjB,IAAMG,IAAOF,EAAQ,gBAAgBC,CAAE;CACvC,IAAI,CAACC,GAAM;CAEX,IAAMC,IAASC,EAAWF,EAAK,MAAMA,EAAK,IAAI;CAC9C,OAAOC,EAAO,SAAS,SAAS,IAAIA,IAAS,KAAA;AAC/C;AAEA,IAAME,IAAmC;CACvC,OAAO;CACP,WAAW;CACX,UAAU;CACV,SAAS;CACT,QAAQ;CACR,MAAM;AACR;AAEA,SAASC,EAAQ,GAAyB;CACxC,OAAOC,EAAE,SAAS,WAAW;AAC/B;AAWA,SAAgBC,EACd,GACA,GACiB;CACjB,IAAMC,IAAM,CAAC,GAAGT,EAAQ,aAAa,CAAC,GAChCU,KAAU,MACdV,EAAQ,YAAYA,EAAQ,UAAUC,CAAE,IAAIU,EAAYX,GAASC,CAAE,KAAK,KAAA,GAKtEW;CACJ,IAAI;EACF,IAAWH,EAAI,KAAK,OAAQ;GAAE;GAAI,MAAMX,EAAYE,GAASC,CAAE;EAAE,EAAE;CACrE,SAASY,GAAK;EACZ,IAAIA,aAAeC,GAAmB,OAAO;GAAE,MAAM;GAAU,QAAQ;GAAiB,OAAOD;EAAI;EACnG,MAAMA;CACR;CACA,IAAME,IAAUH,EACb,QAAQ,MAAuC,EAAE,QAAQ,IAAI,CAAC,CAC9D,MAAM,GAAG,MAAMZ,EAAQ,SAASgB,EAAE,IAAIC,EAAE,EAAE,CAAC;CAE9C,IAAIF,EAAQ,WAAW,GAAG,OAAO;EAAE,MAAM;EAAQ,QAAQ;CAAW;CACpE,IAAIG,MAAO,cAAcH,EAAQ,SAAS,GACxC,OAAO;EAAE,MAAM;EAAQ,QAAQ;CAAuB;CAExD,IAAIA,EAAQ,SAAS,GAAG,OAAO;EAAE,MAAM;EAAQ,QAAQ;CAAW;CAElE,IAAMI,IAAQJ,EAAQ,KAAK,MAAM,EAAE,IAAI,GACnCK;CAEJ,QAAQF,GAAR;EACE,KAAK;GAAa,IAAU,CAACG,EAAU,GAAGF,CAAK,CAAC;GAAG;EACnD,KAAK;GAAa,IAAU,CAACG,EAAc,GAAGH,CAAK,CAAC;GAAG;EACvD,KAAK;GAAa,IAAU,CAACI,EAAY,GAAGJ,CAAK,CAAC;GAAG;EACrD,KAAK,YAAY;GAEf,IAAMK,IAAOL,EAAM,IACbM,IAAQN,EAAM,WAAW,IAAIA,EAAM,KAAKE,EAAU,GAAGF,EAAM,MAAM,CAAC,CAAC;GACzE,IAAU,CAACO,EAAaF,GAAMC,CAAK,CAAC;GACpC;EACF;EACA,KAAK;GACH,IAAUE,EAAW,GAAGR,CAAK;GAC7B;EAEF,KAAK,QAIH,IAAUS,EAAS,GAAGT,CAAK;CAG/B;CAGA,IADA,IAAUC,EAAQ,QAAQ,MAAM,CAACd,EAAQC,CAAC,CAAC,GACvCa,EAAQ,WAAW,GAAG,OAAO;EAAE,MAAM;EAAQ,QAAQ;CAAe;CASxE,IAAMS,IAAYd,EAAQA,EAAQ,SAAS,EAAE,CAAC,IACxCe,IAAYpB,EAAOmB,CAAS,GAC9BE,IAAcD,GAAW;CAC7B,IAAIA,GAAW;EACb,IAAIE,IAAQ;EACZ,KAAK,IAAIC,IAAI,GAAGA,IAAIlB,EAAQ,SAAS,GAAG,KAAK;GAC3C,IAAMmB,IAAIxB,EAAOK,EAAQkB,EAAE,CAAC,EAAE;GAC9B,AAAIC,KAAKA,EAAE,aAAaJ,EAAU,YAAYI,EAAE,QAAQJ,EAAU,SAChE;EAEJ;EACA,IAAcA,EAAU,QAAQE;CAClC;CAEA,IAAMG,IAAWf,EAAQ,KAAK,MAAMpB,EAAQ,eAAeO,GAAGW,GAAIW,CAAS,CAAC,GACtEO,IAAY,CAAC,GACbC,IAAsD,CAAC;CAC7D,KAAK,IAAM,KAAKtB,GAAS;EAMvB,IAAMuB,IAAOtC,EAAQ,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,GAC7CuC,IAAQ7B,EAAO,EAAE,EAAE,CAAC,EAAE,SAAS;EACrC,EAAS,KAAK;GAAE;GAAM;EAAM,CAAC;CAC/B;CAIA,EAAS,MAAM,GAAG,MAAMO,EAAE,QAAQD,EAAE,KAAK;CACzC,KAAK,IAAM,EAAE,SAAM,cAAWqB,GAAU,EAAI,KAAKG,EAAe;EAAE;EAAM;CAAM,CAAC,CAAC;CAChF,KAAK,IAAMC,KAAKN,GAAU,EAAI,KAAKO,EAAe,EAAE,MAAMD,EAAE,CAAC,CAAC;CAkB9D,OAjBIX,KAAaC,MAAgB,KAAA,KAK/BK,EAAI,KAAKO,EAAoB;EAC3B,KAAKR,EAAS,KAAK,MAAMM,EAAE,EAAE;EAC7B,UAAUX,EAAU;EACpB,OAAOC;CACT,CAAC,CAAC,GAEJK,EAAI,KAAKQ,EAAqB;EAC5B,MAAMnC;EACN,IAAI0B,EAAS,KAAK,MAAMM,EAAE,EAAY;CACxC,CAAC,CAAC,GACFI,EAAmB7C,GAASoC,GAAK/B,EAAMa,EAAG,GAEnC;EAAE,MAAM;EAAW,WAAWiB,EAAS,KAAK,MAAMM,EAAE,EAAE;CAAE;AACjE"}
1
+ {"version":3,"file":"booleans.js","names":["LABEL","planBooleanOp","resolved","sel","resolveOperand","adapter","id","opts","err","TextOutlinesError","entries","a","b","op","pieces","booleanPieces","i","paint","operand","previewBooleanOp","plan","piece","applyBooleanOp","slots","locateChild","made","newNodes","m","ops","captured","createDeleteOp","n","createInsertOp","placementOps","createSetSelectionOp","dispatchApplyBatch"],"sources":["../../../../src/interactions/actions/booleans/booleans.ts"],"sourcesContent":["/**\n * Pure action core for path boolean operations. Resolves the current\n * selection into z-ordered paths, runs the chosen op, and dispatches a\n * single batch of `Op`s (delete sources + insert results + set selection).\n */\nimport type { Affine, Path } from '@weasel-js/geom';\nimport { createInsertOp } from 'core/ops/create';\nimport { createDeleteOp } from 'core/ops/delete';\nimport { createSetSelectionOp } from 'core/ops/select';\nimport { locateChild } from 'core/ops/slot';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport { dispatchApplyBatch } from 'core/applyOps';\nimport { TextOutlinesError, type TextNodeSource } from '@weasel-js/text';\nimport type { PathPaint } from 'canvas/nodeShapes/nodePaint';\nimport { resolveOperand, type BooleanOpOptions, type BooleanOperand } from './operands';\nimport { booleanPieces, type ResultPiece } from './pieces';\nimport { placementOps } from './placement';\n\n/** Boolean op identifiers: the five Pathfinder primaries, and Crop, Trim, and Merge. */\nexport type BooleanOp = 'union' | 'intersect' | 'subtract' | 'exclude' | 'divide' | 'crop' | 'trim' | 'merge';\n\n/**\n * z-position descriptor for a path node. `parentId` is the direct parent\n * (or `null` for a top-level node); `index` is the position within that\n * parent's child order — never a global render index.\n */\n/** @internal */\nexport interface BooleanZOrder {\n parentId: string | null;\n index: number;\n}\n\n/** Adapter the hook and the pure core both consume. */\nexport interface BooleansAdapter {\n getSelection(): readonly NodeId[] | readonly string[];\n getWorldPath(id: NodeId): Path | undefined;\n /**\n * Optional: the text node behind `id`, for an id `getWorldPath` has no path\n * for. Its glyph outlines (`textToPath`) become the operand, so text can be\n * cut, united or intersected like any shape.\n */\n getTextSource?(id: NodeId): TextNodeSource | undefined;\n /**\n * Optional: the paint the path node behind `id` wears. An operation told to\n * count strokes (`BooleanOpOptions.strokes`) reads it to learn whether the\n * node is stroked and whether it is filled; without it every operand is its\n * path alone.\n */\n getPaint?(id: NodeId): PathPaint | undefined;\n /**\n * Optional: the frame the node behind `id` draws its stroke in, as the\n * matrix taking that frame to world (`poseFrameOf`); null or absent for a\n * node drawn straight. A counted world-width stroke is skewed and stretched\n * with it. Without it every stroke is outlined in world.\n */\n getStrokeFrame?(id: NodeId): Affine | null | undefined;\n compareZ(a: NodeId, b: NodeId): number;\n /**\n * Mint a new node from a boolean-op result `Path`. `producedBy` names the\n * op that synthesized it — adapters that store provenance (e.g. for a\n * layer-panel icon) record it; others ignore the arg. `sourceId` is the\n * source the result stands in for: the topmost, except that each piece of\n * a Divide, Crop, Trim, or Merge names the topmost source it was cut from. Give the\n * node that source's parent, or the kit's reorder cannot find it there.\n * `paint` is passed when that source's stroke went into the geometry, and\n * the node must wear it as given: wearing the source's stroke again would\n * draw it twice. Without `paint`, give it that source's paint. The kit never\n * reads a node's `data`: anything else the result should keep of its source,\n * a name say, is the adapter's to copy from `sourceId`.\n */\n createPathNode(path: Path, producedBy: BooleanOp, sourceId: NodeId, paint?: PathPaint): { id: string };\n /**\n * The full object for an id. The delete ops capture it, so their `invert`\n * (an insert) restores the complete object on undo.\n */\n getNode(id: NodeId): { id: string } | undefined | null;\n /**\n * The tree. The kit reads each source's slot among its siblings through\n * `getParent` and `getChildren`, and moves each result into the slot of\n * the topmost source in its own source's parent through `setChildOrder`.\n * `defaultCommitAdapter` supplies all three, and `getNode`.\n */\n getParent(id: string): string | null;\n getChildren(parentId: string | null): string[];\n setChildOrder(parentId: string | null, ids: string[]): void;\n applyOps?(ops: Op[], label?: string): void;\n setSelection?(ids: NodeId[]): void;\n insertNode?(node: { id: string }): void;\n removeNode?(id: string): void;\n}\n\n/** Outcome reported back to callers (lets the hook surface no-op signals). */\nexport type BooleanOpResult =\n | { kind: 'applied'; resultIds: string[] }\n | { kind: 'noop'; reason: 'no-paths' | 'too-few-for-subtract' | 'empty-result' }\n /** A text operand had no outline geometry. Nothing was changed: an op that\n * quietly dropped the operand would commit a different shape than asked. */\n | { kind: 'failed'; reason: 'text-outlines'; error: TextOutlinesError };\n\nconst LABEL: Record<BooleanOp, string> = {\n union: 'Union',\n intersect: 'Intersect',\n subtract: 'Subtract',\n exclude: 'Exclude',\n divide: 'Divide',\n crop: 'Crop',\n trim: 'Trim',\n merge: 'Merge',\n};\n\n/** One path a Boolean operation would make. */\nexport interface BooleanPreviewPiece {\n path: Path;\n /** The source the piece stands in for; see `BooleansAdapter.createPathNode`. */\n sourceId: NodeId;\n /** Set when that source's stroke went into `path`: the paint the piece wears. */\n paint?: PathPaint;\n}\n\n/** What {@link previewBooleanOp} answers: the pieces, or why there are none. */\nexport type BooleanOpPreview =\n | { kind: 'pieces'; pieces: BooleanPreviewPiece[] }\n | Exclude<BooleanOpResult, { kind: 'applied' }>;\n\ntype Entry = { id: NodeId; operand: BooleanOperand };\n\n/** The operands back to front and the pieces `op` makes of them, or the\n * result that says why it makes none. Reads the adapter and changes nothing. */\nfunction planBooleanOp(\n adapter: BooleansAdapter,\n sel: readonly NodeId[],\n op: BooleanOp,\n opts: BooleanOpOptions,\n): { entries: Entry[]; pieces: ResultPiece[] } | Exclude<BooleanOpResult, { kind: 'applied' }> {\n // Sorted ascending by `compareZ` so the first entry is the bottommost\n // (back) member. `subtract` relies on this: it computes `back − union(rest)`.\n let resolved: { id: NodeId; operand: BooleanOperand | undefined }[];\n try {\n resolved = sel.map((id) => ({ id, operand: resolveOperand(adapter, id, opts) }));\n } catch (err) {\n if (err instanceof TextOutlinesError) return { kind: 'failed', reason: 'text-outlines', error: err };\n throw err;\n }\n const entries = resolved\n .filter((e): e is Entry => e.operand != null)\n .sort((a, b) => adapter.compareZ(a.id, b.id));\n\n if (entries.length === 0) return { kind: 'noop', reason: 'no-paths' };\n if (op === 'subtract' && entries.length < 2) {\n return { kind: 'noop', reason: 'too-few-for-subtract' };\n }\n if (entries.length < 2) return { kind: 'noop', reason: 'no-paths' };\n\n // Merge unites the operands that wear one fill; one whose paint is unknown is united with nothing.\n const fillKey = (i: number): unknown => {\n const { id, operand } = entries[i]!;\n const paint = operand.paint ?? adapter.getPaint?.(id);\n return paint ? JSON.stringify(paint.fill ?? null) : i;\n };\n const pieces = booleanPieces(op, entries.map((e) => e.operand.path), fillKey);\n if (pieces.length === 0) return { kind: 'noop', reason: 'empty-result' };\n return { entries, pieces };\n}\n\n/**\n * What {@link applyBooleanOp} would make of the selection, without minting a\n * node or committing anything: for drawing an operation before it is applied.\n */\nexport function previewBooleanOp(\n adapter: BooleansAdapter,\n op: BooleanOp,\n opts: BooleanOpOptions = {},\n): BooleanOpPreview {\n const plan = planBooleanOp(adapter, [...adapter.getSelection()] as NodeId[], op, opts);\n if ('kind' in plan) return plan;\n return {\n kind: 'pieces',\n pieces: plan.pieces.map((piece) => {\n const { id, operand } = plan.entries[piece.source]!;\n return operand.paint ? { path: piece.path, sourceId: id, paint: operand.paint } : { path: piece.path, sourceId: id };\n }),\n };\n}\n\n/**\n * Run one Boolean operation over the selected paths and commit the result as a\n * single undoable batch.\n *\n * Operands are ordered back-to-front, which is what makes `subtract` mean\n * \"everything in front removed from the backmost shape\". Returns without\n * mutating anything when the selection holds no paths, or too few for the\n * requested operation. `opts.strokes` says what a stroked operand gives.\n */\nexport function applyBooleanOp(\n adapter: BooleansAdapter,\n op: BooleanOp,\n opts: BooleanOpOptions = {},\n): BooleanOpResult {\n const sel = [...adapter.getSelection()] as NodeId[];\n const plan = planBooleanOp(adapter, sel, op, opts);\n if ('kind' in plan) return plan;\n const { entries, pieces } = plan;\n // Every source's slot, read before the scene is mutated.\n const slots: (BooleanZOrder | undefined)[] =\n entries.map((e) => locateChild(adapter, e.id) ?? undefined);\n // A piece stands in for its own source: it is minted from that source, wears\n // the paint a stroke folded into that source left it, and takes its slot.\n const made = pieces.map((piece) => {\n const { id, operand } = entries[piece.source]!;\n return { node: adapter.createPathNode(piece.path, op, id, operand.paint), slot: slots[piece.source] };\n });\n const newNodes = made.map((m) => m.node);\n const ops: Op[] = [];\n // Capture the full node so the delete's `invert()` (an insert) restores\n // every field on undo. The index is -1 for a source its parent does not list.\n const captured = entries.map((e, i) => ({\n node: adapter.getNode(e.id) ?? { id: e.id },\n index: slots[i]?.index ?? -1,\n }));\n // Order by index DESC so reverse-then-invert (history's undo path)\n // re-inserts ASC — each splice lands on a correctly-sized array\n // instead of clamping high indices to a still-growing length.\n captured.sort((a, b) => b.index - a.index);\n for (const { node, index } of captured) ops.push(createDeleteOp({ node, index }));\n for (const n of newNodes) ops.push(createInsertOp({ node: n }));\n ops.push(...placementOps(made.map((m) => ({ id: m.node.id, slot: m.slot })), slots));\n ops.push(createSetSelectionOp({\n from: sel,\n to: newNodes.map((n) => n.id as NodeId),\n }));\n dispatchApplyBatch(adapter, ops, LABEL[op]);\n\n return { kind: 'applied', resultIds: newNodes.map((n) => n.id) };\n}\n"],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { strokeRegion as e } from "../outlines/strokeRegion.js";
2
+ import { textToPath as t, textToPathsByPaint as n } from "@weasel-js/text";
3
+ import { pathUnion as r } from "@weasel-js/geom/booleans";
4
+ //#region src/interactions/actions/booleans/operands.ts
5
+ function i(t, n, i, a) {
6
+ let { path: o, fill: s } = t, { stroke: c } = t, l = c?.paint;
7
+ if (!c || l == null || n === "ignore" || n === "unfilled" && s !== null) return { path: o };
8
+ let u = e(o, c, i, a === void 0 ? {} : { scale: a });
9
+ return u.commands.length === 0 ? { path: o } : {
10
+ path: s === null ? u : r(o, u),
11
+ paint: { fill: s ?? { paint: l } }
12
+ };
13
+ }
14
+ function a(e, a, { strokes: o = "ignore", scale: s }) {
15
+ let c = e.getWorldPath(a);
16
+ if (c) {
17
+ let t = o === "ignore" ? void 0 : e.getPaint?.(a);
18
+ return t ? i({
19
+ path: c,
20
+ ...t
21
+ }, o, e.getStrokeFrame?.(a), s) : { path: c };
22
+ }
23
+ let l = e.getTextSource?.(a);
24
+ if (!l) return;
25
+ if (o === "ignore") {
26
+ let e = t(l.data, l.pose);
27
+ return e.commands.length > 0 ? { path: e } : void 0;
28
+ }
29
+ let u = n(l.data, l.pose).map((t) => i(t, o, e.getStrokeFrame?.(a), s));
30
+ if (u.length === 0) return;
31
+ let d = u.find((e) => e.paint)?.paint, f = u.length === 1 ? u[0].path : r(...u.map((e) => e.path));
32
+ return d ? {
33
+ path: f,
34
+ paint: d
35
+ } : { path: f };
36
+ }
37
+ //#endregion
38
+ export { a as resolveOperand };
39
+
40
+ //# sourceMappingURL=operands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operands.js","names":["inkOf","source","strokePaint","stroke","strokes","fill","ribbon","strokeRegion","path","frame","scale","pathUnion","resolveOperand","adapter","id","paint","text","glyphs","textToPath","inks","textToPathsByPaint","p","ink","whole"],"sources":["../../../../src/interactions/actions/booleans/operands.ts"],"sourcesContent":["/**\n * What each selected node gives a Boolean operation: its path, its glyph\n * outlines, or the region its ink covers once a stroke is counted.\n */\nimport type { Affine, Path, Scale2 } from '@weasel-js/geom';\nimport { pathUnion } from '@weasel-js/geom/booleans';\nimport { textToPath, textToPathsByPaint } from '@weasel-js/text';\nimport type { PathPaint } from 'canvas/nodeShapes/nodePaint';\nimport type { NodeId } from 'core/scene/types';\nimport type { PaintedPath } from '../outlines/replaceWithPaths';\nimport { strokeRegion } from '../outlines/strokeRegion';\nimport type { BooleansAdapter } from './booleans';\n\n/**\n * What a stroked operand gives a Boolean operation.\n *\n * - `'ignore'`: its path, as though it had no stroke.\n * - `'unfilled'`: the region its stroke covers when it has no fill, as a line\n * or an open pencil stroke has none; its path when it is filled.\n * - `'include'`: what it paints — its fill and its stroke together, or the\n * stroke alone when it has no fill.\n *\n * Any mode but `'ignore'` needs {@link BooleansAdapter.getPaint}.\n */\nexport type BooleanStrokes = 'ignore' | 'unfilled' | 'include';\n\n/** Options for `applyBooleanOp`. */\nexport interface BooleanOpOptions {\n /** Default `'ignore'`. */\n strokes?: BooleanStrokes;\n /** The view scale a `{ px }` stroke width resolves against: one number, or\n * the view's own scale per axis. Default 1. */\n scale?: number | Scale2;\n}\n\n/** @internal */\nexport interface BooleanOperand {\n path: Path;\n /** Set when a stroke went into `path`: what a result standing in for this\n * operand wears, the stroke being part of its shape now. */\n paint?: PathPaint;\n}\n\nfunction inkOf(\n source: PaintedPath,\n strokes: BooleanStrokes,\n frame: Affine | null | undefined,\n scale: number | Scale2 | undefined,\n): BooleanOperand {\n const { path, fill } = source;\n const { stroke } = source;\n const strokePaint = stroke?.paint;\n if (!stroke || strokePaint == null) return { path };\n if (strokes === 'ignore' || (strokes === 'unfilled' && fill !== null)) return { path };\n const ribbon = strokeRegion(path, stroke, frame, scale === undefined ? {} : { scale });\n if (ribbon.commands.length === 0) return { path };\n return { path: fill !== null ? pathUnion(path, ribbon) : ribbon, paint: { fill: fill ?? { paint: strokePaint } } };\n}\n\n/**\n * The operand behind `id`, or `undefined` for a node that is not one: a group,\n * blank text, anything the adapter has neither a path nor text for. Throws\n * `TextOutlinesError` for text whose face has no outlines.\n */\nexport function resolveOperand(\n adapter: BooleansAdapter,\n id: NodeId,\n { strokes = 'ignore', scale }: BooleanOpOptions,\n): BooleanOperand | undefined {\n const path = adapter.getWorldPath(id);\n if (path) {\n const paint = strokes === 'ignore' ? undefined : adapter.getPaint?.(id);\n return paint ? inkOf({ path, ...paint }, strokes, adapter.getStrokeFrame?.(id), scale) : { path };\n }\n const text = adapter.getTextSource?.(id);\n if (!text) return undefined;\n if (strokes === 'ignore') {\n const glyphs = textToPath(text.data, text.pose);\n return glyphs.commands.length > 0 ? { path: glyphs } : undefined;\n }\n const inks = textToPathsByPaint(text.data, text.pose).map((p) => inkOf(p, strokes, adapter.getStrokeFrame?.(id), scale));\n if (inks.length === 0) return undefined;\n const paint = inks.find((ink) => ink.paint)?.paint;\n const whole = inks.length === 1 ? inks[0]!.path : pathUnion(...inks.map((ink) => ink.path));\n return paint ? { path: whole, paint } : { path: whole };\n}\n"],"mappings":";;;;AA2CA,SAASA,EACP,GACA,GACA,GACA,GACgB;CAChB,IAAM,EAAE,SAAM,YAASC,GACjB,EAAE,cAAWA,GACbC,IAAcC,GAAQ;CAE5B,IADI,CAACA,KAAUD,KAAe,QAC1BE,MAAY,YAAaA,MAAY,cAAcC,MAAS,MAAO,OAAO,EAAE,QAAK;CACrF,IAAMC,IAASC,EAAaC,GAAML,GAAQM,GAAOC,MAAU,KAAA,IAAY,CAAC,IAAI,EAAE,SAAM,CAAC;CAErF,OADIJ,EAAO,SAAS,WAAW,IAAU,EAAE,QAAK,IACzC;EAAE,MAAMD,MAAS,OAAiCC,IAA1BK,EAAUH,GAAMF,CAAM;EAAY,OAAO,EAAE,MAAMD,KAAQ,EAAE,OAAOH,EAAY,EAAE;CAAE;AACnH;AAOA,SAAgBU,EACd,GACA,GACA,EAAE,aAAU,UAAU,YACM;CAC5B,IAAMJ,IAAOK,EAAQ,aAAaC,CAAE;CACpC,IAAIN,GAAM;EACR,IAAMO,IAAQX,MAAY,WAAW,KAAA,IAAYS,EAAQ,WAAWC,CAAE;EACtE,OAAOC,IAAQf,EAAM;GAAE;GAAM,GAAGe;EAAM,GAAGX,GAASS,EAAQ,iBAAiBC,CAAE,GAAGJ,CAAK,IAAI,EAAE,QAAK;CAClG;CACA,IAAMM,IAAOH,EAAQ,gBAAgBC,CAAE;CACvC,IAAI,CAACE,GAAM;CACX,IAAIZ,MAAY,UAAU;EACxB,IAAMa,IAASC,EAAWF,EAAK,MAAMA,EAAK,IAAI;EAC9C,OAAOC,EAAO,SAAS,SAAS,IAAI,EAAE,MAAMA,EAAO,IAAI,KAAA;CACzD;CACA,IAAME,IAAOC,EAAmBJ,EAAK,MAAMA,EAAK,IAAI,CAAC,CAAC,KAAK,MAAMhB,EAAMqB,GAAGjB,GAASS,EAAQ,iBAAiBC,CAAE,GAAGJ,CAAK,CAAC;CACvH,IAAIS,EAAK,WAAW,GAAG;CACvB,IAAMJ,IAAQI,EAAK,MAAM,MAAQG,EAAI,KAAK,CAAC,EAAE,OACvCC,IAAQJ,EAAK,WAAW,IAAIA,EAAK,EAAE,CAAE,OAAOR,EAAU,GAAGQ,EAAK,KAAK,MAAQG,EAAI,IAAI,CAAC;CAC1F,OAAOP,IAAQ;EAAE,MAAMQ;EAAO;CAAM,IAAI,EAAE,MAAMA,EAAM;AACxD"}
@@ -0,0 +1,45 @@
1
+ import { pathCropPieces as e, pathDividePieces as t, pathExclude as n, pathIntersect as r, pathMerge as i, pathSubtract as a, pathTrim as o, pathUnion as s } from "@weasel-js/geom/booleans";
2
+ //#region src/interactions/actions/booleans/pieces.ts
3
+ function c(e) {
4
+ return e.map((e) => ({
5
+ path: e.path,
6
+ source: e.sources[e.sources.length - 1]
7
+ }));
8
+ }
9
+ function l(l, u, d) {
10
+ let f = u.length - 1, p = (e) => [{
11
+ path: e,
12
+ source: f
13
+ }], m;
14
+ switch (l) {
15
+ case "union":
16
+ m = p(s(...u));
17
+ break;
18
+ case "intersect":
19
+ m = p(r(...u));
20
+ break;
21
+ case "exclude":
22
+ m = p(n(...u));
23
+ break;
24
+ case "subtract": {
25
+ let e = u.length === 2 ? u[1] : s(...u.slice(1));
26
+ m = p(a(u[0], e));
27
+ break;
28
+ }
29
+ case "divide":
30
+ m = c(t(...u));
31
+ break;
32
+ case "crop":
33
+ m = c(e(...u));
34
+ break;
35
+ case "trim":
36
+ m = c(o(...u));
37
+ break;
38
+ case "merge": m = c(i(u, d));
39
+ }
40
+ return m.filter((e) => e.path.commands.length > 0);
41
+ }
42
+ //#endregion
43
+ export { l as booleanPieces };
44
+
45
+ //# sourceMappingURL=pieces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pieces.js","names":["bySource","pieces","p","booleanPieces","top","paths","whole","op","pathUnion","pathIntersect","pathExclude","front","pathSubtract","pathDividePieces","pathCropPieces","pathTrim","pathMerge","mergeKey"],"sources":["../../../../src/interactions/actions/booleans/pieces.ts"],"sourcesContent":["import {\n pathUnion,\n pathIntersect,\n pathSubtract,\n pathExclude,\n pathDividePieces,\n pathCropPieces,\n pathTrim,\n pathMerge,\n type BooleanPiece,\n} from '@weasel-js/geom/booleans';\nimport type { Path, PolygonPath } from '@weasel-js/geom';\nimport type { BooleanOp } from './booleans';\n\n/** One result path, and the operand it stands in for: an index into the\n * operands, back to front. */\nexport interface ResultPiece {\n path: PolygonPath;\n source: number;\n}\n\n/** A piece stands in for the topmost input left in it. */\nfunction bySource(pieces: BooleanPiece[]): ResultPiece[] {\n return pieces.map((p) => ({ path: p.path, source: p.sources[p.sources.length - 1]! }));\n}\n\n/** Run `op` over `paths`, back to front, dropping empty results. `mergeKey`\n * answers alike for the paths a Merge unites. */\nexport function booleanPieces(op: BooleanOp, paths: Path[], mergeKey: (index: number) => unknown): ResultPiece[] {\n const top = paths.length - 1;\n const whole = (path: PolygonPath): ResultPiece[] => [{ path, source: top }];\n let pieces: ResultPiece[];\n switch (op) {\n case 'union': pieces = whole(pathUnion(...paths)); break;\n case 'intersect': pieces = whole(pathIntersect(...paths)); break;\n case 'exclude': pieces = whole(pathExclude(...paths)); break;\n case 'subtract': {\n // Illustrator \"Minus Front\": back − union(everything in front).\n const front = paths.length === 2 ? paths[1]! : pathUnion(...paths.slice(1));\n pieces = whole(pathSubtract(paths[0]!, front));\n break;\n }\n case 'divide': pieces = bySource(pathDividePieces(...paths)); break;\n // Illustrator \"Crop\": every source below the topmost, clipped to it; the\n // topmost is consumed as the mask.\n case 'crop': pieces = bySource(pathCropPieces(...paths)); break;\n case 'trim': pieces = bySource(pathTrim(...paths)); break;\n case 'merge': pieces = bySource(pathMerge(paths, mergeKey)); break;\n }\n return pieces.filter((p) => p.path.commands.length > 0);\n}\n"],"mappings":";;AAsBA,SAASA,EAAS,GAAuC;CACvD,OAAOC,EAAO,KAAK,OAAO;EAAE,MAAMC,EAAE;EAAM,QAAQA,EAAE,QAAQA,EAAE,QAAQ,SAAS;CAAI,EAAE;AACvF;AAIA,SAAgBC,EAAc,GAAe,GAAe,GAAqD;CAC/G,IAAMC,IAAMC,EAAM,SAAS,GACrBC,KAAS,MAAqC,CAAC;EAAE;EAAM,QAAQF;CAAI,CAAC,GACtEH;CACJ,QAAQM,GAAR;EACE,KAAK;GAAa,IAASD,EAAME,EAAU,GAAGH,CAAK,CAAC;GAAG;EACvD,KAAK;GAAa,IAASC,EAAMG,EAAc,GAAGJ,CAAK,CAAC;GAAG;EAC3D,KAAK;GAAa,IAASC,EAAMI,EAAY,GAAGL,CAAK,CAAC;GAAG;EACzD,KAAK,YAAY;GAEf,IAAMM,IAAQN,EAAM,WAAW,IAAIA,EAAM,KAAMG,EAAU,GAAGH,EAAM,MAAM,CAAC,CAAC;GAC1E,IAASC,EAAMM,EAAaP,EAAM,IAAKM,CAAK,CAAC;GAC7C;EACF;EACA,KAAK;GAAa,IAASX,EAASa,EAAiB,GAAGR,CAAK,CAAC;GAAG;EAGjE,KAAK;GAAa,IAASL,EAASc,EAAe,GAAGT,CAAK,CAAC;GAAG;EAC/D,KAAK;GAAa,IAASL,EAASe,EAAS,GAAGV,CAAK,CAAC;GAAG;EACzD,KAAK,SAAa,IAASL,EAASgB,EAAUX,GAAOY,CAAQ,CAAC;CAChE;CACA,OAAOhB,EAAO,QAAQ,MAAMC,EAAE,KAAK,SAAS,SAAS,CAAC;AACxD"}
@@ -0,0 +1,24 @@
1
+ import { createMoveToIndexOp as e } from "../../../core/ops/reorder/index.js";
2
+ //#region src/interactions/actions/booleans/placement.ts
3
+ function t(t, n) {
4
+ let r = /* @__PURE__ */ new Map();
5
+ for (let e of t) {
6
+ if (!e.slot) continue;
7
+ let t = r.get(e.slot.parentId);
8
+ t ? t.push(e.id) : r.set(e.slot.parentId, [e.id]);
9
+ }
10
+ let i = [];
11
+ for (let [t, a] of r) {
12
+ let r = n.flatMap((e) => e && e.parentId === t ? [e.index] : []), o = Math.max(...r);
13
+ i.push(e({
14
+ ids: a,
15
+ parentId: t,
16
+ index: o - (r.length - 1)
17
+ }));
18
+ }
19
+ return i;
20
+ }
21
+ //#endregion
22
+ export { t as placementOps };
23
+
24
+ //# sourceMappingURL=placement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"placement.js","names":["placementOps","groups","r","results","group","ops","parentId","ids","indices","sourceSlots","s","top","createMoveToIndexOp"],"sources":["../../../../src/interactions/actions/booleans/placement.ts"],"sourcesContent":["import { createMoveToIndexOp } from 'core/ops/reorder';\nimport type { Op } from 'core/ops/types';\nimport type { BooleanZOrder } from './booleans';\n\n/**\n * The ops that put each result where its source was. Results are grouped by\n * their source's parent, and each group lands as one block, in result order,\n * in the slot of the topmost source in that parent.\n *\n * `sourceSlots` holds every source's slot, read before anything is deleted.\n * The sources below a slot in the same parent are deleted before the reorder\n * runs, so the block goes that many places lower. A result whose source has\n * no slot is left wherever the insert put it.\n */\nexport function placementOps(\n results: readonly { id: string; slot: BooleanZOrder | undefined }[],\n sourceSlots: readonly (BooleanZOrder | undefined)[],\n): Op[] {\n const groups = new Map<string | null, string[]>();\n for (const r of results) {\n if (!r.slot) continue;\n const group = groups.get(r.slot.parentId);\n if (group) group.push(r.id);\n else groups.set(r.slot.parentId, [r.id]);\n }\n const ops: Op[] = [];\n for (const [parentId, ids] of groups) {\n const indices = sourceSlots.flatMap((s) => (s && s.parentId === parentId ? [s.index] : []));\n const top = Math.max(...indices);\n ops.push(createMoveToIndexOp({ ids, parentId, index: top - (indices.length - 1) }));\n }\n return ops;\n}\n"],"mappings":";;AAcA,SAAgBA,EACd,GACA,GACM;CACN,IAAMC,oBAAS,IAAI,IAA6B;CAChD,KAAK,IAAMC,KAAKC,GAAS;EACvB,IAAI,CAACD,EAAE,MAAM;EACb,IAAME,IAAQH,EAAO,IAAIC,EAAE,KAAK,QAAQ;EACxC,AAAIE,IAAOA,EAAM,KAAKF,EAAE,EAAE,IACrBD,EAAO,IAAIC,EAAE,KAAK,UAAU,CAACA,EAAE,EAAE,CAAC;CACzC;CACA,IAAMG,IAAY,CAAC;CACnB,KAAK,IAAM,CAACC,GAAUC,MAAQN,GAAQ;EACpC,IAAMO,IAAUC,EAAY,SAAS,MAAOC,KAAKA,EAAE,aAAaJ,IAAW,CAACI,EAAE,KAAK,IAAI,CAAC,CAAE,GACpFC,IAAM,KAAK,IAAI,GAAGH,CAAO;EAC/B,EAAI,KAAKI,EAAoB;GAAE;GAAK;GAAU,OAAOD,KAAOH,EAAQ,SAAS;EAAG,CAAC,CAAC;CACpF;CACA,OAAOH;AACT"}
@@ -2,16 +2,18 @@ import { applyBooleanOp as e } from "./booleans.js";
2
2
  import { useCallback as t } from "react";
3
3
  import { useLatest as n } from "@weasel-js/react";
4
4
  function r(r, i = {}) {
5
- let a = n(r), o = t((t) => {
6
- e(a.current, t);
7
- }, [a]);
5
+ let a = n(r), o = n(i), s = t((t) => {
6
+ e(a.current, t, o.current);
7
+ }, [a, o]);
8
8
  return {
9
- union: t(() => o("union"), [o]),
10
- intersect: t(() => o("intersect"), [o]),
11
- subtract: t(() => o("subtract"), [o]),
12
- exclude: t(() => o("exclude"), [o]),
13
- divide: t(() => o("divide"), [o]),
14
- crop: t(() => o("crop"), [o])
9
+ union: t(() => s("union"), [s]),
10
+ intersect: t(() => s("intersect"), [s]),
11
+ subtract: t(() => s("subtract"), [s]),
12
+ exclude: t(() => s("exclude"), [s]),
13
+ divide: t(() => s("divide"), [s]),
14
+ crop: t(() => s("crop"), [s]),
15
+ trim: t(() => s("trim"), [s]),
16
+ merge: t(() => s("merge"), [s])
15
17
  };
16
18
  }
17
19
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"useBooleans.js","names":["useBooleans","adapterRef","useLatest","adapter","run","useCallback","op"],"sources":["../../../../src/interactions/actions/booleans/useBooleans.ts"],"sourcesContent":["/**\n * `useBooleans` — selection-driven Boolean ops on path layers.\n *\n * Returns six imperative callables (`union` / `intersect` / `subtract` /\n * `exclude` / `divide` / `crop`). Each reads the current selection,\n * performs the op in world space, and dispatches a single batch through\n * the adapter's `applyOps` (one undo step).\n *\n * Adapter shape: see `BooleansAdapter` in `./booleans.ts`. Consumers\n * supply how to read selection, fetch the world-space `Path` for an id,\n * compare ids by stacking order, and mint a node from a result `Path`.\n *\n * No-ops are silent in production; in dev, `subtract` with < 2 selected\n * paths emits a `console.warn`.\n */\nimport { useCallback } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { applyBooleanOp, type BooleansAdapter, type BooleanOp } from './booleans';\n\n/** The six Boolean path operations, each acting on the current selection and\n * committing as one undo step. */\nexport interface UseBooleansReturn {\n union(): void;\n intersect(): void;\n subtract(): void;\n exclude(): void;\n divide(): void;\n crop(): void;\n}\n\n/** Options for `useBooleans`. */\nexport interface UseBooleansOptions {\n /** No-op. Retained for source-compatibility; auto-registration is now\n * handled by `useStandardActions` via the Pathfinder descriptors. */\n enableActions?: boolean;\n}\n\nconst isDev = typeof import.meta !== 'undefined'\n && (import.meta as { env?: { DEV?: boolean } }).env?.DEV;\n\n/** Bind the Boolean path operations to an adapter that knows how to read the\n * selection, fetch world-space paths and mint result nodes. */\nexport function useBooleans(\n adapter: BooleansAdapter,\n _options: UseBooleansOptions = {},\n): UseBooleansReturn {\n const adapterRef = useLatest(adapter);\n\n const run = useCallback((op: BooleanOp) => {\n const result = applyBooleanOp(adapterRef.current, op);\n if (isDev && result.kind === 'noop' && result.reason === 'too-few-for-subtract') {\n console.warn('[useBooleans] subtract requires at least 2 selected paths');\n }\n }, [adapterRef]);\n\n return {\n union: useCallback(() => run('union'), [run]),\n intersect: useCallback(() => run('intersect'), [run]),\n subtract: useCallback(() => run('subtract'), [run]),\n exclude: useCallback(() => run('exclude'), [run]),\n divide: useCallback(() => run('divide'), [run]),\n crop: useCallback(() => run('crop'), [run]),\n };\n}\n"],"mappings":";;;AA0CA,SAAgBA,EACd,GACA,IAA+B,CAAC,GACb;CACnB,IAAMC,IAAaC,EAAUC,CAAO,GAE9BC,IAAMC,GAAa,MAAkB;EAC1B,EAAeJ,EAAW,SAASK,CAAE;CAItD,GAAG,CAACL,CAAU,CAAC;CAEf,OAAO;EACL,OAAOI,QAAkBD,EAAI,OAAO,GAAG,CAACA,CAAG,CAAC;EAC5C,WAAWC,QAAkBD,EAAI,WAAW,GAAG,CAACA,CAAG,CAAC;EACpD,UAAUC,QAAkBD,EAAI,UAAU,GAAG,CAACA,CAAG,CAAC;EAClD,SAASC,QAAkBD,EAAI,SAAS,GAAG,CAACA,CAAG,CAAC;EAChD,QAAQC,QAAkBD,EAAI,QAAQ,GAAG,CAACA,CAAG,CAAC;EAC9C,MAAMC,QAAkBD,EAAI,MAAM,GAAG,CAACA,CAAG,CAAC;CAC5C;AACF"}
1
+ {"version":3,"file":"useBooleans.js","names":["useBooleans","adapterRef","useLatest","adapter","optionsRef","options","run","useCallback","op"],"sources":["../../../../src/interactions/actions/booleans/useBooleans.ts"],"sourcesContent":["/**\n * `useBooleans` — selection-driven Boolean ops on path layers. No-ops are\n * silent in production; in dev, `subtract` with < 2 selected paths emits a\n * `console.warn`.\n */\nimport { useCallback } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { applyBooleanOp, type BooleansAdapter, type BooleanOp } from './booleans';\nimport type { BooleanOpOptions } from './operands';\n\n/** The Boolean path operations, each acting on the current selection and\n * committing as one undo step. */\nexport interface UseBooleansReturn {\n union(): void;\n intersect(): void;\n subtract(): void;\n exclude(): void;\n divide(): void;\n crop(): void;\n trim(): void;\n merge(): void;\n}\n\n/** Options for `useBooleans`. */\nexport interface UseBooleansOptions extends BooleanOpOptions {\n /** No-op. Retained for source-compatibility; `useStandardActions`\n * registers the actions. */\n enableActions?: boolean;\n}\n\nconst isDev = typeof import.meta !== 'undefined'\n && (import.meta as { env?: { DEV?: boolean } }).env?.DEV;\n\n/** Bind the Boolean path operations to an adapter that knows how to read the\n * selection, fetch world-space paths and mint result nodes. */\nexport function useBooleans(\n adapter: BooleansAdapter,\n options: UseBooleansOptions = {},\n): UseBooleansReturn {\n const adapterRef = useLatest(adapter);\n const optionsRef = useLatest(options);\n\n const run = useCallback((op: BooleanOp) => {\n const result = applyBooleanOp(adapterRef.current, op, optionsRef.current);\n if (isDev && result.kind === 'noop' && result.reason === 'too-few-for-subtract') {\n console.warn('[useBooleans] subtract requires at least 2 selected paths');\n }\n }, [adapterRef, optionsRef]);\n\n return {\n union: useCallback(() => run('union'), [run]),\n intersect: useCallback(() => run('intersect'), [run]),\n subtract: useCallback(() => run('subtract'), [run]),\n exclude: useCallback(() => run('exclude'), [run]),\n divide: useCallback(() => run('divide'), [run]),\n crop: useCallback(() => run('crop'), [run]),\n trim: useCallback(() => run('trim'), [run]),\n merge: useCallback(() => run('merge'), [run]),\n };\n}\n"],"mappings":";;;AAmCA,SAAgBA,EACd,GACA,IAA8B,CAAC,GACZ;CACnB,IAAMC,IAAaC,EAAUC,CAAO,GAC9BC,IAAaF,EAAUG,CAAO,GAE9BC,IAAMC,GAAa,MAAkB;EAC1B,EAAeN,EAAW,SAASO,GAAIJ,EAAW,OAAO;CAI1E,GAAG,CAACH,GAAYG,CAAU,CAAC;CAE3B,OAAO;EACL,OAAOG,QAAkBD,EAAI,OAAO,GAAG,CAACA,CAAG,CAAC;EAC5C,WAAWC,QAAkBD,EAAI,WAAW,GAAG,CAACA,CAAG,CAAC;EACpD,UAAUC,QAAkBD,EAAI,UAAU,GAAG,CAACA,CAAG,CAAC;EAClD,SAASC,QAAkBD,EAAI,SAAS,GAAG,CAACA,CAAG,CAAC;EAChD,QAAQC,QAAkBD,EAAI,QAAQ,GAAG,CAACA,CAAG,CAAC;EAC9C,MAAMC,QAAkBD,EAAI,MAAM,GAAG,CAACA,CAAG,CAAC;EAC1C,MAAMC,QAAkBD,EAAI,MAAM,GAAG,CAACA,CAAG,CAAC;EAC1C,OAAOC,QAAkBD,EAAI,OAAO,GAAG,CAACA,CAAG,CAAC;CAC9C;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useBooleansAdapter.js","names":["useBooleansAdapter","adapter"],"sources":["../../../../src/interactions/actions/booleans/useBooleansAdapter.ts"],"sourcesContent":["/**\n * `useBooleansAdapter` — publishes a `BooleansAdapter` to the surrounding\n * `<DepRegistryProvider>` (typically inside `<SceneCanvas>`).\n *\n * The Pathfinder action descriptors (`pathfinderUnionAction`, etc., registered\n * by `useStandardActions`) read this dep both in their `enabled` predicate\n * (via `deps.booleansAdapter` — actually they read selection; the adapter is\n * read by the invoker) and in their immediate invoker. Consumers construct an\n * adapter that bridges to their scene's data shape and call this hook to make\n * the kit's Pathfinder strip operational.\n *\n * No-op when no `<DepRegistryProvider>` is in scope — mirrors the silent-\n * no-op contract of `useDepSource`.\n */\nimport { useDepSource } from '@weasel-js/routing/react';\nimport type { BooleansAdapter } from './booleans';\n\n/** Publish a Boolean-ops adapter so the built-in Pathfinder actions can run.\n * Silently does nothing outside a `<DepRegistryProvider>`. */\nexport function useBooleansAdapter(adapter: BooleansAdapter): void {\n useDepSource('booleansAdapter', () => adapter);\n}\n"],"mappings":";;AAmBA,SAAgBA,EAAmB,GAAgC;CACjE,EAAa,yBAAyBC,CAAO;AAC/C"}
1
+ {"version":3,"file":"useBooleansAdapter.js","names":["useBooleansAdapter","adapter"],"sources":["../../../../src/interactions/actions/booleans/useBooleansAdapter.ts"],"sourcesContent":["import { useDepSource } from '@weasel-js/routing/react';\nimport type { BooleansAdapter } from './booleans';\n\n/** Publish a Boolean-ops adapter so the built-in Pathfinder actions can run.\n * Silently does nothing outside a `<DepRegistryProvider>`. */\nexport function useBooleansAdapter(adapter: BooleansAdapter): void {\n useDepSource('booleansAdapter', () => adapter);\n}\n"],"mappings":";;AAKA,SAAgBA,EAAmB,GAAgC;CACjE,EAAa,yBAAyBC,CAAO;AAC/C"}
@@ -1,16 +1,16 @@
1
1
  import { defaultCommitAdapter as e } from "../defaultCommitAdapter.js";
2
- import { CopyIcon as t, CutIcon as n, PasteIcon as r } from "./icons/editIcons.js";
3
- import { requiresSelection as i } from "./requiresSelection.js";
4
- import { buildDeleteOps as a } from "./delete.js";
2
+ import { CopyIcon as t, CutIcon as n, PasteIcon as r } from "../defaults/icons/editIcons.js";
3
+ import { requiresSelection as i } from "../defaults/requiresSelection.js";
4
+ import { buildDeleteOps as a } from "../defaults/delete.js";
5
5
  import { kitWeaselJsonHandler as o } from "../../../features/ingestion/weaselJsonHandler.js";
6
- import { ANY_INGEST_MODS as s, INGEST_REQUIRES as c, ingestFromEvent as l } from "./ingest.js";
7
- import { createElement as u } from "react";
8
- import { ActionDisabledReason as d } from "@weasel-js/routing";
9
- //#region src/interactions/actions/defaults/clipboard.ts
10
- var f = {
6
+ import { ANY_INGEST_MODS as s, INGEST_REQUIRES as c, claimable as l, ingestFromEvent as u } from "../defaults/ingest.js";
7
+ import { createElement as d } from "react";
8
+ import { ActionDisabledReason as f } from "@weasel-js/routing";
9
+ //#region src/interactions/actions/clipboard/action.ts
10
+ var p = {
11
11
  id: "clipboard.copy",
12
12
  label: "Copy",
13
- icon: u(t),
13
+ icon: d(t),
14
14
  group: "clipboard",
15
15
  defaultBinding: {
16
16
  kind: "key",
@@ -26,10 +26,10 @@ var f = {
26
26
  }
27
27
  },
28
28
  enabled: i
29
- }, p = {
29
+ }, m = {
30
30
  id: "clipboard.cut",
31
31
  label: "Cut",
32
- icon: u(n),
32
+ icon: d(n),
33
33
  group: "clipboard",
34
34
  defaultBinding: {
35
35
  kind: "key",
@@ -56,10 +56,10 @@ var f = {
56
56
  }
57
57
  },
58
58
  enabled: i
59
- }, m = {
59
+ }, h = {
60
60
  id: "clipboard.paste",
61
61
  label: "Paste",
62
- icon: u(r),
62
+ icon: d(r),
63
63
  group: "clipboard",
64
64
  eligible: { capability: "edits-page" },
65
65
  requires: ["clipboard"],
@@ -71,9 +71,9 @@ var f = {
71
71
  },
72
72
  enabled: (e) => {
73
73
  let t = e?.clipboard;
74
- return t && !t.isEmpty() ? !0 : d.NotApplicable;
74
+ return t && !t.isEmpty() ? !0 : f.NotApplicable;
75
75
  }
76
- }, h = [o], g = {
76
+ }, g = [o], _ = {
77
77
  id: "clipboard.pasteEvent",
78
78
  label: "Paste copied nodes",
79
79
  defaultBinding: {
@@ -84,11 +84,11 @@ var f = {
84
84
  requires: [...c],
85
85
  invoker: {
86
86
  timing: "immediate",
87
- run: (e, t) => l(e, t, { handlers: h })
87
+ run: (e, t) => u(e, t, { handlers: g })
88
88
  },
89
- enabled: () => !0
89
+ enabled: (e, t, n) => l(n, g)
90
90
  };
91
91
  //#endregion
92
- export { f as clipboardCopyAction, p as clipboardCutAction, m as clipboardPasteAction, g as clipboardPasteEventAction };
92
+ export { p as clipboardCopyAction, m as clipboardCutAction, h as clipboardPasteAction, _ as clipboardPasteEventAction };
93
93
 
94
- //# sourceMappingURL=clipboard.js.map
94
+ //# sourceMappingURL=action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action.js","names":["clipboardCopyAction","createElement","CopyIcon","requiresSelection","clipboardCutAction","CutIcon","clipboard","deps","selection","scene","applyOps","ids","ops","buildDeleteOps","defaultCommitAdapter","clipboardPasteAction","PasteIcon","ActionDisabledReason","PASTE_EVENT_HANDLERS","kitWeaselJsonHandler","clipboardPasteEventAction","ANY_INGEST_MODS","INGEST_REQUIRES","ingestFromEvent","params","claimable","carried"],"sources":["../../../../src/interactions/actions/clipboard/action.ts"],"sourcesContent":["import { createElement } from 'react';\nimport { CopyIcon, CutIcon, PasteIcon } from '../defaults/icons/editIcons';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { ActionDisabledReason, type Action } from '@weasel-js/routing';\nimport { buildDeleteOps } from '../defaults/delete';\nimport { requiresSelection } from '../defaults/requiresSelection';\nimport { kitWeaselJsonHandler } from 'features/ingestion/weaselJsonHandler';\nimport { ANY_INGEST_MODS, claimable, INGEST_REQUIRES, ingestFromEvent } from '../defaults/ingest';\n\n/**\n * @experimental\n * Static descriptor for the `clipboard.copy` Action (Cmd/Ctrl+C).\n */\nexport const clipboardCopyAction: Action & { requires: string[] } = {\n id: 'clipboard.copy',\n label: 'Copy',\n icon: createElement(CopyIcon),\n group: 'clipboard',\n defaultBinding: { kind: 'key', key: 'c', mods: { mod: true } },\n // Same gate as `duplicate`: a mode that can neither edit the page nor own a\n // selection has nothing to copy. Notably excludes `text-edit`, where Cmd+C\n // must stay the browser's own copy of the caret range.\n eligible: { capability: ['edits-page', 'creates-selection'] },\n // `selection` is read by the `enabled` gate, not the invoker — the\n // dispatcher builds deps for both, and an undeclared read is undefined.\n requires: ['clipboard', 'selection'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n deps.clipboard?.copy();\n },\n },\n enabled: requiresSelection,\n};\n\n/**\n * @experimental\n * Static descriptor for the `clipboard.cut` Action (Cmd/Ctrl+X) — copy, then\n * the same batched delete `deleteAction` performs, as one undo entry.\n */\nexport const clipboardCutAction: Action & { requires: string[] } = {\n id: 'clipboard.cut',\n label: 'Cut',\n icon: createElement(CutIcon),\n group: 'clipboard',\n defaultBinding: { kind: 'key', key: 'x', mods: { mod: true } },\n eligible: { capability: 'edits-page' },\n requires: ['clipboard', 'scene', 'selection', 'applyOps'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const clipboard = deps.clipboard;\n const selection = deps.selection;\n const scene = deps.scene;\n const applyOps = deps.applyOps;\n if (!clipboard || !selection || !scene) return;\n const ids = selection.get();\n if (ids.length === 0) return;\n\n // Snapshot before removal — `snapshotSelection` reads live nodes.\n clipboard.copy();\n\n const ops = buildDeleteOps(scene, ids, 'Cut');\n if (ops.length > 0) {\n if (applyOps) applyOps(ops, 'Cut');\n else scene.applyBatch(ops, 'Cut', defaultCommitAdapter(scene, selection.adapterMethods));\n }\n selection.set([]);\n },\n },\n enabled: requiresSelection,\n};\n\n/**\n * @experimental\n * Static descriptor for the `clipboard.paste` Action — what a Paste button or\n * menu item triggers, pasting the last copy this canvas made. It has no key\n * binding: Cmd/Ctrl+V already arrives as a DOM `paste` event, which the\n * dispatcher routes to `clipboard.pasteEvent` or `ingest`, and a binding here\n * would fire alongside it and paste twice.\n */\nexport const clipboardPasteAction: Action & { requires: string[] } = {\n id: 'clipboard.paste',\n label: 'Paste',\n icon: createElement(PasteIcon),\n group: 'clipboard',\n eligible: { capability: 'edits-page' },\n requires: ['clipboard'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n deps.clipboard?.paste();\n },\n },\n enabled: (deps) => {\n const clipboard = deps?.clipboard;\n return clipboard && !clipboard.isEmpty() ? true : ActionDisabledReason.NotApplicable;\n },\n};\n\nconst PASTE_EVENT_HANDLERS = [kitWeaselJsonHandler];\n\n/**\n * @experimental\n * Static descriptor for the `clipboard.pasteEvent` Action — Cmd/Ctrl+V on a\n * canvas that edits and does not ingest. It answers the DOM `paste` event by\n * pasting nodes a kit canvas copied to the OS clipboard, in this tab or\n * another, and nothing else: an image, SVG, or file on the clipboard, and\n * every consumer content handler, need `ingest`. `ingest` binds the same\n * event and takes this payload among the rest, so `useStandardActions`\n * leaves this one unregistered wherever `ingest` is registered.\n *\n * Bound to `text/plain` because that is the only flavor of a copy a paste\n * event carries; a paste without text stays the page's.\n */\nexport const clipboardPasteEventAction: Action & { requires: string[] } = {\n id: 'clipboard.pasteEvent',\n label: 'Paste copied nodes',\n defaultBinding: { kind: 'paste', types: ['text/plain'], mods: ANY_INGEST_MODS },\n requires: [...INGEST_REQUIRES],\n invoker: {\n timing: 'immediate',\n run: (deps, params) => ingestFromEvent(deps, params, { handlers: PASTE_EVENT_HANDLERS }),\n },\n enabled: (_deps, _at, carried) => claimable(carried, PASTE_EVENT_HANDLERS),\n};\n"],"mappings":";;;;;;;;;AAaA,IAAaA,IAAuD;CAClE,IAAI;CACJ,OAAO;CACP,MAAMC,EAAcC,CAAQ;CAC5B,OAAO;CACP,gBAAgB;EAAE,MAAM;EAAO,KAAK;EAAK,MAAM,EAAE,KAAK,GAAK;CAAE;CAI7D,UAAU,EAAE,YAAY,CAAC,cAAc,mBAAmB,EAAE;CAG5D,UAAU,CAAC,aAAa,WAAW;CACnC,SAAS;EACP,QAAQ;EACR,MAAM,MAAS;GACb,EAAK,WAAW,KAAK;EACvB;CACF;CACA,SAASC;AACX,GAOaC,IAAsD;CACjE,IAAI;CACJ,OAAO;CACP,MAAMH,EAAcI,CAAO;CAC3B,OAAO;CACP,gBAAgB;EAAE,MAAM;EAAO,KAAK;EAAK,MAAM,EAAE,KAAK,GAAK;CAAE;CAC7D,UAAU,EAAE,YAAY,aAAa;CACrC,UAAU;EAAC;EAAa;EAAS;EAAa;CAAU;CACxD,SAAS;EACP,QAAQ;EACR,MAAM,MAAS;GACb,IAAMC,IAAYC,EAAK,WACjBC,IAAYD,EAAK,WACjBE,IAAQF,EAAK,OACbG,IAAWH,EAAK;GACtB,IAAI,CAACD,KAAa,CAACE,KAAa,CAACC,GAAO;GACxC,IAAME,IAAMH,EAAU,IAAI;GAC1B,IAAIG,EAAI,WAAW,GAAG;GAGtB,EAAU,KAAK;GAEf,IAAMC,IAAMC,EAAeJ,GAAOE,GAAK,KAAK;GAK5C,AAJIC,EAAI,SAAS,MACXF,IAAUA,EAASE,GAAK,KAAK,IAC5BH,EAAM,WAAWG,GAAK,OAAOE,EAAqBL,GAAOD,EAAU,cAAc,CAAC,IAEzFA,EAAU,IAAI,CAAC,CAAC;EAClB;CACF;CACA,SAASL;AACX,GAUaY,IAAwD;CACnE,IAAI;CACJ,OAAO;CACP,MAAMd,EAAce,CAAS;CAC7B,OAAO;CACP,UAAU,EAAE,YAAY,aAAa;CACrC,UAAU,CAAC,WAAW;CACtB,SAAS;EACP,QAAQ;EACR,MAAM,MAAS;GACb,EAAK,WAAW,MAAM;EACxB;CACF;CACA,UAAU,MAAS;EACjB,IAAMV,IAAYC,GAAM;EACxB,OAAOD,KAAa,CAACA,EAAU,QAAQ,IAAI,KAAOW,EAAqB;CACzE;AACF,GAEMC,IAAuB,CAACC,CAAoB,GAerCC,IAA6D;CACxE,IAAI;CACJ,OAAO;CACP,gBAAgB;EAAE,MAAM;EAAS,OAAO,CAAC,YAAY;EAAG,MAAMC;CAAgB;CAC9E,UAAU,CAAC,GAAGC,CAAe;CAC7B,SAAS;EACP,QAAQ;EACR,MAAM,GAAM,MAAWC,EAAgBhB,GAAMiB,GAAQ,EAAE,UAAUN,EAAqB,CAAC;CACzF;CACA,UAAU,GAAO,GAAK,MAAYO,EAAUC,GAASR,CAAoB;AAC3E"}
@@ -1,14 +1,14 @@
1
1
  import { dwarn as e } from "../../../debug/flag.js";
2
- import { usePointerContext as t } from "../../../features/pointer/PointerContext.js";
3
- import { dispatchApplyBatch as n } from "../../../core/applyOps.js";
4
- import { materializePaste as r } from "./materializePaste.js";
5
- import { WEASEL_CLIPBOARD_MIME as i, buildWeaselClipboardText as a } from "./wireFormat.js";
6
- import { useCallback as o, useRef as s } from "react";
7
- import { useLatest as c } from "@weasel-js/react";
2
+ import { dispatchApplyBatch as t } from "../../../core/applyOps.js";
3
+ import { materializePaste as n } from "./materializePaste.js";
4
+ import { WEASEL_CLIPBOARD_MIME as r, buildWeaselClipboardText as i } from "./wireFormat.js";
5
+ import { useCallback as a, useRef as o } from "react";
6
+ import { useLatest as s } from "@weasel-js/react";
7
+ import { usePointerContext as c } from "@weasel-js/routing/react";
8
8
  //#region src/interactions/actions/clipboard/clipboardOps.ts
9
9
  var l = { items: [] };
10
- function u(i, a) {
11
- let { getSelection: u, onPaste: f, onPasteOmitted: m, pasteLabel: h = "Paste", getDropPoint: g, produceFlavors: _, jsonReplacer: v } = a, y = t(), b = g ?? y?.getDropPoint, x = s(l), S = c(i), C = c({
10
+ function u(r, i) {
11
+ let { getSelection: u, onPaste: f, onPasteOmitted: m, pasteLabel: h = "Paste", getDropPoint: g, produceFlavors: _, jsonReplacer: v } = i, y = c(), b = g ?? y?.getDropPoint, x = o(l), S = s(r), C = s({
12
12
  getSelection: u,
13
13
  onPaste: f,
14
14
  onPasteOmitted: m,
@@ -18,7 +18,7 @@ function u(i, a) {
18
18
  jsonReplacer: v
19
19
  });
20
20
  return {
21
- copy: o(() => {
21
+ copy: a(() => {
22
22
  let t = C.current.getSelection();
23
23
  if (t.length === 0) return;
24
24
  let n = S.current.snapshotSelection;
@@ -32,23 +32,23 @@ function u(i, a) {
32
32
  }
33
33
  r && p(r);
34
34
  }, [S, C]),
35
- paste: o(() => {
35
+ paste: a(() => {
36
36
  let e = x.current;
37
37
  if (e.items.length === 0) return;
38
- let t = S.current, i = r(t, e, {
38
+ let r = S.current, i = n(r, e, {
39
39
  currentSelection: C.current.getSelection(),
40
40
  dropPoint: C.current.getDropPoint?.(),
41
41
  onOmitted: C.current.onPasteOmitted
42
42
  });
43
- i && (n(t, i.ops, C.current.pasteLabel), x.current = { items: i.created }, C.current.onPaste?.(i.newIds));
43
+ i && (t(r, i.ops, C.current.pasteLabel), x.current = { items: i.created }, C.current.onPaste?.(i.newIds));
44
44
  }, [S, C]),
45
- isEmpty: o(() => x.current.items.length === 0, [])
45
+ isEmpty: a(() => x.current.items.length === 0, [])
46
46
  };
47
47
  }
48
48
  function d(e, t) {
49
- let n = a(e.items, t);
49
+ let n = i(e.items, t);
50
50
  return {
51
- [i]: n,
51
+ [r]: n,
52
52
  "text/plain": n
53
53
  };
54
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"clipboardOps.js","names":["EMPTY","useClipboardOps","options","pointerCtx","usePointerContext","effectiveGetDropPoint","getDropPoint","clipboardRef","useRef","adapterRef","useLatest","adapter","optsRef","useCallback","ids","snap","flavors","defaultFlavors","err","writeOsClipboard","cb","a","result","materializePaste","dispatchApplyBatch","text","buildWeaselClipboardText","snapshot","replacer","WEASEL_CLIPBOARD_MIME","WELL_KNOWN_CLIPBOARD_MIMES","entries","rejected","mime","wireMime","toItem","fs","wire","blob","t","promised","writeLive","live","next","standard","dwarn"],"sources":["../../../../src/interactions/actions/clipboard/clipboardOps.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { NodeId } from 'core/scene/types';\nimport { dispatchApplyBatch } from 'core/applyOps';\nimport type { InsertAdapter, PasteOmission } from 'core/adapters/types';\nimport type { ClipboardSnapshot } from './types';\nimport { usePointerContext } from 'features/pointer/PointerContext';\nimport { dwarn } from 'debug/flag';\nimport { materializePaste } from './materializePaste';\nimport { WEASEL_CLIPBOARD_MIME, buildWeaselClipboardText } from './wireFormat';\n\ntype Replacer = (key: string, value: unknown) => unknown;\n\n/** Options for `useClipboardOps`. */\nexport interface UseClipboardOpsOptions {\n /** How the hook reads \"current selection\" for copy. The kit doesn't assume\n * a global selection store; each consumer wires this. */\n getSelection: () => NodeId[];\n /** Called after a successful paste with the ids of the newly inserted objects. */\n onPaste?: (newIds: NodeId[]) => void;\n /** Called when a paste left copied nodes out, with each one and the reason\n * — an edge whose endpoints were not copied with it, say. Also called for\n * a paste that made nothing. */\n onPasteOmitted?: (omitted: PasteOmission[]) => void;\n /** Label for the history entry produced by paste. Default 'Paste'. */\n pasteLabel?: string;\n /** Pulled once per paste() call. When non-null, threaded to commitPaste\n * as `ctx.dropPoint`; adapters typically use it as the cluster origin\n * (ignoring `offset`). When null/undefined, the hook falls back to the\n * existing cascade-offset behavior. */\n getDropPoint?: () => { worldX: number; worldY: number } | null;\n /** Produce the OS-clipboard flavor map for a copied snapshot. Keys are MIME\n * types, values the serialized payload. The kit default emits\n * `application/x-weasel-clipboard+json` plus `text/plain` carrying the\n * same JSON. Apps override to add richer flavors (e.g. real SVG) or to\n * replace the text flavor. Return an empty object to skip the OS write\n * entirely. A value may be a promise — an SVG flavor waiting on\n * `warmSvg`, say: the write is still issued inside the copy gesture and\n * the clipboard takes the text when it resolves. The producer itself runs\n * synchronously, so it reads the selection as it stood at the copy. */\n produceFlavors?: (snapshot: ClipboardSnapshot) => ClipboardFlavors;\n /** Replacer for the kit-default JSON flavor (typed arrays etc.). Ignored\n * when `produceFlavors` is supplied. */\n jsonReplacer?: Replacer;\n}\n\n/** MIME type to payload, as `produceFlavors` returns it. */\nexport type ClipboardFlavors = Record<string, string | Promise<string>>;\n\n/** Return shape of `useClipboardOps`: imperative `copy`, `paste`, and `isEmpty` functions. */\nexport interface UseClipboardOpsReturn {\n copy(): void;\n paste(): void;\n isEmpty(): boolean;\n}\n\nconst EMPTY: ClipboardSnapshot = { items: [] };\n\n/** In-memory copy/paste of selections via `InsertAdapter.snapshotSelection` / `commitPaste`. */\nexport function useClipboardOps<TNode extends { id: string }>(\n adapter: InsertAdapter<TNode>,\n options: UseClipboardOpsOptions,\n): UseClipboardOpsReturn {\n const {\n getSelection, onPaste, onPasteOmitted, pasteLabel = 'Paste', getDropPoint, produceFlavors, jsonReplacer,\n } = options;\n // Fall back to the ambient pointer context (auto-published by SceneCanvas)\n // when the caller didn't supply an explicit `getDropPoint`. Null context\n // (no provider in scope) and no caller-supplied thunk together mean\n // \"no drop point\" — paste uses the cascade offset instead.\n const pointerCtx = usePointerContext();\n const effectiveGetDropPoint = getDropPoint ?? pointerCtx?.getDropPoint;\n const clipboardRef = useRef<ClipboardSnapshot>(EMPTY);\n // Keep callbacks stable across renders.\n const adapterRef = useLatest(adapter);\n const optsRef = useLatest({\n getSelection, onPaste, onPasteOmitted, pasteLabel, getDropPoint: effectiveGetDropPoint, produceFlavors,\n jsonReplacer,\n });\n\n const copy = useCallback(() => {\n const ids = optsRef.current.getSelection();\n if (ids.length === 0) return;\n const snap = adapterRef.current.snapshotSelection;\n if (!snap) return;\n clipboardRef.current = snap(ids);\n // Best-effort OS write. Never blocks or throws — the in-memory ref is\n // already set, and OS clipboard support varies (custom formats are\n // Chromium-only via the \"web \" prefix; jsdom/non-secure contexts have\n // no API at all). The flavor producer itself is untrusted consumer code\n // (`produceFlavors`), so guard its call too — a throwing producer must\n // not break `copy()`, it just skips the OS write.\n let flavors: ClipboardFlavors | null = null;\n try {\n flavors = optsRef.current.produceFlavors?.(clipboardRef.current)\n ?? defaultFlavors(clipboardRef.current, optsRef.current.jsonReplacer);\n } catch (err) {\n dwarn('clipboard', `flavor producer threw — skipping OS write: ${String(err)}`);\n }\n if (flavors) void writeOsClipboard(flavors);\n }, [adapterRef, optsRef]);\n\n const paste = useCallback(() => {\n const cb = clipboardRef.current;\n if (cb.items.length === 0) return;\n const a = adapterRef.current;\n const result = materializePaste(a, cb, {\n currentSelection: optsRef.current.getSelection(),\n dropPoint: optsRef.current.getDropPoint?.(),\n onOmitted: optsRef.current.onPasteOmitted,\n });\n if (!result) return;\n dispatchApplyBatch(a, result.ops, optsRef.current.pasteLabel);\n // Use the just-created objects as the next cascade source. Re-snapshotting\n // via `adapter.snapshotSelection(newIds)` would read adapter state, but\n // React-state adapters haven't flushed yet — `itemsRef.current` still\n // points at the pre-insert array, so the snapshot would come back empty\n // and the next paste would no-op.\n clipboardRef.current = { items: result.created };\n optsRef.current.onPaste?.(result.newIds as NodeId[]);\n }, [adapterRef, optsRef]);\n\n const isEmpty = useCallback(() => clipboardRef.current.items.length === 0, []);\n\n return { copy, paste, isEmpty };\n}\n\nfunction defaultFlavors(snapshot: ClipboardSnapshot, replacer?: Replacer): ClipboardFlavors {\n const text = buildWeaselClipboardText(snapshot.items, replacer);\n return { [WEASEL_CLIPBOARD_MIME]: text, 'text/plain': text };\n}\n\n/** MIME types the async Clipboard API accepts unprefixed. Every other type\n * (including our own custom MIME, and app-supplied flavors like\n * `image/svg+xml`) must carry Chromium's `web ` prefix or `ClipboardItem`'s\n * constructor throws. */\nconst WELL_KNOWN_CLIPBOARD_MIMES = new Set(['text/plain', 'text/html', 'image/png']);\n\n/** Degradation ladder: full map (every non-well-known MIME web-prefixed) →\n * the same minus any promised flavor that rejected → well-known-only → give\n * up with a dwarn. Chromium writes nothing when one flavor rejects, so a\n * rejection costs only that flavor, never the clipboard's previous content\n * half-overwritten.\n * @internal test seam — exported so unit tests can await the fire-and-forget\n * write directly; tests should still exercise this at least once through\n * the public `copy()` (see clipboardOps.test.tsx). */\nexport async function writeOsClipboard(flavors: ClipboardFlavors): Promise<void> {\n const entries = Object.entries(flavors);\n if (entries.length === 0) return;\n const cb = typeof navigator !== 'undefined' ? navigator.clipboard : undefined;\n if (!cb?.write || typeof ClipboardItem === 'undefined') return;\n const rejected = new Set<string>();\n for (const [mime, text] of entries) {\n if (typeof text !== 'string') text.catch(() => { rejected.add(mime); });\n }\n const wireMime = (mime: string) => (WELL_KNOWN_CLIPBOARD_MIMES.has(mime) ? mime : `web ${mime}`);\n const toItem = (fs: Flavor[]) => new ClipboardItem(Object.fromEntries(\n fs.map(([mime, text]) => {\n const wire = wireMime(mime);\n const blob = (t: string) => new Blob([t], { type: wire });\n if (typeof text === 'string') return [wire, blob(text)];\n const promised = text.then(blob);\n // Chromium leaves a ClipboardItem's rejected promise unhandled.\n promised.catch(() => {});\n return [wire, promised];\n }),\n ));\n // Writes `fs`, dropping flavors whose promise rejected and retrying the\n // rest. Returns the last error, or null once a write lands.\n const writeLive = async (fs: Flavor[]): Promise<unknown> => {\n let live = fs;\n for (;;) {\n try {\n await cb.write([toItem(live)]);\n return null;\n } catch (err) {\n const next = live.filter(([mime]) => !rejected.has(mime));\n if (next.length === live.length || next.length === 0) return err;\n live = next;\n }\n }\n };\n if (await writeLive(entries) === null) return;\n const standard = entries.filter(([mime]) => WELL_KNOWN_CLIPBOARD_MIMES.has(mime) && !rejected.has(mime));\n if (standard.length === 0) { dwarn('clipboard', 'OS write failed; no standard flavors to fall back to'); return; }\n const err = await writeLive(standard);\n if (err !== null) dwarn('clipboard', `OS clipboard write failed twice — copy stays in-memory only: ${String(err)}`);\n}\n\ntype Flavor = [mime: string, text: string | Promise<string>];\n"],"mappings":";;;;;;;;AAwDA,IAAMA,IAA2B,EAAE,OAAO,CAAC,EAAE;AAG7C,SAAgBC,EACd,GACA,GACuB;CACvB,IAAM,EACJ,iBAAc,YAAS,mBAAgB,gBAAa,SAAS,iBAAc,mBAAgB,oBACzFC,GAKEC,IAAaC,EAAkB,GAC/BC,IAAwBC,KAAgBH,GAAY,cACpDI,IAAeC,EAA0BR,CAAK,GAE9CS,IAAaC,EAAUC,CAAO,GAC9BC,IAAUF,EAAU;EACxB;EAAc;EAAS;EAAgB;EAAY,cAAcL;EAAuB;EACxF;CACF,CAAC;CA8CD,OAAO;EAAE,MA5CIQ,QAAkB;GAC7B,IAAMC,IAAMF,EAAQ,QAAQ,aAAa;GACzC,IAAIE,EAAI,WAAW,GAAG;GACtB,IAAMC,IAAON,EAAW,QAAQ;GAChC,IAAI,CAACM,GAAM;GACX,EAAa,UAAUA,EAAKD,CAAG;GAO/B,IAAIE,IAAmC;GACvC,IAAI;IACF,IAAUJ,EAAQ,QAAQ,iBAAiBL,EAAa,OAAO,KAC1DU,EAAeV,EAAa,SAASK,EAAQ,QAAQ,YAAY;GACxE,SAASM,GAAK;IACZ,EAAM,aAAa,8CAA8C,OAAOA,CAAG,GAAG;GAChF;GACA,AAAIF,KAASG,EAAsBH,CAAO;EAC5C,GAAG,CAACP,GAAYG,CAAO,CAwBd;EAAM,OAtBDC,QAAkB;GAC9B,IAAMO,IAAKb,EAAa;GACxB,IAAIa,EAAG,MAAM,WAAW,GAAG;GAC3B,IAAMC,IAAIZ,EAAW,SACfa,IAASC,EAAiBF,GAAGD,GAAI;IACrC,kBAAkBR,EAAQ,QAAQ,aAAa;IAC/C,WAAWA,EAAQ,QAAQ,eAAe;IAC1C,WAAWA,EAAQ,QAAQ;GAC7B,CAAC;GACD,AAAKU,MACLE,EAAmBH,GAAGC,EAAO,KAAKV,EAAQ,QAAQ,UAAU,GAM5D,EAAa,UAAU,EAAE,OAAOU,EAAO,QAAQ,GAC/CV,EAAQ,QAAQ,UAAUU,EAAO,MAAkB;EACrD,GAAG,CAACb,GAAYG,CAAO,CAIR;EAAO,SAFNC,QAAkBN,EAAa,QAAQ,MAAM,WAAW,GAAG,CAAC,CAEtD;CAAQ;AAChC;AAEA,SAASU,EAAe,GAA6B,GAAuC;CAC1F,IAAMQ,IAAOC,EAAyBC,EAAS,OAAOC,CAAQ;CAC9D,OAAO;GAAGC,IAAwBJ;EAAM,cAAcA;CAAK;AAC7D;AAMA,IAAMK,oBAA6B,IAAI,IAAI;CAAC;CAAc;CAAa;AAAW,CAAC;AAUnF,eAAsBX,EAAiB,GAA0C;CAC/E,IAAMY,IAAU,OAAO,QAAQf,CAAO;CACtC,IAAIe,EAAQ,WAAW,GAAG;CAC1B,IAAMX,IAAK,OAAO,YAAc,MAAc,UAAU,YAAY,KAAA;CACpE,IAAI,CAACA,GAAI,SAAS,OAAO,gBAAkB,KAAa;CACxD,IAAMY,oBAAW,IAAI,IAAY;CACjC,KAAK,IAAM,CAACC,GAAMR,MAASM,GACzB,AAAI,OAAON,KAAS,YAAUA,EAAK,YAAY;EAAE,EAAS,IAAIQ,CAAI;CAAG,CAAC;CAExE,IAAMC,KAAY,MAAkBJ,EAA2B,IAAIG,CAAI,IAAIA,IAAO,OAAOA,KACnFE,KAAU,MAAiB,IAAI,cAAc,OAAO,YACxDC,EAAG,KAAK,CAACH,GAAMR,OAAU;EACvB,IAAMY,IAAOH,EAASD,CAAI,GACpBK,KAAQ,MAAc,IAAI,KAAK,CAACC,CAAC,GAAG,EAAE,MAAMF,EAAK,CAAC;EACxD,IAAI,OAAOZ,KAAS,UAAU,OAAO,CAACY,GAAMC,EAAKb,CAAI,CAAC;EACtD,IAAMe,IAAWf,EAAK,KAAKa,CAAI;EAG/B,OADAE,EAAS,YAAY,CAAC,CAAC,GAChB,CAACH,GAAMG,CAAQ;CACxB,CAAC,CACH,CAAC,GAGKC,IAAY,OAAO,MAAmC;EAC1D,IAAIC,IAAON;EACX,SACE,IAAI;GAEF,OADA,MAAMhB,EAAG,MAAM,CAACe,EAAOO,CAAI,CAAC,CAAC,GACtB;EACT,SAASxB,GAAK;GACZ,IAAMyB,IAAOD,EAAK,QAAQ,CAACT,OAAU,CAACD,EAAS,IAAIC,CAAI,CAAC;GACxD,IAAIU,EAAK,WAAWD,EAAK,UAAUC,EAAK,WAAW,GAAG,OAAOzB;GAC7D,IAAOyB;EACT;CAEJ;CACA,IAAI,MAAMF,EAAUV,CAAO,MAAM,MAAM;CACvC,IAAMa,IAAWb,EAAQ,QAAQ,CAACE,OAAUH,EAA2B,IAAIG,CAAI,KAAK,CAACD,EAAS,IAAIC,CAAI,CAAC;CACvG,IAAIW,EAAS,WAAW,GAAG;EAAE,EAAM,aAAa,sDAAsD;EAAG;CAAQ;CACjH,IAAM1B,IAAM,MAAMuB,EAAUG,CAAQ;CACpC,AAAI1B,MAAQ,QAAM2B,EAAM,aAAa,gEAAgE,OAAO3B,CAAG,GAAG;AACpH"}
1
+ {"version":3,"file":"clipboardOps.js","names":["EMPTY","useClipboardOps","options","pointerCtx","usePointerContext","effectiveGetDropPoint","getDropPoint","clipboardRef","useRef","adapterRef","useLatest","adapter","optsRef","useCallback","ids","snap","flavors","defaultFlavors","err","writeOsClipboard","cb","a","result","materializePaste","dispatchApplyBatch","text","buildWeaselClipboardText","snapshot","replacer","WEASEL_CLIPBOARD_MIME","WELL_KNOWN_CLIPBOARD_MIMES","entries","rejected","mime","wireMime","toItem","fs","wire","blob","t","promised","writeLive","live","next","standard","dwarn"],"sources":["../../../../src/interactions/actions/clipboard/clipboardOps.ts"],"sourcesContent":["import { useCallback, useRef } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport type { NodeId } from 'core/scene/types';\nimport { dispatchApplyBatch } from 'core/applyOps';\nimport type { InsertAdapter, PasteOmission } from 'core/adapters/types';\nimport type { ClipboardSnapshot } from './types';\nimport { usePointerContext } from '@weasel-js/routing/react';\nimport { dwarn } from 'debug/flag';\nimport { materializePaste } from './materializePaste';\nimport { WEASEL_CLIPBOARD_MIME, buildWeaselClipboardText } from './wireFormat';\n\ntype Replacer = (key: string, value: unknown) => unknown;\n\n/** Options for `useClipboardOps`. */\nexport interface UseClipboardOpsOptions {\n /** How the hook reads \"current selection\" for copy. The kit doesn't assume\n * a global selection store; each consumer wires this. */\n getSelection: () => NodeId[];\n /** Called after a successful paste with the ids of the newly inserted objects. */\n onPaste?: (newIds: NodeId[]) => void;\n /** Called when a paste left copied nodes out, with each one and the reason\n * — an edge whose endpoints were not copied with it, say. Also called for\n * a paste that made nothing. */\n onPasteOmitted?: (omitted: PasteOmission[]) => void;\n /** Label for the history entry produced by paste. Default 'Paste'. */\n pasteLabel?: string;\n /** Pulled once per paste() call. When non-null, threaded to commitPaste\n * as `ctx.dropPoint`; adapters typically use it as the cluster origin\n * (ignoring `offset`). When null/undefined, the hook falls back to the\n * existing cascade-offset behavior. */\n getDropPoint?: () => { worldX: number; worldY: number } | null;\n /** Produce the OS-clipboard flavor map for a copied snapshot. Keys are MIME\n * types, values the serialized payload. The kit default emits\n * `application/x-weasel-clipboard+json` plus `text/plain` carrying the\n * same JSON. Apps override to add richer flavors (e.g. real SVG) or to\n * replace the text flavor. Return an empty object to skip the OS write\n * entirely. A value may be a promise — an SVG flavor waiting on\n * `warmSvg`, say: the write is still issued inside the copy gesture and\n * the clipboard takes the text when it resolves. The producer itself runs\n * synchronously, so it reads the selection as it stood at the copy. */\n produceFlavors?: (snapshot: ClipboardSnapshot) => ClipboardFlavors;\n /** Replacer for the kit-default JSON flavor (typed arrays etc.). Ignored\n * when `produceFlavors` is supplied. */\n jsonReplacer?: Replacer;\n}\n\n/** MIME type to payload, as `produceFlavors` returns it. */\nexport type ClipboardFlavors = Record<string, string | Promise<string>>;\n\n/** Return shape of `useClipboardOps`: imperative `copy`, `paste`, and `isEmpty` functions. */\nexport interface UseClipboardOpsReturn {\n copy(): void;\n paste(): void;\n isEmpty(): boolean;\n}\n\nconst EMPTY: ClipboardSnapshot = { items: [] };\n\n/** In-memory copy/paste of selections via `InsertAdapter.snapshotSelection` / `commitPaste`. */\nexport function useClipboardOps<TNode extends { id: string }>(\n adapter: InsertAdapter<TNode>,\n options: UseClipboardOpsOptions,\n): UseClipboardOpsReturn {\n const {\n getSelection, onPaste, onPasteOmitted, pasteLabel = 'Paste', getDropPoint, produceFlavors, jsonReplacer,\n } = options;\n // Fall back to the ambient pointer context (auto-published by SceneCanvas)\n // when the caller didn't supply an explicit `getDropPoint`. Null context\n // (no provider in scope) and no caller-supplied thunk together mean\n // \"no drop point\" — paste uses the cascade offset instead.\n const pointerCtx = usePointerContext();\n const effectiveGetDropPoint = getDropPoint ?? pointerCtx?.getDropPoint;\n const clipboardRef = useRef<ClipboardSnapshot>(EMPTY);\n // Keep callbacks stable across renders.\n const adapterRef = useLatest(adapter);\n const optsRef = useLatest({\n getSelection, onPaste, onPasteOmitted, pasteLabel, getDropPoint: effectiveGetDropPoint, produceFlavors,\n jsonReplacer,\n });\n\n const copy = useCallback(() => {\n const ids = optsRef.current.getSelection();\n if (ids.length === 0) return;\n const snap = adapterRef.current.snapshotSelection;\n if (!snap) return;\n clipboardRef.current = snap(ids);\n // Best-effort OS write. Never blocks or throws — the in-memory ref is\n // already set, and OS clipboard support varies (custom formats are\n // Chromium-only via the \"web \" prefix; jsdom/non-secure contexts have\n // no API at all). The flavor producer itself is untrusted consumer code\n // (`produceFlavors`), so guard its call too — a throwing producer must\n // not break `copy()`, it just skips the OS write.\n let flavors: ClipboardFlavors | null = null;\n try {\n flavors = optsRef.current.produceFlavors?.(clipboardRef.current)\n ?? defaultFlavors(clipboardRef.current, optsRef.current.jsonReplacer);\n } catch (err) {\n dwarn('clipboard', `flavor producer threw — skipping OS write: ${String(err)}`);\n }\n if (flavors) void writeOsClipboard(flavors);\n }, [adapterRef, optsRef]);\n\n const paste = useCallback(() => {\n const cb = clipboardRef.current;\n if (cb.items.length === 0) return;\n const a = adapterRef.current;\n const result = materializePaste(a, cb, {\n currentSelection: optsRef.current.getSelection(),\n dropPoint: optsRef.current.getDropPoint?.(),\n onOmitted: optsRef.current.onPasteOmitted,\n });\n if (!result) return;\n dispatchApplyBatch(a, result.ops, optsRef.current.pasteLabel);\n // Use the just-created objects as the next cascade source. Re-snapshotting\n // via `adapter.snapshotSelection(newIds)` would read adapter state, but\n // React-state adapters haven't flushed yet — `itemsRef.current` still\n // points at the pre-insert array, so the snapshot would come back empty\n // and the next paste would no-op.\n clipboardRef.current = { items: result.created };\n optsRef.current.onPaste?.(result.newIds as NodeId[]);\n }, [adapterRef, optsRef]);\n\n const isEmpty = useCallback(() => clipboardRef.current.items.length === 0, []);\n\n return { copy, paste, isEmpty };\n}\n\nfunction defaultFlavors(snapshot: ClipboardSnapshot, replacer?: Replacer): ClipboardFlavors {\n const text = buildWeaselClipboardText(snapshot.items, replacer);\n return { [WEASEL_CLIPBOARD_MIME]: text, 'text/plain': text };\n}\n\n/** MIME types the async Clipboard API accepts unprefixed. Every other type\n * (including our own custom MIME, and app-supplied flavors like\n * `image/svg+xml`) must carry Chromium's `web ` prefix or `ClipboardItem`'s\n * constructor throws. */\nconst WELL_KNOWN_CLIPBOARD_MIMES = new Set(['text/plain', 'text/html', 'image/png']);\n\n/** Degradation ladder: full map (every non-well-known MIME web-prefixed) →\n * the same minus any promised flavor that rejected → well-known-only → give\n * up with a dwarn. Chromium writes nothing when one flavor rejects, so a\n * rejection costs only that flavor, never the clipboard's previous content\n * half-overwritten.\n * @internal test seam — exported so unit tests can await the fire-and-forget\n * write directly; tests should still exercise this at least once through\n * the public `copy()` (see clipboardOps.test.tsx). */\nexport async function writeOsClipboard(flavors: ClipboardFlavors): Promise<void> {\n const entries = Object.entries(flavors);\n if (entries.length === 0) return;\n const cb = typeof navigator !== 'undefined' ? navigator.clipboard : undefined;\n if (!cb?.write || typeof ClipboardItem === 'undefined') return;\n const rejected = new Set<string>();\n for (const [mime, text] of entries) {\n if (typeof text !== 'string') text.catch(() => { rejected.add(mime); });\n }\n const wireMime = (mime: string) => (WELL_KNOWN_CLIPBOARD_MIMES.has(mime) ? mime : `web ${mime}`);\n const toItem = (fs: Flavor[]) => new ClipboardItem(Object.fromEntries(\n fs.map(([mime, text]) => {\n const wire = wireMime(mime);\n const blob = (t: string) => new Blob([t], { type: wire });\n if (typeof text === 'string') return [wire, blob(text)];\n const promised = text.then(blob);\n // Chromium leaves a ClipboardItem's rejected promise unhandled.\n promised.catch(() => {});\n return [wire, promised];\n }),\n ));\n // Writes `fs`, dropping flavors whose promise rejected and retrying the\n // rest. Returns the last error, or null once a write lands.\n const writeLive = async (fs: Flavor[]): Promise<unknown> => {\n let live = fs;\n for (;;) {\n try {\n await cb.write([toItem(live)]);\n return null;\n } catch (err) {\n const next = live.filter(([mime]) => !rejected.has(mime));\n if (next.length === live.length || next.length === 0) return err;\n live = next;\n }\n }\n };\n if (await writeLive(entries) === null) return;\n const standard = entries.filter(([mime]) => WELL_KNOWN_CLIPBOARD_MIMES.has(mime) && !rejected.has(mime));\n if (standard.length === 0) { dwarn('clipboard', 'OS write failed; no standard flavors to fall back to'); return; }\n const err = await writeLive(standard);\n if (err !== null) dwarn('clipboard', `OS clipboard write failed twice — copy stays in-memory only: ${String(err)}`);\n}\n\ntype Flavor = [mime: string, text: string | Promise<string>];\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"wireFormat.js","names":["WEASEL_CLIPBOARD_MIME","WEASEL_CLIPBOARD_MIME_WEB","buildWeaselClipboardText","items","replacer","sniffWeaselClipboardText","text","parsed","SVG_OPEN_TAG","embedWeaselMetadataInSvg","open","svgText","dwarn","cdata","payloadText","at","extractWeaselClipboardFromSvg","block","inner","payload","m","parseWeaselClipboardText","reviver","err"],"sources":["../../../../src/interactions/actions/clipboard/wireFormat.ts"],"sourcesContent":["import { dwarn } from 'debug/flag';\n\n/** MIME type the kit writes its full-fidelity clipboard payload under, so a\n * copy/paste between two weasel canvases round-trips scene nodes rather than\n * the SVG or text flavors other apps read. */\nexport const WEASEL_CLIPBOARD_MIME = 'application/x-weasel-clipboard+json';\n/** Chromium's async-clipboard spelling for custom formats. */\nexport const WEASEL_CLIPBOARD_MIME_WEB = `web ${WEASEL_CLIPBOARD_MIME}`;\n\ninterface WeaselClipboardPayload { weaselClipboard: 1; nodes: unknown[] }\n\ntype Replacer = (key: string, value: unknown) => unknown;\ntype Reviver = (key: string, value: unknown) => unknown;\n\n/** Serialize snapshot items into the versioned wire text.\n *\n * JSON drops a function-valued field (a container's `clipFromPose`, a\n * node's `derivePath`). A scene adapter's snapshot also carries each one's\n * `SceneRegistry` key (`clipFromPoseKey`, `derivePathKey`, …), which does\n * cross, and its paste restores the function from the pasting scene's\n * registry. A function that is not registered does not survive. */\nexport function buildWeaselClipboardText(items: unknown[], replacer?: Replacer): string {\n const payload: WeaselClipboardPayload = { weaselClipboard: 1, nodes: items };\n return JSON.stringify(payload, replacer as Parameters<typeof JSON.stringify>[1]);\n}\n\n/** Cheap check: could this text be a weasel clipboard payload? Substring\n * pre-check, then a guarded parse + marker/version test. */\nexport function sniffWeaselClipboardText(text: string): boolean {\n if (!text.includes('\"weaselClipboard\"')) return false;\n try {\n const parsed = JSON.parse(text) as Partial<WeaselClipboardPayload> | null;\n return !!parsed && parsed.weaselClipboard === 1;\n } catch {\n return false;\n }\n}\n\n// Opening `<svg ...>` tag of a serialized document. `[^>]*` is safe for OUR\n// serializer's output (attribute values are XML-escaped, so no raw `>` can\n// appear inside the tag) — see embedWeaselMetadataInSvg's contract note.\nconst SVG_OPEN_TAG = /<svg(?:\\s[^>]*)?>/i;\n\n/**\n * Embed a weasel clipboard payload in an SVG document as a `<metadata>`\n * child of the root — legal SVG 1.1, ignored by external tools — so one\n * `text/plain` flavor serves both audiences: external tools parse the SVG,\n * weasel extracts the JSON for full fidelity on draw→draw DOM paste.\n *\n * The payload rides in CDATA so JSON's `<` / `&` need no entity escaping; a\n * literal `]]>` inside the payload is split across CDATA sections\n * (`]]]]><![CDATA[>`), which {@link extractWeaselClipboardFromSvg} rejoins.\n *\n * Intended for OUR serializer's output only (`serializeSvg` — single\n * `<svg ...>` open tag, XML-escaped attributes). When no open tag is found\n * the input is returned unchanged with a debug warning.\n */\nexport function embedWeaselMetadataInSvg(svgText: string, payloadText: string): string {\n const open = SVG_OPEN_TAG.exec(svgText);\n if (!open) {\n dwarn('clipboard', 'embedWeaselMetadataInSvg: no <svg ...> open tag found — returning input unchanged');\n return svgText;\n }\n const cdata = `<![CDATA[${payloadText.replaceAll(']]>', ']]]]><![CDATA[>')}]]>`;\n const at = open.index + open[0].length;\n return `${svgText.slice(0, at)}<metadata>${cdata}</metadata>${svgText.slice(at)}`;\n}\n\n/**\n * Recover an embedded weasel clipboard payload from SVG text: read the first\n * `<metadata>` block, rejoin its CDATA sections (concatenation restores the\n * `]]>` split by {@link embedWeaselMetadataInSvg}; plain non-CDATA content\n * passes through as-is), and return the payload text iff it sniffs as the\n * weasel wire format — else null (external/non-weasel metadata declines).\n *\n * A text scan, not an XML parse — the payload is small and ours.\n */\nexport function extractWeaselClipboardFromSvg(svgText: string): string | null {\n const block = /<metadata(?:\\s[^>]*)?>([\\s\\S]*?)<\\/metadata>/i.exec(svgText);\n if (!block) return null;\n const inner = block[1];\n const payload = inner.includes('<![CDATA[')\n ? Array.from(inner.matchAll(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/g), (m) => m[1]).join('')\n : inner;\n return sniffWeaselClipboardText(payload) ? payload : null;\n}\n\n/** Parse wire text to snapshot items, or null when malformed/mismatched\n * (callers decline to the next content handler). */\nexport function parseWeaselClipboardText(text: string, reviver?: Reviver): unknown[] | null {\n try {\n const parsed = JSON.parse(text, reviver as Parameters<typeof JSON.parse>[1]) as\n Partial<WeaselClipboardPayload> | null;\n if (!parsed || parsed.weaselClipboard !== 1 || !Array.isArray(parsed.nodes)) return null;\n return parsed.nodes;\n } catch (err) {\n dwarn('clipboard', `weasel payload failed to parse: ${String(err)}`);\n return null;\n }\n}\n"],"mappings":";;AAKA,IAAaA,IAAwB,uCAExBC,IAA4B,OAAOD;AAchD,SAAgBE,EAAyB,GAAkB,GAA6B;CAEtF,OAAO,KAAK,UAAU;EADoB,iBAAiB;EAAG,OAAOC;CAC/C,GAASC,CAAgD;AACjF;AAIA,SAAgBC,EAAyB,GAAuB;CAC9D,IAAI,CAACC,EAAK,SAAS,qBAAmB,GAAG,OAAO;CAChD,IAAI;EACF,IAAMC,IAAS,KAAK,MAAMD,CAAI;EAC9B,OAAO,CAAC,CAACC,KAAUA,EAAO,oBAAoB;CAChD,QAAQ;EACN,OAAO;CACT;AACF;AAKA,IAAMC,IAAe;AAgBrB,SAAgBC,EAAyB,GAAiB,GAA6B;CACrF,IAAMC,IAAOF,EAAa,KAAKG,CAAO;CACtC,IAAI,CAACD,GAEH,OADAE,EAAM,aAAa,mFAAmF,GAC/FD;CAET,IAAME,IAAQ,YAAYC,EAAY,WAAW,OAAO,iBAAiB,EAAE,MACrEC,IAAKL,EAAK,QAAQA,EAAK,EAAE,CAAC;CAChC,OAAO,GAAGC,EAAQ,MAAM,GAAGI,CAAE,EAAE,YAAYF,EAAM,aAAaF,EAAQ,MAAMI,CAAE;AAChF;AAWA,SAAgBC,EAA8B,GAAgC;CAC5E,IAAMC,IAAQ,gDAAgD,KAAKN,CAAO;CAC1E,IAAI,CAACM,GAAO,OAAO;CACnB,IAAMC,IAAQD,EAAM,IACdE,IAAUD,EAAM,SAAS,WAAW,IACtC,MAAM,KAAKA,EAAM,SAAS,6BAA6B,IAAI,MAAME,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAC9EF;CACJ,OAAOb,EAAyBc,CAAO,IAAIA,IAAU;AACvD;AAIA,SAAgBE,EAAyB,GAAc,GAAqC;CAC1F,IAAI;EACF,IAAMd,IAAS,KAAK,MAAMD,GAAMgB,CAA2C;EAG3E,OADI,CAACf,KAAUA,EAAO,oBAAoB,KAAK,CAAC,MAAM,QAAQA,EAAO,KAAK,IAAU,OAC7EA,EAAO;CAChB,SAASgB,GAAK;EAEZ,OADAX,EAAM,aAAa,mCAAmC,OAAOW,CAAG,GAAG,GAC5D;CACT;AACF"}
1
+ {"version":3,"file":"wireFormat.js","names":["WEASEL_CLIPBOARD_MIME","WEASEL_CLIPBOARD_MIME_WEB","buildWeaselClipboardText","items","replacer","sniffWeaselClipboardText","text","parsed","SVG_OPEN_TAG","embedWeaselMetadataInSvg","open","svgText","dwarn","cdata","payloadText","at","extractWeaselClipboardFromSvg","block","inner","payload","m","parseWeaselClipboardText","reviver","err"],"sources":["../../../../src/interactions/actions/clipboard/wireFormat.ts"],"sourcesContent":["import { dwarn } from 'debug/flag';\n\n/** MIME type the kit writes its full-fidelity clipboard payload under, so a\n * copy/paste between two weasel canvases round-trips scene nodes rather than\n * the SVG or text flavors other apps read. */\nexport const WEASEL_CLIPBOARD_MIME = 'application/x-weasel-clipboard+json';\n/** Chromium's async-clipboard spelling for custom formats. */\nexport const WEASEL_CLIPBOARD_MIME_WEB = `web ${WEASEL_CLIPBOARD_MIME}`;\n\ninterface WeaselClipboardPayload { weaselClipboard: 1; nodes: unknown[] }\n\ntype Replacer = (key: string, value: unknown) => unknown;\ntype Reviver = (key: string, value: unknown) => unknown;\n\n/** Serialize snapshot items into the versioned wire text.\n *\n * JSON drops a function-valued field (a container's `clipFromPose`, a\n * node's `derivePath`). A scene adapter's snapshot also carries each one's\n * `SceneRegistry` key (`clipFromPoseKey`, `derivePathKey`, …), which does\n * cross, and its paste restores the function from the pasting scene's\n * registry. A function that is not registered does not survive. */\nexport function buildWeaselClipboardText(items: unknown[], replacer?: Replacer): string {\n const payload: WeaselClipboardPayload = { weaselClipboard: 1, nodes: items };\n return JSON.stringify(payload, replacer as Parameters<typeof JSON.stringify>[1]);\n}\n\n/** Cheap check: could this text be a weasel clipboard payload? Substring\n * pre-check, then a guarded parse + marker/version test. */\nexport function sniffWeaselClipboardText(text: string): boolean {\n if (!text.includes('\"weaselClipboard\"')) return false;\n try {\n const parsed = JSON.parse(text) as Partial<WeaselClipboardPayload> | null;\n return !!parsed && parsed.weaselClipboard === 1;\n } catch {\n return false;\n }\n}\n\n// `[^>]*` is safe for OUR serializer's output only: attribute values are\n// XML-escaped, so no raw `>` can appear inside the tag.\nconst SVG_OPEN_TAG = /<svg(?:\\s[^>]*)?>/i;\n\n/**\n * Embed a weasel clipboard payload in an SVG document as a `<metadata>`\n * child of the root — legal SVG 1.1, ignored by external tools — so one\n * `text/plain` flavor serves both audiences.\n *\n * Intended for OUR serializer's output only (`serializeSvg` — single\n * `<svg ...>` open tag, XML-escaped attributes). When no open tag is found\n * the input is returned unchanged with a debug warning.\n */\nexport function embedWeaselMetadataInSvg(svgText: string, payloadText: string): string {\n const open = SVG_OPEN_TAG.exec(svgText);\n if (!open) {\n dwarn('clipboard', 'embedWeaselMetadataInSvg: no <svg ...> open tag found — returning input unchanged');\n return svgText;\n }\n const cdata = `<![CDATA[${payloadText.replaceAll(']]>', ']]]]><![CDATA[>')}]]>`;\n const at = open.index + open[0].length;\n return `${svgText.slice(0, at)}<metadata>${cdata}</metadata>${svgText.slice(at)}`;\n}\n\n/**\n * The weasel clipboard payload embedded in SVG text by\n * {@link embedWeaselMetadataInSvg}, or null when the first `<metadata>` block\n * is absent or not the weasel wire format. A text scan, not an XML parse.\n */\nexport function extractWeaselClipboardFromSvg(svgText: string): string | null {\n const block = /<metadata(?:\\s[^>]*)?>([\\s\\S]*?)<\\/metadata>/i.exec(svgText);\n if (!block) return null;\n const inner = block[1];\n const payload = inner.includes('<![CDATA[')\n ? Array.from(inner.matchAll(/<!\\[CDATA\\[([\\s\\S]*?)\\]\\]>/g), (m) => m[1]).join('')\n : inner;\n return sniffWeaselClipboardText(payload) ? payload : null;\n}\n\n/** Parse wire text to snapshot items, or null when malformed/mismatched\n * (callers decline to the next content handler). */\nexport function parseWeaselClipboardText(text: string, reviver?: Reviver): unknown[] | null {\n try {\n const parsed = JSON.parse(text, reviver as Parameters<typeof JSON.parse>[1]) as\n Partial<WeaselClipboardPayload> | null;\n if (!parsed || parsed.weaselClipboard !== 1 || !Array.isArray(parsed.nodes)) return null;\n return parsed.nodes;\n } catch (err) {\n dwarn('clipboard', `weasel payload failed to parse: ${String(err)}`);\n return null;\n }\n}\n"],"mappings":";;AAKA,IAAaA,IAAwB,uCAExBC,IAA4B,OAAOD;AAchD,SAAgBE,EAAyB,GAAkB,GAA6B;CAEtF,OAAO,KAAK,UAAU;EADoB,iBAAiB;EAAG,OAAOC;CAC/C,GAASC,CAAgD;AACjF;AAIA,SAAgBC,EAAyB,GAAuB;CAC9D,IAAI,CAACC,EAAK,SAAS,qBAAmB,GAAG,OAAO;CAChD,IAAI;EACF,IAAMC,IAAS,KAAK,MAAMD,CAAI;EAC9B,OAAO,CAAC,CAACC,KAAUA,EAAO,oBAAoB;CAChD,QAAQ;EACN,OAAO;CACT;AACF;AAIA,IAAMC,IAAe;AAWrB,SAAgBC,EAAyB,GAAiB,GAA6B;CACrF,IAAMC,IAAOF,EAAa,KAAKG,CAAO;CACtC,IAAI,CAACD,GAEH,OADAE,EAAM,aAAa,mFAAmF,GAC/FD;CAET,IAAME,IAAQ,YAAYC,EAAY,WAAW,OAAO,iBAAiB,EAAE,MACrEC,IAAKL,EAAK,QAAQA,EAAK,EAAE,CAAC;CAChC,OAAO,GAAGC,EAAQ,MAAM,GAAGI,CAAE,EAAE,YAAYF,EAAM,aAAaF,EAAQ,MAAMI,CAAE;AAChF;AAOA,SAAgBC,EAA8B,GAAgC;CAC5E,IAAMC,IAAQ,gDAAgD,KAAKN,CAAO;CAC1E,IAAI,CAACM,GAAO,OAAO;CACnB,IAAMC,IAAQD,EAAM,IACdE,IAAUD,EAAM,SAAS,WAAW,IACtC,MAAM,KAAKA,EAAM,SAAS,6BAA6B,IAAI,MAAME,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAC9EF;CACJ,OAAOb,EAAyBc,CAAO,IAAIA,IAAU;AACvD;AAIA,SAAgBE,EAAyB,GAAc,GAAqC;CAC1F,IAAI;EACF,IAAMd,IAAS,KAAK,MAAMD,GAAMgB,CAA2C;EAG3E,OADI,CAACf,KAAUA,EAAO,oBAAoB,KAAK,CAAC,MAAM,QAAQA,EAAO,KAAK,IAAU,OAC7EA,EAAO;CAChB,SAASgB,GAAK;EAEZ,OADAX,EAAM,aAAa,mCAAmC,OAAOW,CAAG,GAAG,GAC5D;CACT;AACF"}