@weasel-js/core 1.7.0 → 1.7.2

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 (1004) hide show
  1. package/CHANGELOG.md +794 -0
  2. package/README.md +14 -8
  3. package/dist/WeaselProvider.js +15 -0
  4. package/dist/WeaselProvider.js.map +1 -0
  5. package/dist/affordances/composeAffordanceLayer.js +224 -0
  6. package/dist/affordances/composeAffordanceLayer.js.map +1 -0
  7. package/dist/affordances/cornerResize.js +69 -0
  8. package/dist/affordances/cornerResize.js.map +1 -0
  9. package/dist/affordances/hitAffordanceRegions.js +138 -0
  10. package/dist/affordances/hitAffordanceRegions.js.map +1 -0
  11. package/dist/affordances/pathAnchors.js +66 -0
  12. package/dist/affordances/pathAnchors.js.map +1 -0
  13. package/dist/affordances/rotationHandle.js +103 -0
  14. package/dist/affordances/rotationHandle.js.map +1 -0
  15. package/dist/animation/behaviors/momentum.js +118 -0
  16. package/dist/animation/behaviors/momentum.js.map +1 -0
  17. package/dist/animation/colorHelpers.js +135 -0
  18. package/dist/animation/colorHelpers.js.map +1 -0
  19. package/dist/animation/colorRegistry.js +37 -0
  20. package/dist/animation/colorRegistry.js.map +1 -0
  21. package/dist/animation/index.js +20 -0
  22. package/dist/animation/loop.js +62 -0
  23. package/dist/animation/loop.js.map +1 -0
  24. package/dist/animation/observe.js +23 -0
  25. package/dist/animation/observe.js.map +1 -0
  26. package/dist/animation/poseHelpers.js +50 -0
  27. package/dist/animation/poseHelpers.js.map +1 -0
  28. package/dist/animation/reflow.js +121 -0
  29. package/dist/animation/reflow.js.map +1 -0
  30. package/dist/animation/rig/bindRig.js +74 -0
  31. package/dist/animation/rig/bindRig.js.map +1 -0
  32. package/dist/animation/rig/blendPoses.js +43 -0
  33. package/dist/animation/rig/blendPoses.js.map +1 -0
  34. package/dist/animation/rig/mirrorPose.js +19 -0
  35. package/dist/animation/rig/mirrorPose.js.map +1 -0
  36. package/dist/animation/rig/resolveSkeleton.js +33 -0
  37. package/dist/animation/rig/resolveSkeleton.js.map +1 -0
  38. package/dist/animation/rig/solveIk.js +103 -0
  39. package/dist/animation/rig/solveIk.js.map +1 -0
  40. package/dist/animation/rig/types.js +12 -0
  41. package/dist/animation/rig/types.js.map +1 -0
  42. package/dist/animation/rig/useRig.js +23 -0
  43. package/dist/animation/rig/useRig.js.map +1 -0
  44. package/dist/animation/slew.js +27 -0
  45. package/dist/animation/slew.js.map +1 -0
  46. package/dist/animation/stagger.js +138 -0
  47. package/dist/animation/stagger.js.map +1 -0
  48. package/dist/animation/timeline/booking.js +106 -0
  49. package/dist/animation/timeline/booking.js.map +1 -0
  50. package/dist/animation/timeline/createTimeline.js +116 -0
  51. package/dist/animation/timeline/createTimeline.js.map +1 -0
  52. package/dist/animation/timeline/sampleTrack.js +29 -0
  53. package/dist/animation/timeline/sampleTrack.js.map +1 -0
  54. package/dist/animation/useAnimator.js +329 -0
  55. package/dist/animation/useAnimator.js.map +1 -0
  56. package/dist/animation/wrappers/animateLifecycle.js +40 -0
  57. package/dist/animation/wrappers/animateLifecycle.js.map +1 -0
  58. package/dist/animation/wrappers/animateOnSetPose.js +44 -0
  59. package/dist/animation/wrappers/animateOnSetPose.js.map +1 -0
  60. package/dist/{autoPoseDescriptor-_XOyF7t4.d.ts → autoPoseDescriptor-vCdt55xm.d.ts} +2 -2
  61. package/dist/{builtins-DLn2lCr_.d.ts → builtins-C-gRyVRx.d.ts} +742 -513
  62. package/dist/canvas/Canvas.js +608 -0
  63. package/dist/canvas/Canvas.js.map +1 -0
  64. package/dist/canvas/CanvasView.js +255 -0
  65. package/dist/canvas/CanvasView.js.map +1 -0
  66. package/dist/canvas/CursorCoordsHud.js +102 -0
  67. package/dist/canvas/CursorCoordsHud.js.map +1 -0
  68. package/dist/canvas/DrawCanvas.js +67 -0
  69. package/dist/canvas/DrawCanvas.js.map +1 -0
  70. package/dist/canvas/MinimapCanvas.js +139 -0
  71. package/dist/canvas/MinimapCanvas.js.map +1 -0
  72. package/dist/canvas/ModalityHud.js +66 -0
  73. package/dist/canvas/ModalityHud.js.map +1 -0
  74. package/dist/canvas/NodeShape.js +391 -0
  75. package/dist/canvas/NodeShape.js.map +1 -0
  76. package/dist/canvas/PickHud.js +93 -0
  77. package/dist/canvas/PickHud.js.map +1 -0
  78. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js +10 -0
  79. package/dist/canvas/SceneCanvas/ActionsProviderIfRoot.js.map +1 -0
  80. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js +10 -0
  81. package/dist/canvas/SceneCanvas/DepRegistryProviderIfRoot.js.map +1 -0
  82. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js +51 -0
  83. package/dist/canvas/SceneCanvas/PointerProviderIfRoot.js.map +1 -0
  84. package/dist/canvas/SceneCanvas/contributionFrameHooks.js +42 -0
  85. package/dist/canvas/SceneCanvas/contributionFrameHooks.js.map +1 -0
  86. package/dist/canvas/SceneCanvas/defaultNodeProperties.js +549 -0
  87. package/dist/canvas/SceneCanvas/defaultNodeProperties.js.map +1 -0
  88. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +26 -0
  89. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -0
  90. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js +69 -0
  91. package/dist/canvas/SceneCanvas/dispatcherGestureBounds.js.map +1 -0
  92. package/dist/canvas/SceneCanvas/features.js +97 -0
  93. package/dist/canvas/SceneCanvas/features.js.map +1 -0
  94. package/dist/canvas/SceneCanvas/poseGeometry.js +46 -0
  95. package/dist/canvas/SceneCanvas/poseGeometry.js.map +1 -0
  96. package/dist/canvas/SceneCanvas/useActionsPropResolver.js +48 -0
  97. package/dist/canvas/SceneCanvas/useActionsPropResolver.js.map +1 -0
  98. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js +70 -0
  99. package/dist/canvas/SceneCanvas/useBuiltinShapeTools.js.map +1 -0
  100. package/dist/canvas/SceneCanvas/useContributionRoles.js +75 -0
  101. package/dist/canvas/SceneCanvas/useContributionRoles.js.map +1 -0
  102. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js +172 -0
  103. package/dist/canvas/SceneCanvas/useDispatcherOverlayLayer.js.map +1 -0
  104. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +69 -0
  105. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -0
  106. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +127 -0
  107. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -0
  108. package/dist/canvas/SceneCanvas/useViewportActions.js +30 -0
  109. package/dist/canvas/SceneCanvas/useViewportActions.js.map +1 -0
  110. package/dist/canvas/SceneCanvas.js +992 -0
  111. package/dist/canvas/SceneCanvas.js.map +1 -0
  112. package/dist/canvas/SceneViewCanvas.js +54 -0
  113. package/dist/canvas/SceneViewCanvas.js.map +1 -0
  114. package/dist/canvas/accentColor.js +9 -0
  115. package/dist/canvas/accentColor.js.map +1 -0
  116. package/dist/canvas/affordanceAt.js +63 -0
  117. package/dist/canvas/affordanceAt.js.map +1 -0
  118. package/dist/canvas/buildSceneTree.js +65 -0
  119. package/dist/canvas/buildSceneTree.js.map +1 -0
  120. package/dist/canvas/canvasRenderer.js +89 -0
  121. package/dist/canvas/canvasRenderer.js.map +1 -0
  122. package/dist/canvas/colorOverrides.js +16 -0
  123. package/dist/canvas/colorOverrides.js.map +1 -0
  124. package/dist/canvas/defaultDrawOne.js +43 -0
  125. package/dist/canvas/defaultDrawOne.js.map +1 -0
  126. package/dist/canvas/deps/areaSelect.js +19 -0
  127. package/dist/canvas/deps/areaSelect.js.map +1 -0
  128. package/dist/canvas/deps/debug.js +9 -0
  129. package/dist/canvas/deps/debug.js.map +1 -0
  130. package/dist/canvas/deps/dispatcher.js +11 -0
  131. package/dist/canvas/deps/dispatcher.js.map +1 -0
  132. package/dist/canvas/deps/editAnchors.js +101 -0
  133. package/dist/canvas/deps/editAnchors.js.map +1 -0
  134. package/dist/canvas/deps/geometryProjection.js +11 -0
  135. package/dist/canvas/deps/geometryProjection.js.map +1 -0
  136. package/dist/canvas/deps/hitTestArea.js +51 -0
  137. package/dist/canvas/deps/hitTestArea.js.map +1 -0
  138. package/dist/canvas/deps/ingestion.js +31 -0
  139. package/dist/canvas/deps/ingestion.js.map +1 -0
  140. package/dist/canvas/deps/insert.js +116 -0
  141. package/dist/canvas/deps/insert.js.map +1 -0
  142. package/dist/canvas/deps/lassoSelect.js +20 -0
  143. package/dist/canvas/deps/lassoSelect.js.map +1 -0
  144. package/dist/canvas/deps/layout.js +34 -0
  145. package/dist/canvas/deps/layout.js.map +1 -0
  146. package/dist/canvas/deps/nodeAtPoint.js +19 -0
  147. package/dist/canvas/deps/nodeAtPoint.js.map +1 -0
  148. package/dist/canvas/deps/poseComposition.js +11 -0
  149. package/dist/canvas/deps/poseComposition.js.map +1 -0
  150. package/dist/canvas/deps/poseDescriptor.js +12 -0
  151. package/dist/canvas/deps/poseDescriptor.js.map +1 -0
  152. package/dist/canvas/deps/resizePolicy.js +35 -0
  153. package/dist/canvas/deps/resizePolicy.js.map +1 -0
  154. package/dist/canvas/deps/slice.js +99 -0
  155. package/dist/canvas/deps/slice.js.map +1 -0
  156. package/dist/canvas/deps/snap.js +11 -0
  157. package/dist/canvas/deps/snap.js.map +1 -0
  158. package/dist/canvas/deps/textEdit.js +21 -0
  159. package/dist/canvas/deps/textEdit.js.map +1 -0
  160. package/dist/canvas/deps/view.js +43 -0
  161. package/dist/canvas/deps/view.js.map +1 -0
  162. package/dist/canvas/derivedPath.js +47 -0
  163. package/dist/canvas/derivedPath.js.map +1 -0
  164. package/dist/canvas/drawEnvelope.js +22 -0
  165. package/dist/canvas/drawEnvelope.js.map +1 -0
  166. package/dist/canvas/getNodeAtPoint.js +18 -0
  167. package/dist/canvas/getNodeAtPoint.js.map +1 -0
  168. package/dist/canvas/hostAnchor.js +29 -0
  169. package/dist/canvas/hostAnchor.js.map +1 -0
  170. package/dist/canvas/hud.module.js +18 -0
  171. package/dist/canvas/hud.module.js.map +1 -0
  172. package/dist/canvas/insertPreviewExtent.js +103 -0
  173. package/dist/canvas/insertPreviewExtent.js.map +1 -0
  174. package/dist/canvas/kitRequirements.js +177 -0
  175. package/dist/canvas/kitRequirements.js.map +1 -0
  176. package/dist/canvas/layerOrder.js +66 -0
  177. package/dist/canvas/layerOrder.js.map +1 -0
  178. package/dist/canvas/layerSlots.js +14 -0
  179. package/dist/canvas/layerSlots.js.map +1 -0
  180. package/dist/canvas/minimapMath.js +80 -0
  181. package/dist/canvas/minimapMath.js.map +1 -0
  182. package/dist/canvas/mountedCanvases.js +20 -0
  183. package/dist/canvas/mountedCanvases.js.map +1 -0
  184. package/dist/canvas/overlayRoleStrokes.js +17 -0
  185. package/dist/canvas/overlayRoleStrokes.js.map +1 -0
  186. package/dist/canvas/paintCull.js +20 -0
  187. package/dist/canvas/paintCull.js.map +1 -0
  188. package/dist/canvas/pickWalk.js +158 -0
  189. package/dist/canvas/pickWalk.js.map +1 -0
  190. package/dist/canvas/planeClips.js +30 -0
  191. package/dist/canvas/planeClips.js.map +1 -0
  192. package/dist/canvas/poseRotation.js +35 -0
  193. package/dist/canvas/poseRotation.js.map +1 -0
  194. package/dist/canvas/rasterToPng.js +21 -0
  195. package/dist/canvas/rasterToPng.js.map +1 -0
  196. package/dist/canvas/renderDebugSnapshot.js +32 -0
  197. package/dist/canvas/renderDebugSnapshot.js.map +1 -0
  198. package/dist/canvas/renderNeeds.js +25 -0
  199. package/dist/canvas/renderNeeds.js.map +1 -0
  200. package/dist/canvas/renderSceneToPixels.js +143 -0
  201. package/dist/canvas/renderSceneToPixels.js.map +1 -0
  202. package/dist/canvas/sceneAdapter.js +270 -0
  203. package/dist/canvas/sceneAdapter.js.map +1 -0
  204. package/dist/canvas/sceneLayerPaint.js +37 -0
  205. package/dist/canvas/sceneLayerPaint.js.map +1 -0
  206. package/dist/canvas/sceneSlotWiring.js +20 -0
  207. package/dist/canvas/sceneSlotWiring.js.map +1 -0
  208. package/dist/canvas/sceneViewRender.js +72 -0
  209. package/dist/canvas/sceneViewRender.js.map +1 -0
  210. package/dist/canvas/slopsDebugLayer.js +61 -0
  211. package/dist/canvas/slopsDebugLayer.js.map +1 -0
  212. package/dist/canvas/surfaceContribution.js +15 -0
  213. package/dist/canvas/surfaceContribution.js.map +1 -0
  214. package/dist/canvas/toolPreview.js +39 -0
  215. package/dist/canvas/toolPreview.js.map +1 -0
  216. package/dist/canvas/useCanvasRenderer.js +11 -0
  217. package/dist/canvas/useCanvasRenderer.js.map +1 -0
  218. package/dist/canvas/useFrameLoop.js +60 -0
  219. package/dist/canvas/useFrameLoop.js.map +1 -0
  220. package/dist/canvas/useHostAnchor.js +71 -0
  221. package/dist/canvas/useHostAnchor.js.map +1 -0
  222. package/dist/canvas/useLateContentRedraw.js +21 -0
  223. package/dist/canvas/useLateContentRedraw.js.map +1 -0
  224. package/dist/canvas/useRedrawOn.js +21 -0
  225. package/dist/canvas/useRedrawOn.js.map +1 -0
  226. package/dist/canvas/useViewHelpers.js +120 -0
  227. package/dist/canvas/useViewHelpers.js.map +1 -0
  228. package/dist/canvas/viewInputs.js +17 -0
  229. package/dist/canvas/viewInputs.js.map +1 -0
  230. package/dist/canvas/viewRegistry.js +61 -0
  231. package/dist/canvas/viewRegistry.js.map +1 -0
  232. package/dist/canvas/wrapNodeOutput.js +14 -0
  233. package/dist/canvas/wrapNodeOutput.js.map +1 -0
  234. package/dist/clipboard.d.ts +10 -5
  235. package/dist/clipboard.js +3 -5
  236. package/dist/clone.d.ts +3 -3
  237. package/dist/clone.js +2 -5
  238. package/dist/core/adapters/arrayAdapter.js +85 -0
  239. package/dist/core/adapters/arrayAdapter.js.map +1 -0
  240. package/dist/core/adapters/useArrayAdapter.js +13 -0
  241. package/dist/core/adapters/useArrayAdapter.js.map +1 -0
  242. package/dist/core/applyOps.js +12 -0
  243. package/dist/core/applyOps.js.map +1 -0
  244. package/dist/core/device/index.js +4 -0
  245. package/dist/core/device/targets.js +17 -0
  246. package/dist/core/device/targets.js.map +1 -0
  247. package/dist/core/device/useDeviceProfile.js +75 -0
  248. package/dist/core/device/useDeviceProfile.js.map +1 -0
  249. package/dist/core/fillInPoseFrame.js +102 -0
  250. package/dist/core/fillInPoseFrame.js.map +1 -0
  251. package/dist/core/geometry/poseDescriptor.js +93 -0
  252. package/dist/core/geometry/poseDescriptor.js.map +1 -0
  253. package/dist/core/geometry/poseRotation.js +58 -0
  254. package/dist/core/geometry/poseRotation.js.map +1 -0
  255. package/dist/core/geometry/regionHit.js +102 -0
  256. package/dist/core/geometry/regionHit.js.map +1 -0
  257. package/dist/core/geometry/unionBounds.js +60 -0
  258. package/dist/core/geometry/unionBounds.js.map +1 -0
  259. package/dist/core/gradient.js +136 -0
  260. package/dist/core/gradient.js.map +1 -0
  261. package/dist/core/isPlainObject.js +11 -0
  262. package/dist/core/isPlainObject.js.map +1 -0
  263. package/dist/core/layers/render.js +150 -0
  264. package/dist/core/layers/render.js.map +1 -0
  265. package/dist/core/markerInset.js +24 -0
  266. package/dist/core/markerInset.js.map +1 -0
  267. package/dist/core/mixed.js +6 -0
  268. package/dist/core/mixed.js.map +1 -0
  269. package/dist/core/ops/arrange.js +31 -0
  270. package/dist/core/ops/arrange.js.map +1 -0
  271. package/dist/core/ops/create.js +32 -0
  272. package/dist/core/ops/create.js.map +1 -0
  273. package/dist/core/ops/createHistory.js +20 -0
  274. package/dist/core/ops/createHistory.js.map +1 -0
  275. package/dist/core/ops/delete.js +89 -0
  276. package/dist/core/ops/delete.js.map +1 -0
  277. package/dist/core/ops/registry.js +17 -0
  278. package/dist/core/ops/registry.js.map +1 -0
  279. package/dist/core/ops/reorder/algorithms.js +55 -0
  280. package/dist/core/ops/reorder/algorithms.js.map +1 -0
  281. package/dist/core/ops/reorder/index.js +140 -0
  282. package/dist/core/ops/reorder/index.js.map +1 -0
  283. package/dist/core/ops/reparent.js +52 -0
  284. package/dist/core/ops/reparent.js.map +1 -0
  285. package/dist/core/ops/select.js +34 -0
  286. package/dist/core/ops/select.js.map +1 -0
  287. package/dist/core/ops/setData.js +34 -0
  288. package/dist/core/ops/setData.js.map +1 -0
  289. package/dist/core/ops/setLayer.js +34 -0
  290. package/dist/core/ops/setLayer.js.map +1 -0
  291. package/dist/core/ops/setLayout.js +31 -0
  292. package/dist/core/ops/setLayout.js.map +1 -0
  293. package/dist/core/ops/setPath.js +57 -0
  294. package/dist/core/ops/setPath.js.map +1 -0
  295. package/dist/core/ops/setText.js +34 -0
  296. package/dist/core/ops/setText.js.map +1 -0
  297. package/dist/core/ops/slot.js +37 -0
  298. package/dist/core/ops/slot.js.map +1 -0
  299. package/dist/core/ops/transform.js +42 -0
  300. package/dist/core/ops/transform.js.map +1 -0
  301. package/dist/core/paintKinds.js +156 -0
  302. package/dist/core/paintKinds.js.map +1 -0
  303. package/dist/core/scene/NodeProperties.js +20 -0
  304. package/dist/core/scene/NodeProperties.js.map +1 -0
  305. package/dist/core/scene/NodeRouting.js +24 -0
  306. package/dist/core/scene/NodeRouting.js.map +1 -0
  307. package/dist/core/scene/arrivals.js +12 -0
  308. package/dist/core/scene/arrivals.js.map +1 -0
  309. package/dist/core/scene/composeFrame.js +29 -0
  310. package/dist/core/scene/composeFrame.js.map +1 -0
  311. package/dist/core/scene/depMemo.js +18 -0
  312. package/dist/core/scene/depMemo.js.map +1 -0
  313. package/dist/core/scene/dependents.js +66 -0
  314. package/dist/core/scene/dependents.js.map +1 -0
  315. package/dist/core/scene/derivedPath.js +31 -0
  316. package/dist/core/scene/derivedPath.js.map +1 -0
  317. package/dist/core/scene/effectivePose.js +78 -0
  318. package/dist/core/scene/effectivePose.js.map +1 -0
  319. package/dist/core/scene/kitRegistry.js +33 -0
  320. package/dist/core/scene/kitRegistry.js.map +1 -0
  321. package/dist/core/scene/layoutPass.js +96 -0
  322. package/dist/core/scene/layoutPass.js.map +1 -0
  323. package/dist/core/scene/nodeFnFields.js +83 -0
  324. package/dist/core/scene/nodeFnFields.js.map +1 -0
  325. package/dist/core/scene/nodeMemo.js +28 -0
  326. package/dist/core/scene/nodeMemo.js.map +1 -0
  327. package/dist/core/scene/poseFeed.js +87 -0
  328. package/dist/core/scene/poseFeed.js.map +1 -0
  329. package/dist/core/scene/poseOverrides.js +52 -0
  330. package/dist/core/scene/poseOverrides.js.map +1 -0
  331. package/dist/core/scene/poseSnapshot.js +54 -0
  332. package/dist/core/scene/poseSnapshot.js.map +1 -0
  333. package/dist/core/scene/scene.js +1271 -0
  334. package/dist/core/scene/scene.js.map +1 -0
  335. package/dist/core/scene/types.js +6 -0
  336. package/dist/core/scene/types.js.map +1 -0
  337. package/dist/core/scene/useScene.js +32 -0
  338. package/dist/core/scene/useScene.js.map +1 -0
  339. package/dist/core/selection/chromeState.js +31 -0
  340. package/dist/core/selection/chromeState.js.map +1 -0
  341. package/dist/core/selection/selectionTarget.js +6 -0
  342. package/dist/core/selection/selectionTarget.js.map +1 -0
  343. package/dist/core/selection/useSelection.js +71 -0
  344. package/dist/core/selection/useSelection.js.map +1 -0
  345. package/dist/core/shapeKinds.js +54 -0
  346. package/dist/core/shapeKinds.js.map +1 -0
  347. package/dist/core/strokeMarkerShapes.js +139 -0
  348. package/dist/core/strokeMarkerShapes.js.map +1 -0
  349. package/dist/core/strokeMarkers.js +28 -0
  350. package/dist/core/strokeMarkers.js.map +1 -0
  351. package/dist/core/stylus/stylus.js +39 -0
  352. package/dist/core/stylus/stylus.js.map +1 -0
  353. package/dist/core/stylus/usePointerStylus.js +51 -0
  354. package/dist/core/stylus/usePointerStylus.js.map +1 -0
  355. package/dist/core/usePaintKinds.js +17 -0
  356. package/dist/core/usePaintKinds.js.map +1 -0
  357. package/dist/core/viewport/clampView.js +24 -0
  358. package/dist/core/viewport/clampView.js.map +1 -0
  359. package/dist/core/viewport/clientToWorld.js +8 -0
  360. package/dist/core/viewport/clientToWorld.js.map +1 -0
  361. package/dist/core/viewport/createVelocityTracker.js +39 -0
  362. package/dist/core/viewport/createVelocityTracker.js.map +1 -0
  363. package/dist/core/viewport/fitToBounds.js +18 -0
  364. package/dist/core/viewport/fitToBounds.js.map +1 -0
  365. package/dist/core/viewport/fitViewToBounds.js +36 -0
  366. package/dist/core/viewport/fitViewToBounds.js.map +1 -0
  367. package/dist/core/viewport/interpolateView.js +34 -0
  368. package/dist/core/viewport/interpolateView.js.map +1 -0
  369. package/dist/core/viewport/meanScale.js +8 -0
  370. package/dist/core/viewport/meanScale.js.map +1 -0
  371. package/dist/core/viewport/parallax.js +111 -0
  372. package/dist/core/viewport/parallax.js.map +1 -0
  373. package/dist/core/viewport/pxExtent.js +42 -0
  374. package/dist/core/viewport/pxExtent.js.map +1 -0
  375. package/dist/core/viewport/sceneNodeClientRect.js +18 -0
  376. package/dist/core/viewport/sceneNodeClientRect.js.map +1 -0
  377. package/dist/core/viewport/screenSlop.js +27 -0
  378. package/dist/core/viewport/screenSlop.js.map +1 -0
  379. package/dist/core/viewport/useAutoCenter.js +32 -0
  380. package/dist/core/viewport/useAutoCenter.js.map +1 -0
  381. package/dist/core/viewport/useCanvasSize.js +29 -0
  382. package/dist/core/viewport/useCanvasSize.js.map +1 -0
  383. package/dist/core/viewport/useDecayLoop.js +63 -0
  384. package/dist/core/viewport/useDecayLoop.js.map +1 -0
  385. package/dist/core/viewport/useVelocityTracker.js +10 -0
  386. package/dist/core/viewport/useVelocityTracker.js.map +1 -0
  387. package/dist/core/viewport/useViewAnimation.js +63 -0
  388. package/dist/core/viewport/useViewAnimation.js.map +1 -0
  389. package/dist/core/viewport/view.js +37 -0
  390. package/dist/core/viewport/view.js.map +1 -0
  391. package/dist/core/viewport/viewTransform.js +11 -0
  392. package/dist/core/viewport/viewTransform.js.map +1 -0
  393. package/dist/core/viewport/viewportWorldRect.js +13 -0
  394. package/dist/core/viewport/viewportWorldRect.js.map +1 -0
  395. package/dist/core/viewport/wheelHandler.js +30 -0
  396. package/dist/core/viewport/wheelHandler.js.map +1 -0
  397. package/dist/core/viewport/zoomAt.js +22 -0
  398. package/dist/core/viewport/zoomAt.js.map +1 -0
  399. package/dist/core/viewport/zoomBounds.js +20 -0
  400. package/dist/core/viewport/zoomBounds.js.map +1 -0
  401. package/dist/{pointSnapToGrid-Dp2IxLGb.d.ts → cornerHandles-BCrDp_mH.d.ts} +3 -13
  402. package/dist/debug/createDebugOverlayLayer.js +358 -0
  403. package/dist/debug/createDebugOverlayLayer.js.map +1 -0
  404. package/dist/debug/createDebugSink.js +83 -0
  405. package/dist/debug/createDebugSink.js.map +1 -0
  406. package/dist/debug/defaultTheme.js +31 -0
  407. package/dist/debug/defaultTheme.js.map +1 -0
  408. package/dist/debug/flag.js +41 -0
  409. package/dist/debug/flag.js.map +1 -0
  410. package/dist/debug/frameStats.js +16 -0
  411. package/dist/debug/frameStats.js.map +1 -0
  412. package/dist/debug/parseDebugFlags.js +32 -0
  413. package/dist/debug/parseDebugFlags.js.map +1 -0
  414. package/dist/features/chrome-caps/buildChromeCtx.js +16 -0
  415. package/dist/features/chrome-caps/buildChromeCtx.js.map +1 -0
  416. package/dist/features/chrome-caps/conditions.js +36 -0
  417. package/dist/features/chrome-caps/conditions.js.map +1 -0
  418. package/dist/features/chrome-caps/defaults.js +26 -0
  419. package/dist/features/chrome-caps/defaults.js.map +1 -0
  420. package/dist/features/chrome-caps/index.js +7 -0
  421. package/dist/features/chrome-caps/resolve.js +23 -0
  422. package/dist/features/chrome-caps/resolve.js.map +1 -0
  423. package/dist/features/chrome-caps/useHoverTracking.js +27 -0
  424. package/dist/features/chrome-caps/useHoverTracking.js.map +1 -0
  425. package/dist/features/cursor/paintedCursorLayer.js +60 -0
  426. package/dist/features/cursor/paintedCursorLayer.js.map +1 -0
  427. package/dist/features/focus/gateLayer.js +14 -0
  428. package/dist/features/focus/gateLayer.js.map +1 -0
  429. package/dist/features/focus/useCanvasFocus.js +29 -0
  430. package/dist/features/focus/useCanvasFocus.js.map +1 -0
  431. package/dist/features/groups/children.js +23 -0
  432. package/dist/features/groups/children.js.map +1 -0
  433. package/dist/features/groups/composePose.js +67 -0
  434. package/dist/features/groups/composePose.js.map +1 -0
  435. package/dist/features/groups/nestedHit.js +40 -0
  436. package/dist/features/groups/nestedHit.js.map +1 -0
  437. package/dist/features/groups/unionOfChildren.js +15 -0
  438. package/dist/features/groups/unionOfChildren.js.map +1 -0
  439. package/dist/features/images/imageCache.js +94 -0
  440. package/dist/features/images/imageCache.js.map +1 -0
  441. package/dist/features/ingestion/contentHandlers.js +37 -0
  442. package/dist/features/ingestion/contentHandlers.js.map +1 -0
  443. package/dist/features/ingestion/imageHandler.js +45 -0
  444. package/dist/features/ingestion/imageHandler.js.map +1 -0
  445. package/dist/features/ingestion/index.js +8 -0
  446. package/dist/features/ingestion/openFilePicker.js +15 -0
  447. package/dist/features/ingestion/openFilePicker.js.map +1 -0
  448. package/dist/features/ingestion/registerKitHandlers.js +26 -0
  449. package/dist/features/ingestion/registerKitHandlers.js.map +1 -0
  450. package/dist/features/ingestion/svgHandler.js +58 -0
  451. package/dist/features/ingestion/svgHandler.js.map +1 -0
  452. package/dist/features/ingestion/weaselJsonHandler.js +39 -0
  453. package/dist/features/ingestion/weaselJsonHandler.js.map +1 -0
  454. package/dist/features/longPress/longPressFeedback.js +96 -0
  455. package/dist/features/longPress/longPressFeedback.js.map +1 -0
  456. package/dist/features/meshPaint/bake.js +79 -0
  457. package/dist/features/meshPaint/bake.js.map +1 -0
  458. package/dist/features/meshPaint/bakeCache.js +59 -0
  459. package/dist/features/meshPaint/bakeCache.js.map +1 -0
  460. package/dist/features/meshPaint/handles.js +86 -0
  461. package/dist/features/meshPaint/handles.js.map +1 -0
  462. package/dist/features/meshPaint/lazyKind.js +1298 -0
  463. package/dist/features/meshPaint/lazyKind.js.map +1 -0
  464. package/dist/features/meshPaint/meshPaint.js +236 -0
  465. package/dist/features/meshPaint/meshPaint.js.map +1 -0
  466. package/dist/features/meshPaint/meshShader.js +6 -0
  467. package/dist/features/meshPaint/meshShader.js.map +1 -0
  468. package/dist/features/meshPaint/register.js +7 -0
  469. package/dist/features/meshPaint/register.js.map +1 -0
  470. package/dist/features/meshPaint/surface.js +110 -0
  471. package/dist/features/meshPaint/surface.js.map +1 -0
  472. package/dist/features/minimap/actions.js +53 -0
  473. package/dist/features/minimap/actions.js.map +1 -0
  474. package/dist/features/minimap/createMinimapContribution.js +96 -0
  475. package/dist/features/minimap/createMinimapContribution.js.map +1 -0
  476. package/dist/features/minimap/layers.js +103 -0
  477. package/dist/features/minimap/layers.js.map +1 -0
  478. package/dist/features/modes/modeLayers.js +113 -0
  479. package/dist/features/modes/modeLayers.js.map +1 -0
  480. package/dist/features/overlays/useNodeOverlayFrame.js +103 -0
  481. package/dist/features/overlays/useNodeOverlayFrame.js.map +1 -0
  482. package/dist/features/parallax/createParallaxLayer.js +26 -0
  483. package/dist/features/parallax/createParallaxLayer.js.map +1 -0
  484. package/dist/features/parallax/createParallaxPlane.js +26 -0
  485. package/dist/features/parallax/createParallaxPlane.js.map +1 -0
  486. package/dist/features/paths/anchorEdits.js +156 -0
  487. package/dist/features/paths/anchorEdits.js.map +1 -0
  488. package/dist/features/paths/anchors.js +154 -0
  489. package/dist/features/paths/anchors.js.map +1 -0
  490. package/dist/features/paths/booleans.js +2 -0
  491. package/dist/features/paths/index.js +15 -0
  492. package/dist/features/paths/markerCommands.js +116 -0
  493. package/dist/features/paths/markerCommands.js.map +1 -0
  494. package/dist/features/paths/markerSites.js +59 -0
  495. package/dist/features/paths/markerSites.js.map +1 -0
  496. package/dist/features/paths/markers.js +95 -0
  497. package/dist/features/paths/markers.js.map +1 -0
  498. package/dist/features/paths/nearestAnchor.js +36 -0
  499. package/dist/features/paths/nearestAnchor.js.map +1 -0
  500. package/dist/features/paths/originProjection.js +16 -0
  501. package/dist/features/paths/originProjection.js.map +1 -0
  502. package/dist/features/paths/pathEditingOverlayLayer.js +137 -0
  503. package/dist/features/paths/pathEditingOverlayLayer.js.map +1 -0
  504. package/dist/features/paths/pathInWorld.js +41 -0
  505. package/dist/features/paths/pathInWorld.js.map +1 -0
  506. package/dist/features/paths/pathLayer.js +44 -0
  507. package/dist/features/paths/pathLayer.js.map +1 -0
  508. package/dist/features/paths/penPreviewLayer.js +220 -0
  509. package/dist/features/paths/penPreviewLayer.js.map +1 -0
  510. package/dist/features/paths/poseDescriptor.js +39 -0
  511. package/dist/features/paths/poseDescriptor.js.map +1 -0
  512. package/dist/features/paths/tessellate/stroke.js +230 -0
  513. package/dist/features/paths/tessellate/stroke.js.map +1 -0
  514. package/dist/features/patterns/index.js +23 -0
  515. package/dist/features/patterns/index.js.map +1 -0
  516. package/dist/features/patterns/patterns-builtin.js +38 -0
  517. package/dist/features/patterns/patterns-builtin.js.map +1 -0
  518. package/dist/features/patterns/resolveSpec.js +57 -0
  519. package/dist/features/patterns/resolveSpec.js.map +1 -0
  520. package/dist/features/patterns/tileGeometry.js +158 -0
  521. package/dist/features/patterns/tileGeometry.js.map +1 -0
  522. package/dist/features/pointer/PointerContext.js +45 -0
  523. package/dist/features/pointer/PointerContext.js.map +1 -0
  524. package/dist/features/poseRun/usePoseRun.js +70 -0
  525. package/dist/features/poseRun/usePoseRun.js.map +1 -0
  526. package/dist/features/selection/SelectionContext.js +46 -0
  527. package/dist/features/selection/SelectionContext.js.map +1 -0
  528. package/dist/features/selection/overlay.js +442 -0
  529. package/dist/features/selection/overlay.js.map +1 -0
  530. package/dist/features/simulation/createSimulation.js +61 -0
  531. package/dist/features/simulation/createSimulation.js.map +1 -0
  532. package/dist/features/simulation/types.js +6 -0
  533. package/dist/features/simulation/types.js.map +1 -0
  534. package/dist/features/simulation/useSimulation.js +74 -0
  535. package/dist/features/simulation/useSimulation.js.map +1 -0
  536. package/dist/features/text/domRuns.js +258 -0
  537. package/dist/features/text/domRuns.js.map +1 -0
  538. package/dist/features/text/fitTextPose.js +38 -0
  539. package/dist/features/text/fitTextPose.js.map +1 -0
  540. package/dist/features/text/hitTest.js +45 -0
  541. package/dist/features/text/hitTest.js.map +1 -0
  542. package/dist/features/text/renderLabel.js +14 -0
  543. package/dist/features/text/renderLabel.js.map +1 -0
  544. package/dist/features/text/runs/effectiveRangeStyle.js +66 -0
  545. package/dist/features/text/runs/effectiveRangeStyle.js.map +1 -0
  546. package/dist/features/text/runs/flagRange.js +53 -0
  547. package/dist/features/text/runs/flagRange.js.map +1 -0
  548. package/dist/features/text/runs/rangeStyle.js +135 -0
  549. package/dist/features/text/runs/rangeStyle.js.map +1 -0
  550. package/dist/features/text/textCommand.js +59 -0
  551. package/dist/features/text/textCommand.js.map +1 -0
  552. package/dist/features/text/textLayer.js +35 -0
  553. package/dist/features/text/textLayer.js.map +1 -0
  554. package/dist/features/text/textToPath.js +181 -0
  555. package/dist/features/text/textToPath.js.map +1 -0
  556. package/dist/features/text/useSceneTextEdit.js +138 -0
  557. package/dist/features/text/useSceneTextEdit.js.map +1 -0
  558. package/dist/features/text/useTextEdit.js +465 -0
  559. package/dist/features/text/useTextEdit.js.map +1 -0
  560. package/dist/features/tiling/createTiledLayer.js +63 -0
  561. package/dist/features/tiling/createTiledLayer.js.map +1 -0
  562. package/dist/features/tiling/tiledProject.js +14 -0
  563. package/dist/features/tiling/tiledProject.js.map +1 -0
  564. package/dist/features/viewports/viewResolver.js +59 -0
  565. package/dist/features/viewports/viewResolver.js.map +1 -0
  566. package/dist/features/viewports/viewportLayer.js +58 -0
  567. package/dist/features/viewports/viewportLayer.js.map +1 -0
  568. package/dist/icons/ArrowIcon.js +23 -0
  569. package/dist/icons/ArrowIcon.js.map +1 -0
  570. package/dist/icons/EllipseIcon.js +21 -0
  571. package/dist/icons/EllipseIcon.js.map +1 -0
  572. package/dist/icons/EyedropperIcon.js +49 -0
  573. package/dist/icons/EyedropperIcon.js.map +1 -0
  574. package/dist/icons/HandIcon.js +59 -0
  575. package/dist/icons/HandIcon.js.map +1 -0
  576. package/dist/icons/ImageIcon.js +34 -0
  577. package/dist/icons/ImageIcon.js.map +1 -0
  578. package/dist/icons/LassoIcon.js +22 -0
  579. package/dist/icons/LassoIcon.js.map +1 -0
  580. package/dist/icons/LineIcon.js +22 -0
  581. package/dist/icons/LineIcon.js.map +1 -0
  582. package/dist/icons/PenIcon.js +36 -0
  583. package/dist/icons/PenIcon.js.map +1 -0
  584. package/dist/icons/PencilIcon.js +25 -0
  585. package/dist/icons/PencilIcon.js.map +1 -0
  586. package/dist/icons/PolygonIcon.js +19 -0
  587. package/dist/icons/PolygonIcon.js.map +1 -0
  588. package/dist/icons/RectIcon.js +37 -0
  589. package/dist/icons/RectIcon.js.map +1 -0
  590. package/dist/icons/SelectIcon.js +20 -0
  591. package/dist/icons/SelectIcon.js.map +1 -0
  592. package/dist/icons/StarIcon.js +19 -0
  593. package/dist/icons/StarIcon.js.map +1 -0
  594. package/dist/icons/TextIcon.js +19 -0
  595. package/dist/icons/TextIcon.js.map +1 -0
  596. package/dist/icons/UnknownIcon.js +33 -0
  597. package/dist/icons/UnknownIcon.js.map +1 -0
  598. package/dist/icons/_base.js +12 -0
  599. package/dist/icons/_base.js.map +1 -0
  600. package/dist/index.d.ts +1960 -1891
  601. package/dist/index.js +312 -13
  602. package/dist/input/keyState.js +76 -0
  603. package/dist/input/keyState.js.map +1 -0
  604. package/dist/input/useKeyState.js +22 -0
  605. package/dist/input/useKeyState.js.map +1 -0
  606. package/dist/interactions/actions/actionShortcuts.js +32 -0
  607. package/dist/interactions/actions/actionShortcuts.js.map +1 -0
  608. package/dist/interactions/actions/align/align.js +81 -0
  609. package/dist/interactions/actions/align/align.js.map +1 -0
  610. package/dist/interactions/actions/booleans/booleans.js +120 -0
  611. package/dist/interactions/actions/booleans/booleans.js.map +1 -0
  612. package/dist/interactions/actions/booleans/useBooleans.js +20 -0
  613. package/dist/interactions/actions/booleans/useBooleans.js.map +1 -0
  614. package/dist/interactions/actions/booleans/useBooleansAdapter.js +9 -0
  615. package/dist/interactions/actions/booleans/useBooleansAdapter.js.map +1 -0
  616. package/dist/interactions/actions/clipboard/clipboardOps.js +94 -0
  617. package/dist/interactions/actions/clipboard/clipboardOps.js.map +1 -0
  618. package/dist/interactions/actions/clipboard/materializePaste.js +25 -0
  619. package/dist/interactions/actions/clipboard/materializePaste.js.map +1 -0
  620. package/dist/interactions/actions/clipboard/wireFormat.js +43 -0
  621. package/dist/interactions/actions/clipboard/wireFormat.js.map +1 -0
  622. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js +26 -0
  623. package/dist/interactions/actions/clone/behaviors/cloneByAltDrag.js.map +1 -0
  624. package/dist/interactions/actions/defaultCommitAdapter.js +42 -0
  625. package/dist/interactions/actions/defaultCommitAdapter.js.map +1 -0
  626. package/dist/interactions/actions/defaults/align.js +71 -0
  627. package/dist/interactions/actions/defaults/align.js.map +1 -0
  628. package/dist/interactions/actions/defaults/anchorEditing.js +235 -0
  629. package/dist/interactions/actions/defaults/anchorEditing.js.map +1 -0
  630. package/dist/interactions/actions/defaults/areaSelect.js +75 -0
  631. package/dist/interactions/actions/defaults/areaSelect.js.map +1 -0
  632. package/dist/interactions/actions/defaults/booleans.js +52 -0
  633. package/dist/interactions/actions/defaults/booleans.js.map +1 -0
  634. package/dist/interactions/actions/defaults/cancelGesture.js +24 -0
  635. package/dist/interactions/actions/defaults/cancelGesture.js.map +1 -0
  636. package/dist/interactions/actions/defaults/clearSelection.js +19 -0
  637. package/dist/interactions/actions/defaults/clearSelection.js.map +1 -0
  638. package/dist/interactions/actions/defaults/clipboard.js +78 -0
  639. package/dist/interactions/actions/defaults/clipboard.js.map +1 -0
  640. package/dist/interactions/actions/defaults/clone.js +107 -0
  641. package/dist/interactions/actions/defaults/clone.js.map +1 -0
  642. package/dist/interactions/actions/defaults/createOutlines.js +47 -0
  643. package/dist/interactions/actions/defaults/createOutlines.js.map +1 -0
  644. package/dist/interactions/actions/defaults/createPaintAction.js +85 -0
  645. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -0
  646. package/dist/interactions/actions/defaults/delete.js +61 -0
  647. package/dist/interactions/actions/defaults/delete.js.map +1 -0
  648. package/dist/interactions/actions/defaults/distribute.js +66 -0
  649. package/dist/interactions/actions/defaults/distribute.js.map +1 -0
  650. package/dist/interactions/actions/defaults/duplicate.js +83 -0
  651. package/dist/interactions/actions/defaults/duplicate.js.map +1 -0
  652. package/dist/interactions/actions/defaults/editAnchors.js +100 -0
  653. package/dist/interactions/actions/defaults/editAnchors.js.map +1 -0
  654. package/dist/interactions/actions/defaults/enterPathEdit.js +29 -0
  655. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -0
  656. package/dist/interactions/actions/defaults/enterTextEdit.js +20 -0
  657. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -0
  658. package/dist/interactions/actions/defaults/escape.js +26 -0
  659. package/dist/interactions/actions/defaults/escape.js.map +1 -0
  660. package/dist/interactions/actions/defaults/exitPathEdit.js +22 -0
  661. package/dist/interactions/actions/defaults/exitPathEdit.js.map +1 -0
  662. package/dist/interactions/actions/defaults/flip.js +119 -0
  663. package/dist/interactions/actions/defaults/flip.js.map +1 -0
  664. package/dist/interactions/actions/defaults/freshNodeId.js +10 -0
  665. package/dist/interactions/actions/defaults/freshNodeId.js.map +1 -0
  666. package/dist/interactions/actions/defaults/group.js +131 -0
  667. package/dist/interactions/actions/defaults/group.js.map +1 -0
  668. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js +40 -0
  669. package/dist/interactions/actions/defaults/icons/actionGlyphIcons.js.map +1 -0
  670. package/dist/interactions/actions/defaults/icons/actionGlyphs.js +10 -0
  671. package/dist/interactions/actions/defaults/icons/actionGlyphs.js.map +1 -0
  672. package/dist/interactions/actions/defaults/icons/alignIcons.js +173 -0
  673. package/dist/interactions/actions/defaults/icons/alignIcons.js.map +1 -0
  674. package/dist/interactions/actions/defaults/icons/booleanIcons.js +171 -0
  675. package/dist/interactions/actions/defaults/icons/booleanIcons.js.map +1 -0
  676. package/dist/interactions/actions/defaults/icons/distributeIcons.js +63 -0
  677. package/dist/interactions/actions/defaults/icons/distributeIcons.js.map +1 -0
  678. package/dist/interactions/actions/defaults/icons/editIcons.js +280 -0
  679. package/dist/interactions/actions/defaults/icons/editIcons.js.map +1 -0
  680. package/dist/interactions/actions/defaults/icons/outlineIcons.js +53 -0
  681. package/dist/interactions/actions/defaults/icons/outlineIcons.js.map +1 -0
  682. package/dist/interactions/actions/defaults/ingest.js +58 -0
  683. package/dist/interactions/actions/defaults/ingest.js.map +1 -0
  684. package/dist/interactions/actions/defaults/insert.js +288 -0
  685. package/dist/interactions/actions/defaults/insert.js.map +1 -0
  686. package/dist/interactions/actions/defaults/insertPathAnchor.js +50 -0
  687. package/dist/interactions/actions/defaults/insertPathAnchor.js.map +1 -0
  688. package/dist/interactions/actions/defaults/lassoSelect.js +156 -0
  689. package/dist/interactions/actions/defaults/lassoSelect.js.map +1 -0
  690. package/dist/interactions/actions/defaults/move.js +760 -0
  691. package/dist/interactions/actions/defaults/move.js.map +1 -0
  692. package/dist/interactions/actions/defaults/nudge.js +110 -0
  693. package/dist/interactions/actions/defaults/nudge.js.map +1 -0
  694. package/dist/interactions/actions/defaults/pinchZoom.js +63 -0
  695. package/dist/interactions/actions/defaults/pinchZoom.js.map +1 -0
  696. package/dist/interactions/actions/defaults/reorder.js +143 -0
  697. package/dist/interactions/actions/defaults/reorder.js.map +1 -0
  698. package/dist/interactions/actions/defaults/requiresSelection.js +10 -0
  699. package/dist/interactions/actions/defaults/requiresSelection.js.map +1 -0
  700. package/dist/interactions/actions/defaults/resize.js +335 -0
  701. package/dist/interactions/actions/defaults/resize.js.map +1 -0
  702. package/dist/interactions/actions/defaults/rotate.js +184 -0
  703. package/dist/interactions/actions/defaults/rotate.js.map +1 -0
  704. package/dist/interactions/actions/defaults/selectAll.js +27 -0
  705. package/dist/interactions/actions/defaults/selectAll.js.map +1 -0
  706. package/dist/interactions/actions/defaults/setFill.js +27 -0
  707. package/dist/interactions/actions/defaults/setFill.js.map +1 -0
  708. package/dist/interactions/actions/defaults/setFillOpacity.js +15 -0
  709. package/dist/interactions/actions/defaults/setFillOpacity.js.map +1 -0
  710. package/dist/interactions/actions/defaults/setStroke.js +36 -0
  711. package/dist/interactions/actions/defaults/setStroke.js.map +1 -0
  712. package/dist/interactions/actions/defaults/setStrokeOpacity.js +21 -0
  713. package/dist/interactions/actions/defaults/setStrokeOpacity.js.map +1 -0
  714. package/dist/interactions/actions/defaults/slice.js +39 -0
  715. package/dist/interactions/actions/defaults/slice.js.map +1 -0
  716. package/dist/interactions/actions/defaults/sliceOps.js +60 -0
  717. package/dist/interactions/actions/defaults/sliceOps.js.map +1 -0
  718. package/dist/interactions/actions/defaults/toolActivate.js +35 -0
  719. package/dist/interactions/actions/defaults/toolActivate.js.map +1 -0
  720. package/dist/interactions/actions/defaults/toolResetToDefault.js +26 -0
  721. package/dist/interactions/actions/defaults/toolResetToDefault.js.map +1 -0
  722. package/dist/interactions/actions/defaults/undoRedo.js +51 -0
  723. package/dist/interactions/actions/defaults/undoRedo.js.map +1 -0
  724. package/dist/interactions/actions/defaults/viewportDragPan.js +88 -0
  725. package/dist/interactions/actions/defaults/viewportDragPan.js.map +1 -0
  726. package/dist/interactions/actions/defaults/viewportWheelPan.js +57 -0
  727. package/dist/interactions/actions/defaults/viewportWheelPan.js.map +1 -0
  728. package/dist/interactions/actions/defaults/viewportZoom.js +143 -0
  729. package/dist/interactions/actions/defaults/viewportZoom.js.map +1 -0
  730. package/dist/interactions/actions/distribute/distribute.js +42 -0
  731. package/dist/interactions/actions/distribute/distribute.js.map +1 -0
  732. package/dist/interactions/actions/distribute/plan.js +29 -0
  733. package/dist/interactions/actions/distribute/plan.js.map +1 -0
  734. package/dist/interactions/actions/edit-anchors/geometry.js +61 -0
  735. package/dist/interactions/actions/edit-anchors/geometry.js.map +1 -0
  736. package/dist/interactions/actions/edit-anchors/handles.js +43 -0
  737. package/dist/interactions/actions/edit-anchors/handles.js.map +1 -0
  738. package/dist/interactions/actions/flip/helpers.js +35 -0
  739. package/dist/interactions/actions/flip/helpers.js.map +1 -0
  740. package/dist/interactions/actions/geometryProjection.js +18 -0
  741. package/dist/interactions/actions/geometryProjection.js.map +1 -0
  742. package/dist/interactions/actions/gestureLifecycle.js +44 -0
  743. package/dist/interactions/actions/gestureLifecycle.js.map +1 -0
  744. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js +39 -0
  745. package/dist/interactions/actions/lasso-select/behaviors/selectFromLasso.js.map +1 -0
  746. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js +36 -0
  747. package/dist/interactions/actions/move/behaviors/snapBackOrDelete.js.map +1 -0
  748. package/dist/interactions/actions/move/behaviors/snapToContainer.js +67 -0
  749. package/dist/interactions/actions/move/behaviors/snapToContainer.js.map +1 -0
  750. package/dist/interactions/actions/move/gestureAdapter.js +37 -0
  751. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -0
  752. package/dist/interactions/actions/outlines/createOutlines.js +84 -0
  753. package/dist/interactions/actions/outlines/createOutlines.js.map +1 -0
  754. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js +9 -0
  755. package/dist/interactions/actions/outlines/useCreateOutlinesAdapter.js.map +1 -0
  756. package/dist/interactions/actions/planeInput.js +181 -0
  757. package/dist/interactions/actions/planeInput.js.map +1 -0
  758. package/dist/interactions/actions/poseDescriptorDep.js +9 -0
  759. package/dist/interactions/actions/poseDescriptorDep.js.map +1 -0
  760. package/dist/interactions/actions/poseFrame.js +38 -0
  761. package/dist/interactions/actions/poseFrame.js.map +1 -0
  762. package/dist/interactions/actions/previewOverrides.js +25 -0
  763. package/dist/interactions/actions/previewOverrides.js.map +1 -0
  764. package/dist/interactions/actions/resize/autoPoseDescriptor.js +31 -0
  765. package/dist/interactions/actions/resize/autoPoseDescriptor.js.map +1 -0
  766. package/dist/interactions/actions/resize/behaviors/clampMinSize.js +18 -0
  767. package/dist/interactions/actions/resize/behaviors/clampMinSize.js.map +1 -0
  768. package/dist/interactions/actions/resize/behaviors/index.js +8 -0
  769. package/dist/interactions/actions/resize/behaviors/index.js.map +1 -0
  770. package/dist/interactions/actions/resize/behaviors/lockAspect.js +24 -0
  771. package/dist/interactions/actions/resize/behaviors/lockAspect.js.map +1 -0
  772. package/dist/interactions/actions/resize/cornerHandles.js +72 -0
  773. package/dist/interactions/actions/resize/cornerHandles.js.map +1 -0
  774. package/dist/interactions/actions/resolveOverlays.js +60 -0
  775. package/dist/interactions/actions/resolveOverlays.js.map +1 -0
  776. package/dist/interactions/actions/resolvePreviews.js +61 -0
  777. package/dist/interactions/actions/resolvePreviews.js.map +1 -0
  778. package/dist/interactions/actions/rotate/geometry.js +46 -0
  779. package/dist/interactions/actions/rotate/geometry.js.map +1 -0
  780. package/dist/interactions/actions/rotate/handle.js +27 -0
  781. package/dist/interactions/actions/rotate/handle.js.map +1 -0
  782. package/dist/interactions/actions/spatialReference.js +42 -0
  783. package/dist/interactions/actions/spatialReference.js.map +1 -0
  784. package/dist/interactions/actions/useStandardActions.js +142 -0
  785. package/dist/interactions/actions/useStandardActions.js.map +1 -0
  786. package/dist/interactions/gestures/dragGesture/dragGesture.js +111 -0
  787. package/dist/interactions/gestures/dragGesture/dragGesture.js.map +1 -0
  788. package/dist/interactions/gestures/dragRadial/dragRadial.js +117 -0
  789. package/dist/interactions/gestures/dragRadial/dragRadial.js.map +1 -0
  790. package/dist/interactions/gestures/dragRect/dragRect.js +164 -0
  791. package/dist/interactions/gestures/dragRect/dragRect.js.map +1 -0
  792. package/dist/interactions/gestures/handleDrag/handleDrag.js +46 -0
  793. package/dist/interactions/gestures/handleDrag/handleDrag.js.map +1 -0
  794. package/dist/interactions/gestures/pointerDrag/pointerDrag.js +118 -0
  795. package/dist/interactions/gestures/pointerDrag/pointerDrag.js.map +1 -0
  796. package/dist/interactions/gestures/shared/originProjection.js +42 -0
  797. package/dist/interactions/gestures/shared/originProjection.js.map +1 -0
  798. package/dist/interactions/gestures/shared/screenTolerance.js +21 -0
  799. package/dist/interactions/gestures/shared/screenTolerance.js.map +1 -0
  800. package/dist/interactions/gestures/shared/snap.js +24 -0
  801. package/dist/interactions/gestures/shared/snap.js.map +1 -0
  802. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +30 -0
  803. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -0
  804. package/dist/layout/arrivals.js +36 -0
  805. package/dist/layout/arrivals.js.map +1 -0
  806. package/dist/{math-MCQcf_gc.d.ts → math-Drrw4ewZ.d.ts} +8 -116
  807. package/dist/math.d.ts +4 -5
  808. package/dist/math.js +6 -4
  809. package/dist/mesh.d.ts +268 -0
  810. package/dist/mesh.js +7 -0
  811. package/dist/move.d.ts +7 -49
  812. package/dist/move.js +3 -142
  813. package/dist/originProjection-DEklpDc_.d.ts +57 -0
  814. package/dist/patterns-builtin.js +3 -3
  815. package/dist/{poseDescriptor-rZa9W5hJ.d.ts → poseDescriptor-D-OH-tu5.d.ts} +0 -4
  816. package/dist/registerProgram-ateHDGjw.d.ts +193 -0
  817. package/dist/renderer/DrawCommand.js +6 -0
  818. package/dist/renderer/DrawCommand.js.map +1 -0
  819. package/dist/renderer/WeaselRenderer.js +328 -0
  820. package/dist/renderer/WeaselRenderer.js.map +1 -0
  821. package/dist/renderer/cache/GLImageCache.js +64 -0
  822. package/dist/renderer/cache/GLImageCache.js.map +1 -0
  823. package/dist/renderer/cache/GLMeshCache.js +102 -0
  824. package/dist/renderer/cache/GLMeshCache.js.map +1 -0
  825. package/dist/renderer/cache/GLTextureCache.js +51 -0
  826. package/dist/renderer/cache/GLTextureCache.js.map +1 -0
  827. package/dist/renderer/cache/GradientRampAtlas.js +82 -0
  828. package/dist/renderer/cache/GradientRampAtlas.js.map +1 -0
  829. package/dist/renderer/cache/cache.js +13 -0
  830. package/dist/renderer/cache/cache.js.map +1 -0
  831. package/dist/renderer/cache/markerCommandCache.js +59 -0
  832. package/dist/renderer/cache/markerCommandCache.js.map +1 -0
  833. package/dist/renderer/cache/outlineMeshCache.js +15 -0
  834. package/dist/renderer/cache/outlineMeshCache.js.map +1 -0
  835. package/dist/renderer/cache/outlineStrokeMeshCache.js +31 -0
  836. package/dist/renderer/cache/outlineStrokeMeshCache.js.map +1 -0
  837. package/dist/renderer/cache/strokeMeshCache.js +44 -0
  838. package/dist/renderer/cache/strokeMeshCache.js.map +1 -0
  839. package/dist/renderer/cullDrawCommands.js +89 -0
  840. package/dist/renderer/cullDrawCommands.js.map +1 -0
  841. package/dist/renderer/draw.js +1109 -0
  842. package/dist/renderer/draw.js.map +1 -0
  843. package/dist/renderer/drawBatch.js +168 -0
  844. package/dist/renderer/drawBatch.js.map +1 -0
  845. package/dist/renderer/effects/EffectTargets.js +45 -0
  846. package/dist/renderer/effects/EffectTargets.js.map +1 -0
  847. package/dist/renderer/effects/builtins.js +31 -0
  848. package/dist/renderer/effects/builtins.js.map +1 -0
  849. package/dist/renderer/effects/composite.js +9 -0
  850. package/dist/renderer/effects/composite.js.map +1 -0
  851. package/dist/renderer/effects/effectPrelude.js +10 -0
  852. package/dist/renderer/effects/effectPrelude.js.map +1 -0
  853. package/dist/renderer/effects/types.js +10 -0
  854. package/dist/renderer/effects/types.js.map +1 -0
  855. package/dist/renderer/index.js +19 -0
  856. package/dist/renderer/math/color.js +341 -0
  857. package/dist/renderer/math/color.js.map +1 -0
  858. package/dist/renderer/math/mat3.js +71 -0
  859. package/dist/renderer/math/mat3.js.map +1 -0
  860. package/dist/renderer/math/patternSpace.js +22 -0
  861. package/dist/renderer/math/patternSpace.js.map +1 -0
  862. package/dist/renderer/math/viewToMat3.js +19 -0
  863. package/dist/renderer/math/viewToMat3.js.map +1 -0
  864. package/dist/renderer/paintResources.js +18 -0
  865. package/dist/renderer/paintResources.js.map +1 -0
  866. package/dist/renderer/paintScratch.js +37 -0
  867. package/dist/renderer/paintScratch.js.map +1 -0
  868. package/dist/renderer/shaders/ShaderProgram.js +74 -0
  869. package/dist/renderer/shaders/ShaderProgram.js.map +1 -0
  870. package/dist/renderer/shaders/batchFill.js +118 -0
  871. package/dist/renderer/shaders/batchFill.js.map +1 -0
  872. package/dist/renderer/shaders/customPrelude.js +34 -0
  873. package/dist/renderer/shaders/customPrelude.js.map +1 -0
  874. package/dist/renderer/shaders/extractUniformNames.js +184 -0
  875. package/dist/renderer/shaders/extractUniformNames.js.map +1 -0
  876. package/dist/renderer/shaders/glyphPaint.js +61 -0
  877. package/dist/renderer/shaders/glyphPaint.js.map +1 -0
  878. package/dist/renderer/shaders/gradFill.js +30 -0
  879. package/dist/renderer/shaders/gradFill.js.map +1 -0
  880. package/dist/renderer/shaders/imageFill.js +14 -0
  881. package/dist/renderer/shaders/imageFill.js.map +1 -0
  882. package/dist/renderer/shaders/pathFill.js +13 -0
  883. package/dist/renderer/shaders/pathFill.js.map +1 -0
  884. package/dist/renderer/shaders/patternFill.js +24 -0
  885. package/dist/renderer/shaders/patternFill.js.map +1 -0
  886. package/dist/renderer/shaders/registerProgram.js +18 -0
  887. package/dist/renderer/shaders/registerProgram.js.map +1 -0
  888. package/dist/renderer/spriteSheet.js +14 -0
  889. package/dist/renderer/spriteSheet.js.map +1 -0
  890. package/dist/renderer/state/GroupState.js +77 -0
  891. package/dist/renderer/state/GroupState.js.map +1 -0
  892. package/dist/renderer/syntheticItalic.js +6 -0
  893. package/dist/renderer/syntheticItalic.js.map +1 -0
  894. package/dist/renderer/textures/registerTexture.js +14 -0
  895. package/dist/renderer/textures/registerTexture.js.map +1 -0
  896. package/dist/renderer.d.ts +11 -21
  897. package/dist/renderer.js +18 -13
  898. package/dist/resize.d.ts +10 -46
  899. package/dist/resize.js +7 -5
  900. package/dist/routing.js +2 -3
  901. package/dist/scheduling/useVisibleRaf.js +69 -0
  902. package/dist/scheduling/useVisibleRaf.js.map +1 -0
  903. package/dist/style.css +2 -0
  904. package/dist/test-hook/createTestHook.js +39 -0
  905. package/dist/test-hook/createTestHook.js.map +1 -0
  906. package/dist/test-hook/install.js +12 -0
  907. package/dist/test-hook/install.js.map +1 -0
  908. package/dist/test-seams-fYf6m5pu.d.ts +356 -0
  909. package/dist/test-seams.d.ts +6 -0
  910. package/dist/test-seams.js +3 -0
  911. package/dist/tools/builtin/ellipse/useEllipseTool.js +33 -0
  912. package/dist/tools/builtin/ellipse/useEllipseTool.js.map +1 -0
  913. package/dist/tools/builtin/eyedropper/useEyedropperTool.js +55 -0
  914. package/dist/tools/builtin/eyedropper/useEyedropperTool.js.map +1 -0
  915. package/dist/tools/builtin/hand/dragPanContribution.js +17 -0
  916. package/dist/tools/builtin/hand/dragPanContribution.js.map +1 -0
  917. package/dist/tools/builtin/hand/useHandTool.js +31 -0
  918. package/dist/tools/builtin/hand/useHandTool.js.map +1 -0
  919. package/dist/tools/builtin/image/useImageTool.js +41 -0
  920. package/dist/tools/builtin/image/useImageTool.js.map +1 -0
  921. package/dist/tools/builtin/lasso/useLassoTool.js +42 -0
  922. package/dist/tools/builtin/lasso/useLassoTool.js.map +1 -0
  923. package/dist/tools/builtin/line/useLineTool.js +33 -0
  924. package/dist/tools/builtin/line/useLineTool.js.map +1 -0
  925. package/dist/tools/builtin/pen/usePenTool.js +414 -0
  926. package/dist/tools/builtin/pen/usePenTool.js.map +1 -0
  927. package/dist/tools/builtin/pencil/usePencilTool.js +36 -0
  928. package/dist/tools/builtin/pencil/usePencilTool.js.map +1 -0
  929. package/dist/tools/builtin/pickTopMostHit.js +45 -0
  930. package/dist/tools/builtin/pickTopMostHit.js.map +1 -0
  931. package/dist/tools/builtin/polygon/usePolygonTool.js +81 -0
  932. package/dist/tools/builtin/polygon/usePolygonTool.js.map +1 -0
  933. package/dist/tools/builtin/rect/useRectTool.js +32 -0
  934. package/dist/tools/builtin/rect/useRectTool.js.map +1 -0
  935. package/dist/tools/builtin/select/selectionContributions.js +109 -0
  936. package/dist/tools/builtin/select/selectionContributions.js.map +1 -0
  937. package/dist/tools/builtin/select/useSelectTool.js +162 -0
  938. package/dist/tools/builtin/select/useSelectTool.js.map +1 -0
  939. package/dist/tools/builtin/shared/insertToolOptions.js +8 -0
  940. package/dist/tools/builtin/shared/insertToolOptions.js.map +1 -0
  941. package/dist/tools/builtin/slice/useSliceTool.js +263 -0
  942. package/dist/tools/builtin/slice/useSliceTool.js.map +1 -0
  943. package/dist/tools/builtin/star/useStarTool.js +82 -0
  944. package/dist/tools/builtin/star/useStarTool.js.map +1 -0
  945. package/dist/tools/builtin/text/useTextTool.js +177 -0
  946. package/dist/tools/builtin/text/useTextTool.js.map +1 -0
  947. package/dist/tools/overlayBinding.js +8 -0
  948. package/dist/tools/overlayBinding.js.map +1 -0
  949. package/dist/tools/prefs.js +47 -0
  950. package/dist/tools/prefs.js.map +1 -0
  951. package/dist/tools/useKeybindings.js +66 -0
  952. package/dist/tools/useKeybindings.js.map +1 -0
  953. package/dist/{types-D-9QWBy5.d.ts → types-A37hYkeR.d.ts} +185 -15
  954. package/dist/{types-qYpyTAiZ.d.ts → types-B_9g6hMM.d.ts} +32 -6
  955. package/dist/util/color.js +26 -0
  956. package/dist/util/color.js.map +1 -0
  957. package/dist/util/constrainTo45.js +17 -0
  958. package/dist/util/constrainTo45.js.map +1 -0
  959. package/dist/util/paint.js +72 -0
  960. package/dist/util/paint.js.map +1 -0
  961. package/dist/version.js +6 -0
  962. package/dist/version.js.map +1 -0
  963. package/package.json +31 -19
  964. package/dist/chunk-3TY6FHAF.js +0 -170
  965. package/dist/chunk-3TY6FHAF.js.map +0 -1
  966. package/dist/chunk-DGWNNKGD.js +0 -248
  967. package/dist/chunk-DGWNNKGD.js.map +0 -1
  968. package/dist/chunk-G4ZGQMY7.js +0 -33372
  969. package/dist/chunk-G4ZGQMY7.js.map +0 -1
  970. package/dist/chunk-L5YNZYEG.js +0 -648
  971. package/dist/chunk-L5YNZYEG.js.map +0 -1
  972. package/dist/chunk-LU4IJ52W.js +0 -111
  973. package/dist/chunk-LU4IJ52W.js.map +0 -1
  974. package/dist/chunk-M24CLARN.js +0 -28
  975. package/dist/chunk-M24CLARN.js.map +0 -1
  976. package/dist/chunk-NE27EOLP.js +0 -146
  977. package/dist/chunk-NE27EOLP.js.map +0 -1
  978. package/dist/chunk-PNNZSYRD.js +0 -318
  979. package/dist/chunk-PNNZSYRD.js.map +0 -1
  980. package/dist/chunk-UPZY4ART.js +0 -29
  981. package/dist/chunk-UPZY4ART.js.map +0 -1
  982. package/dist/chunk-WPNA6L5O.js +0 -250
  983. package/dist/chunk-WPNA6L5O.js.map +0 -1
  984. package/dist/chunk-XMAWPGTK.js +0 -128
  985. package/dist/chunk-XMAWPGTK.js.map +0 -1
  986. package/dist/clipboard.js.map +0 -1
  987. package/dist/clone.js.map +0 -1
  988. package/dist/grid-CY5UKlZh.d.ts +0 -98
  989. package/dist/index.css +0 -62
  990. package/dist/index.css.map +0 -1
  991. package/dist/index.js.map +0 -1
  992. package/dist/insert.d.ts +0 -36
  993. package/dist/insert.js +0 -81
  994. package/dist/insert.js.map +0 -1
  995. package/dist/math.js.map +0 -1
  996. package/dist/move.js.map +0 -1
  997. package/dist/path-JEV2c5If.d.ts +0 -48
  998. package/dist/patterns-builtin.js.map +0 -1
  999. package/dist/renderer.css +0 -62
  1000. package/dist/renderer.css.map +0 -1
  1001. package/dist/renderer.js.map +0 -1
  1002. package/dist/resize.js.map +0 -1
  1003. package/dist/routing.js.map +0 -1
  1004. package/dist/types-D2tTKEU0.d.ts +0 -18
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate.js","names":["DUPLICATE_OFFSET","hasSelectedAncestor","parent","scene","id","set","copySubtree","node","newId","freshNodeId","copy","translatePoseViaDescriptor","offset","d","createInsertOp","childOffset","offsetDescendants","child","ops","duplicateAction","createElement","DuplicateIcon","selection","deps","applyOps","ids","descriptor","poseDescriptorOf","newIds","nid","asNodeId","defaultCommitAdapter","requiresSelection"],"sources":["../../../../src/interactions/actions/defaults/duplicate.ts"],"sourcesContent":["import type { Action } from '@weasel-js/routing';\nimport { createElement } from 'react';\nimport { DuplicateIcon } from './icons/editIcons';\nimport type { Node, NodeId, Scene } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Op } from 'core/ops/types';\nimport { createInsertOp } from 'core/ops/create';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { freshNodeId } from './freshNodeId';\nimport { requiresSelection } from './requiresSelection';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { translatePoseViaDescriptor, type PoseDescriptor } from '../resize/geometry';\n\n/** Same nudge `sceneToAdapter.getPasteOffset` gives a paste, so duplicate and\n * paste land in the same place rather than disagreeing by a few units. */\nconst DUPLICATE_OFFSET = 12;\n\n/** True when any ancestor of `id` is also in `set` — that ancestor's copy\n * already brings this node along, so duplicating it again would double it. */\nfunction hasSelectedAncestor(\n scene: Scene<unknown, string, unknown>,\n id: NodeId,\n set: ReadonlySet<string>,\n): boolean {\n let parent = scene.get(id)?.parent ?? null;\n while (parent != null) {\n if (set.has(parent)) return true;\n parent = scene.get(parent)?.parent ?? null;\n }\n return false;\n}\n\n/**\n * Copy `id`'s whole subtree, appending one insert op per node in pre-order so\n * a parent always exists before its children are inserted. Returns the new\n * root's id.\n *\n * `offsetDescendants` is false for local-pose consumers (those that registered\n * a `poseComposition`): a child's pose is relative there, so offsetting the\n * root already carries the subtree, and offsetting again would double it. With\n * the default absolute poses every node stores world coords and every one\n * moves.\n */\nfunction copySubtree(\n scene: Scene<unknown, string, unknown>,\n id: NodeId,\n parent: NodeId | null,\n offset: { dx: number; dy: number },\n offsetDescendants: boolean,\n ops: Op[],\n d: PoseDescriptor<unknown>,\n): NodeId | null {\n const node = scene.get(id);\n if (!node) return null;\n const newId = freshNodeId();\n const copy = {\n ...node,\n id: newId,\n pose: translatePoseViaDescriptor(node.pose, offset.dx, offset.dy, d),\n parent,\n } as Node<unknown, string, unknown>;\n ops.push(createInsertOp<Node<unknown, string, unknown>>({ node: copy, label: 'Duplicate' }));\n const childOffset = offsetDescendants ? offset : { dx: 0, dy: 0 };\n for (const child of scene.childrenOf(id)) {\n copySubtree(scene, child, newId, childOffset, offsetDescendants, ops, d);\n }\n return newId;\n}\n\n/**\n * @experimental\n * Static descriptor for the `duplicate` Action. Copies each selected node —\n * with its subtree, so duplicating a group produces a populated group — offset\n * by a small nudge, as one undoable batch, then selects the copies.\n */\nexport const duplicateAction: Action & { requires: string[] } = {\n id: 'duplicate',\n label: 'Duplicate',\n icon: createElement(DuplicateIcon),\n group: 'edit',\n defaultBinding: { kind: 'key', key: 'd', mods: { mod: true } },\n eligible: { capability: ['edits-page', 'creates-selection'] },\n // `selection` is read by the `enabled` gate as well as the invoker. An\n // undeclared read throws inside the dev-build deps Proxy before the gate can\n // answer, which is how this action spent a while doing nothing at all.\n requires: ['scene', 'selection', 'applyOps', 'poseComposition', 'poseDescriptor'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const selection = deps.selection as SelectionApi | undefined;\n const scene = deps.scene as Scene<unknown, string, unknown> | undefined;\n const applyOps = deps.applyOps as ((ops: Op[], label: string) => void) | undefined;\n if (!selection || !scene) return;\n const ids = selection.get();\n if (ids.length === 0) return;\n\n const set = new Set<string>(ids);\n const descriptor = poseDescriptorOf(deps.poseDescriptor);\n const offset = { dx: DUPLICATE_OFFSET, dy: DUPLICATE_OFFSET };\n const ops: Op[] = [];\n const newIds: NodeId[] = [];\n for (const id of ids) {\n const nid = asNodeId(id);\n const node = scene.get(nid);\n if (!node) continue;\n if (hasSelectedAncestor(scene, nid, set)) continue;\n const newId = copySubtree(scene, nid, node.parent ?? null, offset, deps.poseComposition === undefined, ops, descriptor);\n if (newId) newIds.push(newId);\n }\n\n if (ops.length === 0) return;\n if (applyOps) applyOps(ops, 'Duplicate');\n else scene.applyBatch(ops, 'Duplicate', defaultCommitAdapter(scene, selection.adapterMethods));\n selection.set(newIds);\n },\n },\n enabled: requiresSelection,\n};\n"],"mappings":";;;;;;;;;;AAgBA,IAAMA,IAAmB;AAIzB,SAASC,EACP,GACA,GACA,GACS;CACT,IAAIC,IAASC,EAAM,IAAIC,CAAE,CAAC,EAAE,UAAU;CACtC,OAAOF,KAAU,OAAM;EACrB,IAAIG,EAAI,IAAIH,CAAM,GAAG,OAAO;EAC5B,IAASC,EAAM,IAAID,CAAM,CAAC,EAAE,UAAU;CACxC;CACA,OAAO;AACT;AAaA,SAASI,EACP,GACA,GACA,GACA,GACA,GACA,GACA,GACe;CACf,IAAMC,IAAOJ,EAAM,IAAIC,CAAE;CACzB,IAAI,CAACG,GAAM,OAAO;CAClB,IAAMC,IAAQC,EAAY,GACpBC,IAAO;EACX,GAAGH;EACH,IAAIC;EACJ,MAAMG,EAA2BJ,EAAK,MAAMK,EAAO,IAAIA,EAAO,IAAIC,CAAC;EACnE;CACF;CACA,EAAI,KAAKC,EAA+C;EAAE,MAAMJ;EAAM,OAAO;CAAY,CAAC,CAAC;CAC3F,IAAMK,IAAcC,IAAoBJ,IAAS;EAAE,IAAI;EAAG,IAAI;CAAE;CAChE,KAAK,IAAMK,KAASd,EAAM,WAAWC,CAAE,GACrC,EAAYD,GAAOc,GAAOT,GAAOO,GAAaC,GAAmBE,GAAKL,CAAC;CAEzE,OAAOL;AACT;AAQA,IAAaW,IAAmD;CAC9D,IAAI;CACJ,OAAO;CACP,MAAMC,EAAcC,CAAa;CACjC,OAAO;CACP,gBAAgB;EAAE,MAAM;EAAO,KAAK;EAAK,MAAM,EAAE,KAAK,GAAK;CAAE;CAC7D,UAAU,EAAE,YAAY,CAAC,cAAc,mBAAmB,EAAE;CAI5D,UAAU;EAAC;EAAS;EAAa;EAAY;EAAmB;CAAgB;CAChF,SAAS;EACP,QAAQ;EACR,MAAM,MAAS;GACb,IAAMC,IAAYC,EAAK,WACjBpB,IAAQoB,EAAK,OACbC,IAAWD,EAAK;GACtB,IAAI,CAACD,KAAa,CAACnB,GAAO;GAC1B,IAAMsB,IAAMH,EAAU,IAAI;GAC1B,IAAIG,EAAI,WAAW,GAAG;GAEtB,IAAMpB,IAAM,IAAI,IAAYoB,CAAG,GACzBC,IAAaC,EAAiBJ,EAAK,cAAc,GACjDX,IAAS;IAAE,IAAIZ;IAAkB,IAAIA;GAAiB,GACtDkB,IAAY,CAAC,GACbU,IAAmB,CAAC;GAC1B,KAAK,IAAMxB,KAAMqB,GAAK;IACpB,IAAMI,IAAMC,EAAS1B,CAAE,GACjBG,IAAOJ,EAAM,IAAI0B,CAAG;IAE1B,IADI,CAACtB,KACDN,EAAoBE,GAAO0B,GAAKxB,CAAG,GAAG;IAC1C,IAAMG,IAAQF,EAAYH,GAAO0B,GAAKtB,EAAK,UAAU,MAAMK,GAAQW,EAAK,oBAAoB,KAAA,GAAWL,GAAKQ,CAAU;IACtH,AAAIlB,KAAOoB,EAAO,KAAKpB,CAAK;GAC9B;GAEA,AAAIU,EAAI,WAAW,MACfM,IAAUA,EAASN,GAAK,WAAW,IAClCf,EAAM,WAAWe,GAAK,aAAaa,EAAqB5B,GAAOmB,EAAU,cAAc,CAAC,GAC7FA,EAAU,IAAIM,CAAM;EACtB;CACF;CACA,SAASI;AACX"}
@@ -0,0 +1,100 @@
1
+ import { editingLayer as e, inPlane as t } from "../planeInput.js";
2
+ import { pathToAnchors as n } from "../../../features/paths/anchors.js";
3
+ import { anchorAt as r, editAnchorSet as i, moveHandleTo as a, translateAnchorBy as o } from "../../../features/paths/anchorEdits.js";
4
+ import { worldEditToStorage as s } from "../../../features/paths/pathInWorld.js";
5
+ import { isAnchorOrControl as c } from "@weasel-js/routing";
6
+ //#region src/interactions/actions/defaults/editAnchors.ts
7
+ function l(e) {
8
+ let t = e.match(/^(anchor|controlIn|controlOut):(\d+)$/);
9
+ return t ? {
10
+ anchorIndex: parseInt(t[2], 10),
11
+ part: t[1]
12
+ } : null;
13
+ }
14
+ function u(e, t, n) {
15
+ if (n) {
16
+ let n = new Set(e);
17
+ return n.has(t) ? n.delete(t) : n.add(t), n;
18
+ }
19
+ return e.has(t) && e.size > 1 ? new Set(e) : /* @__PURE__ */ new Set([t]);
20
+ }
21
+ var d = t({
22
+ id: "editAnchors",
23
+ label: "Edit Anchors",
24
+ defaultBinding: {
25
+ kind: "drag",
26
+ target: { kindOf: c }
27
+ },
28
+ eligible: { capability: "edits-anchors" },
29
+ requires: ["selection", "editAnchors"],
30
+ invoker: {
31
+ timing: "ongoing",
32
+ start(e, t) {
33
+ let c = e.deps.editAnchors;
34
+ if (!c) return {};
35
+ let d = e.drag?.affordance;
36
+ if (!d) return {};
37
+ let f = l(d.kind);
38
+ if (!f) return {};
39
+ let { editingId: p } = c, m = c.getEditablePath(p);
40
+ if (!m || m.kind !== "polygon") return {};
41
+ let h = c.getStorageKind(p);
42
+ if (h !== "pose" && h !== "data") return {};
43
+ let g = n(m), _ = r(g, f.anchorIndex);
44
+ if (!_ || f.part === "controlIn" && !_.inHandle || f.part === "controlOut" && !_.outHandle) return {};
45
+ let v = [f.anchorIndex];
46
+ if (f.part === "anchor") {
47
+ let t = u(c.selectedAnchors, f.anchorIndex, e.modifiers.shift);
48
+ c.setSelectedAnchors(t), v = t.has(f.anchorIndex) ? [...t] : [];
49
+ }
50
+ let y = h === "data" ? c.getNodeShape(p) : null, b = y ? y.pose : void 0, x = y ? y.data : void 0, S = {
51
+ dep: c,
52
+ id: p,
53
+ anchorIndex: f.anchorIndex,
54
+ part: f.part,
55
+ dragging: v,
56
+ anchorOrigin: {
57
+ x: _.x,
58
+ y: _.y
59
+ },
60
+ originPose: m,
61
+ currentPose: m,
62
+ storageKind: h
63
+ }, C = !1;
64
+ return {
65
+ kind: "edit-anchors",
66
+ onMove(e) {
67
+ if (S.part === "anchor") {
68
+ if (S.dragging.length === 0) return;
69
+ let t = e.world.x - S.anchorOrigin.x, n = e.world.y - S.anchorOrigin.y, r = i(S.originPose, (e) => {
70
+ for (let r of S.dragging) o(e, r, t, n);
71
+ });
72
+ r && (S.currentPose = r);
73
+ } else {
74
+ let t = S.part === "controlIn" ? "in" : "out", n = i(S.originPose, (n) => a(n, S.anchorIndex, t, e.world.x, e.world.y, e.modifiers.alt));
75
+ n && (S.currentPose = n);
76
+ }
77
+ C = !0;
78
+ },
79
+ onEnd(e, t) {
80
+ C = !1, t !== "cancel" && S.originPose !== S.currentPose && S.dep.applyEdit(S.id, S.currentPose, "Edit anchors");
81
+ },
82
+ previewIds: () => C ? [S.id] : null,
83
+ previewPose: (e) => !C || e !== S.id ? null : S.storageKind === "pose" ? S.currentPose : b ? s(b, S.currentPose).pose : null,
84
+ previewData: (e) => {
85
+ if (!C || e !== S.id || S.storageKind !== "data" || !x) return null;
86
+ let { path: t } = s(b, S.currentPose);
87
+ return {
88
+ ...x,
89
+ path: t
90
+ };
91
+ }
92
+ };
93
+ }
94
+ },
95
+ enabled: () => !0
96
+ }, e);
97
+ //#endregion
98
+ export { d as editAnchorsAction, u as selectionAfterAnchorPress };
99
+
100
+ //# sourceMappingURL=editAnchors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editAnchors.js","names":["parseAnchorAffordance","m","kind","selectionAfterAnchorPress","additive","next","current","anchorIndex","editAnchorsAction","inPlane","isAnchorOrControl","dep","ctx","affordance","anchorInfo","worldPath","editingId","storageKind","decoded","pathToAnchors","origin","anchorAt","dragging","nodeShape","originRectPose","originData","scratch","active","dx","moveCtx","dy","editAnchorSet","flat","set","side","moveHandleTo","reason","id","worldEditToStorage","editingLayer"],"sources":["../../../../src/interactions/actions/defaults/editAnchors.ts"],"sourcesContent":["/**\n * `editAnchorsAction` — ongoing Action descriptor for editing polygon anchors.\n *\n * Owns the whole press-on-an-anchor gesture, because pressing and dragging\n * an anchor are two outcomes of one interaction rather than two\n * interactions:\n *\n * - **Press** selects. Bare press replaces the anchor selection; Shift\n * toggles the pressed anchor in or out of it. Pressing an anchor that\n * is already part of a multi-anchor selection leaves the selection\n * alone, so you can grab a set and move it.\n * - **Drag** then moves whatever the press left selected — one anchor,\n * or every selected anchor together.\n * - **Dragging a control handle** moves just that handle, mirroring the\n * opposite one while the anchor is smooth. Alt breaks the mirror.\n *\n * Selection lives on the `editAnchors` dep (flat anchor indices) rather\n * than in this handle's scratch, because the keyboard actions\n * (`nudgeAnchors`, `deleteAnchors`) and the overlay all need to read it\n * between gestures.\n *\n * ## Wiring\n *\n * The descriptor is operational when the consumer wires:\n * 1. `buildAffordanceAt` with a `getAnchorState` thunk so the dispatcher\n * classifies anchor/control-handle hits as `anchor:N`, `controlIn:N`,\n * or `controlOut:N` affordances on pointerdown.\n * 2. The `editAnchors` dep in the DepSchema.\n *\n * When `ctx.drag.affordance` is absent or is not an anchor/control kind,\n * `start` returns `{}` (no-op) so other bindings can handle the drag.\n *\n * @see buildAffordanceAt — the classifier that produces anchor affordances.\n * @see anchorEdits — the pure geometry these handlers drive.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { InvocationCtx, OngoingHandle } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\nimport { isAnchorOrControl } from '@weasel-js/routing';\nimport {\n anchorAt,\n editAnchorSet,\n moveHandleTo,\n translateAnchorBy,\n type AnchorSet,\n} from 'features/paths/anchorEdits';\nimport { pathToAnchors } from 'features/paths/anchors';\nimport { worldEditToStorage } from 'features/paths/pathInWorld';\n// Commit goes through dep.applyEdit (routes setPose or setPose+update\n// based on the node's path-storage shape); no direct op or dispatch\n// helpers needed here.\nimport type { PolygonPath } from '@weasel-js/geom';\nimport { inPlane, editingLayer } from '../planeInput';\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Parse an anchor affordance kind string into the anchor it names.\n * Returns `null` when the affordance is not an anchor kind.\n *\n * Format: `'anchor:N'` | `'controlIn:N'` | `'controlOut:N'`, where N is the\n * flat anchor index — the same numbering `enumerateAnchors` produces and\n * `anchorEdits` addresses by.\n */\nfunction parseAnchorAffordance(\n kind: string,\n): { anchorIndex: number; part: 'anchor' | 'controlIn' | 'controlOut' } | null {\n const m = kind.match(/^(anchor|controlIn|controlOut):(\\d+)$/);\n if (!m) return null;\n return {\n anchorIndex: parseInt(m[2], 10),\n part: m[1] as 'anchor' | 'controlIn' | 'controlOut',\n };\n}\n\n/**\n * Resolve what a press on `anchorIndex` should leave selected.\n *\n * Shift toggles. A bare press on an anchor that's already part of the\n * selection keeps the selection intact (so the drag moves the whole set);\n * a bare press anywhere else collapses to just that anchor.\n */\nexport function selectionAfterAnchorPress(\n current: ReadonlySet<number>,\n anchorIndex: number,\n additive: boolean,\n): Set<number> {\n if (additive) {\n const next = new Set(current);\n if (next.has(anchorIndex)) next.delete(anchorIndex);\n else next.add(anchorIndex);\n return next;\n }\n if (current.has(anchorIndex) && current.size > 1) return new Set(current);\n return new Set([anchorIndex]);\n}\n\n// ---------------------------------------------------------------------------\n// Internal scratch\n// ---------------------------------------------------------------------------\n\ninterface EditAnchorsScratch {\n dep: EditAnchorsDep;\n id: string;\n anchorIndex: number;\n /** `'anchor'` drags on-curve points (and their handles) by a delta.\n * `'controlIn'` / `'controlOut'` drag one control point to an absolute\n * world coord. */\n part: 'anchor' | 'controlIn' | 'controlOut';\n /** Anchors this drag moves — the pressed one, or the whole anchor\n * selection when the press landed inside it. Flat indices. */\n dragging: readonly number[];\n /** World position of the pressed anchor at drag start; the drag delta is\n * measured from here rather than accumulated per move, so the geometry\n * is always derived from `originPose` in one step. */\n anchorOrigin: { x: number; y: number };\n originPose: PolygonPath;\n currentPose: PolygonPath;\n /** Where the polygon lives on the node — drives which preview-ghost\n * axes the handle populates (`previewPose` only for pose-as-polygon,\n * `previewPose` + `previewData` for data.path). */\n storageKind: 'pose' | 'data';\n}\n\n// ---------------------------------------------------------------------------\n// Descriptor\n// ---------------------------------------------------------------------------\n\n/**\n * Static descriptor for the `editAnchors` Action.\n *\n * Requires dep-schema entries: `selection`, `editAnchors`.\n */\nexport const editAnchorsAction: Action & { requires: string[] } = inPlane({\n id: 'editAnchors',\n label: 'Edit Anchors',\n defaultBinding: {\n kind: 'drag',\n // Only matches drags whose pointerdown hit an anchor or control handle.\n // Ties moveAction's `selected-body` on specificity and registers after\n // it, so move declines these presses in `start`.\n target: { kindOf: isAnchorOrControl },\n },\n eligible: { capability: 'edits-anchors' },\n requires: ['selection', 'editAnchors'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, _opts): OngoingHandle {\n const dep = ctx.deps.editAnchors as EditAnchorsDep | undefined;\n if (!dep) return {};\n\n const affordance = ctx.drag?.affordance;\n if (!affordance) {\n // No affordance hit → this drag doesn't target an anchor handle.\n // Let other bindings handle it (the handle returns {}, dispatcher moves on).\n return {};\n }\n\n const anchorInfo = parseAnchorAffordance(affordance.kind);\n if (!anchorInfo) {\n // Affordance is a non-anchor kind (e.g. resize handle, rotate handle).\n return {};\n }\n\n const { editingId } = dep;\n // World-coord polygon. For pose-as-polygon nodes this equals\n // node.pose; for data.path nodes it's pathInWorld-projected (translate +\n // rotation) so the anchor world coords match what the user clicked.\n const worldPath = dep.getEditablePath(editingId) as PolygonPath | undefined;\n if (!worldPath || worldPath.kind !== 'polygon') return {};\n const storageKind = dep.getStorageKind(editingId);\n if (storageKind !== 'pose' && storageKind !== 'data') return {};\n\n // Decode once to validate the affordance index against the actual\n // geometry and to read the press origin. A stale affordance (the\n // path changed between pointerdown and now) fails here rather than\n // silently editing whichever anchor now holds that index.\n const decoded = pathToAnchors(worldPath) as AnchorSet;\n const origin = anchorAt(decoded, anchorInfo.anchorIndex);\n if (!origin) return {};\n if (anchorInfo.part === 'controlIn' && !origin.inHandle) return {};\n if (anchorInfo.part === 'controlOut' && !origin.outHandle) return {};\n\n // --- Press semantics: selection updates immediately, before any move.\n let dragging: readonly number[] = [anchorInfo.anchorIndex];\n if (anchorInfo.part === 'anchor') {\n const next = selectionAfterAnchorPress(\n dep.selectedAnchors,\n anchorInfo.anchorIndex,\n ctx.modifiers.shift,\n );\n dep.setSelectedAnchors(next);\n // Shift-pressing an anchor OUT of the selection must not then drag\n // it; drag whatever the press left selected, intersected with the\n // pressed anchor's membership.\n dragging = next.has(anchorInfo.anchorIndex)\n ? [...next]\n : [];\n }\n\n // For data.path nodes, we also need the original rect pose + data\n // so previewPose / previewData can be derived from currentPose.\n // Captured at start so onMove doesn't re-read the scene.\n const nodeShape = storageKind === 'data' ? dep.getNodeShape(editingId) : null;\n const originRectPose =\n nodeShape ? (nodeShape.pose as { x: number; y: number; width: number; height: number }) : undefined;\n const originData = nodeShape ? (nodeShape.data as object) : undefined;\n\n const scratch: EditAnchorsScratch = {\n dep,\n id: editingId,\n anchorIndex: anchorInfo.anchorIndex,\n part: anchorInfo.part,\n dragging,\n anchorOrigin: { x: origin.x, y: origin.y },\n originPose: worldPath,\n currentPose: worldPath,\n storageKind,\n };\n\n let active = false;\n\n return {\n kind: 'edit-anchors',\n onMove(moveCtx: InvocationCtx): void {\n if (scratch.part === 'anchor') {\n if (scratch.dragging.length === 0) return;\n const dx = moveCtx.world.x - scratch.anchorOrigin.x;\n const dy = moveCtx.world.y - scratch.anchorOrigin.y;\n const next = editAnchorSet(scratch.originPose, (set) => {\n for (const flat of scratch.dragging) translateAnchorBy(set, flat, dx, dy);\n });\n if (next) scratch.currentPose = next;\n } else {\n const side = scratch.part === 'controlIn' ? 'in' : 'out';\n const next = editAnchorSet(scratch.originPose, (set) =>\n moveHandleTo(\n set,\n scratch.anchorIndex,\n side,\n moveCtx.world.x,\n moveCtx.world.y,\n // Alt breaks the smooth mirror for this drag — read live so\n // the user can press or release Alt mid-drag.\n moveCtx.modifiers.alt,\n ),\n );\n if (next) scratch.currentPose = next;\n }\n active = true;\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n active = false;\n if (reason === 'cancel') return;\n if (scratch.originPose === scratch.currentPose) return;\n scratch.dep.applyEdit(scratch.id, scratch.currentPose, 'Edit anchors');\n },\n previewIds: () => (active ? [scratch.id] : null),\n previewPose: (id: string): unknown | null => {\n if (!active || id !== scratch.id) return null;\n if (scratch.storageKind === 'pose') {\n // Pose IS the polygon — preview pose is the polygon itself.\n return scratch.currentPose;\n }\n // data.path: invert the world edit the same way the commit does, so\n // the preview ghost (which re-applies pose.rotation via the render\n // wrap) matches the committed result — no double-rotation.\n if (!originRectPose) return null;\n return worldEditToStorage(originRectPose, scratch.currentPose).pose;\n },\n previewData: (id: string): unknown | null => {\n if (!active || id !== scratch.id) return null;\n if (scratch.storageKind !== 'data') return null;\n if (!originData) return null;\n // Stored path is the unrotated, origin-aligned contour; the render\n // invariant `pathInWorld(stored, pose) === world` holds.\n const { path } = worldEditToStorage(originRectPose!, scratch.currentPose);\n return { ...originData, path };\n },\n };\n },\n },\n enabled: () => true,\n}, editingLayer);\n"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { isBody as e } from "@weasel-js/routing";
2
+ //#region src/interactions/actions/defaults/enterPathEdit.ts
3
+ var t = {
4
+ id: "enterPathEdit",
5
+ label: "Edit path anchors",
6
+ defaultBinding: {
7
+ kind: "doubleClick",
8
+ target: { kindOf: e }
9
+ },
10
+ eligible: { mode: { in: ["normal", "isolation"] } },
11
+ requires: ["editAnchors", "selection"],
12
+ invoker: {
13
+ timing: "immediate",
14
+ run(e) {
15
+ let t = e.editAnchors, n = e.selection;
16
+ if (!t || !n) return;
17
+ let r = n.get();
18
+ for (let e of r) if (t.getEditablePath(e)) {
19
+ t.setEditingId(e);
20
+ return;
21
+ }
22
+ }
23
+ },
24
+ enabled: () => !0
25
+ };
26
+ //#endregion
27
+ export { t as enterPathEditAction };
28
+
29
+ //# sourceMappingURL=enterPathEdit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterPathEdit.js","names":["enterPathEditAction","isBody","editAnchors","deps","selection","ids","id"],"sources":["../../../../src/interactions/actions/defaults/enterPathEdit.ts"],"sourcesContent":["/**\n * `enterPathEditAction` — immediate Action that enters path-anchor edit\n * mode on a double-click against a selected polygon. Sets\n * `editAnchors.editingId` to the first selected polygon's id; the\n * gesture-side hit-test (via `buildAffordanceAt`) and the\n * `pathEditingOverlayLayer` chrome both gate on that id.\n *\n * No-op when the selection contains no polygon. The companion\n * `exitPathEditAction` (Escape) clears edit mode.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { ImmediateInvoker } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { NodeId } from 'core/scene/types';\nimport { isBody } from '@weasel-js/routing';\n\nexport const enterPathEditAction: Action & { requires: string[] } = {\n id: 'enterPathEdit',\n label: 'Edit path anchors',\n // Double-click on a polygon body (selected OR unselected) — matches the\n // Figma/Illustrator convention where double-clicking a path enters edit\n // mode regardless of prior selection state. The `kindOf` predicate fires\n // on either body class but not on empty space, so a double-click on\n // empty canvas doesn't accidentally enter edit mode.\n defaultBinding: {\n kind: 'doubleClick',\n target: { kindOf: isBody },\n },\n eligible: { mode: { in: ['normal', 'isolation'] } },\n requires: ['editAnchors', 'selection'],\n invoker: {\n timing: 'immediate',\n run(deps) {\n const editAnchors = deps.editAnchors as EditAnchorsDep | undefined;\n const selection = deps.selection as SelectionApi | undefined;\n if (!editAnchors || !selection) return;\n const ids = selection.get() as NodeId[];\n // Use the dep's editability check rather than poking at node.pose\n // directly — the dep knows whether a node has an editable polygon\n // (pose-as-polygon OR data.path) so this picks up both shapes.\n for (const id of ids) {\n if (editAnchors.getEditablePath(id)) {\n editAnchors.setEditingId(id);\n return;\n }\n }\n },\n } as ImmediateInvoker,\n enabled: () => true,\n};\n"],"mappings":";;AAkBA,IAAaA,IAAuD;CAClE,IAAI;CACJ,OAAO;CAMP,gBAAgB;EACd,MAAM;EACN,QAAQ,EAAE,QAAQC,EAAO;CAC3B;CACA,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,WAAW,EAAE,EAAE;CAClD,UAAU,CAAC,eAAe,WAAW;CACrC,SAAS;EACP,QAAQ;EACR,IAAI,GAAM;GACR,IAAMC,IAAcC,EAAK,aACnBC,IAAYD,EAAK;GACvB,IAAI,CAACD,KAAe,CAACE,GAAW;GAChC,IAAMC,IAAMD,EAAU,IAAI;GAI1B,KAAK,IAAME,KAAMD,GACf,IAAIH,EAAY,gBAAgBI,CAAE,GAAG;IACnC,EAAY,aAAaA,CAAE;IAC3B;GACF;EAEJ;CACF;CACA,eAAe;AACjB"}
@@ -0,0 +1,20 @@
1
+ //#region src/interactions/actions/defaults/enterTextEdit.ts
2
+ var e = {
3
+ id: "enterTextEdit",
4
+ label: "Enter text edit",
5
+ eligible: { mode: { in: ["normal", "isolation"] } },
6
+ requires: ["textEdit", "selection"],
7
+ invoker: {
8
+ timing: "immediate",
9
+ run: (e) => {
10
+ let t = e.selection?.get() ?? [];
11
+ if (t.length !== 1) return;
12
+ let n = t[0], r = e.textEdit;
13
+ r && (!r.isTextNode || r.isTextNode(n)) && r.startEdit(n);
14
+ }
15
+ }
16
+ };
17
+ //#endregion
18
+ export { e as enterTextEditAction };
19
+
20
+ //# sourceMappingURL=enterTextEdit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterTextEdit.js","names":["enterTextEditAction","sel","deps","id","textEdit"],"sources":["../../../../src/interactions/actions/defaults/enterTextEdit.ts"],"sourcesContent":["/**\n * `enterTextEditAction` — immediate Action descriptor for entering in-place\n * text editing on a selected text node.\n *\n * ## Status: REAL\n *\n * Fires via `useTextTool.bindings` when the user clicks on a\n * selected text node. Calls `deps.textEdit.startEdit(id)` to activate the\n * contenteditable overlay managed by `useTextEdit` / `useSceneTextEdit`.\n *\n * ## No defaultBinding / defaultBinding\n *\n * This action has no ambient key or gesture binding — it fires ONLY via\n * `useTextTool`'s `Tool.bindings` entry:\n *\n * ```ts\n * bindings: [\n * { spec: { kind: 'click', target: 'selected-body' }, actionId: 'enterTextEdit' },\n * ]\n * ```\n *\n * Keeping it binding-free avoids ambient double-fire and scopes the action to\n * the text tool context where `classifyTarget` is already wired.\n *\n * ## Self-guard: only act on text nodes\n *\n * The `'selected-body'` target yields a match for any selected node kind. To\n * avoid entering text-edit mode when the text tool happens to have a non-text\n * node selected, the action self-guards via an optional `isTextNode` predicate\n * on `TextEditDep`:\n *\n * - When `isTextNode` is absent: action fires unconditionally (the binding\n * spec is the real gate — consumers should only bind this action from the\n * text tool).\n * - When `isTextNode(id)` returns `false`: action is a no-op for that node.\n *\n * ### Pre-filtering at dispatch time\n *\n * `classifyTarget` now surfaces node kind, so a binding can pre-filter instead\n * of relying on the self-guard:\n *\n * ```ts\n * { spec: { kind: 'click', target: 'kind:text:selected' }, actionId: 'enterTextEdit' }\n * ```\n *\n * That reads the *routing trait's* kind, so it matches whatever names the\n * consumer registered in `<SceneCanvas routing>` — `'text'` under the kit's\n * inferred default. `isTextNode` stays on `TextEditDep` because it also covers\n * consumers who bind the broader `'selected-body'` target, and because it is\n * the only guard for a consumer who opted out of routing entirely.\n *\n * ## Migration plan for useTextTool\n *\n * When wiring `useTextTool` to `Tool.bindings`:\n *\n * 1. Add to `useTextTool`'s `bindings`:\n * ```ts\n * { spec: { kind: 'click', target: 'selected-body' }, actionId: 'enterTextEdit' }\n * ```\n * 2. Register a `textEdit` dep sourced from the `useTextEdit` / `useSceneTextEdit`\n * return value, plus an `isTextNode` predicate that checks `data.kind === 'text'`\n * (or however the consumer identifies text nodes).\n * 3. The existing `hitExisting` gate in `useTextTool`'s click route becomes\n * redundant — remove it in the same pass.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { TextEditDep } from '../depSchema';\nimport type { NodeId } from 'core/scene/types';\n\n// ---------------------------------------------------------------------------\n// TextEditDep\n// ---------------------------------------------------------------------------\n\n// ---------------------------------------------------------------------------\n// Descriptor\n// ---------------------------------------------------------------------------\n\n/**\n * @experimental\n * Static descriptor for the `enterTextEdit` Action.\n *\n * Requires dep-schema entries: `textEdit`, `selection`.\n *\n * No `defaultBinding` / `defaultBinding` — fires only via `Tool.bindings`.\n * Self-guards via `TextEditDep.isTextNode` when provided.\n */\nexport const enterTextEditAction: Action & { requires: string[] } = {\n id: 'enterTextEdit',\n label: 'Enter text edit',\n // No defaultBinding / defaultBinding — fires only via Tool.bindings.\n eligible: { mode: { in: ['normal', 'isolation'] } },\n requires: ['textEdit', 'selection'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const sel = (deps.selection as { get(): NodeId[] } | undefined)?.get() ?? [];\n if (sel.length !== 1) return;\n\n const id = sel[0];\n const textEdit = deps.textEdit as TextEditDep | undefined;\n if (!textEdit) return;\n\n // Self-guard: skip non-text nodes when the predicate is supplied.\n if (textEdit.isTextNode && !textEdit.isTextNode(id)) return;\n\n textEdit.startEdit(id);\n },\n },\n};\n"],"mappings":";AAuFA,IAAaA,IAAuD;CAClE,IAAI;CACJ,OAAO;CAEP,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,WAAW,EAAE,EAAE;CAClD,UAAU,CAAC,YAAY,WAAW;CAClC,SAAS;EACP,QAAQ;EACR,MAAM,MAAS;GACb,IAAMC,IAAOC,EAAK,WAA+C,IAAI,KAAK,CAAC;GAC3E,IAAID,EAAI,WAAW,GAAG;GAEtB,IAAME,IAAKF,EAAI,IACTG,IAAWF,EAAK;GACtB,AAAKE,MAGD,GAAS,cAAeA,EAAS,WAAWD,CAAE,MAElDC,EAAS,UAAUD,CAAE;EACvB;CACF;AACF"}
@@ -0,0 +1,26 @@
1
+ import { ActionDisabledReason as e } from "@weasel-js/routing";
2
+ //#region src/interactions/actions/defaults/escape.ts
3
+ var t = {
4
+ id: "escape",
5
+ label: "Escape",
6
+ defaultBinding: {
7
+ kind: "key",
8
+ key: "Escape",
9
+ phase: [{
10
+ channel: "*",
11
+ phase: "initial"
12
+ }]
13
+ },
14
+ requires: ["selection", "editAnchors"],
15
+ invoker: {
16
+ timing: "immediate",
17
+ run: (e) => {
18
+ (e.selection?.get() ?? []).length !== 0 && e.selection?.set([]);
19
+ }
20
+ },
21
+ enabled: (t) => t?.editAnchors?.editingId || ((t?.selection)?.get() ?? []).length === 0 ? e.NotApplicable : !0
22
+ };
23
+ //#endregion
24
+ export { t as escapeAction };
25
+
26
+ //# sourceMappingURL=escape.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape.js","names":["escapeAction","deps","ActionDisabledReason"],"sources":["../../../../src/interactions/actions/defaults/escape.ts"],"sourcesContent":["import type { NodeId } from 'core/scene/types';\nimport type { Action } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\n\n/**\n * @experimental\n * Static descriptor for the `escape` Action. Clears selection.\n */\n// No `eligible` field → always eligible. Escape works in every mode; the\n// runtime `enabled` thunk handles the path-edit defer-to-exit case.\nexport const escapeAction: Action & { requires: string[] } = {\n id: 'escape',\n label: 'Escape',\n // Gated to \"no tool is engaged\" so a mid-drag Escape goes to\n // `cancelGestureAction` (cancels the drag) instead of clearing\n // selection.\n defaultBinding: {\n kind: 'key',\n key: 'Escape',\n phase: [{ channel: '*', phase: 'initial' }],\n },\n requires: ['selection', 'editAnchors'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const sel = (deps.selection as { get(): NodeId[] } | undefined)?.get() ?? [];\n if (sel.length === 0) return;\n (deps.selection as { set(ids: NodeId[]): void } | undefined)?.set([]);\n },\n },\n // Defer to `exitPathEditAction` while path-anchor edit mode is active.\n // Otherwise the more-specific phase qualifier on this binding would beat\n // `exitPathEdit`'s bare key spec, swallowing the Escape that should leave\n // edit mode. With this gate, `escape` reports a disabled reason in that\n // case and the dispatcher falls through to `exitPathEdit`.\n // With nothing selected there is nothing to clear, so the press falls\n // through to `tool.resetToDefault` instead of being spent here.\n enabled: (deps) => {\n const editAnchors = deps?.editAnchors as EditAnchorsDep | undefined;\n if (editAnchors?.editingId) return ActionDisabledReason.NotApplicable;\n const sel = (deps?.selection as { get(): NodeId[] } | undefined)?.get() ?? [];\n if (sel.length === 0) return ActionDisabledReason.NotApplicable;\n return true;\n },\n};\n"],"mappings":";;AAWA,IAAaA,IAAgD;CAC3D,IAAI;CACJ,OAAO;CAIP,gBAAgB;EACd,MAAM;EACN,KAAK;EACL,OAAO,CAAC;GAAE,SAAS;GAAK,OAAO;EAAU,CAAC;CAC5C;CACA,UAAU,CAAC,aAAa,aAAa;CACrC,SAAS;EACP,QAAQ;EACR,MAAM,MAAS;GAEb,CADaC,EAAK,WAA+C,IAAI,KAAK,CAAC,EAAA,CACnE,WAAW,KACnBA,EAAM,WAAwD,IAAI,CAAC,CAAC;EACtE;CACF;CAQA,UAAU,MACYA,GAAM,aACT,eACJA,GAAM,UAAA,EAA+C,IAAI,KAAK,CAAC,EAAA,CACpE,WAAW,IAAUC,EAAqB,gBAC3C;AAEX"}
@@ -0,0 +1,22 @@
1
+ //#region src/interactions/actions/defaults/exitPathEdit.ts
2
+ var e = {
3
+ id: "exitPathEdit",
4
+ label: "Exit path edit",
5
+ defaultBinding: {
6
+ kind: "key",
7
+ key: "Escape"
8
+ },
9
+ eligible: { mode: "path-edit" },
10
+ requires: ["editAnchors"],
11
+ invoker: {
12
+ timing: "immediate",
13
+ run(e) {
14
+ e.editAnchors?.setEditingId(null);
15
+ }
16
+ },
17
+ enabled: () => !0
18
+ };
19
+ //#endregion
20
+ export { e as exitPathEditAction };
21
+
22
+ //# sourceMappingURL=exitPathEdit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exitPathEdit.js","names":["exitPathEditAction"],"sources":["../../../../src/interactions/actions/defaults/exitPathEdit.ts"],"sourcesContent":["/**\n * `exitPathEditAction` — immediate Action that exits path-anchor edit\n * mode. Bound to Escape by default; companion to `enterPathEditAction`.\n * Clears `editAnchors.editingId`, which the gesture-side hit-test and\n * `pathEditingOverlayLayer` both gate on.\n *\n * Always enabled — calling it when no path is being edited is a no-op.\n */\n\nimport type { Action } from '@weasel-js/routing';\nimport type { ImmediateInvoker } from '@weasel-js/routing';\nimport type { EditAnchorsDep } from '../depSchema';\n\nexport const exitPathEditAction: Action & { requires: string[] } = {\n id: 'exitPathEdit',\n label: 'Exit path edit',\n defaultBinding: { kind: 'key', key: 'Escape' },\n eligible: { mode: 'path-edit' },\n requires: ['editAnchors'],\n invoker: {\n timing: 'immediate',\n run(deps) {\n const editAnchors = deps.editAnchors as EditAnchorsDep | undefined;\n editAnchors?.setEditingId(null);\n },\n } as ImmediateInvoker,\n enabled: () => true,\n};\n"],"mappings":";AAaA,IAAaA,IAAsD;CACjE,IAAI;CACJ,OAAO;CACP,gBAAgB;EAAE,MAAM;EAAO,KAAK;CAAS;CAC7C,UAAU,EAAE,MAAM,YAAY;CAC9B,UAAU,CAAC,aAAa;CACxB,SAAS;EACP,QAAQ;EACR,IAAI,GAAM;GAER,EADyB,aACZ,aAAa,IAAI;EAChC;CACF;CACA,eAAe;AACjB"}
@@ -0,0 +1,119 @@
1
+ import { createTransformOp as e } from "../../../core/ops/transform.js";
2
+ import { geometryDataOp as t } from "../geometryProjection.js";
3
+ import { unionAABB as n } from "../../../core/geometry/unionBounds.js";
4
+ import { visualBoundsViaDescriptor as r } from "../../../core/geometry/poseDescriptor.js";
5
+ import { poseDescriptorOf as i } from "../poseDescriptorDep.js";
6
+ import { defaultCommitAdapter as a } from "../defaultCommitAdapter.js";
7
+ import { scenePoseFrame as o } from "../poseFrame.js";
8
+ import { FlipXIcon as s, FlipYIcon as c } from "./icons/editIcons.js";
9
+ import { requiresSelection as l } from "./requiresSelection.js";
10
+ import { flipPoseAboutBounds as u, flipPoseViaDescriptor as d } from "../flip/helpers.js";
11
+ import { actionReferenceSources as f, resolveSpatialReference as p } from "../spatialReference.js";
12
+ import { multiply as m, rotate as h, translate as g } from "@weasel-js/geom";
13
+ import { createElement as _ } from "react";
14
+ //#region src/interactions/actions/defaults/flip.ts
15
+ function v(e, t, n, r) {
16
+ let i = t.local(n, {
17
+ x: r.x + r.width / 2,
18
+ y: r.y + r.height / 2,
19
+ width: 0,
20
+ height: 0,
21
+ rotation: 0
22
+ }), a = i.rotation ?? 0, o = e === "x" ? [
23
+ -1,
24
+ 0,
25
+ 0,
26
+ 1,
27
+ 0,
28
+ 0
29
+ ] : [
30
+ 1,
31
+ 0,
32
+ 0,
33
+ -1,
34
+ 0,
35
+ 0
36
+ ], s = m(m(h(a), o), h(-a));
37
+ return m(g(i.x, i.y), m(s, g(-i.x, -i.y)));
38
+ }
39
+ function y(i, s, c, l, m, h, g, _, y, b) {
40
+ let x = i.get();
41
+ if (x.length === 0) return;
42
+ let S = o(s, _), C = /* @__PURE__ */ new Map();
43
+ for (let e of x) s.get(e) !== void 0 && C.set(e, S.world(e));
44
+ let w = null;
45
+ if (l === "union") w = n([...C.values()].map((e) => r(e, g)));
46
+ else if (l !== "each" && (w = p(l, f(y, b, s, S, g)), w === null)) return;
47
+ let T = [];
48
+ for (let n of x) {
49
+ let r = s.get(n);
50
+ if (!r) continue;
51
+ let i = C.get(n), a = w ? u(i, c, g, w) : d(i, c, g);
52
+ T.push(e({
53
+ id: n,
54
+ from: r.pose,
55
+ to: S.local(n, a),
56
+ label: "Flip"
57
+ }));
58
+ let o = w ?? g.getBounds(i), l = t(h, {
59
+ id: n,
60
+ data: r.data,
61
+ pose: r.pose
62
+ }, v(c, S, n, o), "Flip");
63
+ l && T.push(l);
64
+ }
65
+ T.length !== 0 && (m ? m(T, "Flip") : s.applyBatch(T, "Flip", a(s, i.adapterMethods)));
66
+ }
67
+ var b = {
68
+ id: "flip",
69
+ label: "Flip",
70
+ group: "flip",
71
+ variants: [{
72
+ key: "x",
73
+ label: "Flip Horizontal",
74
+ icon: _(s),
75
+ params: { axis: "x" }
76
+ }, {
77
+ key: "y",
78
+ label: "Flip Vertical",
79
+ icon: _(c),
80
+ params: { axis: "y" }
81
+ }],
82
+ defaultBinding: [{
83
+ spec: {
84
+ kind: "key",
85
+ key: ["h", "H"],
86
+ mods: { shift: !0 }
87
+ },
88
+ opts: { params: { axis: "x" } }
89
+ }, {
90
+ spec: {
91
+ kind: "key",
92
+ key: ["v", "V"],
93
+ mods: { shift: !0 }
94
+ },
95
+ opts: { params: { axis: "y" } }
96
+ }],
97
+ eligible: { capability: "transforms-selection" },
98
+ requires: [
99
+ "selection",
100
+ "scene",
101
+ "applyOps",
102
+ "geometryProjection",
103
+ "poseDescriptor",
104
+ "poseComposition",
105
+ "pointer"
106
+ ],
107
+ invoker: {
108
+ timing: "immediate",
109
+ run: (e, t) => {
110
+ let n = t?.axis ?? "x", r = t?.pivot ?? "each", a = e.selection, o = e.scene, s = e.applyOps, c = e.geometryProjection;
111
+ a && o && y(a, o, n, r, s, c, i(e.poseDescriptor), e.poseComposition, t, e.pointer);
112
+ }
113
+ },
114
+ enabled: l
115
+ };
116
+ //#endregion
117
+ export { b as flipAction };
118
+
119
+ //# sourceMappingURL=flip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flip.js","names":["localMirror","at","frame","id","pivotWorld","theta","mirror","axis","turned","multiply","rotate","translate","flipSelection","ids","selection","scenePoseFrame","scene","poseComposition","worlds","sharedPivot","pivot","unionAABB","visualBoundsViaDescriptor","p","geom","resolveSpatialReference","actionReferenceSources","params","pointer","ops","node","world","flipped","flipPoseAboutBounds","flipPoseViaDescriptor","createTransformOp","g","dataOp","geometryDataOp","geometryProjection","applyOps","defaultCommitAdapter","flipAction","createElement","FlipXIcon","FlipYIcon","deps","poseDescriptorOf","requiresSelection"],"sources":["../../../../src/interactions/actions/defaults/flip.ts"],"sourcesContent":["import type { Scene } from 'core/scene/types';\nimport { createElement } from 'react';\nimport { FlipXIcon, FlipYIcon } from './icons/editIcons';\nimport type { Op } from 'core/ops/types';\nimport { multiply, rotate, translate, type Mat3 } from '@weasel-js/geom';\nimport { createTransformOp } from 'core/ops/transform';\nimport type { PoseDescriptor } from '../resize/geometry';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport {\n flipPoseAboutBounds,\n flipPoseViaDescriptor,\n type FlipAxis,\n type FlipPivot,\n} from '../flip/helpers';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport { visualBoundsViaDescriptor } from '../align/align';\nimport { scenePoseFrame, type PoseFrame } from '../poseFrame';\nimport { actionReferenceSources, resolveSpatialReference } from '../spatialReference';\nimport type { PointerContextValue } from 'features/pointer/PointerContext';\nimport type { RectPose } from 'core/scene/types';\nimport type { Action } from '@weasel-js/routing';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { requiresSelection } from './requiresSelection';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport { geometryDataOp, type GeometryProjection } from '../geometryProjection';\n\n/**\n * The world mirror about `axis` through the center of `pivotWorld`, written in\n * the frame `id` stores its data in. `geometryProjection.transform` is given\n * the affine the node's own pose underwent, and data-held geometry is local —\n * so a world mirror has to be conjugated by the frame or an asymmetric shape\n * reflects across the wrong line while its pose lands correctly.\n *\n * The frame's turn comes back as the rotation on a rebased zero-size pose at\n * the pivot point, so no composition strategy has to expose one.\n */\nfunction localMirror(\n axis: FlipAxis,\n frame: PoseFrame<unknown>,\n id: Parameters<PoseFrame<unknown>['local']>[0],\n pivotWorld: { x: number; y: number; width: number; height: number },\n): Mat3 {\n const at = frame.local(id, {\n x: pivotWorld.x + pivotWorld.width / 2,\n y: pivotWorld.y + pivotWorld.height / 2,\n width: 0,\n height: 0,\n rotation: 0,\n }) as RectPose;\n const theta = at.rotation ?? 0;\n const mirror: Mat3 = axis === 'x' ? [-1, 0, 0, 1, 0, 0] : [1, 0, 0, -1, 0, 0];\n const turned = multiply(multiply(rotate(theta), mirror), rotate(-theta));\n return multiply(translate(at.x, at.y), multiply(turned, translate(-at.x, -at.y)));\n}\n\n/**\n * Flip the current selection in `scene` along `axis`, using the\n * `poseDescriptor` dep. Called from `flipAction.invoker.run`.\n *\n * Builds one `createTransformOp` per selected node (from = pre-flip pose,\n * to = flipped pose) and routes the batch through the consumer commit hook.\n * Mirrors `moveAction`/`nudge`'s `commitOps` helper: when `deps.applyOps` is\n * present the ops route through the consumer's history (one undo entry there);\n * otherwise they apply straight to the scene's own history via\n * `scene.applyBatch` + `defaultCommitAdapter`. Either way the whole flip is a\n * single batch → one undo entry, preserving the old `scene.batch('Flip', …)`\n * semantics exactly.\n *\n * Pivot: `'each'` (per-item own AABB) unless the caller passes `'union'`,\n * which mirrors every pose about the selection's *visual* union AABB — the\n * rotated ink extents — so items swap sides as well as reflect, or a\n * `SpatialReference`, which mirrors about the center of what it names. A rotated\n * member's own mirrored position needs no expansion: `axisAlignedBounds`\n * keeps the stored box's centre, so mirroring either box lands the same place.\n */\nfunction flipSelection(\n selection: SelectionApi,\n scene: Scene<unknown, string, unknown>,\n axis: FlipAxis,\n pivot: FlipPivot,\n applyOps: ((ops: Op[], label: string) => void) | undefined,\n geometryProjection: GeometryProjection | undefined,\n geom: PoseDescriptor<unknown>,\n poseComposition: unknown,\n params: Record<string, unknown> | undefined,\n pointer: PointerContextValue | undefined,\n): void {\n const ids = selection.get();\n if (ids.length === 0) return;\n const frame = scenePoseFrame(scene, poseComposition);\n\n const worlds = new Map<string, unknown>();\n for (const id of ids) {\n if (scene.get(id) !== undefined) worlds.set(id as string, frame.world(id));\n }\n let sharedPivot: ReturnType<typeof unionAABB> = null;\n if (pivot === 'union') {\n sharedPivot = unionAABB([...worlds.values()].map((p) => visualBoundsViaDescriptor(p, geom)));\n } else if (pivot !== 'each') {\n sharedPivot = resolveSpatialReference(pivot, actionReferenceSources(params, pointer, scene, frame, geom));\n if (sharedPivot === null) return;\n }\n\n // Read poses BEFORE building ops so each op's `from` is the pre-flip value\n // (the same value the old direct mutation captured implicitly).\n const ops: Op[] = [];\n for (const id of ids) {\n const node = scene.get(id);\n if (!node) continue;\n const world = worlds.get(id as string)!;\n const flipped = sharedPivot\n ? flipPoseAboutBounds(world, axis, geom, sharedPivot)\n : flipPoseViaDescriptor(world, axis, geom);\n ops.push(createTransformOp<unknown>({\n id: id as string,\n from: node.pose,\n to: frame.local(id, flipped),\n label: 'Flip',\n }));\n // Mirror the data-held geometry about the SAME pivot the pose flip uses,\n // so a wired geometryProjection reflects the contents in lock-step with\n // the frame. A pose-only flip of a bare-AABB pose is identity, so this\n // data op is the only way an asymmetric shape actually mirrors.\n const g = sharedPivot ?? geom.getBounds(world);\n const dataOp = geometryDataOp(\n geometryProjection,\n { id: id as string, data: node.data, pose: node.pose },\n localMirror(axis, frame, id, g),\n 'Flip',\n );\n if (dataOp) ops.push(dataOp);\n }\n if (ops.length === 0) return;\n\n if (applyOps) applyOps(ops, 'Flip');\n else scene.applyBatch(ops, 'Flip', defaultCommitAdapter(scene, selection.adapterMethods));\n}\n\n/**\n * @experimental\n * Static descriptor for the unified `flip` Action.\n *\n * Collapses the old `flip.horizontal` and `flip.vertical` pair into one action\n * with two parametric gesture bindings. The axis (`'x'` | `'y'`) is carried in\n * `opts.params.axis` and forwarded to `invoker.run` by the dispatcher, as is\n * the optional `opts.params.pivot` (a `FlipPivot`, default `'each'`).\n *\n * Requires dep-schema entries: `selection`, `scene`.\n */\nexport const flipAction: Action & { requires: string[] } = {\n id: 'flip',\n label: 'Flip',\n group: 'flip',\n variants: [\n { key: 'x', label: 'Flip Horizontal', icon: createElement(FlipXIcon), params: { axis: 'x' } },\n { key: 'y', label: 'Flip Vertical', icon: createElement(FlipYIcon), params: { axis: 'y' } },\n ],\n defaultBinding: [\n { spec: { kind: 'key', key: ['h', 'H'], mods: { shift: true } }, opts: { params: { axis: 'x' } } },\n { spec: { kind: 'key', key: ['v', 'V'], mods: { shift: true } }, opts: { params: { axis: 'y' } } },\n ],\n eligible: { capability: 'transforms-selection' },\n requires: ['selection', 'scene', 'applyOps', 'geometryProjection', 'poseDescriptor', 'poseComposition', 'pointer'],\n invoker: {\n timing: 'immediate',\n run: (deps, params) => {\n const axis = (params?.axis as FlipAxis | undefined) ?? 'x';\n const pivot = (params?.pivot as FlipPivot | undefined) ?? 'each';\n const selection = deps.selection as SelectionApi | undefined;\n const scene = deps.scene as Scene<unknown, string, unknown> | undefined;\n const applyOps = deps.applyOps as ((ops: Op[], label: string) => void) | undefined;\n const geometryProjection = deps.geometryProjection as GeometryProjection | undefined;\n if (!selection || !scene) return;\n flipSelection(\n selection, scene, axis, pivot, applyOps, geometryProjection,\n poseDescriptorOf(deps.poseDescriptor), deps.poseComposition,\n params, deps.pointer as PointerContextValue | undefined,\n );\n },\n },\n enabled: requiresSelection,\n};\n"],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { asNodeId as e } from "../../../core/scene/types.js";
2
+ //#region src/interactions/actions/defaults/freshNodeId.ts
3
+ var t = 0;
4
+ function n() {
5
+ return e(`n${(t++).toString(36)}-${Math.random().toString(36).slice(2, 8)}`);
6
+ }
7
+ //#endregion
8
+ export { n as freshNodeId };
9
+
10
+ //# sourceMappingURL=freshNodeId.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshNodeId.js","names":["counter","freshNodeId","asNodeId"],"sources":["../../../../src/interactions/actions/defaults/freshNodeId.ts"],"sourcesContent":["import type { NodeId } from 'core/scene/types';\nimport { asNodeId } from 'core/scene/types';\n\nlet counter = 0;\n\n/**\n * Mint a fresh `NodeId` for a node an action materializes itself.\n *\n * Actions that build `createInsertOp` ops can't let the scene generate the id\n * the way `scene.add(spec)` does — the op carries a whole node, so the id has\n * to exist before the op does. Mirrors the scene's own `n{counter}-{random}`\n * scheme, which `core/scene/scene.ts` keeps module-private.\n */\nexport function freshNodeId(): NodeId {\n return asNodeId(`n${(counter++).toString(36)}-${Math.random().toString(36).slice(2, 8)}`);\n}\n"],"mappings":";;AAGA,IAAIA,IAAU;AAUd,SAAgBC,IAAsB;CACpC,OAAOC,EAAS,KAAK,IAAA,CAAW,SAAS,EAAE,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG;AAC1F"}
@@ -0,0 +1,131 @@
1
+ import { asNodeId as e } from "../../../core/scene/types.js";
2
+ import { createTransformOp as t } from "../../../core/ops/transform.js";
3
+ import { createReparentOp as n } from "../../../core/ops/reparent.js";
4
+ import { unionBounds as r } from "../../../core/geometry/unionBounds.js";
5
+ import { visualBoundsViaDescriptor as i } from "../../../core/geometry/poseDescriptor.js";
6
+ import { poseDescriptorOf as a } from "../poseDescriptorDep.js";
7
+ import { defaultCommitAdapter as o } from "../defaultCommitAdapter.js";
8
+ import { scenePoseFrame as s } from "../poseFrame.js";
9
+ import { createInsertOp as c } from "../../../core/ops/create.js";
10
+ import { GroupIcon as l, UngroupIcon as u } from "./icons/editIcons.js";
11
+ import { requiresSelection as d } from "./requiresSelection.js";
12
+ import { UNION_OF_CHILDREN as f, unionOfChildren as p } from "../../../core/scene/kitRegistry.js";
13
+ import { createElement as m } from "react";
14
+ import { ActionDisabledReason as h } from "@weasel-js/routing";
15
+ //#region src/interactions/actions/defaults/group.ts
16
+ var g = 0;
17
+ function _() {
18
+ return e(`n${(g++).toString(36)}-${Math.random().toString(36).slice(2, 8)}`);
19
+ }
20
+ var v = {
21
+ id: "group",
22
+ label: "Group",
23
+ icon: m(l),
24
+ group: "structure",
25
+ defaultBinding: {
26
+ kind: "key",
27
+ key: "g",
28
+ mods: { mod: !0 }
29
+ },
30
+ eligible: { capability: "edits-page" },
31
+ requires: [
32
+ "scene",
33
+ "selection",
34
+ "applyOps",
35
+ "poseDescriptor",
36
+ "poseComposition"
37
+ ],
38
+ invoker: {
39
+ timing: "immediate",
40
+ run: (e) => {
41
+ let l = e.selection, u = e.scene, d = e.applyOps;
42
+ if (!l || !u) return;
43
+ let m = l.get();
44
+ if (m.length === 0) return;
45
+ let h = m.map((e) => u.get(e)).filter((e) => e !== void 0);
46
+ if (h.length === 0 || new Set(h.map((e) => e.layer)).size > 1) return;
47
+ let g = h[0].layer, v = new Set(h.map((e) => e.parent)).size === 1 ? h[0].parent : null, y = a(e.poseDescriptor), b = s(u, e.poseComposition), x = /* @__PURE__ */ new Map();
48
+ for (let e of h) x.set(e.id, b.world(e.id));
49
+ let S = r([...x.values()].map((e) => i(e, y))), C = S === null ? h[0].pose : y.fromBounds(S, h[0].pose), w = b.localUnder(v, C), T = b.pc.closure === "identity", E = u.registry.derivePose?.[f] ?? p, D = _(), O = [c({
50
+ node: {
51
+ id: D,
52
+ kind: "container",
53
+ layer: g,
54
+ pose: w,
55
+ data: {},
56
+ parent: v ?? null,
57
+ ...T ? {
58
+ dependsOn: "children",
59
+ derivePose: E
60
+ } : {}
61
+ },
62
+ label: "Group"
63
+ })];
64
+ for (let e of h) O.push(n({
65
+ id: e.id,
66
+ fromParentId: e.parent ?? null,
67
+ toParentId: D,
68
+ label: "Group"
69
+ })), !T && O.push(t({
70
+ id: e.id,
71
+ from: e.pose,
72
+ to: b.pc.decompose(C, x.get(e.id)),
73
+ label: "Group"
74
+ }));
75
+ d ? d(O, "Group") : u.applyBatch(O, "Group", o(u, l.adapterMethods)), l.set([D]);
76
+ }
77
+ },
78
+ enabled: d
79
+ }, y = {
80
+ id: "ungroup",
81
+ label: "Ungroup",
82
+ icon: m(u),
83
+ group: "structure",
84
+ defaultBinding: {
85
+ kind: "key",
86
+ key: "g",
87
+ mods: {
88
+ mod: !0,
89
+ shift: !0
90
+ }
91
+ },
92
+ eligible: { capability: "edits-page" },
93
+ requires: [
94
+ "scene",
95
+ "selection",
96
+ "poseComposition"
97
+ ],
98
+ invoker: {
99
+ timing: "immediate",
100
+ run: (e) => {
101
+ let t = e.selection, n = e.scene;
102
+ if (!t || !n) return;
103
+ let r = t.get();
104
+ if (r.length === 0) return;
105
+ let i = r.filter((e) => n.get(e)?.kind === "container");
106
+ if (i.length === 0) return;
107
+ let a = s(n, e.poseComposition), o = a.pc.closure === "identity";
108
+ n.batch("Ungroup", () => {
109
+ let e = [];
110
+ for (let t of i) {
111
+ let r = n.get(t);
112
+ if (!r || r.kind !== "container") continue;
113
+ let i = r.parent ?? null, s = i === null ? n.roots.indexOf(t) : n.childrenOf(i).indexOf(t), c = [...n.childrenOf(t)], l = /* @__PURE__ */ new Map();
114
+ if (!o) for (let e of c) l.set(e, a.world(e));
115
+ c.forEach((t, r) => {
116
+ n.move(t, i, s < 0 ? void 0 : s + r), o || n.setPose(t, a.localUnder(i, l.get(t))), e.push(t);
117
+ }), n.remove(t);
118
+ }
119
+ t.set(e);
120
+ });
121
+ }
122
+ },
123
+ enabled: (e) => {
124
+ let t = e?.selection, n = e?.scene;
125
+ return t?.get().some((e) => n?.get(e)?.kind === "container") ? !0 : h.NotApplicable;
126
+ }
127
+ };
128
+ //#endregion
129
+ export { v as groupAction, y as ungroupAction };
130
+
131
+ //# sourceMappingURL=group.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group.js","names":["containerIdCounter","freshContainerId","asNodeId","groupAction","createElement","GroupIcon","selection","deps","scene","applyOps","ids","nodes","id","n","layer","parent","d","poseDescriptorOf","frame","scenePoseFrame","worlds","node","union","unionBounds","visualBoundsViaDescriptor","p","containerWorldPose","pose","absolutePoses","derive","UNION_OF_CHILDREN","unionOfChildren","containerId","ops","createInsertOp","createReparentOp","createTransformOp","defaultCommitAdapter","requiresSelection","ungroupAction","UngroupIcon","containers","freed","container","baseIndex","children","childId","i","ActionDisabledReason"],"sources":["../../../../src/interactions/actions/defaults/group.ts"],"sourcesContent":["import type { Node, NodeId, Scene } from 'core/scene/types';\nimport { createElement } from 'react';\nimport { GroupIcon, UngroupIcon } from './icons/editIcons';\nimport { asNodeId } from 'core/scene/types';\nimport type { SelectionApi } from 'core/selection/useSelection';\nimport type { Op } from 'core/ops/types';\nimport { createInsertOp } from 'core/ops/create';\nimport { createReparentOp } from 'core/ops/reparent';\nimport { unionBounds } from 'core/geometry/unionBounds';\nimport { unionOfChildren, UNION_OF_CHILDREN } from 'core/scene/kitRegistry';\nimport { poseDescriptorOf } from '../poseDescriptorDep';\nimport { visualBoundsViaDescriptor } from '../resize/geometry';\nimport { createTransformOp } from 'core/ops/transform';\nimport { ActionDisabledReason, type Action } from '@weasel-js/routing';\nimport { requiresSelection } from './requiresSelection';\nimport { scenePoseFrame } from '../poseFrame';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\n\n/** Mint a fresh NodeId for a new container. The old `scene.add(spec)` path\n * (no explicit id) let the scene generate a random id, so the produced id\n * was never deterministic/observable — pre-generating one here to feed the\n * insert op preserves behavior. Mirrors the scene's default id scheme\n * (`n{counter}-{random}`), which `core/scene/scene.ts` keeps module-private.\n * Same approach as `cloneAction`. */\nlet containerIdCounter = 0;\nfunction freshContainerId(): NodeId {\n return asNodeId(`n${(containerIdCounter++).toString(36)}-${Math.random().toString(36).slice(2, 8)}`);\n}\n\n/**\n * @experimental\n * Static descriptor for the `group` Action.\n *\n * \"Group\" here means a structural `ContainerNode` — the real group that\n * round-trips to SVG `<g>` — not the legacy membership-list. `run` creates a\n * fresh container and reparents the current selection under it as a single\n * undoable batch.\n *\n * Grouping never moves a member on screen. The container takes the world\n * envelope of its members' ink; each member is then re-expressed in that\n * container's frame, which is a no-op only when the scene composes poses by\n * identity.\n *\n * Under identity the container's pose is also *derived* from its members, so\n * it tracks one that moves later instead of freezing at the moment the group\n * was made. Under any other composition that derivation is circular — the\n * members' poses are expressed in the container's own frame — so the container\n * keeps the authored envelope instead. Making it track its members again needs\n * its own decision; see the group-as-frame design doc.\n */\nexport const groupAction: Action & { requires: string[] } = {\n id: 'group',\n label: 'Group',\n icon: createElement(GroupIcon),\n group: 'structure',\n defaultBinding: { kind: 'key', key: 'g', mods: { mod: true } },\n eligible: { capability: 'edits-page' },\n requires: ['scene', 'selection', 'applyOps', 'poseDescriptor', 'poseComposition'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const selection = deps.selection as SelectionApi | undefined;\n const scene = deps.scene as Scene<unknown, string, unknown> | undefined;\n const applyOps = deps.applyOps as ((ops: Op[], label: string) => void) | undefined;\n if (!selection || !scene) return;\n\n const ids = selection.get();\n if (ids.length === 0) return;\n\n // Resolve nodes; drop any that have gone missing.\n const nodes = ids\n .map((id) => scene.get(id as NodeId))\n .filter((n): n is NonNullable<typeof n> => n !== undefined);\n if (nodes.length === 0) return;\n\n // Members must share a layer — containers live on a single layer.\n const layers = new Set(nodes.map((n) => n.layer));\n if (layers.size > 1) return;\n const layer = nodes[0]!.layer;\n\n // Nest under the shared parent if the members agree, else at the root.\n const parents = new Set(nodes.map((n) => n.parent));\n const parent = parents.size === 1 ? nodes[0]!.parent : null;\n\n // The container takes the world envelope of its members' ink. The\n // authored pose is only the fallback (an emptied group, a lost registry\n // key); under identity the derived union is what the scene shows.\n const d = poseDescriptorOf(deps.poseDescriptor);\n const frame = scenePoseFrame(scene, deps.poseComposition);\n const worlds = new Map<NodeId, unknown>();\n for (const node of nodes) worlds.set(node.id, frame.world(node.id));\n // Visual, not stored, bounds: a turned member's ink reaches outside its\n // own box, and the container has to cover what is drawn.\n const union = unionBounds([...worlds.values()].map((p) => visualBoundsViaDescriptor(p, d)));\n const containerWorldPose = union === null\n ? nodes[0]!.pose\n : d.fromBounds(union, nodes[0]!.pose);\n const pose = frame.localUnder(parent, containerWorldPose);\n // Under identity the container is an envelope that tracks its members;\n // under a composing strategy it is a frame they are re-expressed in.\n const absolutePoses = frame.pc.closure === 'identity';\n const derive = scene.registry.derivePose?.[UNION_OF_CHILDREN] ?? unionOfChildren;\n\n // Build ops mirroring the old direct mutations, in the same order the\n // `scene.batch('Group', …)` body produced them:\n // 1. insert the fresh container (the old `scene.add` minted a random\n // id; we pre-generate one so the insert op carries a full node —\n // the id was never observable, so behavior is preserved);\n // 2. reparent each selected id under the new container, in selection\n // order, capturing each node's PRE-mutation parent as `from`\n // (the op captures the sibling slot itself, on apply).\n // The container must exist before any child reparents into it, so the\n // insert op is emitted first. A member's pose then follows its reparent,\n // re-expressed in the container's frame so the member does not move.\n const containerId = freshContainerId();\n const ops: Op[] = [\n createInsertOp<Node<unknown, string, unknown>>({\n node: {\n id: containerId,\n kind: 'container',\n layer,\n pose: pose as unknown,\n data: {} as unknown,\n parent: parent ?? null,\n ...(absolutePoses ? { dependsOn: 'children', derivePose: derive } : {}),\n } as Node<unknown, string, unknown>,\n label: 'Group',\n }),\n ];\n for (const node of nodes) {\n ops.push(createReparentOp({\n id: node.id as string,\n fromParentId: (node.parent ?? null) as string | null,\n toParentId: containerId as string,\n label: 'Group',\n }));\n if (absolutePoses) continue;\n ops.push(createTransformOp<unknown>({\n id: node.id as string,\n from: node.pose,\n to: frame.pc.decompose(containerWorldPose, worlds.get(node.id)!),\n label: 'Group',\n }));\n }\n\n // Route the batch through the consumer `applyOps` hook when present (so\n // an app with its own history captures the group as a single undo\n // entry); otherwise commit straight to the scene's own history via\n // `scene.applyBatch`. One applyOps / applyBatch call = one undo entry,\n // matching the prior single `scene.batch('Group', …)`.\n if (applyOps) applyOps(ops, 'Group');\n else scene.applyBatch(ops, 'Group', defaultCommitAdapter(scene, selection.adapterMethods));\n\n // Selection update is selection state, not a scene op — set it after the\n // commit regardless of which path ran (the old code set it inside the\n // batch; it was never an undoable scene mutation).\n selection.set([containerId]);\n },\n },\n enabled: requiresSelection,\n};\n\n/**\n * @experimental\n * Static descriptor for the `ungroup` Action.\n *\n * \"Group\" here means a structural `ContainerNode`. `run` dissolves each\n * selected container by reparenting its children up to the container's own\n * parent (preserving z-order) and removing the now-empty container, as a single\n * undoable batch. Selected non-container nodes are ignored. The freed children\n * become the new selection.\n *\n * A child's pose is expressed in the container's frame, so each one is\n * re-expressed in the frame it lands in and nothing moves on screen.\n */\nexport const ungroupAction: Action & { requires: string[] } = {\n id: 'ungroup',\n label: 'Ungroup',\n icon: createElement(UngroupIcon),\n group: 'structure',\n defaultBinding: { kind: 'key', key: 'g', mods: { mod: true, shift: true } },\n eligible: { capability: 'edits-page' },\n requires: ['scene', 'selection', 'poseComposition'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const selection = deps.selection as SelectionApi | undefined;\n const scene = deps.scene as Scene<unknown, string, unknown> | undefined;\n if (!selection || !scene) return;\n\n const ids = selection.get();\n if (ids.length === 0) return;\n\n const containers = ids.filter((id) => scene.get(id as NodeId)?.kind === 'container');\n if (containers.length === 0) return;\n\n const frame = scenePoseFrame(scene, deps.poseComposition);\n const absolutePoses = frame.pc.closure === 'identity';\n\n scene.batch('Ungroup', () => {\n const freed: NodeId[] = [];\n for (const containerId of containers) {\n const container = scene.get(containerId as NodeId);\n if (!container || container.kind !== 'container') continue;\n\n const parent = container.parent ?? null;\n const baseIndex =\n parent === null\n ? scene.roots.indexOf(containerId as NodeId)\n : scene.childrenOf(parent).indexOf(containerId as NodeId);\n\n const children = [...scene.childrenOf(containerId as NodeId)];\n // Read every world pose before the first move: the frame resolves\n // through the live scene, and the container is about to leave it.\n const worlds = new Map<NodeId, unknown>();\n if (!absolutePoses) {\n for (const childId of children) worlds.set(childId, frame.world(childId));\n }\n children.forEach((childId, i) => {\n scene.move(childId, parent, baseIndex < 0 ? undefined : baseIndex + i);\n if (!absolutePoses) {\n scene.setPose(childId, frame.localUnder(parent, worlds.get(childId)!) as never);\n }\n freed.push(childId);\n });\n\n scene.remove(containerId as NodeId);\n }\n selection.set(freed);\n });\n },\n },\n enabled: (deps) => {\n const selection = deps?.selection as SelectionApi | undefined;\n const scene = deps?.scene as Scene<unknown, string, unknown> | undefined;\n const any = selection?.get().some((id) => scene?.get(id as NodeId)?.kind === 'container');\n return any ? true : ActionDisabledReason.NotApplicable;\n },\n};\n"],"mappings":"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"}