@weasel-js/core 1.9.3 → 1.9.4

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 (542) hide show
  1. package/CHANGELOG.md +356 -0
  2. package/README.md +2 -2
  3. package/dist/WeaselProvider.js +5 -5
  4. package/dist/affordances/composeAffordanceLayer.js +10 -20
  5. package/dist/affordances/composeAffordanceLayer.js.map +1 -1
  6. package/dist/affordances/cornerResize.js +25 -17
  7. package/dist/affordances/cornerResize.js.map +1 -1
  8. package/dist/affordances/hitAffordanceRegions.js +27 -20
  9. package/dist/affordances/hitAffordanceRegions.js.map +1 -1
  10. package/dist/affordances/rotationHandle.js +18 -18
  11. package/dist/affordances/rotationHandle.js.map +1 -1
  12. package/dist/animation/behaviors/momentum.js +93 -55
  13. package/dist/animation/behaviors/momentum.js.map +1 -1
  14. package/dist/animation/loop.js +10 -12
  15. package/dist/animation/loop.js.map +1 -1
  16. package/dist/animation/reflow.js +8 -8
  17. package/dist/animation/reflow.js.map +1 -1
  18. package/dist/animation/stagger.js +64 -56
  19. package/dist/animation/stagger.js.map +1 -1
  20. package/dist/animation/timeline/booking.js +62 -54
  21. package/dist/animation/timeline/booking.js.map +1 -1
  22. package/dist/animation/timeline/createTimeline.js +85 -76
  23. package/dist/animation/timeline/createTimeline.js.map +1 -1
  24. package/dist/animation/timeline/sampleTrack.js +13 -5
  25. package/dist/animation/timeline/sampleTrack.js.map +1 -1
  26. package/dist/animation/useAnimator.js +45 -35
  27. package/dist/animation/useAnimator.js.map +1 -1
  28. package/dist/animation/wrappers/animateLifecycle.js +31 -24
  29. package/dist/animation/wrappers/animateLifecycle.js.map +1 -1
  30. package/dist/animation/wrappers/animateOnSetPose.js +28 -26
  31. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -1
  32. package/dist/animation/wrappers/instantPose.js +13 -0
  33. package/dist/animation/wrappers/instantPose.js.map +1 -0
  34. package/dist/{poseDescriptor-D-OH-tu5.d.ts → autoPoseDescriptor-Ct7yqivU.d.ts} +28 -3
  35. package/dist/barrel/chrome.js +16 -0
  36. package/dist/barrel/input.js +19 -0
  37. package/dist/barrel/interactions.js +42 -0
  38. package/dist/barrel/paint.js +18 -0
  39. package/dist/barrel/paths.js +19 -0
  40. package/dist/barrel/renderer.js +20 -0
  41. package/dist/barrel/routing.js +51 -0
  42. package/dist/barrel/text.js +18 -0
  43. package/dist/barrel/viewport.js +52 -0
  44. package/dist/builtins-DPcdghtB.d.ts +1223 -0
  45. package/dist/canvas/Canvas.js +363 -448
  46. package/dist/canvas/Canvas.js.map +1 -1
  47. package/dist/canvas/CanvasView.js +164 -165
  48. package/dist/canvas/CanvasView.js.map +1 -1
  49. package/dist/canvas/CursorCoordsHud.js +37 -32
  50. package/dist/canvas/CursorCoordsHud.js.map +1 -1
  51. package/dist/canvas/DrawCanvas.js +49 -43
  52. package/dist/canvas/DrawCanvas.js.map +1 -1
  53. package/dist/canvas/MinimapCanvas.js +26 -25
  54. package/dist/canvas/MinimapCanvas.js.map +1 -1
  55. package/dist/canvas/NodeShape.js +59 -377
  56. package/dist/canvas/NodeShape.js.map +1 -1
  57. package/dist/canvas/PickHud.js +50 -47
  58. package/dist/canvas/PickHud.js.map +1 -1
  59. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js +167 -0
  60. package/dist/canvas/SceneCanvas/GestureDispatcherMounter.js.map +1 -0
  61. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +13 -13
  62. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js +67 -0
  63. package/dist/canvas/SceneCanvas/StandardActionsRegistrar.js.map +1 -0
  64. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js +16 -0
  65. package/dist/canvas/SceneCanvas/ToolKeybindingsMounter.js.map +1 -0
  66. package/dist/canvas/SceneCanvas/coordTrace.js +10 -0
  67. package/dist/canvas/SceneCanvas/coordTrace.js.map +1 -0
  68. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +112 -70
  69. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -1
  70. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +9 -8
  71. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  72. package/dist/canvas/SceneCanvas/features.js +1 -0
  73. package/dist/canvas/SceneCanvas/features.js.map +1 -1
  74. package/dist/canvas/SceneCanvas/isDev.js +12 -0
  75. package/dist/canvas/SceneCanvas/isDev.js.map +1 -0
  76. package/dist/canvas/SceneCanvas/poseGeometry.js +29 -28
  77. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -1
  78. package/dist/canvas/SceneCanvas/poseRegistrars.js +13 -0
  79. package/dist/canvas/SceneCanvas/poseRegistrars.js.map +1 -0
  80. package/dist/canvas/SceneCanvas/props.js +38 -0
  81. package/dist/canvas/SceneCanvas/props.js.map +1 -0
  82. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +21 -62
  83. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -1
  84. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -1
  85. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +46 -48
  86. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  87. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +33 -33
  88. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  89. package/dist/canvas/SceneCanvas.js +534 -788
  90. package/dist/canvas/SceneCanvas.js.map +1 -1
  91. package/dist/canvas/SceneViewCanvas.js +45 -43
  92. package/dist/canvas/SceneViewCanvas.js.map +1 -1
  93. package/dist/canvas/buildSceneLayer.js +91 -0
  94. package/dist/canvas/buildSceneLayer.js.map +1 -0
  95. package/dist/canvas/buildSceneTree.js +16 -19
  96. package/dist/canvas/buildSceneTree.js.map +1 -1
  97. package/dist/canvas/canvasRenderer.js +68 -52
  98. package/dist/canvas/canvasRenderer.js.map +1 -1
  99. package/dist/canvas/deps/changes.js +13 -0
  100. package/dist/canvas/deps/changes.js.map +1 -0
  101. package/dist/canvas/deps/editAnchors.js +28 -28
  102. package/dist/canvas/deps/insert.js +119 -91
  103. package/dist/canvas/deps/insert.js.map +1 -1
  104. package/dist/canvas/deps/slice.js +46 -45
  105. package/dist/canvas/deps/slice.js.map +1 -1
  106. package/dist/canvas/deps/textEdit.js +10 -9
  107. package/dist/canvas/deps/textEdit.js.map +1 -1
  108. package/dist/canvas/derivedPath.js +46 -23
  109. package/dist/canvas/derivedPath.js.map +1 -1
  110. package/dist/canvas/getNodeAtPoint.js +7 -7
  111. package/dist/canvas/getNodeAtPoint.js.map +1 -1
  112. package/dist/canvas/hud.module.js +1 -1
  113. package/dist/canvas/hud.module.js.map +1 -1
  114. package/dist/canvas/kitRequirements.js +2 -2
  115. package/dist/canvas/kitRequirements.js.map +1 -1
  116. package/dist/canvas/layerOrder.js +13 -6
  117. package/dist/canvas/layerOrder.js.map +1 -1
  118. package/dist/canvas/minimapMath.js +12 -10
  119. package/dist/canvas/minimapMath.js.map +1 -1
  120. package/dist/canvas/nodeShapes/derivedPainter.js +34 -0
  121. package/dist/canvas/nodeShapes/derivedPainter.js.map +1 -0
  122. package/dist/canvas/nodeShapes/imagePainter.js +87 -0
  123. package/dist/canvas/nodeShapes/imagePainter.js.map +1 -0
  124. package/dist/canvas/nodeShapes/memo.js +9 -0
  125. package/dist/canvas/nodeShapes/memo.js.map +1 -0
  126. package/dist/canvas/nodeShapes/nodePaint.js +57 -0
  127. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -0
  128. package/dist/canvas/nodeShapes/pathPainter.js +38 -0
  129. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -0
  130. package/dist/canvas/nodeShapes/poseBox.js +20 -0
  131. package/dist/canvas/nodeShapes/poseBox.js.map +1 -0
  132. package/dist/canvas/nodeShapes/rectFallbackPainter.js +38 -0
  133. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -0
  134. package/dist/canvas/nodeShapes/shapePainter.js +72 -0
  135. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -0
  136. package/dist/canvas/nodeShapes/textPainter.js +55 -0
  137. package/dist/canvas/nodeShapes/textPainter.js.map +1 -0
  138. package/dist/canvas/overlayRoleStrokes.js.map +1 -1
  139. package/dist/canvas/paintCull.js +10 -11
  140. package/dist/canvas/paintCull.js.map +1 -1
  141. package/dist/canvas/pickWalk.js +52 -63
  142. package/dist/canvas/pickWalk.js.map +1 -1
  143. package/dist/canvas/poseRotation.js +11 -23
  144. package/dist/canvas/poseRotation.js.map +1 -1
  145. package/dist/canvas/renderDebugSnapshot.js +5 -5
  146. package/dist/canvas/renderSceneToPixels.js +3 -1
  147. package/dist/canvas/renderSceneToPixels.js.map +1 -1
  148. package/dist/canvas/sceneAdapter.js +66 -148
  149. package/dist/canvas/sceneAdapter.js.map +1 -1
  150. package/dist/canvas/sceneClipboard.js +112 -0
  151. package/dist/canvas/sceneClipboard.js.map +1 -0
  152. package/dist/canvas/sceneSlotWiring.js +4 -4
  153. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  154. package/dist/canvas/sceneViewRender.js +39 -40
  155. package/dist/canvas/sceneViewRender.js.map +1 -1
  156. package/dist/canvas/useCanvasRenderer.js +14 -6
  157. package/dist/canvas/useCanvasRenderer.js.map +1 -1
  158. package/dist/canvas/useCanvasView.js +58 -0
  159. package/dist/canvas/useCanvasView.js.map +1 -0
  160. package/dist/canvas/useFrameLoop.js +35 -26
  161. package/dist/canvas/useFrameLoop.js.map +1 -1
  162. package/dist/canvas/useSceneLayerList.js +21 -0
  163. package/dist/canvas/useSceneLayerList.js.map +1 -0
  164. package/dist/clipboard.d.ts +10 -6
  165. package/dist/clone.d.ts +4 -3
  166. package/dist/core/adapters/arrayAdapter.js +48 -39
  167. package/dist/core/adapters/arrayAdapter.js.map +1 -1
  168. package/dist/core/device/index.js +5 -4
  169. package/dist/core/device/useDeviceProfile.js +38 -44
  170. package/dist/core/device/useDeviceProfile.js.map +1 -1
  171. package/dist/core/device/watchDevicePixelRatio.js +17 -0
  172. package/dist/core/device/watchDevicePixelRatio.js.map +1 -0
  173. package/dist/core/fillInPoseFrame.js.map +1 -1
  174. package/dist/core/geometry/poseDescriptor.js +21 -19
  175. package/dist/core/geometry/poseDescriptor.js.map +1 -1
  176. package/dist/core/geometry/poseFrame.js +44 -0
  177. package/dist/core/geometry/poseFrame.js.map +1 -0
  178. package/dist/core/geometry/poseRotation.js.map +1 -1
  179. package/dist/core/geometry/regionHit.js +9 -10
  180. package/dist/core/geometry/regionHit.js.map +1 -1
  181. package/dist/core/geometry/unionBounds.js +31 -29
  182. package/dist/core/geometry/unionBounds.js.map +1 -1
  183. package/dist/core/isPlainObject.js +2 -11
  184. package/dist/core/ops/arrange.js +1 -0
  185. package/dist/core/ops/arrange.js.map +1 -1
  186. package/dist/core/ops/create.js +10 -5
  187. package/dist/core/ops/create.js.map +1 -1
  188. package/dist/core/ops/delete.js +12 -24
  189. package/dist/core/ops/delete.js.map +1 -1
  190. package/dist/core/ops/reorder/index.js +43 -40
  191. package/dist/core/ops/reorder/index.js.map +1 -1
  192. package/dist/core/ops/reorder/setChildOrder.js +34 -0
  193. package/dist/core/ops/reorder/setChildOrder.js.map +1 -0
  194. package/dist/core/paintKinds.js +5 -5
  195. package/dist/core/paintKinds.js.map +1 -1
  196. package/dist/core/scene/NodeProperties.js.map +1 -1
  197. package/dist/core/scene/appliedLog.js +37 -0
  198. package/dist/core/scene/appliedLog.js.map +1 -0
  199. package/dist/core/scene/arrivalWindow.js +101 -0
  200. package/dist/core/scene/arrivalWindow.js.map +1 -0
  201. package/dist/core/scene/derivedPath.js.map +1 -1
  202. package/dist/core/scene/historyFacade.js +84 -0
  203. package/dist/core/scene/historyFacade.js.map +1 -0
  204. package/dist/core/scene/kitOps.js +173 -0
  205. package/dist/core/scene/kitOps.js.map +1 -0
  206. package/dist/core/scene/layerStack.js +38 -0
  207. package/dist/core/scene/layerStack.js.map +1 -0
  208. package/dist/core/scene/lockGuard.js +37 -0
  209. package/dist/core/scene/lockGuard.js.map +1 -0
  210. package/dist/core/scene/nodeFnFields.js +5 -6
  211. package/dist/core/scene/nodeFnFields.js.map +1 -1
  212. package/dist/core/scene/nodeMemo.js +45 -19
  213. package/dist/core/scene/nodeMemo.js.map +1 -1
  214. package/dist/core/scene/nodeStore.js +126 -0
  215. package/dist/core/scene/nodeStore.js.map +1 -0
  216. package/dist/core/scene/pickability.js +6 -0
  217. package/dist/core/scene/pickability.js.map +1 -0
  218. package/dist/core/scene/poseFeed.js +38 -38
  219. package/dist/core/scene/poseFeed.js.map +1 -1
  220. package/dist/core/scene/poseOverrides.js +34 -38
  221. package/dist/core/scene/poseOverrides.js.map +1 -1
  222. package/dist/core/scene/renderOrder.js +84 -0
  223. package/dist/core/scene/renderOrder.js.map +1 -0
  224. package/dist/core/scene/scene.js +289 -866
  225. package/dist/core/scene/scene.js.map +1 -1
  226. package/dist/core/scene/serialization.js +68 -0
  227. package/dist/core/scene/serialization.js.map +1 -0
  228. package/dist/core/scene/treeOrder.js +13 -0
  229. package/dist/core/scene/treeOrder.js.map +1 -0
  230. package/dist/core/scene/types.js.map +1 -1
  231. package/dist/core/viewport/meanScale.js +1 -1
  232. package/dist/core/viewport/meanScale.js.map +1 -1
  233. package/dist/core/viewport/view.js +12 -12
  234. package/dist/core/viewport/view.js.map +1 -1
  235. package/dist/core/viewport/zoomBounds.js +10 -8
  236. package/dist/core/viewport/zoomBounds.js.map +1 -1
  237. package/dist/{cornerHandles-BCrDp_mH.d.ts → cornerHandles-CtCb8a3G.d.ts} +1 -1
  238. package/dist/debug/createDebugOverlayLayer.js +14 -14
  239. package/dist/debug/createDebugOverlayLayer.js.map +1 -1
  240. package/dist/debug/flag.js +2 -41
  241. package/dist/features/chrome-caps/useHoverTracking.js +22 -17
  242. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -1
  243. package/dist/features/focus/gateLayer.js +3 -4
  244. package/dist/features/focus/gateLayer.js.map +1 -1
  245. package/dist/features/images/imageCache.js +19 -9
  246. package/dist/features/images/imageCache.js.map +1 -1
  247. package/dist/features/ingestion/contentHandlers.js +14 -11
  248. package/dist/features/ingestion/contentHandlers.js.map +1 -1
  249. package/dist/features/ingestion/index.js +1 -1
  250. package/dist/features/ingestion/registerKitHandlers.js +7 -7
  251. package/dist/features/ingestion/weaselJsonHandler.js +17 -14
  252. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -1
  253. package/dist/features/meshPaint/lazyKind.js +201 -35
  254. package/dist/features/meshPaint/lazyKind.js.map +1 -1
  255. package/dist/features/meshPaint/meshPaint.js +82 -79
  256. package/dist/features/meshPaint/meshPaint.js.map +1 -1
  257. package/dist/features/minimap/createMinimapContribution.js +42 -42
  258. package/dist/features/minimap/layers.js +44 -62
  259. package/dist/features/minimap/layers.js.map +1 -1
  260. package/dist/features/parallax/createParallaxPlane.js +10 -14
  261. package/dist/features/parallax/createParallaxPlane.js.map +1 -1
  262. package/dist/features/paths/anchorEdits.js +19 -8
  263. package/dist/features/paths/anchorEdits.js.map +1 -1
  264. package/dist/features/paths/anchors.js +31 -26
  265. package/dist/features/paths/anchors.js.map +1 -1
  266. package/dist/features/paths/booleans.js +2 -2
  267. package/dist/features/paths/index.js +13 -11
  268. package/dist/features/paths/markerCommands.js +37 -36
  269. package/dist/features/paths/markerCommands.js.map +1 -1
  270. package/dist/features/paths/pathInWorld.js +19 -19
  271. package/dist/features/paths/pathInWorld.js.map +1 -1
  272. package/dist/features/paths/pathLayer.js.map +1 -1
  273. package/dist/features/paths/strokeToPath.js +40 -0
  274. package/dist/features/paths/strokeToPath.js.map +1 -0
  275. package/dist/features/paths/tessellate/stroke.js.map +1 -1
  276. package/dist/features/patterns/commandPaint.js +18 -0
  277. package/dist/features/patterns/commandPaint.js.map +1 -0
  278. package/dist/features/patterns/index.js +5 -17
  279. package/dist/features/patterns/index.js.map +1 -1
  280. package/dist/features/patterns/rasterizeTile.js +17 -0
  281. package/dist/features/patterns/rasterizeTile.js.map +1 -0
  282. package/dist/features/patterns/resolveSpec.js +52 -44
  283. package/dist/features/patterns/resolveSpec.js.map +1 -1
  284. package/dist/features/poseRun/usePoseRun.js +8 -3
  285. package/dist/features/poseRun/usePoseRun.js.map +1 -1
  286. package/dist/features/selection/SelectionContext.js +5 -0
  287. package/dist/features/selection/SelectionContext.js.map +1 -1
  288. package/dist/features/selection/overlay.js +18 -18
  289. package/dist/features/selection/overlay.js.map +1 -1
  290. package/dist/features/text/domOffsets.js +82 -0
  291. package/dist/features/text/domOffsets.js.map +1 -0
  292. package/dist/features/text/domRuns.js +103 -131
  293. package/dist/features/text/domRuns.js.map +1 -1
  294. package/dist/features/text/hitTest.js +5 -2
  295. package/dist/features/text/hitTest.js.map +1 -1
  296. package/dist/features/text/isTextData.js +8 -0
  297. package/dist/features/text/isTextData.js.map +1 -0
  298. package/dist/features/text/overlayDirection.js +15 -0
  299. package/dist/features/text/overlayDirection.js.map +1 -0
  300. package/dist/features/text/runs/rangeStyle.js +32 -34
  301. package/dist/features/text/runs/rangeStyle.js.map +1 -1
  302. package/dist/features/text/textCommand.js +34 -33
  303. package/dist/features/text/textCommand.js.map +1 -1
  304. package/dist/features/text/textToPath.js +40 -40
  305. package/dist/features/text/textToPath.js.map +1 -1
  306. package/dist/features/text/useSceneTextEdit.js +76 -82
  307. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  308. package/dist/features/text/useTextEdit.js +184 -160
  309. package/dist/features/text/useTextEdit.js.map +1 -1
  310. package/dist/features/tiling/createTiledLayer.js +24 -22
  311. package/dist/features/tiling/createTiledLayer.js.map +1 -1
  312. package/dist/index.d.ts +11033 -7749
  313. package/dist/index.js +316 -309
  314. package/dist/input/keyState.js +42 -43
  315. package/dist/input/keyState.js.map +1 -1
  316. package/dist/input/useKeyModifiers.js +11 -0
  317. package/dist/input/useKeyModifiers.js.map +1 -0
  318. package/dist/interactions/actions/align/align.js +8 -8
  319. package/dist/interactions/actions/clipboard/clipboardOps.js +34 -32
  320. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -1
  321. package/dist/interactions/actions/clipboard/materializePaste.js +10 -7
  322. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -1
  323. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -1
  324. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +1 -1
  325. package/dist/interactions/actions/defaultCommitAdapter.js +20 -18
  326. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -1
  327. package/dist/interactions/actions/defaults/align.js +9 -10
  328. package/dist/interactions/actions/defaults/align.js.map +1 -1
  329. package/dist/interactions/actions/defaults/anchorEditing.js +59 -81
  330. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -1
  331. package/dist/interactions/actions/defaults/areaSelect.js +35 -38
  332. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -1
  333. package/dist/interactions/actions/defaults/clipboard.js +26 -10
  334. package/dist/interactions/actions/defaults/clipboard.js.map +1 -1
  335. package/dist/interactions/actions/defaults/clone.js +44 -60
  336. package/dist/interactions/actions/defaults/clone.js.map +1 -1
  337. package/dist/interactions/actions/defaults/copySubtree.js +40 -0
  338. package/dist/interactions/actions/defaults/copySubtree.js.map +1 -0
  339. package/dist/interactions/actions/defaults/distribute.js +14 -13
  340. package/dist/interactions/actions/defaults/distribute.js.map +1 -1
  341. package/dist/interactions/actions/defaults/duplicate.js +17 -57
  342. package/dist/interactions/actions/defaults/duplicate.js.map +1 -1
  343. package/dist/interactions/actions/defaults/editAnchors.js +18 -18
  344. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  345. package/dist/interactions/actions/defaults/flip.js +52 -46
  346. package/dist/interactions/actions/defaults/flip.js.map +1 -1
  347. package/dist/interactions/actions/defaults/group.js +43 -48
  348. package/dist/interactions/actions/defaults/group.js.map +1 -1
  349. package/dist/interactions/actions/defaults/ingest.js +35 -33
  350. package/dist/interactions/actions/defaults/ingest.js.map +1 -1
  351. package/dist/interactions/actions/defaults/insert.js +50 -51
  352. package/dist/interactions/actions/defaults/insert.js.map +1 -1
  353. package/dist/interactions/actions/defaults/insertPathAnchor.js +7 -7
  354. package/dist/interactions/actions/defaults/lassoSelect.js +67 -70
  355. package/dist/interactions/actions/defaults/lassoSelect.js.map +1 -1
  356. package/dist/interactions/actions/defaults/move.js +267 -249
  357. package/dist/interactions/actions/defaults/move.js.map +1 -1
  358. package/dist/interactions/actions/defaults/nudge.js +40 -68
  359. package/dist/interactions/actions/defaults/nudge.js.map +1 -1
  360. package/dist/interactions/actions/defaults/nudgeSteps.js +37 -0
  361. package/dist/interactions/actions/defaults/nudgeSteps.js.map +1 -0
  362. package/dist/interactions/actions/defaults/reorder.js +2 -0
  363. package/dist/interactions/actions/defaults/reorder.js.map +1 -1
  364. package/dist/interactions/actions/defaults/resize.js +104 -98
  365. package/dist/interactions/actions/defaults/resize.js.map +1 -1
  366. package/dist/interactions/actions/defaults/rotate.js +111 -110
  367. package/dist/interactions/actions/defaults/rotate.js.map +1 -1
  368. package/dist/interactions/actions/defaults/setFill.js +7 -7
  369. package/dist/interactions/actions/defaults/setFillOpacity.js +4 -4
  370. package/dist/interactions/actions/defaults/setStroke.js +12 -12
  371. package/dist/interactions/actions/defaults/setStrokeOpacity.js +6 -6
  372. package/dist/interactions/actions/defaults/sliceOps.js +19 -19
  373. package/dist/interactions/actions/defaults/viewportDragPan.js +37 -26
  374. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -1
  375. package/dist/interactions/actions/edit-anchors/geometry.js +28 -23
  376. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -1
  377. package/dist/interactions/actions/flip/helpers.js +30 -17
  378. package/dist/interactions/actions/flip/helpers.js.map +1 -1
  379. package/dist/interactions/actions/hitSelection.js +8 -0
  380. package/dist/interactions/actions/hitSelection.js.map +1 -0
  381. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +14 -18
  382. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -1
  383. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +5 -5
  384. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -1
  385. package/dist/interactions/actions/move/behaviors/snapToContainer.js +32 -21
  386. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -1
  387. package/dist/interactions/actions/move/gestureAdapter.js +32 -15
  388. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  389. package/dist/interactions/actions/move/landedDescendants.js +33 -0
  390. package/dist/interactions/actions/move/landedDescendants.js.map +1 -0
  391. package/dist/interactions/actions/outlines/createOutlines.js +18 -18
  392. package/dist/interactions/actions/poseDescriptorDep.js +16 -4
  393. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -1
  394. package/dist/interactions/actions/poseFrame.js +11 -6
  395. package/dist/interactions/actions/poseFrame.js.map +1 -1
  396. package/dist/interactions/actions/previewOverrides.js +5 -5
  397. package/dist/interactions/actions/previewOverrides.js.map +1 -1
  398. package/dist/interactions/actions/selectionSubtree.js +69 -0
  399. package/dist/interactions/actions/selectionSubtree.js.map +1 -0
  400. package/dist/interactions/actions/useStandardActions.js +66 -62
  401. package/dist/interactions/actions/useStandardActions.js.map +1 -1
  402. package/dist/interactions/gestures/dragGesture/dragGesture.js +4 -7
  403. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -1
  404. package/dist/interactions/gestures/dragGesture/dragPointOf.js +23 -0
  405. package/dist/interactions/gestures/dragGesture/dragPointOf.js.map +1 -0
  406. package/dist/interactions/gestures/handleDrag/handleDrag.js +21 -26
  407. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -1
  408. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +8 -6
  409. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -1
  410. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +8 -4
  411. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  412. package/dist/{math-Drrw4ewZ.d.ts → math-J-ACHyEg.d.ts} +1 -2
  413. package/dist/math.d.ts +2 -3
  414. package/dist/move.d.ts +12 -11
  415. package/dist/{originProjection-DEklpDc_.d.ts → originProjection-gHnOup4e.d.ts} +1 -1
  416. package/dist/{registerProgram-BMZRDgrh.d.ts → registerProgram-T9S_PfAX.d.ts} +18 -7
  417. package/dist/renderer/DrawCommand.js.map +1 -1
  418. package/dist/renderer/WeaselRenderer.js +75 -73
  419. package/dist/renderer/WeaselRenderer.js.map +1 -1
  420. package/dist/renderer/cache/GLImageCache.js +15 -5
  421. package/dist/renderer/cache/GLImageCache.js.map +1 -1
  422. package/dist/renderer/cache/GLMeshCache.js +23 -23
  423. package/dist/renderer/cache/GLMeshCache.js.map +1 -1
  424. package/dist/renderer/cache/GLTextureCache.js +18 -1
  425. package/dist/renderer/cache/GLTextureCache.js.map +1 -1
  426. package/dist/renderer/cache/cache.js.map +1 -1
  427. package/dist/renderer/cache/markerCommandCache.js.map +1 -1
  428. package/dist/renderer/cache/strokeMeshCache.js.map +1 -1
  429. package/dist/renderer/cullDrawCommands.js +11 -11
  430. package/dist/renderer/draw/batch.js +133 -0
  431. package/dist/renderer/draw/batch.js.map +1 -0
  432. package/dist/renderer/draw/clip.js +89 -0
  433. package/dist/renderer/draw/clip.js.map +1 -0
  434. package/dist/renderer/draw/customShader.js +230 -0
  435. package/dist/renderer/draw/customShader.js.map +1 -0
  436. package/dist/renderer/draw/drawTriangles.js +8 -0
  437. package/dist/renderer/draw/drawTriangles.js.map +1 -0
  438. package/dist/renderer/draw/effects.js +28 -0
  439. package/dist/renderer/draw/effects.js.map +1 -0
  440. package/dist/renderer/draw/flushBatch.js +35 -0
  441. package/dist/renderer/draw/flushBatch.js.map +1 -0
  442. package/dist/renderer/draw/gradient.js +90 -0
  443. package/dist/renderer/draw/gradient.js.map +1 -0
  444. package/dist/renderer/draw/image.js +38 -0
  445. package/dist/renderer/draw/image.js.map +1 -0
  446. package/dist/renderer/draw/mesh.js +16 -0
  447. package/dist/renderer/draw/mesh.js.map +1 -0
  448. package/dist/renderer/draw/paintBind.js +70 -0
  449. package/dist/renderer/draw/paintBind.js.map +1 -0
  450. package/dist/renderer/draw/pathPaint.js +142 -0
  451. package/dist/renderer/draw/pathPaint.js.map +1 -0
  452. package/dist/renderer/draw/scratchPass.js +83 -0
  453. package/dist/renderer/draw/scratchPass.js.map +1 -0
  454. package/dist/renderer/draw/stencil.js +28 -0
  455. package/dist/renderer/draw/stencil.js.map +1 -0
  456. package/dist/renderer/draw/text.js +167 -0
  457. package/dist/renderer/draw/text.js.map +1 -0
  458. package/dist/renderer/draw/uniforms.js +77 -0
  459. package/dist/renderer/draw/uniforms.js.map +1 -0
  460. package/dist/renderer/draw.js +60 -1116
  461. package/dist/renderer/draw.js.map +1 -1
  462. package/dist/renderer/effects/EffectTargets.js +3 -0
  463. package/dist/renderer/effects/EffectTargets.js.map +1 -1
  464. package/dist/renderer/effects/composite.js +7 -5
  465. package/dist/renderer/effects/composite.js.map +1 -1
  466. package/dist/renderer/index.js +18 -17
  467. package/dist/renderer/math/color.js +63 -83
  468. package/dist/renderer/math/color.js.map +1 -1
  469. package/dist/renderer/math/mat3.js +15 -11
  470. package/dist/renderer/math/mat3.js.map +1 -1
  471. package/dist/renderer/math/viewToMat3.js +1 -1
  472. package/dist/renderer/math/viewToMat3.js.map +1 -1
  473. package/dist/renderer/shaders/ShaderProgram.js +13 -13
  474. package/dist/renderer/shaders/ShaderProgram.js.map +1 -1
  475. package/dist/renderer/shaders/glyphPaint.js +3 -3
  476. package/dist/renderer/shaders/glyphPaint.js.map +1 -1
  477. package/dist/renderer/shaders/gradFill.js +2 -1
  478. package/dist/renderer/shaders/gradFill.js.map +1 -1
  479. package/dist/renderer/shaders/pathFill.js +2 -1
  480. package/dist/renderer/shaders/pathFill.js.map +1 -1
  481. package/dist/renderer/shaders/patternFill.js +2 -1
  482. package/dist/renderer/shaders/patternFill.js.map +1 -1
  483. package/dist/renderer/shaders/registerProgram.js.map +1 -1
  484. package/dist/renderer/strokeLengths.js.map +1 -1
  485. package/dist/renderer/textures/registerTexture.js +25 -5
  486. package/dist/renderer/textures/registerTexture.js.map +1 -1
  487. package/dist/renderer.d.ts +16 -15
  488. package/dist/renderer.js +17 -16
  489. package/dist/resize.d.ts +5 -6
  490. package/dist/resize.js +5 -5
  491. package/dist/style.css +1 -1
  492. package/dist/test-hook/install.js +12 -6
  493. package/dist/test-hook/install.js.map +1 -1
  494. package/dist/{test-seams-CuIxe0xY.d.ts → test-seams-DM2B87-g.d.ts} +4 -4
  495. package/dist/test-seams.d.ts +2 -2
  496. package/dist/tools/builtin/ellipse/useEllipseTool.js +1 -0
  497. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -1
  498. package/dist/tools/builtin/hand/useHandTool.js +1 -0
  499. package/dist/tools/builtin/hand/useHandTool.js.map +1 -1
  500. package/dist/tools/builtin/lasso/useLassoTool.js +11 -11
  501. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -1
  502. package/dist/tools/builtin/line/useLineTool.js +1 -0
  503. package/dist/tools/builtin/line/useLineTool.js.map +1 -1
  504. package/dist/tools/builtin/pen/usePenTool.js +153 -103
  505. package/dist/tools/builtin/pen/usePenTool.js.map +1 -1
  506. package/dist/tools/builtin/pencil/usePencilTool.js +1 -0
  507. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -1
  508. package/dist/tools/builtin/polygon/usePolygonTool.js +13 -8
  509. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -1
  510. package/dist/tools/builtin/rect/useRectTool.js +1 -0
  511. package/dist/tools/builtin/rect/useRectTool.js.map +1 -1
  512. package/dist/tools/builtin/select/selectionContributions.js +24 -23
  513. package/dist/tools/builtin/select/selectionContributions.js.map +1 -1
  514. package/dist/tools/builtin/select/useSelectTool.js +51 -48
  515. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  516. package/dist/tools/builtin/shared/pointerFollower.js +17 -0
  517. package/dist/tools/builtin/shared/pointerFollower.js.map +1 -0
  518. package/dist/tools/builtin/slice/useSliceTool.js +49 -54
  519. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -1
  520. package/dist/tools/builtin/star/useStarTool.js +22 -16
  521. package/dist/tools/builtin/star/useStarTool.js.map +1 -1
  522. package/dist/tools/builtin/text/useTextTool.js +1 -0
  523. package/dist/tools/builtin/text/useTextTool.js.map +1 -1
  524. package/dist/tools/useKeybindings.js +14 -30
  525. package/dist/tools/useKeybindings.js.map +1 -1
  526. package/dist/{types-B_9g6hMM.d.ts → types-B4iJRHC3.d.ts} +5 -1
  527. package/dist/{types-A37hYkeR.d.ts → types-k-5Oqh-U.d.ts} +31 -7
  528. package/dist/util/color.js +3 -3
  529. package/dist/util/color.js.map +1 -1
  530. package/dist/util/paint.js.map +1 -1
  531. package/dist/version.js +1 -1
  532. package/package.json +20 -18
  533. package/dist/autoPoseDescriptor-vCdt55xm.d.ts +0 -27
  534. package/dist/builtins-C-VgUlWI.d.ts +0 -4514
  535. package/dist/core/isPlainObject.js.map +0 -1
  536. package/dist/debug/flag.js.map +0 -1
  537. package/dist/interactions/actions/defaults/freshNodeId.js +0 -10
  538. package/dist/interactions/actions/defaults/freshNodeId.js.map +0 -1
  539. package/dist/renderer/shaders/imageFill.js +0 -14
  540. package/dist/renderer/shaders/imageFill.js.map +0 -1
  541. package/dist/tools/prefs.js +0 -62
  542. package/dist/tools/prefs.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"selectFromLasso.js","names":["LASSO_VERTICES","scratchKey","MIN_AREA","selectFromLasso","mode","opts","adapter","ctx","vertices","getScratch","startPose","shiftHeld","from","polygonAabbArea","createSetSelectionOp","hits","to","mergeUnique","minX","minY","maxX","maxY","v","out","a","id","b"],"sources":["../../../../../src/interactions/actions/lasso-select/behaviors/selectFromLasso.ts"],"sourcesContent":["import { createSetSelectionOp } from 'core/ops/select';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport type {\n LassoHitMode,\n LassoSelectAdapter,\n} from 'core/adapters/types';\nimport type { LassoSelectBehavior } from '../../../gestures/types';\nimport { scratchKey, getScratch } from '@weasel-js/routing';\n\n/** Typed scratch slot the lasso tool's gesture writes into for this behavior\n * to consume. Shared identity: tools producing the polygon for a lasso\n * selection write under this same key. */\nexport const LASSO_VERTICES = scratchKey<ReadonlyArray<{ x: number; y: number }>>('lassoSelect.vertices');\n\nconst MIN_AREA = 4;\n\n/** Options for `selectFromLasso`. */\nexport interface SelectFromLassoOptions {\n /** Hit mode for `hitTestLasso`. Default 'intersect'. */\n mode?: LassoHitMode;\n}\n\n/** A lasso behavior (`useLassoTool({ behaviors })`): replace selection with\n * polygon hits in its own `mode`, or extend the existing selection when shift\n * is held at gesture start. Tiny / degenerate lassos behave like a click —\n * clear (or preserve, with shift). Hits come from the gesture adapter's\n * `hitTestLasso`, which under `lassoSelectAction` is the `lassoSelect` dep. */\nexport function selectFromLasso(opts?: SelectFromLassoOptions): LassoSelectBehavior {\n const mode: LassoHitMode = opts?.mode ?? 'intersect';\n return {\n defaultTransient: true,\n onEnd(ctx) {\n const adapter = ctx.adapter as unknown as LassoSelectAdapter;\n if (!adapter.getSelection || !adapter.hitTestLasso) return null;\n\n const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n const startPose = ctx.origin.get('gesture');\n const shiftHeld = startPose ? (startPose as { shiftHeld?: boolean }).shiftHeld === true : false;\n const from = adapter.getSelection();\n\n // Tiny / degenerate lassos behave like a click: clear (or preserve on shift).\n const tiny = vertices.length < 3 || polygonAabbArea(vertices) < MIN_AREA;\n if (tiny) {\n const to = shiftHeld ? from : [];\n const op: Op = createSetSelectionOp({ from: from as NodeId[], to: to as NodeId[] });\n return [op];\n }\n\n const hits = adapter.hitTestLasso(vertices, mode);\n const to = shiftHeld\n ? mergeUnique(from, hits)\n : hits;\n const op: Op = createSetSelectionOp({ from: from as NodeId[], to: to as NodeId[] });\n return [op];\n },\n };\n}\n\nfunction polygonAabbArea(vertices: ReadonlyArray<{ x: number; y: number }>): number {\n if (vertices.length === 0) return 0;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const v of vertices) {\n if (v.x < minX) minX = v.x;\n if (v.y < minY) minY = v.y;\n if (v.x > maxX) maxX = v.x;\n if (v.y > maxY) maxY = v.y;\n }\n return (maxX - minX) * (maxY - minY);\n}\n\nfunction mergeUnique(a: ReadonlyArray<string>, b: ReadonlyArray<string>): string[] {\n const out = [...a];\n for (const id of b) if (!out.includes(id)) out.push(id);\n return out;\n}\n"],"mappings":";;;AAaA,IAAaA,IAAiBC,EAAoD,sBAAsB,GAElGC,IAAW;AAajB,SAAgBC,EAAgB,GAAoD;CAClF,IAAMC,IAAqBC,GAAM,QAAQ;CACzC,OAAO;EACL,kBAAkB;EAClB,MAAM,GAAK;GACT,IAAMC,IAAUC,EAAI;GACpB,IAAI,CAACD,EAAQ,gBAAgB,CAACA,EAAQ,cAAc,OAAO;GAE3D,IAAME,IAAWC,EAAWF,EAAI,SAASP,CAAc,KAAK,CAAC,GACvDU,IAAYH,EAAI,OAAO,IAAI,SAAS,GACpCI,IAAYD,IAAaA,EAAsC,cAAc,KAAO,IACpFE,IAAON,EAAQ,aAAa;GAIlC,IADaE,EAAS,SAAS,KAAKK,EAAgBL,CAAQ,IAAIN,GAI9D,OAAO,CADQY,EAAqB;IAAQ;IAAsB,IADvDH,IAAYC,IAAO,CAAC;GACkD,CACzE,CAAE;GAGZ,IAAMG,IAAOT,EAAQ,aAAaE,GAAUJ,CAAI,GAC1CY,IAAKL,IACPM,EAAYL,GAAMG,CAAI,IACtBA;GAEJ,OAAO,CADQD,EAAqB;IAAQ;IAAsB;GAAe,CACzE,CAAE;EACZ;CACF;AACF;AAEA,SAASD,EAAgB,GAA2D;CAClF,IAAIL,EAAS,WAAW,GAAG,OAAO;CAClC,IAAIU,IAAO,UAAUC,IAAO,UAAUC,IAAO,WAAWC,IAAO;CAC/D,KAAK,IAAMC,KAAKd,GAId,AAHIc,EAAE,IAAIJ,MAAM,IAAOI,EAAE,IACrBA,EAAE,IAAIH,MAAM,IAAOG,EAAE,IACrBA,EAAE,IAAIF,MAAM,IAAOE,EAAE,IACrBA,EAAE,IAAID,MAAM,IAAOC,EAAE;CAE3B,QAAQF,IAAOF,MAASG,IAAOF;AACjC;AAEA,SAASF,EAAY,GAA0B,GAAoC;CACjF,IAAMM,IAAM,CAAC,GAAGC,CAAC;CACjB,KAAK,IAAMC,KAAMC,GAAG,AAAKH,EAAI,SAASE,CAAE,KAAGF,EAAI,KAAKE,CAAE;CACtD,OAAOF;AACT"}
1
+ {"version":3,"file":"selectFromLasso.js","names":["LASSO_VERTICES","scratchKey","MIN_AREA","selectFromLasso","mode","opts","adapter","ctx","vertices","getScratch","startPose","shiftHeld","from","polygonAabbArea","createSetSelectionOp","hits","to","selectionFromHits","minX","minY","maxX","maxY","v"],"sources":["../../../../../src/interactions/actions/lasso-select/behaviors/selectFromLasso.ts"],"sourcesContent":["import { createSetSelectionOp } from 'core/ops/select';\nimport type { Op } from 'core/ops/types';\nimport type { NodeId } from 'core/scene/types';\nimport type {\n LassoHitMode,\n LassoSelectAdapter,\n} from 'core/adapters/types';\nimport type { LassoSelectBehavior } from '../../../gestures/types';\nimport { scratchKey, getScratch } from '@weasel-js/routing';\nimport { selectionFromHits } from '../../hitSelection';\n\n/** Typed scratch slot the lasso tool's gesture writes into for this behavior\n * to consume. Shared identity: tools producing the polygon for a lasso\n * selection write under this same key. */\nexport const LASSO_VERTICES = scratchKey<ReadonlyArray<{ x: number; y: number }>>('lassoSelect.vertices');\n\nconst MIN_AREA = 4;\n\n/** Options for `selectFromLasso`. */\nexport interface SelectFromLassoOptions {\n /** Hit mode for `hitTestLasso`. Default 'intersect'. */\n mode?: LassoHitMode;\n}\n\n/** A lasso behavior (`useLassoTool({ behaviors })`): replace selection with\n * polygon hits in its own `mode`, or extend the existing selection when shift\n * is held at gesture start. Tiny / degenerate lassos behave like a click —\n * clear (or preserve, with shift). Hits come from the gesture adapter's\n * `hitTestLasso`, which under `lassoSelectAction` is the `lassoSelect` dep. */\nexport function selectFromLasso(opts?: SelectFromLassoOptions): LassoSelectBehavior {\n const mode: LassoHitMode = opts?.mode ?? 'intersect';\n return {\n defaultTransient: true,\n onEnd(ctx) {\n const adapter = ctx.adapter as unknown as LassoSelectAdapter;\n if (!adapter.getSelection || !adapter.hitTestLasso) return null;\n\n const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n const startPose = ctx.origin.get('gesture');\n const shiftHeld = startPose ? (startPose as { shiftHeld?: boolean }).shiftHeld === true : false;\n const from = adapter.getSelection();\n\n // Tiny / degenerate lassos behave like a click: clear (or preserve on shift).\n const tiny = vertices.length < 3 || polygonAabbArea(vertices) < MIN_AREA;\n if (tiny) {\n const to = shiftHeld ? from : [];\n const op: Op = createSetSelectionOp({ from: from as NodeId[], to: to as NodeId[] });\n return [op];\n }\n\n const hits = adapter.hitTestLasso(vertices, mode);\n const to = selectionFromHits(from, hits, shiftHeld);\n const op: Op = createSetSelectionOp({ from: from as NodeId[], to: to as NodeId[] });\n return [op];\n },\n };\n}\n\nfunction polygonAabbArea(vertices: ReadonlyArray<{ x: number; y: number }>): number {\n if (vertices.length === 0) return 0;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const v of vertices) {\n if (v.x < minX) minX = v.x;\n if (v.y < minY) minY = v.y;\n if (v.x > maxX) maxX = v.x;\n if (v.y > maxY) maxY = v.y;\n }\n return (maxX - minX) * (maxY - minY);\n}\n"],"mappings":";;;;AAcA,IAAaA,IAAiBC,EAAoD,sBAAsB,GAElGC,IAAW;AAajB,SAAgBC,EAAgB,GAAoD;CAClF,IAAMC,IAAqBC,GAAM,QAAQ;CACzC,OAAO;EACL,kBAAkB;EAClB,MAAM,GAAK;GACT,IAAMC,IAAUC,EAAI;GACpB,IAAI,CAACD,EAAQ,gBAAgB,CAACA,EAAQ,cAAc,OAAO;GAE3D,IAAME,IAAWC,EAAWF,EAAI,SAASP,CAAc,KAAK,CAAC,GACvDU,IAAYH,EAAI,OAAO,IAAI,SAAS,GACpCI,IAAYD,IAAaA,EAAsC,cAAc,KAAO,IACpFE,IAAON,EAAQ,aAAa;GAIlC,IADaE,EAAS,SAAS,KAAKK,EAAgBL,CAAQ,IAAIN,GAI9D,OAAO,CADQY,EAAqB;IAAQ;IAAsB,IADvDH,IAAYC,IAAO,CAAC;GACkD,CACzE,CAAE;GAGZ,IAAMG,IAAOT,EAAQ,aAAaE,GAAUJ,CAAI,GAC1CY,IAAKC,EAAkBL,GAAMG,GAAMJ,CAAS;GAElD,OAAO,CADQG,EAAqB;IAAQ;IAAsB;GAAe,CACzE,CAAE;EACZ;CACF;AACF;AAEA,SAASD,EAAgB,GAA2D;CAClF,IAAIL,EAAS,WAAW,GAAG,OAAO;CAClC,IAAIU,IAAO,UAAUC,IAAO,UAAUC,IAAO,WAAWC,IAAO;CAC/D,KAAK,IAAMC,KAAKd,GAId,AAHIc,EAAE,IAAIJ,MAAM,IAAOI,EAAE,IACrBA,EAAE,IAAIH,MAAM,IAAOG,EAAE,IACrBA,EAAE,IAAIF,MAAM,IAAOE,EAAE,IACrBA,EAAE,IAAID,MAAM,IAAOC,EAAE;CAE3B,QAAQF,IAAOF,MAASG,IAAOF;AACjC"}
@@ -19,12 +19,12 @@ function s(r) {
19
19
  let r = t.draggedIds[0], i = u.getOrigin(t.origin.get(r)), s = u.getOrigin(t.current.get(r)), f = s.x - i.x, p = s.y - i.y;
20
20
  if (f * f + p * p <= d) return null;
21
21
  if (c === "delete") {
22
- let i = n(t.scratch, a), s = n(t.scratch, o), c = i?.get(r) ?? { id: r }, u = s?.get(r) ?? -1;
23
- return [e({
24
- node: c,
22
+ let r = n(t.scratch, a), i = n(t.scratch, o), s = (e) => i?.get(e) ?? -1;
23
+ return [...t.draggedIds].sort((e, t) => s(t) - s(e)).map((t) => e({
24
+ node: r?.get(t) ?? { id: t },
25
25
  label: l,
26
- index: u
27
- })];
26
+ index: s(t)
27
+ }));
28
28
  }
29
29
  return null;
30
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"snapBackOrDelete.js","names":["SNAPSHOTS","scratchKey","INDEXES","snapBackOrDelete","args","proj","AUTO_ORIGIN_PROJECTION","r2","radius","snapshots","indexes","nodes","ctx","id","obj","n","setScratch","o0","o1","dx","dy","onFreeRelease","getScratch","index","createDeleteOp","deleteLabel"],"sources":["../../../../../src/interactions/actions/move/behaviors/snapBackOrDelete.ts"],"sourcesContent":["import { createDeleteOp } from 'core/ops/delete';\nimport type { Op } from 'core/ops/types';\nimport type { MoveBehavior } from '../../../gestures/types';\nimport {\n AUTO_ORIGIN_PROJECTION,\n type OriginProjection,\n} from '../../../gestures/shared/originProjection';\nimport { scratchKey, getScratch, setScratch } from '@weasel-js/routing';\n\nconst SNAPSHOTS = scratchKey<Map<string, { id: string }>>('snapBackOrDelete.snapshots');\nconst INDEXES = scratchKey<Map<string, number>>('snapBackOrDelete.indexes');\n\n/**\n * Move behavior for a drag that is only meaningful near where it started:\n * release inside `radius` and the node returns to its original pose; release\n * outside it and the node either springs back anyway or is deleted, per\n * `onFreeRelease`. A deletion is recorded as an undoable op with paint order\n * preserved.\n */\nexport function snapBackOrDelete<TPose extends { x: number; y: number }>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n}): MoveBehavior<TPose>;\n/** As above, for a `TPose` that is not a rect: `origin` tells the behavior how\n * to read and write the pose's origin. */\nexport function snapBackOrDelete<TPose>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n origin: OriginProjection<TPose>;\n}): MoveBehavior<TPose>;\n/** Snap back to the origin pose, or delete, depending on where the drag is\n * released. */\nexport function snapBackOrDelete<TPose>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n origin?: OriginProjection<TPose>;\n}): MoveBehavior<TPose> {\n const { radius, onFreeRelease, deleteLabel = 'Delete' } = args;\n const proj: OriginProjection<TPose> =\n args.origin ?? (AUTO_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n const r2 = radius * radius;\n\n return {\n onStart(ctx) {\n // Snapshot the dragged objects + their z-indexes at gesture start so\n // delete can undo with paint order intact.\n const snapshots = new Map<string, { id: string }>();\n const indexes = new Map<string, number>();\n const nodes = ctx.adapter.getNodes();\n for (const id of ctx.draggedIds) {\n const obj = ctx.adapter.getNode(id) ?? { id };\n snapshots.set(id, obj);\n indexes.set(id, nodes.findIndex((n) => n.id === id));\n }\n setScratch(ctx.scratch, SNAPSHOTS, snapshots);\n setScratch(ctx.scratch, INDEXES, indexes);\n },\n\n onEnd(ctx) {\n if (ctx.snap) return;\n const id = ctx.draggedIds[0];\n const o0 = proj.getOrigin(ctx.origin.get(id)!);\n const o1 = proj.getOrigin(ctx.current.get(id)!);\n const dx = o1.x - o0.x;\n const dy = o1.y - o0.y;\n const within = dx * dx + dy * dy <= r2;\n if (within) {\n return null;\n }\n if (onFreeRelease === 'delete') {\n const snapshots = getScratch(ctx.scratch, SNAPSHOTS);\n const indexes = getScratch(ctx.scratch, INDEXES);\n const obj = snapshots?.get(id) ?? { id };\n const index = indexes?.get(id) ?? -1;\n const ops: Op[] = [createDeleteOp({ node: obj, label: deleteLabel, index })];\n return ops;\n }\n // `'snap-back'` — abort, same as a release inside the radius. Returning\n // `undefined` would defer to the default translate and leave the node\n // where it was dropped, which is the one thing this policy rules out.\n return null;\n },\n };\n}\n"],"mappings":";;;;AASA,IAAMA,IAAYC,EAAwC,4BAA4B,GAChFC,IAAUD,EAAgC,0BAA0B;AAwB1E,SAAgBE,EAAwB,GAKhB;CACtB,IAAM,EAAE,WAAQ,kBAAe,iBAAc,aAAaC,GACpDC,IACJD,EAAK,UAAWE,GACZC,IAAKC,IAASA;CAEpB,OAAO;EACL,QAAQ,GAAK;GAGX,IAAMC,oBAAY,IAAI,IAA4B,GAC5CC,oBAAU,IAAI,IAAoB,GAClCC,IAAQC,EAAI,QAAQ,SAAS;GACnC,KAAK,IAAMC,KAAMD,EAAI,YAAY;IAC/B,IAAME,IAAMF,EAAI,QAAQ,QAAQC,CAAE,KAAK,EAAE,MAAG;IAE5C,AADAJ,EAAU,IAAII,GAAIC,CAAG,GACrBJ,EAAQ,IAAIG,GAAIF,EAAM,WAAW,MAAMI,EAAE,OAAOF,CAAE,CAAC;GACrD;GAEA,AADAG,EAAWJ,EAAI,SAASZ,GAAWS,CAAS,GAC5CO,EAAWJ,EAAI,SAASV,GAASQ,CAAO;EAC1C;EAEA,MAAM,GAAK;GACT,IAAIE,EAAI,MAAM;GACd,IAAMC,IAAKD,EAAI,WAAW,IACpBK,IAAKZ,EAAK,UAAUO,EAAI,OAAO,IAAIC,CAAE,CAAE,GACvCK,IAAKb,EAAK,UAAUO,EAAI,QAAQ,IAAIC,CAAE,CAAE,GACxCM,IAAKD,EAAG,IAAID,EAAG,GACfG,IAAKF,EAAG,IAAID,EAAG;GAErB,IADeE,IAAKA,IAAKC,IAAKA,KAAMb,GAElC,OAAO;GAET,IAAIc,MAAkB,UAAU;IAC9B,IAAMZ,IAAYa,EAAWV,EAAI,SAASZ,CAAS,GAC7CU,IAAUY,EAAWV,EAAI,SAASV,CAAO,GACzCY,IAAML,GAAW,IAAII,CAAE,KAAK,EAAE,MAAG,GACjCU,IAAQb,GAAS,IAAIG,CAAE,KAAK;IAElC,OAAO,CADYW,EAAe;KAAE,MAAMV;KAAK,OAAOW;KAAa;IAAM,CAAC,CACnE;GACT;GAIA,OAAO;EACT;CACF;AACF"}
1
+ {"version":3,"file":"snapBackOrDelete.js","names":["SNAPSHOTS","scratchKey","INDEXES","snapBackOrDelete","args","proj","AUTO_ORIGIN_PROJECTION","r2","radius","snapshots","indexes","nodes","ctx","id","obj","n","setScratch","o0","o1","dx","dy","onFreeRelease","getScratch","indexOf","dragged","q","p","createDeleteOp","deleteLabel"],"sources":["../../../../../src/interactions/actions/move/behaviors/snapBackOrDelete.ts"],"sourcesContent":["import { createDeleteOp } from 'core/ops/delete';\nimport type { Op } from 'core/ops/types';\nimport type { MoveBehavior } from '../../../gestures/types';\nimport {\n AUTO_ORIGIN_PROJECTION,\n type OriginProjection,\n} from '../../../gestures/shared/originProjection';\nimport { scratchKey, getScratch, setScratch } from '@weasel-js/routing';\n\nconst SNAPSHOTS = scratchKey<Map<string, { id: string }>>('snapBackOrDelete.snapshots');\nconst INDEXES = scratchKey<Map<string, number>>('snapBackOrDelete.indexes');\n\n/**\n * Move behavior for a drag that is only meaningful near where it started:\n * release inside `radius` and every dragged node returns to its original\n * pose; release outside it and they all either spring back anyway or are\n * deleted, per `onFreeRelease`. The distance is the first dragged node's. A\n * deletion is recorded as undoable ops with paint order preserved.\n */\nexport function snapBackOrDelete<TPose extends { x: number; y: number }>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n}): MoveBehavior<TPose>;\n/** As above, for a `TPose` that is not a rect: `origin` tells the behavior how\n * to read and write the pose's origin. */\nexport function snapBackOrDelete<TPose>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n origin: OriginProjection<TPose>;\n}): MoveBehavior<TPose>;\n/** Snap back to the origin pose, or delete, depending on where the drag is\n * released. */\nexport function snapBackOrDelete<TPose>(args: {\n radius: number;\n onFreeRelease: 'snap-back' | 'delete';\n deleteLabel?: string;\n origin?: OriginProjection<TPose>;\n}): MoveBehavior<TPose> {\n const { radius, onFreeRelease, deleteLabel = 'Delete' } = args;\n const proj: OriginProjection<TPose> =\n args.origin ?? (AUTO_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n const r2 = radius * radius;\n\n return {\n onStart(ctx) {\n // Snapshot the dragged objects + their z-indexes at gesture start so\n // delete can undo with paint order intact.\n const snapshots = new Map<string, { id: string }>();\n const indexes = new Map<string, number>();\n const nodes = ctx.adapter.getNodes();\n for (const id of ctx.draggedIds) {\n const obj = ctx.adapter.getNode(id) ?? { id };\n snapshots.set(id, obj);\n indexes.set(id, nodes.findIndex((n) => n.id === id));\n }\n setScratch(ctx.scratch, SNAPSHOTS, snapshots);\n setScratch(ctx.scratch, INDEXES, indexes);\n },\n\n onEnd(ctx) {\n if (ctx.snap) return;\n const id = ctx.draggedIds[0];\n const o0 = proj.getOrigin(ctx.origin.get(id)!);\n const o1 = proj.getOrigin(ctx.current.get(id)!);\n const dx = o1.x - o0.x;\n const dy = o1.y - o0.y;\n const within = dx * dx + dy * dy <= r2;\n if (within) {\n return null;\n }\n if (onFreeRelease === 'delete') {\n const snapshots = getScratch(ctx.scratch, SNAPSHOTS);\n const indexes = getScratch(ctx.scratch, INDEXES);\n const indexOf = (dragged: string): number => indexes?.get(dragged) ?? -1;\n // Topmost first, so an undo, which replays in reverse, restores each index in turn.\n return [...ctx.draggedIds]\n .sort((p, q) => indexOf(q) - indexOf(p))\n .map((dragged): Op => createDeleteOp({\n node: snapshots?.get(dragged) ?? { id: dragged },\n label: deleteLabel,\n index: indexOf(dragged),\n }));\n }\n // `'snap-back'` — abort, same as a release inside the radius. Returning\n // `undefined` would defer to the default translate and leave the node\n // where it was dropped, which is the one thing this policy rules out.\n return null;\n },\n };\n}\n"],"mappings":";;;;AASA,IAAMA,IAAYC,EAAwC,4BAA4B,GAChFC,IAAUD,EAAgC,0BAA0B;AAwB1E,SAAgBE,EAAwB,GAKhB;CACtB,IAAM,EAAE,WAAQ,kBAAe,iBAAc,aAAaC,GACpDC,IACJD,EAAK,UAAWE,GACZC,IAAKC,IAASA;CAEpB,OAAO;EACL,QAAQ,GAAK;GAGX,IAAMC,oBAAY,IAAI,IAA4B,GAC5CC,oBAAU,IAAI,IAAoB,GAClCC,IAAQC,EAAI,QAAQ,SAAS;GACnC,KAAK,IAAMC,KAAMD,EAAI,YAAY;IAC/B,IAAME,IAAMF,EAAI,QAAQ,QAAQC,CAAE,KAAK,EAAE,MAAG;IAE5C,AADAJ,EAAU,IAAII,GAAIC,CAAG,GACrBJ,EAAQ,IAAIG,GAAIF,EAAM,WAAW,MAAMI,EAAE,OAAOF,CAAE,CAAC;GACrD;GAEA,AADAG,EAAWJ,EAAI,SAASZ,GAAWS,CAAS,GAC5CO,EAAWJ,EAAI,SAASV,GAASQ,CAAO;EAC1C;EAEA,MAAM,GAAK;GACT,IAAIE,EAAI,MAAM;GACd,IAAMC,IAAKD,EAAI,WAAW,IACpBK,IAAKZ,EAAK,UAAUO,EAAI,OAAO,IAAIC,CAAE,CAAE,GACvCK,IAAKb,EAAK,UAAUO,EAAI,QAAQ,IAAIC,CAAE,CAAE,GACxCM,IAAKD,EAAG,IAAID,EAAG,GACfG,IAAKF,EAAG,IAAID,EAAG;GAErB,IADeE,IAAKA,IAAKC,IAAKA,KAAMb,GAElC,OAAO;GAET,IAAIc,MAAkB,UAAU;IAC9B,IAAMZ,IAAYa,EAAWV,EAAI,SAASZ,CAAS,GAC7CU,IAAUY,EAAWV,EAAI,SAASV,CAAO,GACzCqB,KAAW,MAA4Bb,GAAS,IAAIc,CAAO,KAAK;IAEtE,OAAO,CAAC,GAAGZ,EAAI,UAAU,CAAC,CACvB,MAAM,GAAG,MAAMW,EAAQE,CAAC,IAAIF,EAAQG,CAAC,CAAC,CAAC,CACvC,KAAK,MAAgBC,EAAe;KACnC,MAAMlB,GAAW,IAAIe,CAAO,KAAK,EAAE,IAAIA,EAAQ;KAC/C,OAAOI;KACP,OAAOL,EAAQC,CAAO;IACxB,CAAC,CAAC;GACN;GAIA,OAAO;EACT;CACF;AACF"}
@@ -15,25 +15,30 @@ function s(e) {
15
15
  e.pendingTimer !== null && (clearTimeout(e.pendingTimer), e.pendingTimer = null), e.pendingTargetId = null;
16
16
  }
17
17
  function c(n) {
18
- let { dwellMs: r, findTarget: i, isInstant: a, moveLabel: c = "Move", reparentLabel: l = "Move and reparent" } = n;
18
+ let { dwellMs: r, findTarget: i, isInstant: a, moveLabel: c = "Move", reparentLabel: l = "Move and reparent" } = n, u = (e, t) => {
19
+ let [n, ...r] = e.draggedIds, a = /* @__PURE__ */ new Map([[n, t.slotPose]]);
20
+ for (let n of r) {
21
+ let r = i(n, e.pointer.worldX, e.pointer.worldY);
22
+ r?.parentId === t.parentId && a.set(n, r.slotPose);
23
+ }
24
+ return a;
25
+ }, d = (e, t) => ({
26
+ pose: t.slotPose,
27
+ poses: u(e, t),
28
+ snap: t
29
+ });
19
30
  return {
20
31
  onMove(e, t) {
21
32
  let n = o(e), c = i(e.draggedIds[0], e.pointer.worldX, e.pointer.worldY);
22
33
  if (n.committedSnap) {
23
- if (c && c.parentId === n.committedSnap.parentId) return {
24
- pose: n.committedSnap.slotPose,
25
- snap: n.committedSnap
26
- };
34
+ if (c && c.parentId === n.committedSnap.parentId) return d(e, n.committedSnap);
27
35
  n.committedSnap = null;
28
36
  }
29
37
  if (!c) {
30
38
  s(n);
31
39
  return;
32
40
  }
33
- if (a?.(c)) return s(n), n.committedSnap = c, {
34
- pose: c.slotPose,
35
- snap: c
36
- };
41
+ if (a?.(c)) return s(n), n.committedSnap = c, d(e, c);
37
42
  n.pendingTargetId !== c.parentId && (s(n), n.pendingTargetId = c.parentId, n.pendingTimer = setTimeout(() => {
38
43
  n.committedSnap = c, n.pendingTimer = null;
39
44
  }, r));
@@ -46,18 +51,24 @@ function c(n) {
46
51
  s(r);
47
52
  let i = r.committedSnap ?? n.snap;
48
53
  if (!i) return;
49
- let a = n.draggedIds[0], u = n.adapter.getParent?.(a) ?? null, d = n.origin.get(a), f = [e({
50
- id: a,
51
- from: d,
52
- to: i.slotPose,
53
- label: c
54
- })];
55
- return u !== i.parentId && f.push(t({
56
- id: a,
57
- fromParentId: u,
58
- toParentId: i.parentId,
59
- label: l
60
- })), f;
54
+ let a = [], d = u(n, i);
55
+ for (let e of n.draggedIds) d.has(e) || d.set(e, n.current.get(e));
56
+ for (let [r, o] of d) {
57
+ a.push(e({
58
+ id: r,
59
+ from: n.origin.get(r),
60
+ to: o,
61
+ label: c
62
+ }));
63
+ let s = n.adapter.getParent?.(r) ?? null;
64
+ s !== i.parentId && a.push(t({
65
+ id: r,
66
+ fromParentId: s,
67
+ toParentId: i.parentId,
68
+ label: l
69
+ }));
70
+ }
71
+ return a;
61
72
  }
62
73
  };
63
74
  }
@@ -1 +1 @@
1
- {"version":3,"file":"snapToContainer.js","names":["STATE","scratchKey","getState","s","getScratch","ctx","setScratch","clearTimer","snapToContainer","args","target","findTarget","isInstant","dwellMs","snap","draggedId","oldParent","fromPose","ops","createTransformOp","moveLabel","createReparentOp","reparentLabel"],"sources":["../../../../../src/interactions/actions/move/behaviors/snapToContainer.ts"],"sourcesContent":["import { createTransformOp } from 'core/ops/transform';\nimport { createReparentOp } from 'core/ops/reparent';\nimport type { Op } from 'core/ops/types';\nimport type { SnapTarget } from 'core/adapters/types';\nimport type { MoveBehavior, GestureContext } from '../../../gestures/types';\nimport { scratchKey, getScratch, setScratch } from '@weasel-js/routing';\n\ninterface SnapState<TPose> {\n pendingTargetId: string | null;\n pendingTimer: ReturnType<typeof setTimeout> | null;\n committedSnap: SnapTarget<TPose> | null;\n}\n\n// The slot is generic over TPose; we keep the unknown-pose key at module\n// scope and project it through `as` at the read site (each consumer call\n// of `snapToContainer<TPose>` is the only writer of its own SnapState\n// instance, so the cast is safe at runtime).\nconst STATE = scratchKey<SnapState<unknown>>('snapToContainer');\n\nfunction getState<TPose>(ctx: GestureContext<TPose>): SnapState<TPose> {\n let s = getScratch(ctx.scratch, STATE) as SnapState<TPose> | undefined;\n if (!s) {\n s = { pendingTargetId: null, pendingTimer: null, committedSnap: null };\n setScratch(ctx.scratch, STATE, s as SnapState<unknown>);\n }\n return s;\n}\n\nfunction clearTimer<TPose>(s: SnapState<TPose>) {\n if (s.pendingTimer !== null) {\n clearTimeout(s.pendingTimer);\n s.pendingTimer = null;\n }\n s.pendingTargetId = null;\n}\n\n/**\n * Move behavior that drops the dragged node into a container it hovers over\n * for `dwellMs`, reparenting it and taking the pose the container's layout\n * assigns.\n *\n * The dwell is what keeps a drag that merely passes over a container from\n * being captured by it.\n */\nexport function snapToContainer<TPose>(args: {\n dwellMs: number;\n findTarget: (\n draggedId: string,\n worldX: number,\n worldY: number,\n ) => SnapTarget<TPose> | null;\n isInstant?: (target: SnapTarget<TPose>) => boolean;\n moveLabel?: string;\n reparentLabel?: string;\n}): MoveBehavior<TPose> {\n const { dwellMs, findTarget, isInstant, moveLabel = 'Move', reparentLabel = 'Move and reparent' } = args;\n\n return {\n onMove(ctx, _proposed) {\n const s = getState<TPose>(ctx);\n const target = findTarget(ctx.draggedIds[0], ctx.pointer.worldX, ctx.pointer.worldY);\n\n if (s.committedSnap) {\n if (target && target.parentId === s.committedSnap.parentId) {\n return { pose: s.committedSnap.slotPose, snap: s.committedSnap };\n }\n s.committedSnap = null;\n }\n\n if (!target) {\n clearTimer(s);\n return;\n }\n\n if (isInstant?.(target)) {\n clearTimer(s);\n s.committedSnap = target;\n return { pose: target.slotPose, snap: target };\n }\n\n if (s.pendingTargetId === target.parentId) {\n return;\n }\n clearTimer(s);\n s.pendingTargetId = target.parentId;\n s.pendingTimer = setTimeout(() => {\n s.committedSnap = target;\n s.pendingTimer = null;\n }, dwellMs);\n return;\n },\n\n onCancel(ctx) { clearTimer(getState<TPose>(ctx)); },\n\n onEnd(ctx) {\n const s = getState<TPose>(ctx);\n clearTimer(s);\n const snap = s.committedSnap ?? ctx.snap;\n if (!snap) return;\n const draggedId = ctx.draggedIds[0];\n const oldParent = ctx.adapter.getParent?.(draggedId) ?? null;\n const fromPose = ctx.origin.get(draggedId)!;\n const ops: Op[] = [\n createTransformOp<TPose>({\n id: draggedId,\n from: fromPose,\n to: snap.slotPose,\n label: moveLabel,\n }),\n ];\n if (oldParent !== snap.parentId) {\n ops.push(createReparentOp({\n id: draggedId,\n fromParentId: oldParent,\n toParentId: snap.parentId,\n label: reparentLabel,\n }));\n }\n return ops;\n },\n };\n}\n"],"mappings":";;;;AAiBA,IAAMA,IAAQC,EAA+B,iBAAiB;AAE9D,SAASC,EAAgB,GAA8C;CACrE,IAAIC,IAAIC,EAAWC,EAAI,SAASL,CAAK;CAKrC,OAJKG,MACH,IAAI;EAAE,iBAAiB;EAAM,cAAc;EAAM,eAAe;CAAK,GACrEG,EAAWD,EAAI,SAASL,GAAOG,CAAuB,IAEjDA;AACT;AAEA,SAASI,EAAkB,GAAqB;CAK9C,AAJIJ,EAAE,iBAAiB,SACrB,aAAaA,EAAE,YAAY,GAC3B,EAAE,eAAe,OAEnB,EAAE,kBAAkB;AACtB;AAUA,SAAgBK,EAAuB,GAUf;CACtB,IAAM,EAAE,YAAS,eAAY,cAAW,eAAY,QAAQ,mBAAgB,wBAAwBC;CAEpG,OAAO;EACL,OAAO,GAAK,GAAW;GACrB,IAAMN,IAAID,EAAgBG,CAAG,GACvBK,IAASC,EAAWN,EAAI,WAAW,IAAIA,EAAI,QAAQ,QAAQA,EAAI,QAAQ,MAAM;GAEnF,IAAIF,EAAE,eAAe;IACnB,IAAIO,KAAUA,EAAO,aAAaP,EAAE,cAAc,UAChD,OAAO;KAAE,MAAMA,EAAE,cAAc;KAAU,MAAMA,EAAE;IAAc;IAEjE,EAAE,gBAAgB;GACpB;GAEA,IAAI,CAACO,GAAQ;IACX,EAAWP,CAAC;IACZ;GACF;GAEA,IAAIS,IAAYF,CAAM,GAGpB,OAFAH,EAAWJ,CAAC,GACZ,EAAE,gBAAgBO,GACX;IAAE,MAAMA,EAAO;IAAU,MAAMA;GAAO;GAG/C,AAAIP,EAAE,oBAAoBO,EAAO,aAGjCH,EAAWJ,CAAC,GACZ,EAAE,kBAAkBO,EAAO,UAC3B,EAAE,eAAe,iBAAiB;IAEhC,AADA,EAAE,gBAAgBA,GAClB,EAAE,eAAe;GACnB,GAAGG,CAAO;EAEZ;EAEA,SAAS,GAAK;GAAE,EAAWX,EAAgBG,CAAG,CAAC;EAAG;EAElD,MAAM,GAAK;GACT,IAAMF,IAAID,EAAgBG,CAAG;GAC7B,EAAWF,CAAC;GACZ,IAAMW,IAAOX,EAAE,iBAAiBE,EAAI;GACpC,IAAI,CAACS,GAAM;GACX,IAAMC,IAAYV,EAAI,WAAW,IAC3BW,IAAYX,EAAI,QAAQ,YAAYU,CAAS,KAAK,MAClDE,IAAWZ,EAAI,OAAO,IAAIU,CAAS,GACnCG,IAAY,CAChBC,EAAyB;IACvB,IAAIJ;IACJ,MAAME;IACN,IAAIH,EAAK;IACT,OAAOM;GACT,CAAC,CACH;GASA,OARIJ,MAAcF,EAAK,YACrBI,EAAI,KAAKG,EAAiB;IACxB,IAAIN;IACJ,cAAcC;IACd,YAAYF,EAAK;IACjB,OAAOQ;GACT,CAAC,CAAC,GAEGJ;EACT;CACF;AACF"}
1
+ {"version":3,"file":"snapToContainer.js","names":["STATE","scratchKey","getState","s","getScratch","ctx","setScratch","clearTimer","snapToContainer","args","slotsFor","primary","rest","slots","snap","id","own","findTarget","snapped","target","isInstant","dwellMs","ops","to","createTransformOp","moveLabel","oldParent","createReparentOp","reparentLabel"],"sources":["../../../../../src/interactions/actions/move/behaviors/snapToContainer.ts"],"sourcesContent":["import { createTransformOp } from 'core/ops/transform';\nimport { createReparentOp } from 'core/ops/reparent';\nimport type { Op } from 'core/ops/types';\nimport type { SnapTarget } from 'core/adapters/types';\nimport type { BehaviorResult, MoveBehavior, GestureContext } from '../../../gestures/types';\nimport { scratchKey, getScratch, setScratch } from '@weasel-js/routing';\n\ninterface SnapState<TPose> {\n pendingTargetId: string | null;\n pendingTimer: ReturnType<typeof setTimeout> | null;\n committedSnap: SnapTarget<TPose> | null;\n}\n\n// The slot is generic over TPose; we keep the unknown-pose key at module\n// scope and project it through `as` at the read site (each consumer call\n// of `snapToContainer<TPose>` is the only writer of its own SnapState\n// instance, so the cast is safe at runtime).\nconst STATE = scratchKey<SnapState<unknown>>('snapToContainer');\n\nfunction getState<TPose>(ctx: GestureContext<TPose>): SnapState<TPose> {\n let s = getScratch(ctx.scratch, STATE) as SnapState<TPose> | undefined;\n if (!s) {\n s = { pendingTargetId: null, pendingTimer: null, committedSnap: null };\n setScratch(ctx.scratch, STATE, s as SnapState<unknown>);\n }\n return s;\n}\n\nfunction clearTimer<TPose>(s: SnapState<TPose>) {\n if (s.pendingTimer !== null) {\n clearTimeout(s.pendingTimer);\n s.pendingTimer = null;\n }\n s.pendingTargetId = null;\n}\n\n/**\n * Move behavior that drops the dragged nodes into a container the pointer\n * hovers over for `dwellMs`, reparenting each and giving it the slot\n * `findTarget` answers for its id. A node `findTarget` has no slot for in\n * that container rides along with the first, at its offset from it.\n *\n * The dwell is what keeps a drag that merely passes over a container from\n * being captured by it.\n */\nexport function snapToContainer<TPose>(args: {\n dwellMs: number;\n findTarget: (\n draggedId: string,\n worldX: number,\n worldY: number,\n ) => SnapTarget<TPose> | null;\n isInstant?: (target: SnapTarget<TPose>) => boolean;\n moveLabel?: string;\n reparentLabel?: string;\n}): MoveBehavior<TPose> {\n const { dwellMs, findTarget, isInstant, moveLabel = 'Move', reparentLabel = 'Move and reparent' } = args;\n\n /** Each dragged node's slot in the snapped container: the snapped slot for\n * the first, and for each other node the one `findTarget` answers for it. */\n const slotsFor = (ctx: GestureContext<TPose>, snap: SnapTarget<TPose>): Map<string, TPose> => {\n const [primary, ...rest] = ctx.draggedIds;\n const slots = new Map<string, TPose>([[primary, snap.slotPose]]);\n for (const id of rest) {\n const own = findTarget(id, ctx.pointer.worldX, ctx.pointer.worldY);\n if (own?.parentId === snap.parentId) slots.set(id, own.slotPose);\n }\n return slots;\n };\n const snapped = (ctx: GestureContext<TPose>, snap: SnapTarget<TPose>): BehaviorResult<TPose> =>\n ({ pose: snap.slotPose, poses: slotsFor(ctx, snap), snap });\n\n return {\n onMove(ctx, _proposed) {\n const s = getState<TPose>(ctx);\n const target = findTarget(ctx.draggedIds[0], ctx.pointer.worldX, ctx.pointer.worldY);\n\n if (s.committedSnap) {\n if (target && target.parentId === s.committedSnap.parentId) {\n return snapped(ctx, s.committedSnap);\n }\n s.committedSnap = null;\n }\n\n if (!target) {\n clearTimer(s);\n return;\n }\n\n if (isInstant?.(target)) {\n clearTimer(s);\n s.committedSnap = target;\n return snapped(ctx, target);\n }\n\n if (s.pendingTargetId === target.parentId) {\n return;\n }\n clearTimer(s);\n s.pendingTargetId = target.parentId;\n s.pendingTimer = setTimeout(() => {\n s.committedSnap = target;\n s.pendingTimer = null;\n }, dwellMs);\n return;\n },\n\n onCancel(ctx) { clearTimer(getState<TPose>(ctx)); },\n\n onEnd(ctx) {\n const s = getState<TPose>(ctx);\n clearTimer(s);\n const snap = s.committedSnap ?? ctx.snap;\n if (!snap) return;\n const ops: Op[] = [];\n const slots = slotsFor(ctx, snap);\n // A node with no slot of its own lands where the preview drew it.\n for (const id of ctx.draggedIds) if (!slots.has(id)) slots.set(id, ctx.current.get(id)!);\n for (const [id, to] of slots) {\n ops.push(createTransformOp<TPose>({ id, from: ctx.origin.get(id)!, to, label: moveLabel }));\n const oldParent = ctx.adapter.getParent?.(id) ?? null;\n if (oldParent !== snap.parentId) {\n ops.push(createReparentOp({\n id,\n fromParentId: oldParent,\n toParentId: snap.parentId,\n label: reparentLabel,\n }));\n }\n }\n return ops;\n },\n };\n}\n"],"mappings":";;;;AAiBA,IAAMA,IAAQC,EAA+B,iBAAiB;AAE9D,SAASC,EAAgB,GAA8C;CACrE,IAAIC,IAAIC,EAAWC,EAAI,SAASL,CAAK;CAKrC,OAJKG,MACH,IAAI;EAAE,iBAAiB;EAAM,cAAc;EAAM,eAAe;CAAK,GACrEG,EAAWD,EAAI,SAASL,GAAOG,CAAuB,IAEjDA;AACT;AAEA,SAASI,EAAkB,GAAqB;CAK9C,AAJIJ,EAAE,iBAAiB,SACrB,aAAaA,EAAE,YAAY,GAC3B,EAAE,eAAe,OAEnB,EAAE,kBAAkB;AACtB;AAWA,SAAgBK,EAAuB,GAUf;CACtB,IAAM,EAAE,YAAS,eAAY,cAAW,eAAY,QAAQ,mBAAgB,wBAAwBC,GAI9FC,KAAY,GAA4B,MAAgD;EAC5F,IAAM,CAACC,GAAS,GAAGC,KAAQP,EAAI,YACzBQ,oBAAQ,IAAI,IAAmB,CAAC,CAACF,GAASG,EAAK,QAAQ,CAAC,CAAC;EAC/D,KAAK,IAAMC,KAAMH,GAAM;GACrB,IAAMI,IAAMC,EAAWF,GAAIV,EAAI,QAAQ,QAAQA,EAAI,QAAQ,MAAM;GACjE,AAAIW,GAAK,aAAaF,EAAK,YAAUD,EAAM,IAAIE,GAAIC,EAAI,QAAQ;EACjE;EACA,OAAOH;CACT,GACMK,KAAW,GAA4B,OAC1C;EAAE,MAAMJ,EAAK;EAAU,OAAOJ,EAASL,GAAKS,CAAI;EAAG;CAAK;CAE3D,OAAO;EACL,OAAO,GAAK,GAAW;GACrB,IAAMX,IAAID,EAAgBG,CAAG,GACvBc,IAASF,EAAWZ,EAAI,WAAW,IAAIA,EAAI,QAAQ,QAAQA,EAAI,QAAQ,MAAM;GAEnF,IAAIF,EAAE,eAAe;IACnB,IAAIgB,KAAUA,EAAO,aAAahB,EAAE,cAAc,UAChD,OAAOe,EAAQb,GAAKF,EAAE,aAAa;IAErC,EAAE,gBAAgB;GACpB;GAEA,IAAI,CAACgB,GAAQ;IACX,EAAWhB,CAAC;IACZ;GACF;GAEA,IAAIiB,IAAYD,CAAM,GAGpB,OAFAZ,EAAWJ,CAAC,GACZ,EAAE,gBAAgBgB,GACXD,EAAQb,GAAKc,CAAM;GAG5B,AAAIhB,EAAE,oBAAoBgB,EAAO,aAGjCZ,EAAWJ,CAAC,GACZ,EAAE,kBAAkBgB,EAAO,UAC3B,EAAE,eAAe,iBAAiB;IAEhC,AADA,EAAE,gBAAgBA,GAClB,EAAE,eAAe;GACnB,GAAGE,CAAO;EAEZ;EAEA,SAAS,GAAK;GAAE,EAAWnB,EAAgBG,CAAG,CAAC;EAAG;EAElD,MAAM,GAAK;GACT,IAAMF,IAAID,EAAgBG,CAAG;GAC7B,EAAWF,CAAC;GACZ,IAAMW,IAAOX,EAAE,iBAAiBE,EAAI;GACpC,IAAI,CAACS,GAAM;GACX,IAAMQ,IAAY,CAAC,GACbT,IAAQH,EAASL,GAAKS,CAAI;GAEhC,KAAK,IAAMC,KAAMV,EAAI,YAAY,AAAKQ,EAAM,IAAIE,CAAE,KAAGF,EAAM,IAAIE,GAAIV,EAAI,QAAQ,IAAIU,CAAE,CAAE;GACvF,KAAK,IAAM,CAACA,GAAIQ,MAAOV,GAAO;IAC5B,EAAI,KAAKW,EAAyB;KAAE;KAAI,MAAMnB,EAAI,OAAO,IAAIU,CAAE;KAAI;KAAI,OAAOU;IAAU,CAAC,CAAC;IAC1F,IAAMC,IAAYrB,EAAI,QAAQ,YAAYU,CAAE,KAAK;IACjD,AAAIW,MAAcZ,EAAK,YACrBQ,EAAI,KAAKK,EAAiB;KACxB;KACA,cAAcD;KACd,YAAYZ,EAAK;KACjB,OAAOc;IACT,CAAC,CAAC;GAEN;GACA,OAAON;EACT;CACF;AACF"}
@@ -1,18 +1,33 @@
1
1
  import { documentPose as e } from "../../../core/scene/effectivePose.js";
2
2
  import { asNodeId as t } from "../../../core/scene/types.js";
3
3
  import { fnFieldsOfNode as n } from "../../../core/scene/nodeFnFields.js";
4
+ import { pickability as r } from "../../../core/scene/pickability.js";
4
5
  //#region src/interactions/actions/move/gestureAdapter.ts
5
- function r(r) {
6
- return {
7
- getNode: (e) => r.get(t(e)),
8
- getNodes: () => [...r.renderOrderNodes()],
9
- getPose: (n) => e(r, r.get(t(n))),
10
- getParent: (e) => r.get(t(e))?.parent ?? null,
11
- setPose: (e, n) => r.setPose(t(e), n),
12
- setParent: (e, n) => r.move(t(e), n === null ? null : t(n)),
13
- setData: (e, n) => r.update(t(e), { data: n }),
14
- removeNode: (e) => r.remove(t(e)),
15
- insertNode: (e, t) => r.add({
6
+ function i(i, a) {
7
+ let o = /* @__PURE__ */ new Map(), s = {
8
+ ...a ? { applyOps: (e, t) => a(e, t, s) } : {},
9
+ previewPoses: (e) => {
10
+ let { overrides: n } = i;
11
+ for (let [r, i] of e) {
12
+ let e = t(r), a = o.get(r), s = a !== void 0 && n.get(e) === a;
13
+ if (i === null) o.delete(r), s && n.clear(e);
14
+ else if (s) a.pose = i;
15
+ else {
16
+ let t = { pose: i };
17
+ o.set(r, t), n.set(e, t);
18
+ }
19
+ }
20
+ n.commit();
21
+ },
22
+ getNode: (e) => i.get(t(e)),
23
+ getNodes: () => [...i.renderOrderNodes()],
24
+ getPose: (n) => e(i, i.get(t(n))),
25
+ getParent: (e) => i.get(t(e))?.parent ?? null,
26
+ setPose: (e, n) => i.setPose(t(e), n),
27
+ setParent: (e, n) => i.move(t(e), n === null ? null : t(n)),
28
+ setData: (e, n) => i.update(t(e), { data: n }),
29
+ removeNode: (e) => i.remove(t(e)),
30
+ insertNode: (e, t) => i.add({
16
31
  kind: e.kind,
17
32
  layer: e.layer,
18
33
  pose: e.pose,
@@ -21,17 +36,19 @@ function r(r) {
21
36
  ...t === void 0 ? {} : { index: t },
22
37
  ...e.parent === null ? {} : { parent: e.parent },
23
38
  ...e.dependsOn === void 0 ? {} : { dependsOn: e.dependsOn },
39
+ ...r(e),
24
40
  ...n(e)
25
41
  }),
26
- getChildren: (e) => e === null ? [...r.roots] : [...r.childrenOf(t(e))],
42
+ getChildren: (e) => e === null ? [...i.roots] : [...i.childrenOf(t(e))],
27
43
  setChildOrder: (e, n) => {
28
- r.batch("Reorder", () => {
29
- for (let i = 0; i < n.length; i++) (e === null ? r.roots : r.childrenOf(t(e)))[i] !== n[i] && r.reorder(t(n[i]), i);
44
+ i.batch("Reorder", () => {
45
+ for (let r = 0; r < n.length; r++) (e === null ? i.roots : i.childrenOf(t(e)))[r] !== n[r] && i.reorder(t(n[r]), r);
30
46
  });
31
47
  }
32
48
  };
49
+ return s;
33
50
  }
34
51
  //#endregion
35
- export { r as moveGestureAdapter };
52
+ export { i as moveGestureAdapter };
36
53
 
37
54
  //# sourceMappingURL=gestureAdapter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gestureAdapter.js","names":["moveGestureAdapter","scene","asNodeId","id","documentPose","pose","parentId","node","index","fnFieldsOfNode","ids"],"sources":["../../../../src/interactions/actions/move/gestureAdapter.ts"],"sourcesContent":["/**\n * Minimal scene-backed adapter for the move behavior pipeline.\n *\n * Lives in `interactions/` rather than reusing `canvas/sceneAdapter.ts` so the\n * move action does not import from `canvas/` (that back-edge would create an\n * `interactions → canvas → interactions` cycle). Carries exactly the methods\n * the move behaviors call (`getParent` / `getNodes` / `getNode`) plus the\n * mutators the committed ops apply through (`setPose` / `setParent` /\n * `setData` / `removeNode` / `insertNode` — `setData` carries the\n * geometryProjection seam's data-sync op) and the sibling-order seam\n * (`getChildren` / `setChildOrder`) those ops read to restore a node's slot.\n */\nimport { documentPose } from 'core/scene/effectivePose';\nimport { fnFieldsOfNode } from 'core/scene/nodeFnFields';\nimport type { Node, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport type { MoveAdapter } from 'core/adapters/types';\n\nexport type MoveGestureAdapter<TPose> = MoveAdapter<Node<unknown, string, TPose>, TPose> & {\n /** Required override — this adapter always provides parent lookup. */\n getParent(id: string): string | null;\n setParent(id: string, parentId: string | null): void;\n setData(id: string, data: unknown): void;\n removeNode(id: string): void;\n insertNode(node: Node<unknown, string, TPose>, index?: number): void;\n getChildren(parentId: string | null): string[];\n setChildOrder(parentId: string | null, ids: string[]): void;\n};\n\nexport function moveGestureAdapter<TPose>(\n scene: Scene<unknown, string, TPose>,\n): MoveGestureAdapter<TPose> {\n return {\n getNode: (id) => scene.get(asNodeId(id)),\n getNodes: () => {\n return [...scene.renderOrderNodes()] as Node<unknown, string, TPose>[];\n },\n getPose: (id) => documentPose(scene, scene.get(asNodeId(id))!),\n getParent: (id) => scene.get(asNodeId(id))?.parent ?? null,\n setPose: (id, pose) => scene.setPose(asNodeId(id), pose),\n setParent: (id, parentId) =>\n scene.move(asNodeId(id), parentId === null ? null : asNodeId(parentId)),\n setData: (id, data) => scene.update(asNodeId(id), { data } as never),\n removeNode: (id) => scene.remove(asNodeId(id)),\n insertNode: (node, index) =>\n scene.add({\n kind: node.kind,\n layer: node.layer,\n pose: node.pose,\n data: node.data,\n id: node.id,\n ...(index !== undefined ? { index } : {}),\n ...(node.parent !== null ? { parent: node.parent } : {}),\n ...(node.dependsOn !== undefined ? { dependsOn: node.dependsOn } : {}),\n ...fnFieldsOfNode(node),\n }),\n getChildren: (parentId) =>\n parentId === null ? [...scene.roots] : [...scene.childrenOf(asNodeId(parentId))],\n setChildOrder: (parentId, ids) => {\n scene.batch('Reorder', () => {\n for (let i = 0; i < ids.length; i++) {\n const current = parentId === null ? scene.roots : scene.childrenOf(asNodeId(parentId));\n if (current[i] === ids[i]) continue;\n scene.reorder(asNodeId(ids[i]), i);\n }\n });\n },\n };\n}\n"],"mappings":";;;;AA6BA,SAAgBA,EACd,GAC2B;CAC3B,OAAO;EACL,UAAU,MAAOC,EAAM,IAAIC,EAASC,CAAE,CAAC;EACvC,gBACS,CAAC,GAAGF,EAAM,iBAAiB,CAAC;EAErC,UAAU,MAAOG,EAAaH,GAAOA,EAAM,IAAIC,EAASC,CAAE,CAAC,CAAE;EAC7D,YAAY,MAAOF,EAAM,IAAIC,EAASC,CAAE,CAAC,CAAC,EAAE,UAAU;EACtD,UAAU,GAAI,MAASF,EAAM,QAAQC,EAASC,CAAE,GAAGE,CAAI;EACvD,YAAY,GAAI,MACdJ,EAAM,KAAKC,EAASC,CAAE,GAAGG,MAAa,OAAO,OAAOJ,EAASI,CAAQ,CAAC;EACxE,UAAU,GAAI,MAASL,EAAM,OAAOC,EAASC,CAAE,GAAG,EAAE,QAAK,CAAU;EACnE,aAAa,MAAOF,EAAM,OAAOC,EAASC,CAAE,CAAC;EAC7C,aAAa,GAAM,MACjBF,EAAM,IAAI;GACR,MAAMM,EAAK;GACX,OAAOA,EAAK;GACZ,MAAMA,EAAK;GACX,MAAMA,EAAK;GACX,IAAIA,EAAK;GACT,GAAIC,MAAU,KAAA,IAAwB,CAAC,IAAb,EAAE,SAAM;GAClC,GAAID,EAAK,WAAW,OAAiC,CAAC,IAA3B,EAAE,QAAQA,EAAK,OAAO;GACjD,GAAIA,EAAK,cAAc,KAAA,IAA4C,CAAC,IAAjC,EAAE,WAAWA,EAAK,UAAU;GAC/D,GAAGE,EAAeF,CAAI;EACxB,CAAC;EACH,cAAc,MACZD,MAAa,OAAO,CAAC,GAAGL,EAAM,KAAK,IAAI,CAAC,GAAGA,EAAM,WAAWC,EAASI,CAAQ,CAAC,CAAC;EACjF,gBAAgB,GAAU,MAAQ;GAChC,EAAM,MAAM,iBAAiB;IAC3B,KAAK,IAAI,IAAI,GAAG,IAAII,EAAI,QAAQ,KAE9B,CADgBJ,MAAa,OAAOL,EAAM,QAAQA,EAAM,WAAWC,EAASI,CAAQ,CAAC,EAAA,CACzE,OAAOI,EAAI,MACvBT,EAAM,QAAQC,EAASQ,EAAI,EAAE,GAAG,CAAC;GAErC,CAAC;EACH;CACF;AACF"}
1
+ {"version":3,"file":"gestureAdapter.js","names":["moveGestureAdapter","previews","adapter","commit","ops","label","scene","id","pose","poses","nodeId","asNodeId","mine","installed","overrides","entry","documentPose","parentId","node","index","pickability","fnFieldsOfNode","i","ids"],"sources":["../../../../src/interactions/actions/move/gestureAdapter.ts"],"sourcesContent":["/**\n * Minimal scene-backed adapter for the move behavior pipeline.\n *\n * Lives in `interactions/` rather than reusing `canvas/sceneAdapter.ts` so the\n * move action does not import from `canvas/` (that back-edge would create an\n * `interactions → canvas → interactions` cycle). Carries exactly the methods\n * the move behaviors call (`getParent` / `getNodes` / `getNode`) plus the\n * mutators the committed ops apply through (`setPose` / `setParent` /\n * `setData` / `removeNode` / `insertNode` — `setData` carries the\n * geometryProjection seam's data-sync op) and the sibling-order seam\n * (`getChildren` / `setChildOrder`) those ops read to restore a node's slot.\n */\nimport { documentPose } from 'core/scene/effectivePose';\nimport { fnFieldsOfNode } from 'core/scene/nodeFnFields';\nimport { pickability } from 'core/scene/pickability';\nimport type { Op } from 'core/ops/types';\nimport type { Node, PoseOverride, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport type { MoveAdapter } from 'core/adapters/types';\n\nexport type MoveGestureAdapter<TPose> = MoveAdapter<Node<unknown, string, TPose>, TPose> & {\n /** Required override — this adapter always provides parent lookup. */\n getParent(id: string): string | null;\n setParent(id: string, parentId: string | null): void;\n setData(id: string, data: unknown): void;\n removeNode(id: string): void;\n insertNode(node: Node<unknown, string, TPose>, index?: number): void;\n getChildren(parentId: string | null): string[];\n setChildOrder(parentId: string | null, ids: string[]): void;\n previewPoses(poses: ReadonlyMap<string, TPose | null>): void;\n};\n\n/** `commit` is how a behavior's own `applyOps` batch lands; the returned\n * adapter is passed back so the ops apply through it. Left out, the adapter\n * has no `applyOps`. */\nexport function moveGestureAdapter<TPose>(\n scene: Scene<unknown, string, TPose>,\n commit?: (ops: Op[], label: string, adapter: MoveGestureAdapter<TPose>) => void,\n): MoveGestureAdapter<TPose> {\n const previews = new Map<string, PoseOverride<TPose>>();\n const adapter: MoveGestureAdapter<TPose> = {\n ...(commit ? { applyOps: (ops: Op[], label: string) => commit(ops, label, adapter) } : {}),\n previewPoses: (poses) => {\n const { overrides } = scene;\n for (const [id, pose] of poses) {\n const nodeId = asNodeId(id);\n const mine = previews.get(id);\n const installed = mine !== undefined && overrides.get(nodeId) === mine;\n if (pose === null) {\n previews.delete(id);\n if (installed) overrides.clear(nodeId);\n } else if (installed) {\n mine.pose = pose;\n } else {\n const entry = { pose };\n previews.set(id, entry);\n overrides.set(nodeId, entry);\n }\n }\n overrides.commit();\n },\n getNode: (id) => scene.get(asNodeId(id)),\n getNodes: () => {\n return [...scene.renderOrderNodes()] as Node<unknown, string, TPose>[];\n },\n getPose: (id) => documentPose(scene, scene.get(asNodeId(id))!),\n getParent: (id) => scene.get(asNodeId(id))?.parent ?? null,\n setPose: (id, pose) => scene.setPose(asNodeId(id), pose),\n setParent: (id, parentId) =>\n scene.move(asNodeId(id), parentId === null ? null : asNodeId(parentId)),\n setData: (id, data) => scene.update(asNodeId(id), { data } as never),\n removeNode: (id) => scene.remove(asNodeId(id)),\n insertNode: (node, index) =>\n scene.add({\n kind: node.kind,\n layer: node.layer,\n pose: node.pose,\n data: node.data,\n id: node.id,\n ...(index !== undefined ? { index } : {}),\n ...(node.parent !== null ? { parent: node.parent } : {}),\n ...(node.dependsOn !== undefined ? { dependsOn: node.dependsOn } : {}),\n ...pickability(node),\n ...fnFieldsOfNode(node),\n }),\n getChildren: (parentId) =>\n parentId === null ? [...scene.roots] : [...scene.childrenOf(asNodeId(parentId))],\n setChildOrder: (parentId, ids) => {\n scene.batch('Reorder', () => {\n for (let i = 0; i < ids.length; i++) {\n const current = parentId === null ? scene.roots : scene.childrenOf(asNodeId(parentId));\n if (current[i] === ids[i]) continue;\n scene.reorder(asNodeId(ids[i]), i);\n }\n });\n },\n };\n return adapter;\n}\n"],"mappings":";;;;;AAmCA,SAAgBA,EACd,GACA,GAC2B;CAC3B,IAAMC,oBAAW,IAAI,IAAiC,GAChDC,IAAqC;EACzC,GAAIC,IAAS,EAAE,WAAW,GAAW,MAAkBA,EAAOC,GAAKC,GAAOH,CAAO,EAAE,IAAI,CAAC;EACxF,eAAe,MAAU;GACvB,IAAM,EAAE,iBAAcI;GACtB,KAAK,IAAM,CAACC,GAAIC,MAASC,GAAO;IAC9B,IAAMC,IAASC,EAASJ,CAAE,GACpBK,IAAOX,EAAS,IAAIM,CAAE,GACtBM,IAAYD,MAAS,KAAA,KAAaE,EAAU,IAAIJ,CAAM,MAAME;IAClE,IAAIJ,MAAS,MAEX,AADAP,EAAS,OAAOM,CAAE,GACdM,KAAWC,EAAU,MAAMJ,CAAM;SAChC,IAAIG,GACT,EAAK,OAAOL;SACP;KACL,IAAMO,IAAQ,EAAE,QAAK;KAErB,AADAd,EAAS,IAAIM,GAAIQ,CAAK,GACtBD,EAAU,IAAIJ,GAAQK,CAAK;IAC7B;GACF;GACA,EAAU,OAAO;EACnB;EACA,UAAU,MAAOT,EAAM,IAAIK,EAASJ,CAAE,CAAC;EACvC,gBACS,CAAC,GAAGD,EAAM,iBAAiB,CAAC;EAErC,UAAU,MAAOU,EAAaV,GAAOA,EAAM,IAAIK,EAASJ,CAAE,CAAC,CAAE;EAC7D,YAAY,MAAOD,EAAM,IAAIK,EAASJ,CAAE,CAAC,CAAC,EAAE,UAAU;EACtD,UAAU,GAAI,MAASD,EAAM,QAAQK,EAASJ,CAAE,GAAGC,CAAI;EACvD,YAAY,GAAI,MACdF,EAAM,KAAKK,EAASJ,CAAE,GAAGU,MAAa,OAAO,OAAON,EAASM,CAAQ,CAAC;EACxE,UAAU,GAAI,MAASX,EAAM,OAAOK,EAASJ,CAAE,GAAG,EAAE,QAAK,CAAU;EACnE,aAAa,MAAOD,EAAM,OAAOK,EAASJ,CAAE,CAAC;EAC7C,aAAa,GAAM,MACjBD,EAAM,IAAI;GACR,MAAMY,EAAK;GACX,OAAOA,EAAK;GACZ,MAAMA,EAAK;GACX,MAAMA,EAAK;GACX,IAAIA,EAAK;GACT,GAAIC,MAAU,KAAA,IAAwB,CAAC,IAAb,EAAE,SAAM;GAClC,GAAID,EAAK,WAAW,OAAiC,CAAC,IAA3B,EAAE,QAAQA,EAAK,OAAO;GACjD,GAAIA,EAAK,cAAc,KAAA,IAA4C,CAAC,IAAjC,EAAE,WAAWA,EAAK,UAAU;GAC/D,GAAGE,EAAYF,CAAI;GACnB,GAAGG,EAAeH,CAAI;EACxB,CAAC;EACH,cAAc,MACZD,MAAa,OAAO,CAAC,GAAGX,EAAM,KAAK,IAAI,CAAC,GAAGA,EAAM,WAAWK,EAASM,CAAQ,CAAC,CAAC;EACjF,gBAAgB,GAAU,MAAQ;GAChC,EAAM,MAAM,iBAAiB;IAC3B,KAAK,IAAIK,IAAI,GAAGA,IAAIC,EAAI,QAAQ,KAE9B,CADgBN,MAAa,OAAOX,EAAM,QAAQA,EAAM,WAAWK,EAASM,CAAQ,CAAC,EAAA,CACzEK,OAAOC,EAAID,MACvBhB,EAAM,QAAQK,EAASY,EAAID,EAAE,GAAGA,CAAC;GAErC,CAAC;EACH;CACF;CACA,OAAOpB;AACT"}
@@ -0,0 +1,33 @@
1
+ import { createTransformOp as e } from "../../../core/ops/transform.js";
2
+ import { translatePoseViaDescriptor as t } from "../../../core/geometry/poseDescriptor.js";
3
+ import { subtreeIds as n } from "../selectionSubtree.js";
4
+ //#region src/interactions/actions/move/landedDescendants.ts
5
+ function r(r, i) {
6
+ let { scene: a, projection: o, startPoses: s, carried: c, label: l } = r, u = /* @__PURE__ */ new Map();
7
+ for (let e of i) {
8
+ if (e.name !== "transform") continue;
9
+ let t = e.args;
10
+ u.set(t.id, t.to);
11
+ }
12
+ let d = [];
13
+ for (let i of r.roots) {
14
+ let r = u.get(i), f = s.get(i);
15
+ if (r === void 0 || f === void 0) continue;
16
+ let p = o.getBounds(f), m = o.getBounds(r), h = m.x - p.x, g = m.y - p.y;
17
+ if (h !== 0 || g !== 0) for (let r of n(a, i)) {
18
+ if (r === i || u.has(r) || c.has(r)) continue;
19
+ let n = a.get(r);
20
+ n && d.push(e({
21
+ id: r,
22
+ from: n.pose,
23
+ to: t(n.pose, h, g, o),
24
+ label: l
25
+ }));
26
+ }
27
+ }
28
+ return d;
29
+ }
30
+ //#endregion
31
+ export { r as landedDescendantOps };
32
+
33
+ //# sourceMappingURL=landedDescendants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"landedDescendants.js","names":["landedDescendantOps","input","landed","op","ops","a","out","root","to","start","startPoses","projection","b","dx","dy","id","subtreeIds","scene","carried","node","createTransformOp","translatePoseViaDescriptor"],"sources":["../../../../src/interactions/actions/move/landedDescendants.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createTransformOp } from 'core/ops/transform';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from 'core/geometry/poseDescriptor';\nimport { subtreeIds } from '../selectionSubtree';\n\n/** What a move gesture captured at its start, as this pass reads it. */\nexport interface LandedDescendantsInput {\n scene: Scene<unknown, string, unknown>;\n projection: PoseDescriptor<unknown>;\n /** The dragged roots. */\n roots: readonly NodeId[];\n /** Start pose of every root and descendant. */\n startPoses: ReadonlyMap<NodeId, unknown>;\n /** Descendants stored in a moving node's frame, which that node carries. */\n carried: ReadonlySet<NodeId>;\n label: string;\n}\n\n/**\n * Ops that bring each dragged root's descendants along to wherever `ops` put\n * the root. A layout drop or a behavior places the root itself, somewhere the\n * drag delta does not describe, so each descendant moves by its root's landed\n * pose less its start pose. A descendant `ops` already writes, or that a\n * moving frame carries, is left alone.\n */\nexport function landedDescendantOps(input: LandedDescendantsInput, ops: readonly Op[]): Op[] {\n const { scene, projection, startPoses, carried, label } = input;\n const landed = new Map<string, unknown>();\n for (const op of ops) {\n if (op.name !== 'transform') continue;\n const a = op.args as { id: string; to: unknown };\n landed.set(a.id, a.to);\n }\n const out: Op[] = [];\n for (const root of input.roots) {\n const to = landed.get(root);\n const start = startPoses.get(root);\n if (to === undefined || start === undefined) continue;\n const a = projection.getBounds(start);\n const b = projection.getBounds(to);\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n if (dx === 0 && dy === 0) continue;\n for (const id of subtreeIds(scene, root)) {\n if (id === root || landed.has(id) || carried.has(id)) continue;\n const node = scene.get(id);\n if (!node) continue;\n out.push(createTransformOp<unknown>({\n id,\n from: node.pose,\n to: translatePoseViaDescriptor(node.pose, dx, dy, projection),\n label,\n }));\n }\n }\n return out;\n}\n"],"mappings":";;;;AA0BA,SAAgBA,EAAoB,GAA+B,GAA0B;CAC3F,IAAM,EAAE,UAAO,eAAY,eAAY,YAAS,aAAUC,GACpDC,oBAAS,IAAI,IAAqB;CACxC,KAAK,IAAMC,KAAMC,GAAK;EACpB,IAAID,EAAG,SAAS,aAAa;EAC7B,IAAME,IAAIF,EAAG;EACb,EAAO,IAAIE,EAAE,IAAIA,EAAE,EAAE;CACvB;CACA,IAAMC,IAAY,CAAC;CACnB,KAAK,IAAMC,KAAQN,EAAM,OAAO;EAC9B,IAAMO,IAAKN,EAAO,IAAIK,CAAI,GACpBE,IAAQC,EAAW,IAAIH,CAAI;EACjC,IAAIC,MAAO,KAAA,KAAaC,MAAU,KAAA,GAAW;EAC7C,IAAMJ,IAAIM,EAAW,UAAUF,CAAK,GAC9BG,IAAID,EAAW,UAAUH,CAAE,GAC3BK,IAAKD,EAAE,IAAIP,EAAE,GACbS,IAAKF,EAAE,IAAIP,EAAE;EACnB,IAAIQ,MAAO,KAAKC,MAAO,GACvB,KAAK,IAAMC,KAAMC,EAAWC,GAAOV,CAAI,GAAG;GACxC,IAAIQ,MAAOR,KAAQL,EAAO,IAAIa,CAAE,KAAKG,EAAQ,IAAIH,CAAE,GAAG;GACtD,IAAMI,IAAOF,EAAM,IAAIF,CAAE;GACzB,AAAKI,KACLb,EAAI,KAAKc,EAA2B;IAClC;IACA,MAAMD,EAAK;IACX,IAAIE,EAA2BF,EAAK,MAAMN,GAAIC,GAAIH,CAAU;IAC5D;GACF,CAAC,CAAC;EACJ;CACF;CACA,OAAOL;AACT"}
@@ -1,5 +1,5 @@
1
- import { locateChild as e } from "../../../core/ops/slot.js";
2
- import { unionBounds as t } from "../../../core/geometry/unionBounds.js";
1
+ import { unionBounds as e } from "../../../core/geometry/unionBounds.js";
2
+ import { locateChild as t } from "../../../core/ops/slot.js";
3
3
  import { createDeleteOp as n } from "../../../core/ops/delete.js";
4
4
  import { createInsertOp as r } from "../../../core/ops/create.js";
5
5
  import { dispatchApplyBatch as i } from "../../../core/applyOps.js";
@@ -7,15 +7,15 @@ import { createSetSelectionOp as a } from "../../../core/ops/select.js";
7
7
  import { TextOutlinesError as o, textToPathsByPaint as s } from "../../../features/text/textToPath.js";
8
8
  import { boundsOfPath as c } from "@weasel-js/geom";
9
9
  //#region src/interactions/actions/outlines/createOutlines.ts
10
- function l(t) {
11
- let c = [...t.getSelection()], l = [];
10
+ function l(e) {
11
+ let c = [...e.getSelection()], l = [];
12
12
  try {
13
- for (let e of c) {
14
- let n = t.getTextSource(e);
13
+ for (let t of c) {
14
+ let n = e.getTextSource(t);
15
15
  if (!n) continue;
16
16
  let r = s(n.data, n.pose);
17
17
  r.length > 0 && l.push({
18
- id: e,
18
+ id: t,
19
19
  paths: r
20
20
  });
21
21
  }
@@ -33,10 +33,10 @@ function l(t) {
33
33
  };
34
34
  let f = [], p = /* @__PURE__ */ new Map(), m = [...l.map((n) => ({
35
35
  ...n,
36
- at: e(t, n.id)
36
+ at: t(e, n.id)
37
37
  }))].sort((e, t) => (t.at?.index ?? -1) - (e.at?.index ?? -1));
38
- for (let { id: e, paths: i, at: a } of m) {
39
- let o = t.getNode?.(e) ?? { id: e }, s = a?.index ?? -1, c = a?.parentId ?? t.getParent?.(e) ?? null, l = (e, t) => r(s >= 0 ? {
38
+ for (let { id: t, paths: i, at: a } of m) {
39
+ let o = e.getNode?.(t) ?? { id: t }, s = a?.index ?? -1, c = a?.parentId ?? e.getParent?.(t) ?? null, l = (e, t) => r(s >= 0 ? {
40
40
  node: e,
41
41
  index: s + t
42
42
  } : { node: e });
@@ -44,23 +44,23 @@ function l(t) {
44
44
  node: o,
45
45
  index: s
46
46
  }));
47
- let m = i.length > 1 ? t.createContainerNode?.(e, {
47
+ let m = i.length > 1 ? e.createContainerNode?.(t, {
48
48
  parent: c,
49
49
  bounds: d(i)
50
50
  }) : void 0;
51
51
  if (m) {
52
52
  f.push(l(m, 0));
53
- for (let n of i) f.push(r({ node: t.createPathNode(n.path, e, u(n, m.id)) }));
54
- p.set(e, [m.id]);
53
+ for (let n of i) f.push(r({ node: e.createPathNode(n.path, t, u(n, m.id)) }));
54
+ p.set(t, [m.id]);
55
55
  } else {
56
- let n = i.map((n) => t.createPathNode(n.path, e, u(n, c)));
57
- n.forEach((e, t) => f.push(l(e, t))), p.set(e, n.map((e) => e.id));
56
+ let n = i.map((n) => e.createPathNode(n.path, t, u(n, c)));
57
+ n.forEach((e, t) => f.push(l(e, t))), p.set(t, n.map((e) => e.id));
58
58
  }
59
59
  }
60
60
  return f.push(a({
61
61
  from: c,
62
62
  to: c.flatMap((e) => p.get(e) ?? [e])
63
- })), i(t, f, "Create Outlines"), {
63
+ })), i(e, f, "Create Outlines"), {
64
64
  kind: "applied",
65
65
  resultIds: l.flatMap((e) => p.get(e.id))
66
66
  };
@@ -75,8 +75,8 @@ function u(e, t) {
75
75
  parent: t
76
76
  };
77
77
  }
78
- function d(e) {
79
- return t(e.map((e) => c(e.path)));
78
+ function d(t) {
79
+ return e(t.map((e) => c(e.path)));
80
80
  }
81
81
  //#endregion
82
82
  export { l as applyCreateOutlines };
@@ -1,9 +1,21 @@
1
- import { AUTO_POSE_DESCRIPTOR as e } from "./resize/autoPoseDescriptor.js";
1
+ import { poseDescriptorForNode as e } from "../../core/geometry/poseDescriptor.js";
2
+ import { AUTO_POSE_DESCRIPTOR as t } from "./resize/autoPoseDescriptor.js";
2
3
  //#region src/interactions/actions/poseDescriptorDep.ts
3
- function t(t) {
4
- return t ?? e;
4
+ function n(e) {
5
+ return e ?? t;
6
+ }
7
+ function r(t, n) {
8
+ let r = /* @__PURE__ */ new Map();
9
+ return (i) => {
10
+ let a = r.get(i);
11
+ if (a === void 0) {
12
+ let o = t.get(i);
13
+ a = o === void 0 ? n : e(n, o), r.set(i, a);
14
+ }
15
+ return a;
16
+ };
5
17
  }
6
18
  //#endregion
7
- export { t as poseDescriptorOf };
19
+ export { r as nodeDescriptors, n as poseDescriptorOf };
8
20
 
9
21
  //# sourceMappingURL=poseDescriptorDep.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"poseDescriptorDep.js","names":["poseDescriptorOf","dep","AUTO_POSE_DESCRIPTOR"],"sources":["../../../src/interactions/actions/poseDescriptorDep.ts"],"sourcesContent":["import type { PoseDescriptor } from './resize/geometry';\nimport { AUTO_POSE_DESCRIPTOR } from './resize/autoPoseDescriptor';\n\n/** The `poseDescriptor` dep's value, or the auto descriptor when unsourced. */\nexport function poseDescriptorOf(dep: unknown): PoseDescriptor<unknown> {\n return (dep as PoseDescriptor<unknown> | undefined) ?? AUTO_POSE_DESCRIPTOR;\n}\n"],"mappings":";;AAIA,SAAgBA,EAAiB,GAAuC;CACtE,OAAQC,KAA+CC;AACzD"}
1
+ {"version":3,"file":"poseDescriptorDep.js","names":["poseDescriptorOf","dep","AUTO_POSE_DESCRIPTOR","nodeDescriptors","resolved","d","id","node","scene","descriptor","poseDescriptorForNode"],"sources":["../../../src/interactions/actions/poseDescriptorDep.ts"],"sourcesContent":["import type { NodeId, Scene } from 'core/scene/types';\nimport { poseDescriptorForNode, type PoseDescriptor } from './resize/geometry';\nimport { AUTO_POSE_DESCRIPTOR } from './resize/autoPoseDescriptor';\n\n/** The `poseDescriptor` dep's value, or the auto descriptor when unsourced. */\nexport function poseDescriptorOf(dep: unknown): PoseDescriptor<unknown> {\n return (dep as PoseDescriptor<unknown> | undefined) ?? AUTO_POSE_DESCRIPTOR;\n}\n\n/**\n * A reader of each node's own descriptor (`PoseDescriptor.forNode`), resolved\n * once per id. An action builds one where it captures its start poses and\n * reads and writes every pose through it, so a node measured as its own shape\n * is written as that shape too. An id that is not a scene node, such as a\n * multi-selection's stand-in target, reads through `descriptor` itself.\n */\nexport function nodeDescriptors(\n scene: Scene<unknown, string, unknown>,\n descriptor: PoseDescriptor<unknown>,\n): (id: NodeId | string) => PoseDescriptor<unknown> {\n const resolved = new Map<string, PoseDescriptor<unknown>>();\n return (id) => {\n let d = resolved.get(id);\n if (d === undefined) {\n const node = scene.get(id as NodeId);\n d = node === undefined ? descriptor : poseDescriptorForNode(descriptor, node);\n resolved.set(id, d);\n }\n return d;\n };\n}\n"],"mappings":";;;AAKA,SAAgBA,EAAiB,GAAuC;CACtE,OAAQC,KAA+CC;AACzD;AASA,SAAgBC,EACd,GACA,GACkD;CAClD,IAAMC,oBAAW,IAAI,IAAqC;CAC1D,QAAQ,MAAO;EACb,IAAIC,IAAID,EAAS,IAAIE,CAAE;EACvB,IAAID,MAAM,KAAA,GAAW;GACnB,IAAME,IAAOC,EAAM,IAAIF,CAAY;GAEnC,AADA,IAAIC,MAAS,KAAA,IAAYE,IAAaC,EAAsBD,GAAYF,CAAI,GAC5EH,EAAS,IAAIE,GAAID,CAAC;EACpB;EACA,OAAOA;CACT;AACF"}
@@ -1,10 +1,15 @@
1
1
  import { IDENTITY_POSE_COMPOSITION as e, composeWorldPose as t, frameAtOrAbove as n, rebaseLocalPose as r } from "../../core/scene/composeFrame.js";
2
2
  import { definesFrame as i, effectivePose as a } from "../../core/scene/effectivePose.js";
3
+ import { asNodeId as o } from "../../core/scene/types.js";
3
4
  //#region src/interactions/actions/poseFrame.ts
4
- function o(e, i) {
5
+ function s(e, i) {
5
6
  return {
6
7
  pc: i,
7
8
  world: (n) => t(e, n, i.compose),
9
+ frame: (t) => {
10
+ let r = n(e, e.getParent(t));
11
+ return r === null ? null : o(r);
12
+ },
8
13
  parentWorld: (r) => {
9
14
  let a = n(e, e.getParent(r));
10
15
  return a === null ? null : t(e, a, i.compose);
@@ -13,9 +18,9 @@ function o(e, i) {
13
18
  localUnder: (t, n) => r(e, n, t, i.compose, i.decompose)
14
19
  };
15
20
  }
16
- function s(t, n) {
17
- let r = n ?? e, s = t;
18
- return o({
21
+ function c(t, n) {
22
+ let r = n ?? e, o = t;
23
+ return s({
19
24
  getPose: (e) => {
20
25
  let n = t.get(e);
21
26
  return n === void 0 ? {
@@ -23,7 +28,7 @@ function s(t, n) {
23
28
  y: 0,
24
29
  width: 0,
25
30
  height: 0
26
- } : a(s, n);
31
+ } : a(o, n);
27
32
  },
28
33
  getParent: (e) => t.get(e)?.parent ?? null,
29
34
  definesFrame: (e) => {
@@ -33,6 +38,6 @@ function s(t, n) {
33
38
  }, r);
34
39
  }
35
40
  //#endregion
36
- export { o as poseFrame, s as scenePoseFrame };
41
+ export { s as poseFrame, c as scenePoseFrame };
37
42
 
38
43
  //# sourceMappingURL=poseFrame.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"poseFrame.js","names":["poseFrame","composeWorldPose","adapter","id","pc","frame","frameAtOrAbove","rebaseLocalPose","worldPose","parentId","scenePoseFrame","poseComposition","IDENTITY_POSE_COMPOSITION","source","scene","node","effectivePose","definesFrame"],"sources":["../../../src/interactions/actions/poseFrame.ts"],"sourcesContent":["/**\n * World reads and local writes, paired, for the default actions.\n *\n * A container's pose defines a frame, so a node's stored pose is expressed in\n * its parent's. The geometry an action reasons about — a rotate pivot, an\n * alignment edge, a distribute span, a flip axis — is world; every pose it\n * writes back through `setPose` or a pose op is local. An action that reads\n * world and writes world looks right for one gesture and drifts on the next,\n * because the stored pose is then read in the parent's frame again.\n *\n * Under `IDENTITY_POSE_COMPOSITION` — the default, and what every consumer\n * ships today — local and world are the same value and all of this is an\n * identity. `features/groups/frameFixture.ts` is the scene where they differ.\n */\nimport { definesFrame, effectivePose, type PoseSource } from 'core/scene/effectivePose';\nimport type { NodeId, Scene } from 'core/scene/types';\nimport {\n composeWorldPose,\n frameAtOrAbove,\n rebaseLocalPose,\n IDENTITY_POSE_COMPOSITION,\n type PoseAdapter,\n type PoseComposition,\n} from 'features/groups/composePose';\n\n/** The two directions an action needs, over one composition strategy. */\nexport interface PoseFrame<TPose> {\n /** The strategy in force. `closure` says what it can express exactly. */\n readonly pc: PoseComposition<TPose>;\n /** `id`'s pose in world coordinates, honoring an in-flight gesture override. */\n world(id: NodeId): TPose;\n /** World pose of the frame `id` is stored in, or `null` for the root frame. */\n parentWorld(id: NodeId): TPose | null;\n /** `worldPose` expressed in `id`'s own parent frame — what `setPose` stores. */\n local(id: NodeId, worldPose: TPose): TPose;\n /** `worldPose` expressed under `parentId`'s frame. For a node about to be\n * reparented, whose current parent is not the frame it will be stored in. */\n localUnder(parentId: NodeId | null, worldPose: TPose): TPose;\n}\n\n/** Pair the two directions over an arbitrary pose adapter. */\nexport function poseFrame<TPose>(\n adapter: PoseAdapter<TPose>,\n pc: PoseComposition<TPose>,\n): PoseFrame<TPose> {\n return {\n pc,\n world: (id) => composeWorldPose(adapter, id as string, pc.compose),\n parentWorld: (id) => {\n const frame = frameAtOrAbove(adapter, adapter.getParent(id as string));\n return frame === null ? null : composeWorldPose(adapter, frame, pc.compose);\n },\n local: (id, worldPose) =>\n rebaseLocalPose(adapter, worldPose, adapter.getParent(id as string), pc.compose, pc.decompose),\n localUnder: (parentId, worldPose) =>\n rebaseLocalPose(adapter, worldPose, parentId as string | null, pc.compose, pc.decompose),\n };\n}\n\n/** The `poseFrame` a scene-backed action works in. `poseComposition` is the\n * dep as it arrives — absent means IDENTITY, where every method is a no-op. */\nexport function scenePoseFrame(\n scene: Scene<unknown, string, unknown>,\n poseComposition: unknown,\n): PoseFrame<unknown> {\n const pc =\n (poseComposition as PoseComposition<unknown> | undefined) ?? IDENTITY_POSE_COMPOSITION;\n const source = scene as unknown as PoseSource<unknown>;\n const adapter: PoseAdapter<unknown> = {\n getPose: (id) => {\n const node = scene.get(id as NodeId);\n return node === undefined ? { x: 0, y: 0, width: 0, height: 0 } : effectivePose(source, node);\n },\n getParent: (id) => scene.get(id as NodeId)?.parent ?? null,\n definesFrame: (id) => {\n const node = scene.get(id as NodeId);\n return node === undefined || definesFrame(node);\n },\n };\n return poseFrame(adapter, pc);\n}\n"],"mappings":";;;AAyCA,SAAgBA,EACd,GACA,GACkB;CAClB,OAAO;EACL;EACA,QAAQ,MAAOC,EAAiBC,GAASC,GAAcC,EAAG,OAAO;EACjE,cAAc,MAAO;GACnB,IAAMC,IAAQC,EAAeJ,GAASA,EAAQ,UAAUC,CAAY,CAAC;GACrE,OAAOE,MAAU,OAAO,OAAOJ,EAAiBC,GAASG,GAAOD,EAAG,OAAO;EAC5E;EACA,QAAQ,GAAI,MACVG,EAAgBL,GAASM,GAAWN,EAAQ,UAAUC,CAAY,GAAGC,EAAG,SAASA,EAAG,SAAS;EAC/F,aAAa,GAAU,MACrBG,EAAgBL,GAASM,GAAWC,GAA2BL,EAAG,SAASA,EAAG,SAAS;CAC3F;AACF;AAIA,SAAgBM,EACd,GACA,GACoB;CACpB,IAAMN,IACHO,KAA4DC,GACzDC,IAASC;CAYf,OAAOd,EAAU;EAVf,UAAU,MAAO;GACf,IAAMe,IAAOD,EAAM,IAAIX,CAAY;GACnC,OAAOY,MAAS,KAAA,IAAY;IAAE,GAAG;IAAG,GAAG;IAAG,OAAO;IAAG,QAAQ;GAAE,IAAIC,EAAcH,GAAQE,CAAI;EAC9F;EACA,YAAY,MAAOD,EAAM,IAAIX,CAAY,CAAC,EAAE,UAAU;EACtD,eAAe,MAAO;GACpB,IAAMY,IAAOD,EAAM,IAAIX,CAAY;GACnC,OAAOY,MAAS,KAAA,KAAaE,EAAaF,CAAI;EAChD;CAEe,GAASX,CAAE;AAC9B"}
1
+ {"version":3,"file":"poseFrame.js","names":["poseFrame","composeWorldPose","adapter","id","pc","frame","frameAtOrAbove","asNodeId","rebaseLocalPose","worldPose","parentId","scenePoseFrame","poseComposition","IDENTITY_POSE_COMPOSITION","source","scene","node","effectivePose","definesFrame"],"sources":["../../../src/interactions/actions/poseFrame.ts"],"sourcesContent":["/**\n * World reads and local writes, paired, for the default actions.\n *\n * A container's pose defines a frame, so a node's stored pose is expressed in\n * its parent's. The geometry an action reasons about — a rotate pivot, an\n * alignment edge, a distribute span, a flip axis — is world; every pose it\n * writes back through `setPose` or a pose op is local. An action that reads\n * world and writes world looks right for one gesture and drifts on the next,\n * because the stored pose is then read in the parent's frame again.\n *\n * Under `IDENTITY_POSE_COMPOSITION` — the default, and what every consumer\n * ships today — local and world are the same value and all of this is an\n * identity. `features/groups/frameFixture.ts` is the scene where they differ.\n */\nimport { definesFrame, effectivePose, type PoseSource } from 'core/scene/effectivePose';\nimport { asNodeId, type NodeId, type Scene } from 'core/scene/types';\nimport {\n composeWorldPose,\n frameAtOrAbove,\n rebaseLocalPose,\n IDENTITY_POSE_COMPOSITION,\n type PoseAdapter,\n type PoseComposition,\n} from 'features/groups/composePose';\n\n/** The two directions an action needs, over one composition strategy. */\nexport interface PoseFrame<TPose> {\n /** The strategy in force. `closure` says what it can express exactly. */\n readonly pc: PoseComposition<TPose>;\n /** `id`'s pose in world coordinates, honoring an in-flight gesture override. */\n world(id: NodeId): TPose;\n /** The node whose frame `id` is stored in, or `null` for the root frame. */\n frame(id: NodeId): NodeId | null;\n /** World pose of the frame `id` is stored in, or `null` for the root frame. */\n parentWorld(id: NodeId): TPose | null;\n /** `worldPose` expressed in `id`'s own parent frame — what `setPose` stores. */\n local(id: NodeId, worldPose: TPose): TPose;\n /** `worldPose` expressed under `parentId`'s frame. For a node about to be\n * reparented, whose current parent is not the frame it will be stored in. */\n localUnder(parentId: NodeId | null, worldPose: TPose): TPose;\n}\n\n/** Pair the two directions over an arbitrary pose adapter. */\nexport function poseFrame<TPose>(\n adapter: PoseAdapter<TPose>,\n pc: PoseComposition<TPose>,\n): PoseFrame<TPose> {\n return {\n pc,\n world: (id) => composeWorldPose(adapter, id as string, pc.compose),\n frame: (id) => {\n const frame = frameAtOrAbove(adapter, adapter.getParent(id as string));\n return frame === null ? null : asNodeId(frame);\n },\n parentWorld: (id) => {\n const frame = frameAtOrAbove(adapter, adapter.getParent(id as string));\n return frame === null ? null : composeWorldPose(adapter, frame, pc.compose);\n },\n local: (id, worldPose) =>\n rebaseLocalPose(adapter, worldPose, adapter.getParent(id as string), pc.compose, pc.decompose),\n localUnder: (parentId, worldPose) =>\n rebaseLocalPose(adapter, worldPose, parentId as string | null, pc.compose, pc.decompose),\n };\n}\n\n/** The `poseFrame` a scene-backed action works in. `poseComposition` is the\n * dep as it arrives — absent means IDENTITY, where every method is a no-op. */\nexport function scenePoseFrame(\n scene: Scene<unknown, string, unknown>,\n poseComposition: unknown,\n): PoseFrame<unknown> {\n const pc =\n (poseComposition as PoseComposition<unknown> | undefined) ?? IDENTITY_POSE_COMPOSITION;\n const source = scene as unknown as PoseSource<unknown>;\n const adapter: PoseAdapter<unknown> = {\n getPose: (id) => {\n const node = scene.get(id as NodeId);\n return node === undefined ? { x: 0, y: 0, width: 0, height: 0 } : effectivePose(source, node);\n },\n getParent: (id) => scene.get(id as NodeId)?.parent ?? null,\n definesFrame: (id) => {\n const node = scene.get(id as NodeId);\n return node === undefined || definesFrame(node);\n },\n };\n return poseFrame(adapter, pc);\n}\n"],"mappings":";;;;AA2CA,SAAgBA,EACd,GACA,GACkB;CAClB,OAAO;EACL;EACA,QAAQ,MAAOC,EAAiBC,GAASC,GAAcC,EAAG,OAAO;EACjE,QAAQ,MAAO;GACb,IAAMC,IAAQC,EAAeJ,GAASA,EAAQ,UAAUC,CAAY,CAAC;GACrE,OAAOE,MAAU,OAAO,OAAOE,EAASF,CAAK;EAC/C;EACA,cAAc,MAAO;GACnB,IAAMA,IAAQC,EAAeJ,GAASA,EAAQ,UAAUC,CAAY,CAAC;GACrE,OAAOE,MAAU,OAAO,OAAOJ,EAAiBC,GAASG,GAAOD,EAAG,OAAO;EAC5E;EACA,QAAQ,GAAI,MACVI,EAAgBN,GAASO,GAAWP,EAAQ,UAAUC,CAAY,GAAGC,EAAG,SAASA,EAAG,SAAS;EAC/F,aAAa,GAAU,MACrBI,EAAgBN,GAASO,GAAWC,GAA2BN,EAAG,SAASA,EAAG,SAAS;CAC3F;AACF;AAIA,SAAgBO,EACd,GACA,GACoB;CACpB,IAAMP,IACHQ,KAA4DC,GACzDC,IAASC;CAYf,OAAOf,EAAU;EAVf,UAAU,MAAO;GACf,IAAMgB,IAAOD,EAAM,IAAIZ,CAAY;GACnC,OAAOa,MAAS,KAAA,IAAY;IAAE,GAAG;IAAG,GAAG;IAAG,OAAO;IAAG,QAAQ;GAAE,IAAIC,EAAcH,GAAQE,CAAI;EAC9F;EACA,YAAY,MAAOD,EAAM,IAAIZ,CAAY,CAAC,EAAE,UAAU;EACtD,eAAe,MAAO;GACpB,IAAMa,IAAOD,EAAM,IAAIZ,CAAY;GACnC,OAAOa,MAAS,KAAA,KAAaE,EAAaF,CAAI;EAChD;CAEe,GAASZ,CAAE;AAC9B"}
@@ -10,14 +10,14 @@ function e(e) {
10
10
  let a = { pose: r };
11
11
  e.overrideEntries.set(n, a), t.set(n, a);
12
12
  }
13
- for (let n of e.overrideEntries.keys()) e.previews.has(n) || (e.overrideEntries.delete(n), t.clear(n));
13
+ for (let [n, r] of e.overrideEntries) e.previews.has(n) || (e.overrideEntries.delete(n), t.get(n) === r && t.clear(n));
14
14
  t.commit();
15
15
  }
16
16
  function t(e) {
17
- if (e.overrideEntries.size !== 0) {
18
- for (let t of e.overrideEntries.keys()) e.scene.overrides.clear(t);
19
- e.overrideEntries.clear(), e.scene.overrides.commit();
20
- }
17
+ if (e.overrideEntries.size === 0) return;
18
+ let { overrides: t } = e.scene;
19
+ for (let [n, r] of e.overrideEntries) t.get(n) === r && t.clear(n);
20
+ e.overrideEntries.clear(), e.scene.overrides.commit();
21
21
  }
22
22
  //#endregion
23
23
  export { t as dropPreviewOverrides, e as syncPreviewOverrides };
@@ -1 +1 @@
1
- {"version":3,"file":"previewOverrides.js","names":["syncPreviewOverrides","state","id","pose","existing","entry","overrides","dropPreviewOverrides"],"sources":["../../../src/interactions/actions/previewOverrides.ts"],"sourcesContent":["/**\n * Publishing an in-flight gesture's poses where the *scene* can see them.\n *\n * An ongoing action keeps its per-frame poses in its own scratch and exposes\n * them as `previewIds` / `previewPose`. That surface is enough to paint a\n * ghost and to size selection chrome, but it is invisible to anything that\n * asks the scene where a node is — `sceneDepLookup`, which resolves a derived\n * node's geometry, and the pick source, which decides what the pointer can\n * grab. A node deriving its path from a dragged one therefore stayed anchored\n * to the pre-drag position and jumped on drop.\n *\n * These publish the same frame into the scene's ephemeral override table, the\n * one channel both of those already read. Nothing here reaches `executeAndLog`,\n * so a drag still commits as exactly one undo entry.\n */\nimport type { NodeId, Scene } from 'core/scene/types';\n\n/** The scratch fields these operate on. Actions carry more; this is the part\n * that has to agree across them. */\nexport interface PreviewOverrideState {\n scene: Scene<unknown, string, unknown>;\n /** This frame's poses, keyed by node id — the action's own buffer. */\n previews: Map<NodeId, unknown>;\n /** The entry published per id, held by reference so a frame mutates it in\n * place. Initialize to an empty map in the action's scratch. */\n overrideEntries: Map<NodeId, { pose: unknown }>;\n}\n\n/**\n * Publish `previews` as scene overrides. Call once per frame, after every\n * pass that can add to `previews` (a layout reflow, a cascade).\n *\n * Entries are set once and mutated in place, then published with a single\n * `commit()` — `PoseOverrides.set` notifies subscribers per call, so setting\n * every id every frame would fan out one repaint per node.\n */\nexport function syncPreviewOverrides(state: PreviewOverrideState): void {\n const { overrides } = state.scene;\n for (const [id, pose] of state.previews) {\n const existing = state.overrideEntries.get(id);\n if (existing) {\n existing.pose = pose;\n continue;\n }\n const entry = { pose };\n state.overrideEntries.set(id, entry);\n overrides.set(id, entry);\n }\n // An id can leave the preview set mid-gesture — a cascade child whose\n // container stopped being the drag root, a layout sibling that stopped\n // reflowing. Left published, it would pin that node to a stale frame.\n for (const id of state.overrideEntries.keys()) {\n if (state.previews.has(id)) continue;\n state.overrideEntries.delete(id);\n overrides.clear(id);\n }\n overrides.commit();\n}\n\n/**\n * Drop everything this gesture published. Call on both ends — on commit the\n * document poses take over, on cancel the untouched originals do.\n *\n * On commit, call it *after* the ops land: dropping first leaves a window in\n * which the scene answers with the pre-gesture pose.\n */\nexport function dropPreviewOverrides(state: PreviewOverrideState): void {\n if (state.overrideEntries.size === 0) return;\n for (const id of state.overrideEntries.keys()) state.scene.overrides.clear(id);\n state.overrideEntries.clear();\n state.scene.overrides.commit();\n}\n"],"mappings":";AAoCA,SAAgBA,EAAqB,GAAmC;CACtE,IAAM,EAAE,iBAAcC,EAAM;CAC5B,KAAK,IAAM,CAACC,GAAIC,MAASF,EAAM,UAAU;EACvC,IAAMG,IAAWH,EAAM,gBAAgB,IAAIC,CAAE;EAC7C,IAAIE,GAAU;GACZ,EAAS,OAAOD;GAChB;EACF;EACA,IAAME,IAAQ,EAAE,QAAK;EAErB,AADAJ,EAAM,gBAAgB,IAAIC,GAAIG,CAAK,GACnCC,EAAU,IAAIJ,GAAIG,CAAK;CACzB;CAIA,KAAK,IAAMH,KAAMD,EAAM,gBAAgB,KAAK,GAC1C,AAAIA,EAAM,SAAS,IAAIC,CAAE,MACzBD,EAAM,gBAAgB,OAAOC,CAAE,GAC/BI,EAAU,MAAMJ,CAAE;CAEpB,EAAU,OAAO;AACnB;AASA,SAAgBK,EAAqB,GAAmC;CACtE,IAAIN,EAAM,gBAAgB,SAAS,GACnC;OAAK,IAAMC,KAAMD,EAAM,gBAAgB,KAAK,GAAG,EAAM,MAAM,UAAU,MAAMC,CAAE;EAE7E,AADAD,EAAM,gBAAgB,MAAM,GAC5BA,EAAM,MAAM,UAAU,OAAO;CAFgD;AAG/E"}
1
+ {"version":3,"file":"previewOverrides.js","names":["syncPreviewOverrides","state","id","pose","existing","entry","overrides","dropPreviewOverrides"],"sources":["../../../src/interactions/actions/previewOverrides.ts"],"sourcesContent":["/**\n * Publishing an in-flight gesture's poses where the *scene* can see them.\n *\n * An ongoing action keeps its per-frame poses in its own scratch and exposes\n * them as `previewIds` / `previewPose`. That surface is enough to paint a\n * ghost and to size selection chrome, but it is invisible to anything that\n * asks the scene where a node is — `sceneDepLookup`, which resolves a derived\n * node's geometry, and the pick source, which decides what the pointer can\n * grab. A node deriving its path from a dragged one therefore stayed anchored\n * to the pre-drag position and jumped on drop.\n *\n * These publish the same frame into the scene's ephemeral override table, the\n * one channel both of those already read. Nothing here reaches `executeAndLog`,\n * so a drag still commits as exactly one undo entry.\n */\nimport type { NodeId, Scene } from 'core/scene/types';\n\n/** The scratch fields these operate on. Actions carry more; this is the part\n * that has to agree across them. */\nexport interface PreviewOverrideState {\n scene: Scene<unknown, string, unknown>;\n /** This frame's poses, keyed by node id — the action's own buffer. */\n previews: Map<NodeId, unknown>;\n /** The entry published per id, held by reference so a frame mutates it in\n * place. Initialize to an empty map in the action's scratch. */\n overrideEntries: Map<NodeId, { pose: unknown }>;\n}\n\n/**\n * Publish `previews` as scene overrides. Call once per frame, after every\n * pass that can add to `previews` (a layout reflow, a cascade).\n *\n * Entries are set once and mutated in place, then published with a single\n * `commit()` — `PoseOverrides.set` notifies subscribers per call, so setting\n * every id every frame would fan out one repaint per node.\n */\nexport function syncPreviewOverrides(state: PreviewOverrideState): void {\n const { overrides } = state.scene;\n for (const [id, pose] of state.previews) {\n const existing = state.overrideEntries.get(id);\n if (existing) {\n existing.pose = pose;\n continue;\n }\n const entry = { pose };\n state.overrideEntries.set(id, entry);\n overrides.set(id, entry);\n }\n // An id can leave the preview set mid-gesture — a cascade child whose\n // container stopped being the drag root, a layout sibling that stopped\n // reflowing. Left published, it would pin that node to a stale frame.\n for (const [id, entry] of state.overrideEntries) {\n if (state.previews.has(id)) continue;\n state.overrideEntries.delete(id);\n if (overrides.get(id) === entry) overrides.clear(id);\n }\n overrides.commit();\n}\n\n/**\n * Drop everything this gesture published. Call on both ends — on commit the\n * document poses take over, on cancel the untouched originals do.\n *\n * On commit, call it *after* the ops land: dropping first leaves a window in\n * which the scene answers with the pre-gesture pose.\n *\n * An id whose entry something else has since replaced is left alone: a\n * behavior that carries the node on past the release owns it now.\n */\nexport function dropPreviewOverrides(state: PreviewOverrideState): void {\n if (state.overrideEntries.size === 0) return;\n const { overrides } = state.scene;\n for (const [id, entry] of state.overrideEntries) {\n if (overrides.get(id) === entry) overrides.clear(id);\n }\n state.overrideEntries.clear();\n state.scene.overrides.commit();\n}\n"],"mappings":";AAoCA,SAAgBA,EAAqB,GAAmC;CACtE,IAAM,EAAE,iBAAcC,EAAM;CAC5B,KAAK,IAAM,CAACC,GAAIC,MAASF,EAAM,UAAU;EACvC,IAAMG,IAAWH,EAAM,gBAAgB,IAAIC,CAAE;EAC7C,IAAIE,GAAU;GACZ,EAAS,OAAOD;GAChB;EACF;EACA,IAAME,IAAQ,EAAE,QAAK;EAErB,AADAJ,EAAM,gBAAgB,IAAIC,GAAIG,CAAK,GACnCC,EAAU,IAAIJ,GAAIG,CAAK;CACzB;CAIA,KAAK,IAAM,CAACH,GAAIG,MAAUJ,EAAM,iBAC9B,AAAIA,EAAM,SAAS,IAAIC,CAAE,MACzBD,EAAM,gBAAgB,OAAOC,CAAE,GAC3BI,EAAU,IAAIJ,CAAE,MAAMG,KAAOC,EAAU,MAAMJ,CAAE;CAErD,EAAU,OAAO;AACnB;AAYA,SAAgBK,EAAqB,GAAmC;CACtE,IAAIN,EAAM,gBAAgB,SAAS,GAAG;CACtC,IAAM,EAAE,iBAAcA,EAAM;CAC5B,KAAK,IAAM,CAACC,GAAIG,MAAUJ,EAAM,iBAC9B,AAAIK,EAAU,IAAIJ,CAAE,MAAMG,KAAOC,EAAU,MAAMJ,CAAE;CAGrD,AADAD,EAAM,gBAAgB,MAAM,GAC5BA,EAAM,MAAM,UAAU,OAAO;AAC/B"}