@weasel-js/core 1.12.0 → 1.13.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (292) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/dist/animation/poseTarget.js +46 -15
  3. package/dist/animation/poseTarget.js.map +1 -1
  4. package/dist/animation/poseTransition.js +3 -3
  5. package/dist/animation/poseTransition.js.map +1 -1
  6. package/dist/animation/reflow.js +3 -6
  7. package/dist/animation/reflow.js.map +1 -1
  8. package/dist/animation/rig/bindRig.js +2 -2
  9. package/dist/animation/rig/bindRig.js.map +1 -1
  10. package/dist/animation/rig/skinBinding.js +2 -2
  11. package/dist/animation/rig/skinBinding.js.map +1 -1
  12. package/dist/barrel/canvas.js +5 -3
  13. package/dist/barrel/chrome.js +3 -1
  14. package/dist/barrel/paths.js +3 -2
  15. package/dist/barrel/routing.js +2 -2
  16. package/dist/barrel/scene.js +6 -1
  17. package/dist/canvas/NodeShape.js +1 -0
  18. package/dist/canvas/NodeShape.js.map +1 -1
  19. package/dist/canvas/SceneCanvas/SceneCanvasInput.js +2 -0
  20. package/dist/canvas/SceneCanvas/SceneCanvasInput.js.map +1 -1
  21. package/dist/canvas/SceneCanvas/canvasPassThrough.js +1 -1
  22. package/dist/canvas/SceneCanvas/canvasPassThrough.js.map +1 -1
  23. package/dist/canvas/SceneCanvas/defaultNodeRouting.js +2 -2
  24. package/dist/canvas/SceneCanvas/defaultNodeRouting.js.map +1 -1
  25. package/dist/canvas/SceneCanvas/scenePointQuery.js +20 -2
  26. package/dist/canvas/SceneCanvas/scenePointQuery.js.map +1 -1
  27. package/dist/canvas/SceneCanvas/useCanvasTools.js +3 -0
  28. package/dist/canvas/SceneCanvas/useCanvasTools.js.map +1 -1
  29. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js +25 -19
  30. package/dist/canvas/SceneCanvas/usePreviewGhostLayer.js.map +1 -1
  31. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js +7 -0
  32. package/dist/canvas/SceneCanvas/useSceneCanvasLayers.js.map +1 -1
  33. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js +1 -0
  34. package/dist/canvas/SceneCanvas/useSceneCanvasTools.js.map +1 -1
  35. package/dist/canvas/SceneCanvas/useScenePicking.js +31 -6
  36. package/dist/canvas/SceneCanvas/useScenePicking.js.map +1 -1
  37. package/dist/canvas/SceneCanvas/useSceneSelectTool.js +4 -5
  38. package/dist/canvas/SceneCanvas/useSceneSelectTool.js.map +1 -1
  39. package/dist/canvas/SceneCanvas/useSceneStandardActions.js +5 -3
  40. package/dist/canvas/SceneCanvas/useSceneStandardActions.js.map +1 -1
  41. package/dist/canvas/SceneCanvas.js +19 -2
  42. package/dist/canvas/SceneCanvas.js.map +1 -1
  43. package/dist/canvas/accentColor.js +26 -3
  44. package/dist/canvas/accentColor.js.map +1 -1
  45. package/dist/canvas/buildSceneTree.js +14 -20
  46. package/dist/canvas/buildSceneTree.js.map +1 -1
  47. package/dist/canvas/copiesAbove.js +1 -1
  48. package/dist/canvas/copiesAbove.js.map +1 -1
  49. package/dist/canvas/defaultDrawOne.js +10 -7
  50. package/dist/canvas/defaultDrawOne.js.map +1 -1
  51. package/dist/canvas/deps/areaSelect.js +5 -2
  52. package/dist/canvas/deps/areaSelect.js.map +1 -1
  53. package/dist/canvas/deps/booleans.js +1 -1
  54. package/dist/canvas/deps/booleans.js.map +1 -1
  55. package/dist/canvas/deps/enteredGroup.js +81 -0
  56. package/dist/canvas/deps/enteredGroup.js.map +1 -0
  57. package/dist/canvas/deps/hitTestArea.js +27 -15
  58. package/dist/canvas/deps/hitTestArea.js.map +1 -1
  59. package/dist/canvas/deps/insert.js +4 -36
  60. package/dist/canvas/deps/insert.js.map +1 -1
  61. package/dist/canvas/deps/insertSite.js +39 -0
  62. package/dist/canvas/deps/insertSite.js.map +1 -0
  63. package/dist/canvas/deps/lassoSelect.js +6 -3
  64. package/dist/canvas/deps/lassoSelect.js.map +1 -1
  65. package/dist/canvas/deps/pathLeaf.js +1 -1
  66. package/dist/canvas/deps/pathLeaf.js.map +1 -1
  67. package/dist/canvas/deps/slice.js +2 -1
  68. package/dist/canvas/deps/slice.js.map +1 -1
  69. package/dist/canvas/derivedPath.js +14 -6
  70. package/dist/canvas/derivedPath.js.map +1 -1
  71. package/dist/canvas/doubleClickTarget.js +9 -11
  72. package/dist/canvas/doubleClickTarget.js.map +1 -1
  73. package/dist/canvas/drawnBounds.js +16 -7
  74. package/dist/canvas/drawnBounds.js.map +1 -1
  75. package/dist/canvas/inheritedPaints.js +22 -11
  76. package/dist/canvas/inheritedPaints.js.map +1 -1
  77. package/dist/canvas/nodeShapes/nodePaint.js +1 -7
  78. package/dist/canvas/nodeShapes/nodePaint.js.map +1 -1
  79. package/dist/canvas/nodeShapes/pathPainter.js +2 -3
  80. package/dist/canvas/nodeShapes/pathPainter.js.map +1 -1
  81. package/dist/canvas/nodeShapes/rectFallbackPainter.js +1 -1
  82. package/dist/canvas/nodeShapes/rectFallbackPainter.js.map +1 -1
  83. package/dist/canvas/nodeShapes/shapePainter.js +2 -3
  84. package/dist/canvas/nodeShapes/shapePainter.js.map +1 -1
  85. package/dist/canvas/ownClip.js +24 -0
  86. package/dist/canvas/ownClip.js.map +1 -0
  87. package/dist/canvas/paintCull.js.map +1 -1
  88. package/dist/canvas/pickIndex/nodeBroadBox.js +86 -0
  89. package/dist/canvas/pickIndex/nodeBroadBox.js.map +1 -0
  90. package/dist/canvas/pickIndex/scenePickIndex.js +208 -0
  91. package/dist/canvas/pickIndex/scenePickIndex.js.map +1 -0
  92. package/dist/canvas/pickWalk.js +14 -90
  93. package/dist/canvas/pickWalk.js.map +1 -1
  94. package/dist/canvas/poseCascade.js +1 -1
  95. package/dist/canvas/poseCascade.js.map +1 -1
  96. package/dist/canvas/publishPreviews.js +97 -0
  97. package/dist/canvas/publishPreviews.js.map +1 -0
  98. package/dist/canvas/sceneAdapter.js +7 -5
  99. package/dist/canvas/sceneAdapter.js.map +1 -1
  100. package/dist/canvas/sceneClipboard.js +17 -10
  101. package/dist/canvas/sceneClipboard.js.map +1 -1
  102. package/dist/canvas/scenePickReads.js +37 -0
  103. package/dist/canvas/scenePickReads.js.map +1 -0
  104. package/dist/canvas/scenePickSource.js +74 -0
  105. package/dist/canvas/scenePickSource.js.map +1 -0
  106. package/dist/canvas/sceneSlotWiring.js +9 -4
  107. package/dist/canvas/sceneSlotWiring.js.map +1 -1
  108. package/dist/canvas/sceneViewRender.js +9 -5
  109. package/dist/canvas/sceneViewRender.js.map +1 -1
  110. package/dist/canvas/shownNodes.js +15 -0
  111. package/dist/canvas/shownNodes.js.map +1 -0
  112. package/dist/canvas/useSceneAdapter.js +5 -3
  113. package/dist/canvas/useSceneAdapter.js.map +1 -1
  114. package/dist/clipboard.d.ts +2 -2
  115. package/dist/{clone-C3e0OTuF.d.ts → clone-qb2e1F5p.d.ts} +2 -2
  116. package/dist/clone.d.ts +3 -3
  117. package/dist/core/isPlainObject.js +2 -2
  118. package/dist/core/layers/layerGroup.js.map +1 -1
  119. package/dist/core/scene/NodeRouting.js.map +1 -1
  120. package/dist/core/scene/arrivalWindow.js +1 -1
  121. package/dist/core/scene/arrivalWindow.js.map +1 -1
  122. package/dist/core/scene/clipNothing.js +2 -5
  123. package/dist/core/scene/clipNothing.js.map +1 -1
  124. package/dist/core/scene/declaredFieldSetters.js +44 -0
  125. package/dist/core/scene/declaredFieldSetters.js.map +1 -0
  126. package/dist/core/scene/depMemo.js +3 -0
  127. package/dist/core/scene/depMemo.js.map +1 -1
  128. package/dist/core/scene/dependents.js +3 -1
  129. package/dist/core/scene/dependents.js.map +1 -1
  130. package/dist/core/scene/documentOf.js +43 -0
  131. package/dist/core/scene/documentOf.js.map +1 -0
  132. package/dist/core/scene/effectivePose.js +37 -13
  133. package/dist/core/scene/effectivePose.js.map +1 -1
  134. package/dist/core/scene/fieldEdits.js +17 -14
  135. package/dist/core/scene/fieldEdits.js.map +1 -1
  136. package/dist/core/scene/historyForm.js +4 -4
  137. package/dist/core/scene/historyForm.js.map +1 -1
  138. package/dist/core/scene/inheritedPaint.js +27 -5
  139. package/dist/core/scene/inheritedPaint.js.map +1 -1
  140. package/dist/core/scene/kitOps.js +3 -23
  141. package/dist/core/scene/kitOps.js.map +1 -1
  142. package/dist/core/scene/layoutPass.js +1 -2
  143. package/dist/core/scene/layoutPass.js.map +1 -1
  144. package/dist/core/scene/nodeAsShown.js +72 -0
  145. package/dist/core/scene/nodeAsShown.js.map +1 -0
  146. package/dist/core/scene/nodeFnFields.js +2 -10
  147. package/dist/core/scene/nodeFnFields.js.map +1 -1
  148. package/dist/core/scene/nodeMemo.js +6 -1
  149. package/dist/core/scene/nodeMemo.js.map +1 -1
  150. package/dist/core/scene/nodeStore.js +2 -4
  151. package/dist/core/scene/nodeStore.js.map +1 -1
  152. package/dist/core/scene/pathEffects/derive.js +3 -2
  153. package/dist/core/scene/pathEffects/derive.js.map +1 -1
  154. package/dist/core/scene/pathEffects/foundHidden.js +35 -0
  155. package/dist/core/scene/pathEffects/foundHidden.js.map +1 -0
  156. package/dist/core/scene/plyStacks.js +89 -0
  157. package/dist/core/scene/plyStacks.js.map +1 -0
  158. package/dist/core/scene/poseHold.js +42 -24
  159. package/dist/core/scene/poseHold.js.map +1 -1
  160. package/dist/core/scene/poseOverrides.js +35 -38
  161. package/dist/core/scene/poseOverrides.js.map +1 -1
  162. package/dist/core/scene/posePlies.js +59 -0
  163. package/dist/core/scene/posePlies.js.map +1 -0
  164. package/dist/core/scene/reconcileSpecs.js +6 -15
  165. package/dist/core/scene/reconcileSpecs.js.map +1 -1
  166. package/dist/core/scene/renderOrder.js +10 -4
  167. package/dist/core/scene/renderOrder.js.map +1 -1
  168. package/dist/core/scene/sameValue.js +17 -0
  169. package/dist/core/scene/sameValue.js.map +1 -0
  170. package/dist/core/scene/scene.js +3 -3
  171. package/dist/core/scene/scene.js.map +1 -1
  172. package/dist/core/scene/sceneEdits.js +8 -0
  173. package/dist/core/scene/sceneEdits.js.map +1 -1
  174. package/dist/core/scene/sceneState.js +1 -2
  175. package/dist/core/scene/sceneState.js.map +1 -1
  176. package/dist/core/scene/serialization.js +45 -9
  177. package/dist/core/scene/serialization.js.map +1 -1
  178. package/dist/core/scene/staleReplay.js +5 -2
  179. package/dist/core/scene/staleReplay.js.map +1 -1
  180. package/dist/core/scene/statedFields.js +4 -2
  181. package/dist/core/scene/statedFields.js.map +1 -1
  182. package/dist/core/scene/treeEdits.js +2 -4
  183. package/dist/core/scene/treeEdits.js.map +1 -1
  184. package/dist/core/scene/treeOrder.js +3 -1
  185. package/dist/core/scene/treeOrder.js.map +1 -1
  186. package/dist/core/scene/treeReads.js +1 -2
  187. package/dist/core/scene/treeReads.js.map +1 -1
  188. package/dist/core/scene/treeShape.js +13 -0
  189. package/dist/core/scene/treeShape.js.map +1 -0
  190. package/dist/core/scene/types.js.map +1 -1
  191. package/dist/core/scene/useScene.js +1 -1
  192. package/dist/core/scene/useScene.js.map +1 -1
  193. package/dist/{cornerHandles-p8fDIAKt.d.ts → cornerHandles-CNCb7aTY.d.ts} +1 -1
  194. package/dist/{depSchema-mG19aEdD.d.ts → depSchema-B1RS-IJx.d.ts} +27 -54
  195. package/dist/devtools/handlers.js +1 -1
  196. package/dist/devtools/handlers.js.map +1 -1
  197. package/dist/devtools/protocol.js.map +1 -1
  198. package/dist/devtools-protocol.d.ts +4 -3
  199. package/dist/devtools.d.ts +3 -2
  200. package/dist/features/measure/measureHit.js +5 -3
  201. package/dist/features/measure/measureHit.js.map +1 -1
  202. package/dist/features/measure/measurement.js +1 -1
  203. package/dist/features/measure/measurement.js.map +1 -1
  204. package/dist/features/modes/modeLayers.js +14 -7
  205. package/dist/features/modes/modeLayers.js.map +1 -1
  206. package/dist/features/modes/modeTriggers.js +3 -3
  207. package/dist/features/modes/modeTriggers.js.map +1 -1
  208. package/dist/features/pathEffects/effectSources.js +25 -16
  209. package/dist/features/pathEffects/effectSources.js.map +1 -1
  210. package/dist/features/pathEffects/readSource.js +1 -1
  211. package/dist/features/pathEffects/readSource.js.map +1 -1
  212. package/dist/features/pathEffects/useEffectSourcesLayer.js +15 -19
  213. package/dist/features/pathEffects/useEffectSourcesLayer.js.map +1 -1
  214. package/dist/features/paths/editablePath.js +1 -1
  215. package/dist/features/paths/editablePath.js.map +1 -1
  216. package/dist/features/paths/pathSnap/sceneIndex.js +1 -1
  217. package/dist/features/paths/pathSnap/sceneIndex.js.map +1 -1
  218. package/dist/features/selection/enteredGroupFrame.js +65 -0
  219. package/dist/features/selection/enteredGroupFrame.js.map +1 -0
  220. package/dist/features/selection/enteredGroupScope.js +44 -0
  221. package/dist/features/selection/enteredGroupScope.js.map +1 -0
  222. package/dist/features/text/sceneTextDrafts.js +26 -27
  223. package/dist/features/text/sceneTextDrafts.js.map +1 -1
  224. package/dist/features/text/textHitAt.js +4 -2
  225. package/dist/features/text/textHitAt.js.map +1 -1
  226. package/dist/features/text/useSceneTextEdit.js +3 -3
  227. package/dist/features/text/useSceneTextEdit.js.map +1 -1
  228. package/dist/index.d.ts +225 -73
  229. package/dist/index.js +15 -5
  230. package/dist/interactions/actions/admitsChild.js +11 -0
  231. package/dist/interactions/actions/admitsChild.js.map +1 -0
  232. package/dist/interactions/actions/defaults/contextMenu.js +16 -3
  233. package/dist/interactions/actions/defaults/contextMenu.js.map +1 -1
  234. package/dist/interactions/actions/defaults/createPaintAction.js +4 -1
  235. package/dist/interactions/actions/defaults/createPaintAction.js.map +1 -1
  236. package/dist/interactions/actions/defaults/enterGroup.js +88 -0
  237. package/dist/interactions/actions/defaults/enterGroup.js.map +1 -0
  238. package/dist/interactions/actions/defaults/enterPathEdit.js +1 -1
  239. package/dist/interactions/actions/defaults/enterPathEdit.js.map +1 -1
  240. package/dist/interactions/actions/defaults/enterTextEdit.js +1 -1
  241. package/dist/interactions/actions/defaults/enterTextEdit.js.map +1 -1
  242. package/dist/interactions/actions/defaults/group.js +7 -7
  243. package/dist/interactions/actions/defaults/group.js.map +1 -1
  244. package/dist/interactions/actions/defaults/selectAll.js +7 -3
  245. package/dist/interactions/actions/defaults/selectAll.js.map +1 -1
  246. package/dist/interactions/actions/defaults/selectDeep.js +35 -0
  247. package/dist/interactions/actions/defaults/selectDeep.js.map +1 -0
  248. package/dist/interactions/actions/drawnBoxes.js +2 -1
  249. package/dist/interactions/actions/drawnBoxes.js.map +1 -1
  250. package/dist/interactions/actions/insert/action.js +1 -0
  251. package/dist/interactions/actions/insert/action.js.map +1 -1
  252. package/dist/interactions/actions/insert/parent.js +7 -5
  253. package/dist/interactions/actions/insert/parent.js.map +1 -1
  254. package/dist/interactions/actions/insert/placeAction.js +3 -2
  255. package/dist/interactions/actions/insert/placeAction.js.map +1 -1
  256. package/dist/interactions/actions/insert/session.js +2 -2
  257. package/dist/interactions/actions/insert/session.js.map +1 -1
  258. package/dist/interactions/actions/move/commit/reparent.js +1 -1
  259. package/dist/interactions/actions/move/commit/reparent.js.map +1 -1
  260. package/dist/interactions/actions/move/gestureAdapter.js +6 -7
  261. package/dist/interactions/actions/move/gestureAdapter.js.map +1 -1
  262. package/dist/interactions/actions/move/layout/exits.js +1 -1
  263. package/dist/interactions/actions/move/layout/exits.js.map +1 -1
  264. package/dist/interactions/actions/move/session.js +4 -4
  265. package/dist/interactions/actions/move/session.js.map +1 -1
  266. package/dist/interactions/actions/pathCommands/pathNodes.js +14 -5
  267. package/dist/interactions/actions/pathCommands/pathNodes.js.map +1 -1
  268. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js +14 -2
  269. package/dist/interactions/gestures/thresholdDrag/thresholdDrag.js.map +1 -1
  270. package/dist/{math-B56zxVs5.d.ts → math-C_elShP_.d.ts} +2 -5
  271. package/dist/math.d.ts +1 -1
  272. package/dist/move.d.ts +4 -4
  273. package/dist/{options-DBxEryYq.d.ts → options-ClEm3SEl.d.ts} +1 -1
  274. package/dist/resize.d.ts +4 -4
  275. package/dist/test-seams.d.ts +6 -6
  276. package/dist/tools/builtin/pressTarget.js +22 -0
  277. package/dist/tools/builtin/pressTarget.js.map +1 -0
  278. package/dist/tools/builtin/select/adapterPointQuery.js +3 -3
  279. package/dist/tools/builtin/select/adapterPointQuery.js.map +1 -1
  280. package/dist/tools/builtin/select/collapseDeferred.js +40 -0
  281. package/dist/tools/builtin/select/collapseDeferred.js.map +1 -0
  282. package/dist/tools/builtin/select/groupEntry.js +82 -0
  283. package/dist/tools/builtin/select/groupEntry.js.map +1 -0
  284. package/dist/tools/builtin/select/pressDecision.js +1 -1
  285. package/dist/tools/builtin/select/pressDecision.js.map +1 -1
  286. package/dist/tools/builtin/select/useSelectTool.js +61 -45
  287. package/dist/tools/builtin/select/useSelectTool.js.map +1 -1
  288. package/dist/{types-7puAuVD2.d.ts → types-49uYJN3j.d.ts} +1 -1
  289. package/dist/{types-CniVctmk.d.ts → types-BEdRIhNc.d.ts} +272 -109
  290. package/dist/{types-oFeQ5VjV.d.ts → types-p2alu-R1.d.ts} +1 -1
  291. package/dist/version.js +1 -1
  292. package/package.json +25 -25
package/dist/index.js CHANGED
@@ -18,6 +18,10 @@ import { RECT_POSE_COMPOSITION, RIGID_POSE_COMPOSITION, composeRectPose, compose
18
18
  import { noteFontRead } from "./core/scene/fontReads.js";
19
19
  import { isPlainObject } from "./core/isPlainObject.js";
20
20
  import { derivedPartsOf, pathFromParts, resolvePartPaint } from "./core/scene/derivedParts.js";
21
+ import { sourcesOf } from "./core/scene/dependents.js";
22
+ import { inheritedPaintIn, inheritedPaintOf, inheritsPaint, withInheritedPaint } from "./core/scene/inheritedPaint.js";
23
+ import { documentOf } from "./core/scene/documentOf.js";
24
+ import { nodeAsShown } from "./core/scene/nodeAsShown.js";
21
25
  import { definesFrame, derivedDepOf, derivedPose, documentDepOf, documentPose, effectivePose } from "./core/scene/effectivePose.js";
22
26
  import { useNodeOverlayFrame } from "./core/viewport/useNodeOverlayFrame.js";
23
27
  import { screenToWorld, worldToScreen } from "./core/viewport/viewTransform.js";
@@ -52,8 +56,7 @@ import { useSelection } from "./core/selection/useSelection.js";
52
56
  import { pathPoseDescriptor } from "./core/geometry/pathPoseDescriptor.js";
53
57
  import { AUTO_POSE_DESCRIPTOR, isPathLike, isRectPose } from "./core/geometry/autoPoseDescriptor.js";
54
58
  import { paintsLayer } from "./core/selection/chromeState.js";
55
- import { inheritedPaintOf, inheritsPaint, withInheritedPaint } from "./core/scene/inheritedPaint.js";
56
- import { inheritedPaintIn, paintAbove, withInheritedPaints } from "./canvas/inheritedPaints.js";
59
+ import { paintAbove, withInheritedPaintBounds, withInheritedPaints } from "./canvas/inheritedPaints.js";
57
60
  import { pathPaintOf } from "./canvas/nodeShapes/nodePaint.js";
58
61
  import { OVERLAY_ROLE_STROKES } from "./canvas/overlayRoleStrokes.js";
59
62
  import { measureBetween, measureEndsOf, measureNode, measurePose, measurementOf } from "./features/measure/measurement.js";
@@ -76,12 +79,15 @@ import { releaseCanvasRenderer } from "./canvas/canvasRenderer.js";
76
79
  import { getPaintKind, listGradientKinds, listPaintKinds, paintKindOf, paintKindRegistry, patternFamily, registerPaintKind, registerPaintKindLoader, seedTile, switchGradientKind } from "./core/paint/paintKinds.js";
77
80
  import { rotateAroundAABBCenter } from "./canvas/poseRotation.js";
78
81
  import { isOverChildren, overChildren, splitOverChildren } from "./canvas/overChildren.js";
82
+ import { clipOutline } from "./canvas/ownClip.js";
79
83
  import { asNodeId } from "./core/scene/types.js";
80
84
  import { annotationLayerIds, isAnnotationLayer, isAnnotationNode } from "./core/scene/annotation.js";
81
85
  import { hidesSubtree, isNodeHidden, isNodeLocked, nodeGates } from "./core/scene/nodeGates.js";
82
86
  import { drawnBoundsScene } from "./canvas/derivedPath.js";
87
+ import { statedFields } from "./core/scene/statedFields.js";
83
88
  import { applyOpsTo, dispatchApplyBatch } from "./core/applyOps.js";
84
89
  import { createPoseTarget, poseAxes, scenePoseTarget } from "./animation/poseTarget.js";
90
+ import { hasChildren, isLeaf } from "./core/scene/treeShape.js";
85
91
  import { sceneToAdapter } from "./canvas/sceneAdapter.js";
86
92
  import { defaultDrawOne, defaultPaintBounds } from "./canvas/defaultDrawOne.js";
87
93
  import { buildSceneViewCommands, renderSceneToCanvas } from "./canvas/sceneViewRender.js";
@@ -158,7 +164,7 @@ import { lassoSelectAction } from "./interactions/actions/lasso-select/action.js
158
164
  import { sliceAction } from "./interactions/actions/defaults/slice.js";
159
165
  import { textAlongParts } from "./core/scene/pathEffects/textAlong.js";
160
166
  import { PATH_EFFECT, createPathEffectDerivations, pathEffectNode, pathEffectOf, pathEffectParts, registeredPathEffects } from "./core/scene/pathEffects/derive.js";
161
- import { effectSourceFor, hiddenSourcesTakenWith } from "./features/pathEffects/effectSources.js";
167
+ import { effectSourceFor, hiddenSourcesTakenWith, sourcesHiddenBy } from "./features/pathEffects/effectSources.js";
162
168
  import { commitDeleteToScene, createDeleteAction, deleteAction, hiddenSourceDeleteOps } from "./interactions/actions/defaults/delete.js";
163
169
  import { makePinchZoomAction, pinchZoomAction } from "./interactions/actions/defaults/pinchZoom.js";
164
170
  import { WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, buildWeaselClipboardText, embedWeaselMetadataInSvg, extractWeaselClipboardFromSvg, parseWeaselClipboardText, sniffWeaselClipboardText } from "./interactions/actions/clipboard/wireFormat.js";
@@ -175,6 +181,7 @@ import { createMoveToIndexOp, createReorderOp } from "./core/ops/reorder/index.j
175
181
  import { arrangePreset } from "./canvas/SceneCanvas/presets/arrange.js";
176
182
  import { CLIP_NOTHING, clipNothing } from "./core/scene/clipNothing.js";
177
183
  import { UNION_OF_CHILDREN, unionOfChildren } from "./core/scene/kitRegistry.js";
184
+ import { createEnteredGroup, useEnteredGroup } from "./canvas/deps/enteredGroup.js";
178
185
  import { getAlpha01, mergeAlphaFromPrev, toHex8, withAlpha01 } from "./util/color.js";
179
186
  import { DEFAULT_FILL_COLOR, DEFAULT_PALETTE, DEFAULT_STROKE_COLOR, GHOST_STROKE, cycleFill, paintAlpha, paintWithAlpha, paintWithColor, solid, strokeOf, strokeWith } from "./util/paint.js";
180
187
  import { editPreset } from "./canvas/SceneCanvas/presets/edit.js";
@@ -233,7 +240,7 @@ import { measureAt, measureEndSource } from "./features/measure/measureHit.js";
233
240
  import { MEASURE_ACTION_IDS } from "./features/measure/actionIds.js";
234
241
  import { useMeasureTool } from "./tools/builtin/measure/useMeasureTool.js";
235
242
  import { isToolSet, toolIdsOf, toolSet, toolSetHas, withoutTools } from "./tools/index.js";
236
- import { ActionDisabledReason, ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, DepRegistryProvider, InputScope, Yoke, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, actionsTagged, bindingId, bodyPredicate, buildDepsFromRequires, createDepRegistry, createDispatcher, deleteScratch, evaluateActive, evaluateEnabled, getScratch, heldKeySpec, hitPredicate, keySpecShortcut, keysHeld, matchActionItem, overlaysOf, readActionSettings, resolveBindingOverrides, resolveParams, resolveSchemaMenu, roleReader, scratchKey, setScratch, specificity, taggedActionItems, tuneAction, useAction, useActionsRegistry, useActiveToolContext, useCommand, useDepRegistry, useDepSource, useGestureDispatcher, useLatest, useMenuHost, useMenus, useOngoingAction, useOpenKeymap, useOptionalActiveToolContext, useOptionalDepRegistry, useYoke } from "./barrel/routing.js";
243
+ import { ActionDisabledReason, ActionsProvider, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, DepRegistryProvider, InputScope, Yoke, actionBindings, actionCursor, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, actionsTagged, bindingId, bodyPredicate, buildDepsFromRequires, createDepRegistry, createDispatcher, deleteScratch, evaluateActive, evaluateEnabled, getScratch, heldKeySpec, hitPredicate, keySpecShortcut, keysHeld, matchActionItem, modifierStateOf, overlaysOf, readActionSettings, resolveBindingOverrides, resolveParams, resolveSchemaMenu, roleReader, scratchKey, setScratch, specificity, taggedActionItems, tuneAction, useAction, useActionsRegistry, useActiveToolContext, useCommand, useDepRegistry, useDepSource, useGestureDispatcher, useLatest, useMenuHost, useMenus, useOngoingAction, useOpenKeymap, useOptionalActiveToolContext, useOptionalDepRegistry, useYoke } from "./barrel/routing.js";
237
244
  import { PAINTED_CURSOR_LAYER_ID, createPaintedCursorLayer } from "./canvas/paintedCursorLayer.js";
238
245
  import { hostAnchorCss, hostAnchorRect } from "./canvas/hostAnchor.js";
239
246
  import { useHostAnchor } from "./canvas/useHostAnchor.js";
@@ -261,7 +268,9 @@ import { createArrangeOp } from "./core/ops/arrange.js";
261
268
  import { createHistory } from "./core/ops/createHistory.js";
262
269
  import { SCENE_HISTORY_FORM } from "./core/scene/historyForm.js";
263
270
  import { sceneSelectionStore } from "./core/scene/sceneSelection.js";
271
+ import { nodeKindOf, specsFromSerialized } from "./core/scene/serialization.js";
264
272
  import { createScene, sceneFromJSON } from "./core/scene/scene.js";
273
+ import { publishPreviews } from "./canvas/publishPreviews.js";
265
274
  import { actionIs, always, and, canHover, capabilityAll, capabilityIn, capabilityIs, capabilityNot, coarsePointer, cond, editingAnchors, focused, gesturing, hovering, hoveringSelected, modeIn, modeIs, modeNot, modifierHeld, multiActive, never, not, or, selectionAtLeast, selectionEmpty, selectionIs, when, zoomAtLeast } from "./features/chrome-caps/conditions.js";
266
275
  import { SCENE_CANVAS_FEATURES } from "./canvas/SceneCanvas/features.js";
267
276
  import { BUILTIN_TOOLS, BUILTIN_TOOL_IDS, DRAW_TOOLS, PAGE_TOOLS, SELECT_TOOLS, SHAPE_TOOLS, TYPE_TOOLS, VIEW_TOOLS } from "./canvas/SceneCanvas/builtinToolSets.js";
@@ -284,6 +293,7 @@ import { resolveVisibility } from "./features/chrome-caps/resolve.js";
284
293
  import { buildChromeCtx } from "./features/chrome-caps/buildChromeCtx.js";
285
294
  import { useHoverTracking } from "./features/chrome-caps/useHoverTracking.js";
286
295
  import { ALWAYS, DEFAULT_ALLOWED_CAPABILITIES, NEVER, buildRuleCtx, describeRule, evaluate } from "./features/chrome-caps/index.js";
296
+ import { createEnteredGroupScope } from "./features/selection/enteredGroupScope.js";
287
297
  import { useSceneAdapter } from "./canvas/useSceneAdapter.js";
288
298
  import { createNodeRouting, routeKind } from "./core/scene/NodeRouting.js";
289
299
  import { SceneCanvas } from "./canvas/SceneCanvas.js";
@@ -354,4 +364,4 @@ import { mergeContributions } from "./canvas/surfaceContribution.js";
354
364
  import { CURSOR_ANGLE_STEPS, CURSOR_MAX_CSS_PX, KEYMAP_HOLD, SPRITE_STRIDE, assembleEntries, bakeCursor, bindingSpec, blur, canQueryLocalFonts, captureGesture, captureKey, createCursorSink, createKeymapStack, createPaintedCursorState, createReflectable, cssFamilyName, cssFontFamily, cssFontFamilyLoading, cullDrawCommands, cursorFor, describeKeymap, enableLocalFontOutlines, fontOutlineRegistry, fontRegistry, frameRect, hasFontOutlines, held, isCanvasFont, key, keySpecRoute, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, listFontOutlines, liveScope, loadFontOutlines, mat3, modeShortcutSpec, modeShortcuts, outlineStatus, refreshCanvasFont, registerCanvasFont, registerEffect, registerFont, registerFontOutlines, resolveCursor, resolveCursorTier, scopeBindings, subscribeGlyphReady, unbound, unregisterCanvasFont, unregisterFontOutlines, viewToMat3, vignette, warmFonts } from "./barrel/renderer.js";
355
365
  import { coreKitSettingsSchema } from "./kitSettingsSchema.js";
356
366
 
357
- export { ALWAYS, ANCHOR_HIT_BASE_PX, ANGLE_RADIANS, AREA_SELECT_ID, AUTO_ORIGIN_PROJECTION, AUTO_POSE_DESCRIPTOR, ActionDisabledReason, ActionsProvider, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, BUILTIN_MARKERS, BUILTIN_TOOLS, BUILTIN_TOOL_IDS, CANVAS_CONTEXT_ATTRIBUTES, CLIP_NOTHING, COARSE_TARGET_SCALE, COMPOSITE_FEATURES, CONSTRAINT_TOLERANCE, CONTROL_SELECTOR, CORNER_ANCHORS, CORNER_FIT_TOLERANCE, CORNER_KEYWORDS, CURSOR_ANGLE_STEPS, CURSOR_MAX_CSS_PX, CURVE_REPS, CanvasView, CursorCoordsHud, DEBUG_FEATURES, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DECORATION_METRICS, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_FLATTEN_TOLERANCE, DEFAULT_HANDLE_SIZE, DEFAULT_INK, DEFAULT_LAYER_RETAIN, DEFAULT_MAX_ZOOM, DEFAULT_MIN_ZOOM, DEFAULT_OVERLAY_STYLE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_SIMPLIFY_TOLERANCE, DEFAULT_SNAP_PX, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_FILL, DEFAULT_TEXT_STYLE, DEFAULT_VELOCITY_DECAY, DRAG_PAN_ID, DRAG_THRESHOLD_PX, DRAW_TOOLS, DepRegistryProvider, DepRegistryProviderIfRoot, DeviceProfileProvider, DevtoolsLabel, DrawCanvas, EASINGS, EDGE_HANDLE_MIN_RADII, FALLBACK_ACCENT, FEATURE_ACTION_IDS, GEOMETRY_BOUND_DATA, GHOST_STROKE, HANDLE_BASE_PX, HANDLE_LOCK_ROLES, IDENTITY_POSE_COMPOSITION, IMPERIAL_INCHES, INHERIT, INSERT_REPOSITION_BINDING, IconRegistryProvider, IconRegistryProviderIfRoot, InputScope, KEYMAP_HOLD, KIT_SHAPE_KINDS, KIT_STANDARD_ACTION_IDS, KIT_VERSIONS, LONG_PRESS_FEEDBACK_ID, LONG_PRESS_MS, LeanSceneCanvas, MARKDOWN_RUN_GRAMMAR, MEASURE_ACTION_IDS, MEASURE_AFFORDANCE_KIND, MEASURE_LAYER_ID, METRIC_MM, MIXED, MOVE_NODES_REQUIRES, NEVER, OVERLAY_ROLE_STROKES, PAGES_DOC_KEY, PAGE_TOOLS, PAINTED_CURSOR_LAYER_ID, PATHFINDER_STROKES, PATH_ANCHOR_CHROME_ID, PATH_C, PATH_CMD_LENGTHS, PATH_EFFECT, PATH_EFFECT_DERIVATIONS, PATH_GESTURE_TAGS, PATH_L, PATH_M, PATH_OVERLAY_ROLES, PATH_Q, PATH_SNAP_KINDS, PATH_SNAP_LABELS, PATH_Z, PIXELS, PathBuilder, PickHud, PointerContextProvider, PointerProviderIfRoot, RECT_ORIGIN_PROJECTION, RECT_POSE_COMPOSITION, RECT_POSE_DESCRIPTOR, RESIZE_HANDLE_ANCHORS, RIGID_POSE_COMPOSITION, ROTATED_POSE_DESCRIPTOR, ROTATION_HANDLE_BASE_PX, SCENE_CANVAS_FEATURES, SCENE_HISTORY_FORM, SCRIPT_METRICS, SELECTION_MOVE_ID, SELECTION_RESIZE_ID, SELECTION_ROTATE_ID, SELECTION_TRANSFORM_ID, SELECT_TOOLS, SHAPE_COUNT_RANGE, SHAPE_KINDS, SHAPE_TOOLS, SMALL_CAPS_SCALE, SNAP_ANGLE_STEP, SNAP_AXIS_STEP, SNAP_ROLES, SPRING_PRESETS, SPRITE_STRIDE, STAR_RATIO_RANGE, STICKY_DEFAULTS, STROKE_DASH_RATIOS, SceneArrivalRefused, SceneCanvas, SceneViewCanvas, SelectionContextProvider, SelectionContextProviderIfRoot, TEXT_EDIT_FONT_HOLD, TILE_KINDS, TOOL_DRIVEN_ACTION_IDS, TYPE_TOOLS, TextOutlinesError, UNION_OF_CHILDREN, VERSION, VIEW_ANIMATION_KEY, VIEW_MARKER_DEFAULT_STYLE, VIEW_MARKER_DRAG, VIEW_MARKER_HIT_SLOP_PX, VIEW_TOOLS, ViewMarker, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, WHEEL_ZOOM_STEP, WeaselProvider, Yoke, ZOOM_FLOOR, aabbCenter, accentColorOf, actionBindings, actionCursor, actionIs, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, actionsTagged, activatesFocusedControl, addPage, adjacentPage, aimSpace2d, alignDeltaFor, alignTargetBounds, alignedStrokeRect, always, anchorEditWouldChange, and, animateLifecycle, animateOnSetPose, annotationLayerIds, annulusSemiAxes, applyBooleanOp, applyCreateOutlines, applyOpsTo, applyOutlineStroke, applyStyleToRange, areaSelectAction, areaSelectContribution, arrangePreset, asNodeId, asPaint, asPolygonPath, assembleEntries, assertSnapSourceIds, averageAnchorsAt, axisAlignedBounds, axisUnits, axisZoomFactor, bakeCursor, bendAlongPath, bezierCubic, bezierQuadratic, bindPoseTransition, bindRig, bindingId, bindingSpec, bitmapSrc, blendPaths, blur, bodyPredicate, boundsOfPath, buildChromeCtx, buildDebugOverlayCommands, buildDepsFromRequires, buildRuleCtx, buildSceneViewCommands, buildWeaselClipboardText, cachedLayoutRuns, cachedPaintRuns, canBringForward, canHover, canQueryLocalFonts, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, captureGesture, captureKey, caretIndexAt, carriedDescendants, charOffsetToDomPosition, checkRequirements, circlePath, clampShapeGenerator, clampView, classifyPathStorage, clearSelectionAction, clientToCanvas, clipNothing, clipboardCopyAction, clipboardCutAction, clipboardPasteAction, clipboardPasteEventAction, cloneAction, coarsePointer, commandFill, commandPaint, commandStroke, commitAnchorEdit, commitBooleanPieces, commitDeleteToScene, commitOps, composeAffordanceLayer, composePath, composePatternTransform, composeRectPose, composeRigidPose, composeSelectionPose, composeWorldPose, composesFrames, computeFitViewport, computeSliceOps, computeWheelAction, cond, constrainPathEdit, constraintAnchors, contextMenuAction, contrastLineColor, contrastRatio, coreKitSettingsSchema, cornerAt, cornerFrameAt, cornerFrames, cornerKeywordOf, cornerPoint, cornerResizeHandles, cornerShapeK, cornerShapePieces, cornerSpecAt, countPathAnchors, createArrangeOp, createChildrenLayer, createCornerResizeAffordance, createCursorSink, createDebugOverlayLayer, createDebugSink, createDeleteAction, createDeleteOp, createDepRegistry, createDepartures, createDispatcher, createHistory, createInsertOp, createKeyState, createKeymapStack, createLongPressFeedbackContribution, createLongPressStore, createMarkdownRenderer, createMeasurements, createMoveToIndexOp, createNodeProperties, createNodeRouting, createPaintedCursorLayer, createPaintedCursorState, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathEffectDerivations, createPathLayer, createPathOverlay, createPathSnapIndex, createPenPreviewLayer, createPointerFollower, createPointerStore, createPoseFeed, createPoseOverrides, createPoseTarget, createRasterSession, createReflectable, createReflowTransition, createReorderOp, createReparentOp, createResizeAction, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetChildOrderOp, createSetDataOp, createSetDependsOnOp, createSetHiddenOp, createSetLayerOp, createSetLayoutOp, createSetLockedOp, createSetPathOp, createSetSelectionOp, createSetTextOp, createSimulation, createSnapOutcomeStore, createSnapReadoutLayer, createTextLayer, createTilePattern, createTransformOp, createVelocityTracker, createViewMarkerContribution, createViewMarkerLayer, createViewResolver, createViewportLayer, createWrittenPoseTarget, cssFamilyName, cssFontFamily, cssFontFamilyLoading, cubicBezierEasing, cullDrawCommands, currentMeasureId, cursorFor, cycleFill, dashForStrokeStyle, dataRestPath, debugSnapshotArgs, decomposePath, decomposePatternTransform, decomposeRectPose, decomposeRigidPose, decorationMetrics, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultPaintBounds, defaultVisibilityRules, defineTool, definesFrame, deleteAction, deleteAnchorsAction, deleteNode, deleteScratch, deleteSelectedMark, depOf, depsUnchanged, deriveParallaxView, derivedDepOf, derivedPartsOf, derivedPose, describeKeymap, describeRule, dispatchApplyBatch, dlog, documentDepOf, documentPose, domPositionToCharOffset, domToRuns, dragPanContribution, dragPointOf, drawLayers, drawOneLayer, drawnAABBOf, drawnBoundsOf, drawnBoundsScene, dwarn, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, editPreset, editTargetOf, editedPathSymmetries, editingAnchors, editingLayer, effectSourceFor, effectivePose, effectiveRangeStyle, ellipsePath, embedWeaselMetadataInSvg, enableLocalFontOutlines, enterTextEditAction, enumerateAnchors, evaluate, evaluateActive, evaluateEnabled, exitPathEditToolAction, extendToMeet, extractWeaselClipboardFromSvg, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findPathSnap, findShapeBounds, findShapeDrawnBounds, findShapeInk, findShapeSilhouette, finishPathEditFrame, fitTextPose, fitToBounds, fitViewToBounds, fitViewToPage, fitZoom, fixedCornerOf, flattenCubic, flattenCubicWithArcLen, flattenPreviews, flattenQuadratic, flattenQuadraticWithArcLen, flipAction, focused, focusedControlOwnsKey, fontOutlineRegistry, fontRegistry, fontString, forEachCoalesced, forgetTransform, formatAxes, formatScoped, formatUnit, frameRect, fromPlane, fromRoot, gateLayer, gatherSnapCandidates, gesturePlaneReader, gestureViewReader, gesturing, getAlpha01, getImageBitmap, getMarker, getNodeShapes, getPaintKind, getScratch, getStylusData, glidesByDefault, grabViewMarker, gradientForBounds, gradientGeometry, groupNodeRouting, handlePoint, hasCorners, hasEditablePath, hasFontOutlines, hasOpenSubpath, held, heldKeySpec, hexToOklchDeg, hexToRgbBytes, hexToRgba, hiddenSourceDeleteOps, hiddenSourcesTakenWith, hidesSubtree, historyKey, hitAffordanceRegions, hitAnchor, hitCornerHandle, hitPredicate, hitRotationHandle, hostAnchorCss, hostAnchorRect, hovering, hoveringSelected, hslToSrgb, imageStatus, inPlane, inferredNodeProperties, inferredNodeRouting, ingestPreset, inheritedPaintIn, inheritedPaintOf, inheritsPaint, inkExtentsOf, insertAction, insertAt, insertLayer, insertPreviewExtent, insertRepositionAction, interpolateSrgb, interpolateView, intersectSegments, isAnnotationLayer, isAnnotationNode, isBoldWeight, isCanvasFont, isCornerHandle, isCornerShape, isDebugEnabled, isEditableTarget, isGradientPaint, isInControlWithin, isLayerPainted, isLayerVisible, isNodeHidden, isNodeLocked, isOverChildren, isPaintKindKnown, isPathLike, isPatternPaint, isPlainObject, isRectAim, isRectPose, isShapeGenerator, isSmallCapsLetter, isSolidPaint, isTextData, isTileKind, isTilePaint, isToolSet, isVectorImageSrc, joinAnchorsAt, joinPathsCommand, joinSelectedAnchors, key, keySpecRoute, keySpecShortcut, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, keysHeld, kitTextHandler, lassoSelectAction, lastTransform, layoutMarkdown, layoutPages, layoutRuns, layoutTextPose, lengthenOpenEnd, lerpColorArray, lerpFill, lerpOklab, lerpOklch, lerpPaint, lerpStroke, linePath, linear, linearSrgbToOklab, linearToSrgb, listFontOutlines, listGradientKinds, listMarkers, listPaintKinds, livePathEdit, liveScope, loadFontOutlines, loadTextOutlines, locksInForce, makeHandleCommand, makePinchZoomAction, makeViewportWheelPanAction, makeViewportZoomAction, markUnder, markdownToRuns, markerInset, markerKeyOf, markerRegistry, markerSites, mat3, matchActionItem, matchesKeyBinding, meanScale, measureAt, measureBetween, measureEndSource, measureEndsOf, measureIds, measureNode, measurePath, measurePose, measureText, measureTextBounds, measuredSegmentCommands, measuredWidth, measurementOf, measurementsContribution, mergeAlphaFromPrev, mergeContributions, minSizeOf, modeDecorationLayer, modeIn, modeIs, modeNot, modeShortcutSpec, modeShortcuts, modeTriggers, modifierHeld, momentum, moveAction, moveNodes, moveNodesOps, movePage, movePreset, multiActive, nestedHitTester, never, nextCornerShape, nextPageId, nodeGates, nodeHasFlag, nodeOutline, normalizeHex, normalizeView, normalizeZoom, not, noteFontRead, nudgeAnchorsDownAction, nudgeAnchorsLeftAction, nudgeAnchorsRightAction, nudgeAnchorsUpAction, numericWeight, nurbs, offsetPath, oklabToLinearSrgb, oklabToOklch, oklabToSrgbU8, oklchDegToHex, oklchToOklab, onEmptyCanvas, opFactoryRegistry, openContextMenu, openEndRay, openFilePicker, openPathEnds, openPointerSession, or, outlinePreset, outlineStatus, overChildren, overlaysOf, pageAt, pageHolding, pageInView, pageMembers, pageName, pageOfBounds, pagesBounds, pagesLayer, pagesOf, paintAbove, paintAlpha, paintKindOf, paintKindRegistry, paintRuns, paintWithAlpha, paintWithColor, paintedLayers, paintsLayer, paletteInsertPaint, paragraphDirection, parseColor, parseColorToRgba255, parseDebugFlags, parseHexBytes, parseUnitExpr, parseWeaselClipboardText, pastDragThreshold, patchRangeStyle, pathAnchorPoints, pathCommandCoordCount, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCopy, pathCrossings, pathDistanceToPoint, pathDivide, pathEditPathOf, pathEditPreview, pathEditToolAction, pathEditToolActive, pathEffectNode, pathEffectOf, pathEffectParts, pathExclude, pathFromD, pathFromParts, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathNodesOf, pathOperationTags, pathOriginProjection, pathPaintOf, pathPoseDescriptor, pathSegments, pathSignedArea, pathSnapGlyph, pathSnapSource, pathSubtract, pathThroughPoseFrame, pathToAnchors, pathToD, pathUnion, pathsPreset, patternFamily, patternPlacementOf, pickTopMostHit, pillCommands, pinchZoomAction, placeAction, placeSkeleton, placedPagesOf, planJoin, planPixelRender, planeMap, planeMatrix, planeToPlane, pointAlongPath, pointInPath, pointInRotatedRect, pointInTextPose, pointRegionFrame, pointSnap, polygonFromPoints, polylineFromPoints, poseAxes, poseDescriptorForNode, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, pressureToWidth, previewBooleanOp, pxExtent, rangeWeight, rasterToPng, readActionSettings, readEffectSource, rebaseLocalPose, rebuildOp, reconcileSpecs, recordTransform, rectAim, rectCorners, rectFromPlane, rectMarkerPath, rectPath, rectToPlane, refreshCanvasFont, regenerateShape, registerBidi, registerCanvasFont, registerContentHandler, registerEffect, registerFont, registerFontOutlines, registerMarker, registerNodeShape, registerOpFactory, registerPaintKind, registerPaintKindLoader, registeredOpNames, registeredPathEffects, regularPolygonPath, releaseCanvasRenderer, releaseImage, remapPerAnchor, removePage, renamePage, renderDebugSnapshot, renderLabel, renderNeeds, renderSceneToCanvas, renderSceneToPixels, repeatAlongPath, requiresAnchorSelection, reshapeOps, reshapeTo, resizeAction, resizeHandlesFor, resizePage, resizePreset, resolveAlign, resolveAxes, resolveBindingOverrides, resolveBooleanOperands, resolveColor, resolveCorners, resolveCornersWithSources, resolveCursor, resolveCursorTier, resolveDeviceProfile, resolveEasing, resolveEditablePathOf, resolveFill, resolveFillPattern, resolveMarkerSize, resolveOverlays, resolveParams, resolvePartPaint, resolvePatternSpec, resolvePreviews, resolveRunFace, resolveRuns, resolveSchemaMenu, resolveScoped, resolveScreenLength, resolveSpatialReference, resolveStroke, resolveStrokeWidth, resolveTextStyle, resolveUnit, resolveUnitExpr, resolveVisibility, resolvedSnapMarks, retryImage, reversePath, rgbaToHex, rigFromNode, rigidRigApply, roleReader, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatePreset, rotatedRectCorners, rotationDegreesUnit, rotationHandle, rotationSnapSource, roundRectPath, routeKind, runsToDom, runsToMarkdown, runsToPlainText, sampleGradientStops, satisfiesRange, scaleDelta, scalePathToBounds, scaleVertexWidth, sceneCarrySource, sceneClipTargets, sceneFromJSON, sceneNodeClientRect, scenePoseAdapter, scenePoseFrame, scenePoseTarget, sceneSelectionStore, sceneSharedUnitScopes, sceneToAdapter, sceneUnitScopes, scopeBindings, scopesOf, scratchKey, screenAngleOf, screenToWorld, screenTolerance, scriptMetrics, scriptMetricsFor, seedTile, segmentUnder, selectAnchorAction, selectFromLasso, selectPreset, selectedPathNodes, selectionAtLeast, selectionEmpty, selectionIs, selectionLayer, selectionMoveBindings, selectionMoveContribution, selectionResizeBindings, selectionResizeContribution, selectionRotateBindings, selectionRotateContribution, selectionTransformBindings, selectionTransformContribution, setFlagOverRange, setImageCacheBudget, setPages, setScratch, settleShapeGenerator, shapeCoversPoint, shapeGeneratorOf, shapeGeneratorPath, simplifyAnchorsAt, simplifyPath, sliceAction, slotOf, smallCapsScale, smallCapsScaleFor, smallCapsText, smudgePath, snapMods, snapSourcesFor, sniffWeaselClipboardText, snipPathByPolyline, snipPathsAtCrossings, solid, solveConstraints, solvePathConstraints, specificity, spiro, splitByClosure, splitOverChildren, splitPathByPolyline, splitPathBySegment, splitSubpaths, springPose, squarePath, srgbFloatToOklab, srgbToHsl, srgbToLinear, srgbU8ToOklab, stableStringify, staggerSpringPose, standoff, starPath, startCarry, startThresholdDrag, stationsAlongPath, stepAngles, stickyData, stickyNodeFactory, storeEditablePath, strokeDashStyleOf, strokeInsets, strokeOf, strokeRegion, strokeToPath, strokeWith, styleAtRange, subscribeGlyphReady, subscribeImageReady, subscribeToSources, swapOp, switchGradientKind, taggedActionItems, textAlongParts, textBoxOf, textCommand, textCommandFromPose, textCommandFromRuns, textLineBoxes, textPoseLayoutInput, textToPath, textToPathsByPaint, tickedSegment, tileSpecOf, toHex8, toIconRef, toPlane, toRoot, toRuns, toolIdsOf, toolSet, toolSetHas, transformPath, transformRunTexts, translatePath, translatePoseViaDescriptor, translateRectPose, trianglesToPath, trimPathAt, trimPolyline, tuneAction, tweenPose, unboldPatch, unbound, unionAABB, unionBounds, unionBoundsPath, unionOfChildren, unionOfChildrenVia, unitScale, unplaceSkeleton, unregisterCanvasFont, unregisterFontOutlines, unsatisfiedConstraints, useAction, useActionsRegistry, useActiveToolContext, useAlign, useAnchorFields, useAnimatedReflow, useAutoCenter, useBooleans, useBooleansAdapter, useBooleansAdapterSource, useCanvasFocus, useCanvasSize, useClipboardOps, useCommand, useCreateOutlinesAdapter, useDecayLoop, useDepRegistry, useDepSource, useDeviceProfile, useDevtoolsLabel, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEffectSourcesLayer, useElementSize, useEllipseTool, useEyedropperTool, useFrameClock, useGestureDispatcher, useGradientKinds, useHandTool, useHandleDrag, useHostAnchor, useHoverTracking, useIconGlyph, useIconRegistry, useIconVariant, useImageTool, useKeyModifiers, useKeyState, useKeybindings, useLassoTool, useLatest, useLineTool, useMeasureTool, useMenuHost, useMenus, useNodeOverlayFrame, useOngoingAction, useOpenKeymap, useOptionalActiveToolContext, useOptionalDepRegistry, usePaintKind, usePaintKinds, usePenTool, usePencilTool, usePointerContext, usePointerPosition, usePointerStylus, usePolygonTool, usePoseDescriptorDepSource, usePoseRun, usePoseTransition, usePublishSelection, useRectTool, useResizePolicy, useRig, useRigNode, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useSliceDepSource, useSliceTool, useSnapSource, useStandardActions, useStarTool, useStickyTool, useTextEdit, useTextTool, useTools, useTransformFollower, useVelocityTracker, useViewAnimation, useViewAnimationOn, useVisibleRaf, useYoke, vertexHalfWidths, vertexWidthFromSides, verticalAlignOffset, viewAxes, viewForAim, viewMarkerDragAction, viewPreset, viewToMat3, viewToTransform, viewZoom, viewportDragPanAction, viewportWheelPanAction, viewportWorldRect, viewportZoomAction, vignette, visualBoundsViaDescriptor, warmFonts, warmPaintKinds, warmRender, watchDevicePixelRatio, wcagLevels, wheelPan, wheelZoom, wheelZoomFactor, when, widestHalfWidth, withAlpha01, withCoord, withCorner, withGradientKind, withInheritedPaint, withInheritedPaints, withPath, withPathEffectsRegistry, withinPxBox, withinPxRadius, withoutCorners, withoutGeometryBoundData, withoutShapeGenerator, withoutTools, workspaceTintLayer, worldEditToStorage, worldPoseLookup, worldToScreen, writtenBy, zoomAt, zoomAtLeast };
367
+ export { ALWAYS, ANCHOR_HIT_BASE_PX, ANGLE_RADIANS, AREA_SELECT_ID, AUTO_ORIGIN_PROJECTION, AUTO_POSE_DESCRIPTOR, ActionDisabledReason, ActionsProvider, ActionsProviderIfRoot, ActiveToolContextProvider, ActiveToolContextProviderIfRoot, BUILTIN_MARKERS, BUILTIN_TOOLS, BUILTIN_TOOL_IDS, CANVAS_CONTEXT_ATTRIBUTES, CLIP_NOTHING, COARSE_TARGET_SCALE, COMPOSITE_FEATURES, CONSTRAINT_TOLERANCE, CONTROL_SELECTOR, CORNER_ANCHORS, CORNER_FIT_TOLERANCE, CORNER_KEYWORDS, CURSOR_ANGLE_STEPS, CURSOR_MAX_CSS_PX, CURVE_REPS, CanvasView, CursorCoordsHud, DEBUG_FEATURES, DEFAULT_ALLOWED_CAPABILITIES, DEFAULT_ALPHA_DECAY, DEFAULT_ALPHA_MIN, DEFAULT_DEBUG_STROKES, DEFAULT_DEBUG_THEME, DEFAULT_DECORATION_METRICS, DEFAULT_DEVICE_PROFILE, DEFAULT_FILL_COLOR, DEFAULT_FLATTEN_TOLERANCE, DEFAULT_HANDLE_SIZE, DEFAULT_INK, DEFAULT_LAYER_RETAIN, DEFAULT_MAX_ZOOM, DEFAULT_MIN_ZOOM, DEFAULT_OVERLAY_STYLE, DEFAULT_PALETTE, DEFAULT_ROTATION_HANDLE_DISTANCE, DEFAULT_SIMPLIFY_TOLERANCE, DEFAULT_SNAP_PX, DEFAULT_STROKE_COLOR, DEFAULT_TEXT_FILL, DEFAULT_TEXT_STYLE, DEFAULT_VELOCITY_DECAY, DRAG_PAN_ID, DRAG_THRESHOLD_PX, DRAW_TOOLS, DepRegistryProvider, DepRegistryProviderIfRoot, DeviceProfileProvider, DevtoolsLabel, DrawCanvas, EASINGS, EDGE_HANDLE_MIN_RADII, FALLBACK_ACCENT, FEATURE_ACTION_IDS, GEOMETRY_BOUND_DATA, GHOST_STROKE, HANDLE_BASE_PX, HANDLE_LOCK_ROLES, IDENTITY_POSE_COMPOSITION, IMPERIAL_INCHES, INHERIT, INSERT_REPOSITION_BINDING, IconRegistryProvider, IconRegistryProviderIfRoot, InputScope, KEYMAP_HOLD, KIT_SHAPE_KINDS, KIT_STANDARD_ACTION_IDS, KIT_VERSIONS, LONG_PRESS_FEEDBACK_ID, LONG_PRESS_MS, LeanSceneCanvas, MARKDOWN_RUN_GRAMMAR, MEASURE_ACTION_IDS, MEASURE_AFFORDANCE_KIND, MEASURE_LAYER_ID, METRIC_MM, MIXED, MOVE_NODES_REQUIRES, NEVER, OVERLAY_ROLE_STROKES, PAGES_DOC_KEY, PAGE_TOOLS, PAINTED_CURSOR_LAYER_ID, PATHFINDER_STROKES, PATH_ANCHOR_CHROME_ID, PATH_C, PATH_CMD_LENGTHS, PATH_EFFECT, PATH_EFFECT_DERIVATIONS, PATH_GESTURE_TAGS, PATH_L, PATH_M, PATH_OVERLAY_ROLES, PATH_Q, PATH_SNAP_KINDS, PATH_SNAP_LABELS, PATH_Z, PIXELS, PathBuilder, PickHud, PointerContextProvider, PointerProviderIfRoot, RECT_ORIGIN_PROJECTION, RECT_POSE_COMPOSITION, RECT_POSE_DESCRIPTOR, RESIZE_HANDLE_ANCHORS, RIGID_POSE_COMPOSITION, ROTATED_POSE_DESCRIPTOR, ROTATION_HANDLE_BASE_PX, SCENE_CANVAS_FEATURES, SCENE_HISTORY_FORM, SCRIPT_METRICS, SELECTION_MOVE_ID, SELECTION_RESIZE_ID, SELECTION_ROTATE_ID, SELECTION_TRANSFORM_ID, SELECT_TOOLS, SHAPE_COUNT_RANGE, SHAPE_KINDS, SHAPE_TOOLS, SMALL_CAPS_SCALE, SNAP_ANGLE_STEP, SNAP_AXIS_STEP, SNAP_ROLES, SPRING_PRESETS, SPRITE_STRIDE, STAR_RATIO_RANGE, STICKY_DEFAULTS, STROKE_DASH_RATIOS, SceneArrivalRefused, SceneCanvas, SceneViewCanvas, SelectionContextProvider, SelectionContextProviderIfRoot, TEXT_EDIT_FONT_HOLD, TILE_KINDS, TOOL_DRIVEN_ACTION_IDS, TYPE_TOOLS, TextOutlinesError, UNION_OF_CHILDREN, VERSION, VIEW_ANIMATION_KEY, VIEW_MARKER_DEFAULT_STYLE, VIEW_MARKER_DRAG, VIEW_MARKER_HIT_SLOP_PX, VIEW_TOOLS, ViewMarker, WEASEL_CLIPBOARD_MIME, WEASEL_CLIPBOARD_MIME_WEB, WHEEL_ZOOM_STEP, WeaselProvider, Yoke, ZOOM_FLOOR, aabbCenter, accentColorOf, actionBindings, actionCursor, actionIs, actionItemTitle, actionItems, actionSettingsParams, actionShortcuts, actionsTagged, activatesFocusedControl, addPage, adjacentPage, aimSpace2d, alignDeltaFor, alignTargetBounds, alignedStrokeRect, always, anchorEditWouldChange, and, animateLifecycle, animateOnSetPose, annotationLayerIds, annulusSemiAxes, applyBooleanOp, applyCreateOutlines, applyOpsTo, applyOutlineStroke, applyStyleToRange, areaSelectAction, areaSelectContribution, arrangePreset, asNodeId, asPaint, asPolygonPath, assembleEntries, assertSnapSourceIds, averageAnchorsAt, axisAlignedBounds, axisUnits, axisZoomFactor, bakeCursor, bendAlongPath, bezierCubic, bezierQuadratic, bindPoseTransition, bindRig, bindingId, bindingSpec, bitmapSrc, blendPaths, blur, bodyPredicate, boundsOfPath, buildChromeCtx, buildDebugOverlayCommands, buildDepsFromRequires, buildRuleCtx, buildSceneViewCommands, buildWeaselClipboardText, cachedLayoutRuns, cachedPaintRuns, canBringForward, canHover, canQueryLocalFonts, canSendBackward, capabilityAll, capabilityIn, capabilityIs, capabilityNot, captureGesture, captureKey, caretIndexAt, carriedDescendants, charOffsetToDomPosition, checkRequirements, circlePath, clampShapeGenerator, clampView, classifyPathStorage, clearSelectionAction, clientToCanvas, clipNothing, clipOutline, clipboardCopyAction, clipboardCutAction, clipboardPasteAction, clipboardPasteEventAction, cloneAction, coarsePointer, commandFill, commandPaint, commandStroke, commitAnchorEdit, commitBooleanPieces, commitDeleteToScene, commitOps, composeAffordanceLayer, composePath, composePatternTransform, composeRectPose, composeRigidPose, composeSelectionPose, composeWorldPose, composesFrames, computeFitViewport, computeSliceOps, computeWheelAction, cond, constrainPathEdit, constraintAnchors, contextMenuAction, contrastLineColor, contrastRatio, coreKitSettingsSchema, cornerAt, cornerFrameAt, cornerFrames, cornerKeywordOf, cornerPoint, cornerResizeHandles, cornerShapeK, cornerShapePieces, cornerSpecAt, countPathAnchors, createArrangeOp, createChildrenLayer, createCornerResizeAffordance, createCursorSink, createDebugOverlayLayer, createDebugSink, createDeleteAction, createDeleteOp, createDepRegistry, createDepartures, createDispatcher, createEnteredGroup, createEnteredGroupScope, createHistory, createInsertOp, createKeyState, createKeymapStack, createLongPressFeedbackContribution, createLongPressStore, createMarkdownRenderer, createMeasurements, createMoveToIndexOp, createNodeProperties, createNodeRouting, createPaintedCursorLayer, createPaintedCursorState, createPathAnchorAffordances, createPathEditingOverlayLayer, createPathEffectDerivations, createPathLayer, createPathOverlay, createPathSnapIndex, createPenPreviewLayer, createPointerFollower, createPointerStore, createPoseFeed, createPoseOverrides, createPoseTarget, createRasterSession, createReflectable, createReflowTransition, createReorderOp, createReparentOp, createResizeAction, createRotationAffordance, createScene, createSelectionHandlesLayer, createSelectionOutlineLayer, createSelectionOverlayLayer, createSetChildOrderOp, createSetDataOp, createSetDependsOnOp, createSetHiddenOp, createSetLayerOp, createSetLayoutOp, createSetLockedOp, createSetPathOp, createSetSelectionOp, createSetTextOp, createSimulation, createSnapOutcomeStore, createSnapReadoutLayer, createTextLayer, createTilePattern, createTransformOp, createVelocityTracker, createViewMarkerContribution, createViewMarkerLayer, createViewResolver, createViewportLayer, createWrittenPoseTarget, cssFamilyName, cssFontFamily, cssFontFamilyLoading, cubicBezierEasing, cullDrawCommands, currentMeasureId, cursorFor, cycleFill, dashForStrokeStyle, dataRestPath, debugSnapshotArgs, decomposePath, decomposePatternTransform, decomposeRectPose, decomposeRigidPose, decorationMetrics, defaultCommitAdapter, defaultDrawOne, defaultLabelTextRenderer, defaultNodeProperties, defaultNodeRouting, defaultPaintBounds, defaultVisibilityRules, defineTool, definesFrame, deleteAction, deleteAnchorsAction, deleteNode, deleteScratch, deleteSelectedMark, depOf, depsUnchanged, deriveParallaxView, derivedDepOf, derivedPartsOf, derivedPose, describeKeymap, describeRule, dispatchApplyBatch, dlog, documentDepOf, documentOf, documentPose, domPositionToCharOffset, domToRuns, dragPanContribution, dragPointOf, drawLayers, drawOneLayer, drawnAABBOf, drawnBoundsOf, drawnBoundsScene, dwarn, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorsAction, editPreset, editTargetOf, editedPathSymmetries, editingAnchors, editingLayer, effectSourceFor, effectivePose, effectiveRangeStyle, ellipsePath, embedWeaselMetadataInSvg, enableLocalFontOutlines, enterTextEditAction, enumerateAnchors, evaluate, evaluateActive, evaluateEnabled, exitPathEditToolAction, extendToMeet, extractWeaselClipboardFromSvg, fillInPoseFrame, fillToBoundsFrame, findNodeShape, findPathSnap, findShapeBounds, findShapeDrawnBounds, findShapeInk, findShapeSilhouette, finishPathEditFrame, fitTextPose, fitToBounds, fitViewToBounds, fitViewToPage, fitZoom, fixedCornerOf, flattenCubic, flattenCubicWithArcLen, flattenPreviews, flattenQuadratic, flattenQuadraticWithArcLen, flipAction, focused, focusedControlOwnsKey, fontOutlineRegistry, fontRegistry, fontString, forEachCoalesced, forgetTransform, formatAxes, formatScoped, formatUnit, frameRect, fromPlane, fromRoot, gateLayer, gatherSnapCandidates, gesturePlaneReader, gestureViewReader, gesturing, getAlpha01, getImageBitmap, getMarker, getNodeShapes, getPaintKind, getScratch, getStylusData, glidesByDefault, grabViewMarker, gradientForBounds, gradientGeometry, groupNodeRouting, handlePoint, hasChildren, hasCorners, hasEditablePath, hasFontOutlines, hasOpenSubpath, held, heldKeySpec, hexToOklchDeg, hexToRgbBytes, hexToRgba, hiddenSourceDeleteOps, hiddenSourcesTakenWith, hidesSubtree, historyKey, hitAffordanceRegions, hitAnchor, hitCornerHandle, hitPredicate, hitRotationHandle, hostAnchorCss, hostAnchorRect, hovering, hoveringSelected, hslToSrgb, imageStatus, inPlane, inferredNodeProperties, inferredNodeRouting, ingestPreset, inheritedPaintIn, inheritedPaintOf, inheritsPaint, inkExtentsOf, insertAction, insertAt, insertLayer, insertPreviewExtent, insertRepositionAction, interpolateSrgb, interpolateView, intersectSegments, isAnnotationLayer, isAnnotationNode, isBoldWeight, isCanvasFont, isCornerHandle, isCornerShape, isDebugEnabled, isEditableTarget, isGradientPaint, isInControlWithin, isLayerPainted, isLayerVisible, isLeaf, isNodeHidden, isNodeLocked, isOverChildren, isPaintKindKnown, isPathLike, isPatternPaint, isPlainObject, isRectAim, isRectPose, isShapeGenerator, isSmallCapsLetter, isSolidPaint, isTextData, isTileKind, isTilePaint, isToolSet, isVectorImageSrc, joinAnchorsAt, joinPathsCommand, joinSelectedAnchors, key, keySpecRoute, keySpecShortcut, keymapContribution, keymapLeaderBindingId, keymapLeaderId, keymapShortcuts, keysHeld, kitTextHandler, lassoSelectAction, lastTransform, layoutMarkdown, layoutPages, layoutRuns, layoutTextPose, lengthenOpenEnd, lerpColorArray, lerpFill, lerpOklab, lerpOklch, lerpPaint, lerpStroke, linePath, linear, linearSrgbToOklab, linearToSrgb, listFontOutlines, listGradientKinds, listMarkers, listPaintKinds, livePathEdit, liveScope, loadFontOutlines, loadTextOutlines, locksInForce, makeHandleCommand, makePinchZoomAction, makeViewportWheelPanAction, makeViewportZoomAction, markUnder, markdownToRuns, markerInset, markerKeyOf, markerRegistry, markerSites, mat3, matchActionItem, matchesKeyBinding, meanScale, measureAt, measureBetween, measureEndSource, measureEndsOf, measureIds, measureNode, measurePath, measurePose, measureText, measureTextBounds, measuredSegmentCommands, measuredWidth, measurementOf, measurementsContribution, mergeAlphaFromPrev, mergeContributions, minSizeOf, modeDecorationLayer, modeIn, modeIs, modeNot, modeShortcutSpec, modeShortcuts, modeTriggers, modifierHeld, modifierStateOf, momentum, moveAction, moveNodes, moveNodesOps, movePage, movePreset, multiActive, nestedHitTester, never, nextCornerShape, nextPageId, nodeAsShown, nodeGates, nodeHasFlag, nodeKindOf, nodeOutline, normalizeHex, normalizeView, normalizeZoom, not, noteFontRead, nudgeAnchorsDownAction, nudgeAnchorsLeftAction, nudgeAnchorsRightAction, nudgeAnchorsUpAction, numericWeight, nurbs, offsetPath, oklabToLinearSrgb, oklabToOklch, oklabToSrgbU8, oklchDegToHex, oklchToOklab, onEmptyCanvas, opFactoryRegistry, openContextMenu, openEndRay, openFilePicker, openPathEnds, openPointerSession, or, outlinePreset, outlineStatus, overChildren, overlaysOf, pageAt, pageHolding, pageInView, pageMembers, pageName, pageOfBounds, pagesBounds, pagesLayer, pagesOf, paintAbove, paintAlpha, paintKindOf, paintKindRegistry, paintRuns, paintWithAlpha, paintWithColor, paintedLayers, paintsLayer, paletteInsertPaint, paragraphDirection, parseColor, parseColorToRgba255, parseDebugFlags, parseHexBytes, parseUnitExpr, parseWeaselClipboardText, pastDragThreshold, patchRangeStyle, pathAnchorPoints, pathCommandCoordCount, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCopy, pathCrossings, pathDistanceToPoint, pathDivide, pathEditPathOf, pathEditPreview, pathEditToolAction, pathEditToolActive, pathEffectNode, pathEffectOf, pathEffectParts, pathExclude, pathFromD, pathFromParts, pathInPoseFrame, pathInWorld, pathIntersect, pathIntersectsPolygon, pathIntersectsRect, pathNodesOf, pathOperationTags, pathOriginProjection, pathPaintOf, pathPoseDescriptor, pathSegments, pathSignedArea, pathSnapGlyph, pathSnapSource, pathSubtract, pathThroughPoseFrame, pathToAnchors, pathToD, pathUnion, pathsPreset, patternFamily, patternPlacementOf, pickTopMostHit, pillCommands, pinchZoomAction, placeAction, placeSkeleton, placedPagesOf, planJoin, planPixelRender, planeMap, planeMatrix, planeToPlane, pointAlongPath, pointInPath, pointInRotatedRect, pointInTextPose, pointRegionFrame, pointSnap, polygonFromPoints, polylineFromPoints, poseAxes, poseDescriptorForNode, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, pressureToWidth, previewBooleanOp, publishPreviews, pxExtent, rangeWeight, rasterToPng, readActionSettings, readEffectSource, rebaseLocalPose, rebuildOp, reconcileSpecs, recordTransform, rectAim, rectCorners, rectFromPlane, rectMarkerPath, rectPath, rectToPlane, refreshCanvasFont, regenerateShape, registerBidi, registerCanvasFont, registerContentHandler, registerEffect, registerFont, registerFontOutlines, registerMarker, registerNodeShape, registerOpFactory, registerPaintKind, registerPaintKindLoader, registeredOpNames, registeredPathEffects, regularPolygonPath, releaseCanvasRenderer, releaseImage, remapPerAnchor, removePage, renamePage, renderDebugSnapshot, renderLabel, renderNeeds, renderSceneToCanvas, renderSceneToPixels, repeatAlongPath, requiresAnchorSelection, reshapeOps, reshapeTo, resizeAction, resizeHandlesFor, resizePage, resizePreset, resolveAlign, resolveAxes, resolveBindingOverrides, resolveBooleanOperands, resolveColor, resolveCorners, resolveCornersWithSources, resolveCursor, resolveCursorTier, resolveDeviceProfile, resolveEasing, resolveEditablePathOf, resolveFill, resolveFillPattern, resolveMarkerSize, resolveOverlays, resolveParams, resolvePartPaint, resolvePatternSpec, resolvePreviews, resolveRunFace, resolveRuns, resolveSchemaMenu, resolveScoped, resolveScreenLength, resolveSpatialReference, resolveStroke, resolveStrokeWidth, resolveTextStyle, resolveUnit, resolveUnitExpr, resolveVisibility, resolvedSnapMarks, retryImage, reversePath, rgbaToHex, rigFromNode, rigidRigApply, roleReader, rotateAction, rotateAroundAABBCenter, rotatePathAround, rotatePoint, rotatePreset, rotatedRectCorners, rotationDegreesUnit, rotationHandle, rotationSnapSource, roundRectPath, routeKind, runsToDom, runsToMarkdown, runsToPlainText, sampleGradientStops, satisfiesRange, scaleDelta, scalePathToBounds, scaleVertexWidth, sceneCarrySource, sceneClipTargets, sceneFromJSON, sceneNodeClientRect, scenePoseAdapter, scenePoseFrame, scenePoseTarget, sceneSelectionStore, sceneSharedUnitScopes, sceneToAdapter, sceneUnitScopes, scopeBindings, scopesOf, scratchKey, screenAngleOf, screenToWorld, screenTolerance, scriptMetrics, scriptMetricsFor, seedTile, segmentUnder, selectAnchorAction, selectFromLasso, selectPreset, selectedPathNodes, selectionAtLeast, selectionEmpty, selectionIs, selectionLayer, selectionMoveBindings, selectionMoveContribution, selectionResizeBindings, selectionResizeContribution, selectionRotateBindings, selectionRotateContribution, selectionTransformBindings, selectionTransformContribution, setFlagOverRange, setImageCacheBudget, setPages, setScratch, settleShapeGenerator, shapeCoversPoint, shapeGeneratorOf, shapeGeneratorPath, simplifyAnchorsAt, simplifyPath, sliceAction, slotOf, smallCapsScale, smallCapsScaleFor, smallCapsText, smudgePath, snapMods, snapSourcesFor, sniffWeaselClipboardText, snipPathByPolyline, snipPathsAtCrossings, solid, solveConstraints, solvePathConstraints, sourcesHiddenBy, sourcesOf, specificity, specsFromSerialized, spiro, splitByClosure, splitOverChildren, splitPathByPolyline, splitPathBySegment, splitSubpaths, springPose, squarePath, srgbFloatToOklab, srgbToHsl, srgbToLinear, srgbU8ToOklab, stableStringify, staggerSpringPose, standoff, starPath, startCarry, startThresholdDrag, statedFields, stationsAlongPath, stepAngles, stickyData, stickyNodeFactory, storeEditablePath, strokeDashStyleOf, strokeInsets, strokeOf, strokeRegion, strokeToPath, strokeWith, styleAtRange, subscribeGlyphReady, subscribeImageReady, subscribeToSources, swapOp, switchGradientKind, taggedActionItems, textAlongParts, textBoxOf, textCommand, textCommandFromPose, textCommandFromRuns, textLineBoxes, textPoseLayoutInput, textToPath, textToPathsByPaint, tickedSegment, tileSpecOf, toHex8, toIconRef, toPlane, toRoot, toRuns, toolIdsOf, toolSet, toolSetHas, transformPath, transformRunTexts, translatePath, translatePoseViaDescriptor, translateRectPose, trianglesToPath, trimPathAt, trimPolyline, tuneAction, tweenPose, unboldPatch, unbound, unionAABB, unionBounds, unionBoundsPath, unionOfChildren, unionOfChildrenVia, unitScale, unplaceSkeleton, unregisterCanvasFont, unregisterFontOutlines, unsatisfiedConstraints, useAction, useActionsRegistry, useActiveToolContext, useAlign, useAnchorFields, useAnimatedReflow, useAutoCenter, useBooleans, useBooleansAdapter, useBooleansAdapterSource, useCanvasFocus, useCanvasSize, useClipboardOps, useCommand, useCreateOutlinesAdapter, useDecayLoop, useDepRegistry, useDepSource, useDeviceProfile, useDevtoolsLabel, useDistribute, useDragGesture, useDragHandle, useDragRadial, useDragRect, useDropZone, useEffectSourcesLayer, useElementSize, useEllipseTool, useEnteredGroup, useEyedropperTool, useFrameClock, useGestureDispatcher, useGradientKinds, useHandTool, useHandleDrag, useHostAnchor, useHoverTracking, useIconGlyph, useIconRegistry, useIconVariant, useImageTool, useKeyModifiers, useKeyState, useKeybindings, useLassoTool, useLatest, useLineTool, useMeasureTool, useMenuHost, useMenus, useNodeOverlayFrame, useOngoingAction, useOpenKeymap, useOptionalActiveToolContext, useOptionalDepRegistry, usePaintKind, usePaintKinds, usePenTool, usePencilTool, usePointerContext, usePointerPosition, usePointerStylus, usePolygonTool, usePoseDescriptorDepSource, usePoseRun, usePoseTransition, usePublishSelection, useRectTool, useResizePolicy, useRig, useRigNode, useScene, useSceneAdapter, useSceneTextEdit, useSelectTool, useSelection, useSelectionContext, useSimulation, useSliceDep, useSliceDepSource, useSliceTool, useSnapSource, useStandardActions, useStarTool, useStickyTool, useTextEdit, useTextTool, useTools, useTransformFollower, useVelocityTracker, useViewAnimation, useViewAnimationOn, useVisibleRaf, useYoke, vertexHalfWidths, vertexWidthFromSides, verticalAlignOffset, viewAxes, viewForAim, viewMarkerDragAction, viewPreset, viewToMat3, viewToTransform, viewZoom, viewportDragPanAction, viewportWheelPanAction, viewportWorldRect, viewportZoomAction, vignette, visualBoundsViaDescriptor, warmFonts, warmPaintKinds, warmRender, watchDevicePixelRatio, wcagLevels, wheelPan, wheelZoom, wheelZoomFactor, when, widestHalfWidth, withAlpha01, withCoord, withCorner, withGradientKind, withInheritedPaint, withInheritedPaintBounds, withInheritedPaints, withPath, withPathEffectsRegistry, withinPxBox, withinPxRadius, withoutCorners, withoutGeometryBoundData, withoutShapeGenerator, withoutTools, workspaceTintLayer, worldEditToStorage, worldPoseLookup, worldToScreen, writtenBy, zoomAt, zoomAtLeast };
@@ -0,0 +1,11 @@
1
+ //#region src/interactions/actions/admitsChild.ts
2
+ /** The one rule for whether `parent` takes `ids` as children, by drop or by insert:
3
+ * `canDropInto` decides when present, else a group does and a mark does not. */
4
+ function admitsChild(scene, parent, ids, canDropInto) {
5
+ if (canDropInto !== void 0) return canDropInto(parent, ids);
6
+ return scene.get(parent)?.kind === "group";
7
+ }
8
+
9
+ //#endregion
10
+ export { admitsChild };
11
+ //# sourceMappingURL=admitsChild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admitsChild.js","names":[],"sources":["../../../src/interactions/actions/admitsChild.ts"],"sourcesContent":["import type { NodeId } from 'core/scene/types';\nimport type { CanDropIntoDep } from './layoutDeps';\n\n/** The one rule for whether `parent` takes `ids` as children, by drop or by insert:\n * `canDropInto` decides when present, else a group does and a mark does not. */\nexport function admitsChild(\n scene: { get(id: NodeId): { kind: string } | undefined },\n parent: NodeId,\n ids: readonly string[],\n canDropInto: CanDropIntoDep | undefined,\n): boolean {\n if (canDropInto !== undefined) return canDropInto(parent as string, ids);\n return scene.get(parent)?.kind === 'group';\n}\n"],"mappings":";;;AAKA,SAAgB,YACd,OACA,QACA,KACA,aACS;CACT,IAAI,gBAAgB,QAAW,OAAO,YAAY,QAAkB,GAAG;CACvE,OAAO,MAAM,IAAI,MAAM,CAAC,EAAE,SAAS;AACrC"}
@@ -5,6 +5,7 @@ import { visualBoundsViaDescriptor } from "../../../core/geometry/poseDescriptor
5
5
  import { asNodeId } from "../../../core/scene/types.js";
6
6
  import { scenePoseFrame } from "../poseFrame.js";
7
7
  import { nodeDescriptors, poseDescriptorOf } from "../poseDescriptorDep.js";
8
+ import { pressTarget } from "../../../tools/builtin/pressTarget.js";
8
9
  import { ActionDisabledReason } from "@weasel-js/routing";
9
10
 
10
11
  //#region src/interactions/actions/defaults/contextMenu.ts
@@ -41,12 +42,13 @@ function menuHitFor(deps, at) {
41
42
  const hit = deps.hitAt?.(at);
42
43
  if (!hit) return { hit: {} };
43
44
  if (hit.bodyTarget === "empty") return { hit: { bodyTarget: "empty" } };
45
+ const target = hit.bodyTarget === "unselected-body" && hit.id !== void 0 ? groupFor(deps, hit.id) : void 0;
44
46
  return {
45
47
  hit: {
46
48
  bodyTarget: "selected-body",
47
- bodyKind: hit.bodyKind
49
+ bodyKind: (target !== void 0 ? deps.kindOfNode?.(target) : void 0) ?? hit.bodyKind
48
50
  },
49
- ...hit.bodyTarget === "unselected-body" && hit.id !== void 0 ? { select: hit.id } : {}
51
+ ...target !== void 0 ? { select: target } : {}
50
52
  };
51
53
  }
52
54
  if (!deps.selection) return { hit: {} };
@@ -56,6 +58,16 @@ function menuHitFor(deps, at) {
56
58
  bodyKind: ids.length === 1 ? deps.kindOfNode?.(ids[0]) : void 0
57
59
  } };
58
60
  }
61
+ /** The node a right-click selects: the press target for `id`, as a left press would pick. */
62
+ function groupFor(deps, id) {
63
+ const scene = deps.scene;
64
+ if (!scene) return id;
65
+ const node = (n) => scene.get(asNodeId(n));
66
+ return pressTarget({
67
+ getParent: (n) => node(n)?.parent ?? null,
68
+ getNode: node
69
+ }, id, deps.enteredGroup?.get() ?? null);
70
+ }
59
71
  /**
60
72
  * Open the menu for a right-click, or for Shift+F10 when `params` carry no client point. Reads
61
73
  * only `menuHost`, `view` and `worldToClient` on a surface without a scene; `selection`, `scene`,
@@ -135,7 +147,8 @@ var contextMenuAction = {
135
147
  "view",
136
148
  "worldToClient",
137
149
  "hitAt",
138
- "kindOfNode"
150
+ "kindOfNode",
151
+ "enteredGroup"
139
152
  ],
140
153
  enabled: (deps, at) => deps?.menuHost?.has({
141
154
  hit: menuHitFor(deps, at).hit,
@@ -1 +1 @@
1
- {"version":3,"file":"contextMenu.js","names":[],"sources":["../../../../src/interactions/actions/defaults/contextMenu.ts"],"sourcesContent":["import { ActionDisabledReason, type Action, type ActionDeps, type MenuHit } from '@weasel-js/routing';\nimport { scenePoseFrame } from '../poseFrame';\nimport { nodeDescriptors, poseDescriptorOf } from '../poseDescriptorDep';\nimport { visualBoundsViaDescriptor } from '../resize/geometry';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport { screenToWorld } from 'core/viewport/viewTransform';\nimport { viewToTransform } from 'core/viewport/view';\nimport { asNodeId } from 'core/scene/types';\nimport type { Point } from '@weasel-js/geom';\n\n/** World center of the selection's bounds, else of the visible canvas. */\nexport function keyboardAnchor(deps: ActionDeps): Point | null {\n const ids = deps.selection?.get() ?? [];\n if (ids.length && deps.scene) {\n const frame = scenePoseFrame(deps.scene);\n const descriptorOf = nodeDescriptors(deps.scene, poseDescriptorOf(deps.poseDescriptor));\n const box = unionAABB(ids.map((id) => visualBoundsViaDescriptor(frame.world(id), descriptorOf(id))));\n if (box) return { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n }\n const view = deps.view?.get();\n const size = deps.view?.hostSize?.();\n if (!view || !size) return null;\n const [x, y] = screenToWorld(size.width / 2, size.height / 2, viewToTransform(view));\n return { x, y };\n}\n\n/**\n * The hit a menu is picked for, from the dispatcher's own classifier (the\n * `hitAt` and `kindOfNode` deps). A shape under `at` counts as selected, since\n * opening selects it first, and `select` names it when it is not yet; with no\n * `at`, the current selection. Without a classifier wired, a pointer hit names\n * no body at all, and without a selection neither does a keyboard one.\n */\nexport function menuHitFor(deps: ActionDeps, at?: Point): { hit: MenuHit; select?: string } {\n if (at) {\n const hit = deps.hitAt?.(at);\n if (!hit) return { hit: {} };\n if (hit.bodyTarget === 'empty') return { hit: { bodyTarget: 'empty' } };\n return {\n hit: { bodyTarget: 'selected-body', bodyKind: hit.bodyKind },\n ...(hit.bodyTarget === 'unselected-body' && hit.id !== undefined ? { select: hit.id } : {}),\n };\n }\n if (!deps.selection) return { hit: {} };\n const ids = deps.selection.get();\n return { hit: { bodyTarget: ids.length ? 'selected-body' : 'empty', bodyKind: ids.length === 1 ? deps.kindOfNode?.(ids[0]!) : undefined } };\n}\n\n/**\n * Open the menu for a right-click, or for Shift+F10 when `params` carry no client point. Reads\n * only `menuHost`, `view` and `worldToClient` on a surface without a scene; `selection`, `scene`,\n * `hitAt` and `kindOfNode` refine the hit and the keyboard anchor where they are supplied.\n */\nexport function openContextMenu(\n deps: ActionDeps,\n params?: Record<string, unknown>,\n anchorOf: (deps: ActionDeps) => Point | null = keyboardAnchor,\n): boolean {\n const host = deps.menuHost;\n if (!host) return false;\n const p = params ?? {};\n if (typeof p.clientX === 'number' && typeof p.worldX === 'number') {\n const world = { x: p.worldX, y: p.worldY as number };\n const { hit, select } = menuHitFor(deps, world);\n if (select) deps.selection?.set([asNodeId(select)]);\n return host.open({\n hit,\n client: { x: p.clientX, y: p.clientY as number }, world, source: 'pointer',\n });\n }\n const world = anchorOf(deps);\n const client = world && deps.worldToClient?.(world.x, world.y);\n if (!world || !client) return false;\n return host.open({ hit: menuHitFor(deps).hit, client, world, source: 'keyboard' });\n}\n\nconst INITIAL = [{ channel: '*', phase: 'initial' }] as const;\n\n/**\n * Opens the context menu: for the pointer on a right-click or an unclaimed\n * long-press, selecting the shape under it first; for the keyboard on\n * Shift+F10 or the ContextMenu key, at the selection or else the middle of the view.\n */\nexport const contextMenuAction: Action & { requires: string[] } = {\n id: 'menu.context',\n label: 'Show Context Menu',\n defaultBinding: [\n { spec: { kind: 'contextMenu' }, opts: { id: 'menu.context.contextMenu' } },\n { spec: { kind: 'key', key: 'F10', mods: { shift: true }, phase: [...INITIAL] }, opts: { id: 'menu.context.key' } },\n { spec: { kind: 'key', key: 'ContextMenu', phase: [...INITIAL] }, opts: { id: 'menu.context.menuKey' } },\n ],\n requires: ['menuHost', 'selection', 'scene', 'poseDescriptor', 'view', 'worldToClient', 'hitAt', 'kindOfNode'],\n // Disabled when no menu would open, so the dispatcher leaves the press, click and drag to whatever else is bound.\n enabled: (deps, at) => (deps?.menuHost?.has({ hit: menuHitFor(deps, at).hit, client: { x: 0, y: 0 }, world: at })\n ? true\n : ActionDisabledReason.NotApplicable),\n invoker: { timing: 'immediate', run: (deps, params) => { openContextMenu(deps, params); } },\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"contextMenu.js","names":[],"sources":["../../../../src/interactions/actions/defaults/contextMenu.ts"],"sourcesContent":["import { ActionDisabledReason, type Action, type ActionDeps, type MenuHit } from '@weasel-js/routing';\nimport { scenePoseFrame } from '../poseFrame';\nimport { nodeDescriptors, poseDescriptorOf } from '../poseDescriptorDep';\nimport { visualBoundsViaDescriptor } from '../resize/geometry';\nimport { unionAABB } from 'core/geometry/unionBounds';\nimport { screenToWorld } from 'core/viewport/viewTransform';\nimport { viewToTransform } from 'core/viewport/view';\nimport { asNodeId } from 'core/scene/types';\nimport type { Point } from '@weasel-js/geom';\nimport { pressTarget } from 'tools/builtin/pressTarget';\n\n/** World center of the selection's bounds, else of the visible canvas. */\nexport function keyboardAnchor(deps: ActionDeps): Point | null {\n const ids = deps.selection?.get() ?? [];\n if (ids.length && deps.scene) {\n const frame = scenePoseFrame(deps.scene);\n const descriptorOf = nodeDescriptors(deps.scene, poseDescriptorOf(deps.poseDescriptor));\n const box = unionAABB(ids.map((id) => visualBoundsViaDescriptor(frame.world(id), descriptorOf(id))));\n if (box) return { x: box.x + box.width / 2, y: box.y + box.height / 2 };\n }\n const view = deps.view?.get();\n const size = deps.view?.hostSize?.();\n if (!view || !size) return null;\n const [x, y] = screenToWorld(size.width / 2, size.height / 2, viewToTransform(view));\n return { x, y };\n}\n\n/**\n * The hit a menu is picked for, from the dispatcher's own classifier (the\n * `hitAt` and `kindOfNode` deps). A shape under `at` counts as selected, since\n * opening selects it first, and `select` names it when it is not yet; with no\n * `at`, the current selection. Without a classifier wired, a pointer hit names\n * no body at all, and without a selection neither does a keyboard one.\n */\nexport function menuHitFor(deps: ActionDeps, at?: Point): { hit: MenuHit; select?: string } {\n if (at) {\n const hit = deps.hitAt?.(at);\n if (!hit) return { hit: {} };\n if (hit.bodyTarget === 'empty') return { hit: { bodyTarget: 'empty' } };\n const target = hit.bodyTarget === 'unselected-body' && hit.id !== undefined ? groupFor(deps, hit.id) : undefined;\n const bodyKind = (target !== undefined ? deps.kindOfNode?.(target) : undefined) ?? hit.bodyKind;\n return { hit: { bodyTarget: 'selected-body', bodyKind }, ...(target !== undefined ? { select: target } : {}) };\n }\n if (!deps.selection) return { hit: {} };\n const ids = deps.selection.get();\n return { hit: { bodyTarget: ids.length ? 'selected-body' : 'empty', bodyKind: ids.length === 1 ? deps.kindOfNode?.(ids[0]!) : undefined } };\n}\n\n/** The node a right-click selects: the press target for `id`, as a left press would pick. */\nfunction groupFor(deps: ActionDeps, id: string): string {\n const scene = deps.scene;\n if (!scene) return id;\n const node = (n: string) => scene.get(asNodeId(n));\n return pressTarget(\n { getParent: (n) => node(n)?.parent ?? null, getNode: node },\n id,\n deps.enteredGroup?.get() ?? null,\n );\n}\n\n/**\n * Open the menu for a right-click, or for Shift+F10 when `params` carry no client point. Reads\n * only `menuHost`, `view` and `worldToClient` on a surface without a scene; `selection`, `scene`,\n * `hitAt` and `kindOfNode` refine the hit and the keyboard anchor where they are supplied.\n */\nexport function openContextMenu(\n deps: ActionDeps,\n params?: Record<string, unknown>,\n anchorOf: (deps: ActionDeps) => Point | null = keyboardAnchor,\n): boolean {\n const host = deps.menuHost;\n if (!host) return false;\n const p = params ?? {};\n if (typeof p.clientX === 'number' && typeof p.worldX === 'number') {\n const world = { x: p.worldX, y: p.worldY as number };\n const { hit, select } = menuHitFor(deps, world);\n if (select) deps.selection?.set([asNodeId(select)]);\n return host.open({\n hit,\n client: { x: p.clientX, y: p.clientY as number }, world, source: 'pointer',\n });\n }\n const world = anchorOf(deps);\n const client = world && deps.worldToClient?.(world.x, world.y);\n if (!world || !client) return false;\n return host.open({ hit: menuHitFor(deps).hit, client, world, source: 'keyboard' });\n}\n\nconst INITIAL = [{ channel: '*', phase: 'initial' }] as const;\n\n/**\n * Opens the context menu: for the pointer on a right-click or an unclaimed\n * long-press, selecting the shape under it first; for the keyboard on\n * Shift+F10 or the ContextMenu key, at the selection or else the middle of the view.\n */\nexport const contextMenuAction: Action & { requires: string[] } = {\n id: 'menu.context',\n label: 'Show Context Menu',\n defaultBinding: [\n { spec: { kind: 'contextMenu' }, opts: { id: 'menu.context.contextMenu' } },\n { spec: { kind: 'key', key: 'F10', mods: { shift: true }, phase: [...INITIAL] }, opts: { id: 'menu.context.key' } },\n { spec: { kind: 'key', key: 'ContextMenu', phase: [...INITIAL] }, opts: { id: 'menu.context.menuKey' } },\n ],\n requires: ['menuHost', 'selection', 'scene', 'poseDescriptor', 'view', 'worldToClient', 'hitAt', 'kindOfNode', 'enteredGroup'],\n // Disabled when no menu would open, so the dispatcher leaves the press, click and drag to whatever else is bound.\n enabled: (deps, at) => (deps?.menuHost?.has({ hit: menuHitFor(deps, at).hit, client: { x: 0, y: 0 }, world: at })\n ? true\n : ActionDisabledReason.NotApplicable),\n invoker: { timing: 'immediate', run: (deps, params) => { openContextMenu(deps, params); } },\n};\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { paintInheritors } from "../../../core/scene/inheritedPaint.js";
1
2
  import { defaultCommitAdapter } from "../defaultCommitAdapter.js";
2
3
  import { createSetDataOp } from "../../../core/ops/setData.js";
3
4
  import { ActionDisabledReason } from "@weasel-js/routing";
@@ -58,6 +59,8 @@ function createPaintAction(spec) {
58
59
  applyOps
59
60
  };
60
61
  refreshPreviews(scratch);
62
+ const key = spec.dataKey;
63
+ const inheritors = key === "fill" || key === "stroke" ? [...new Set(ids.flatMap((id) => paintInheritors(scene, id, key)))].filter((id) => !startData.has(id)) : [];
61
64
  return {
62
65
  onMove(moveCtx) {
63
66
  const next = spec.readParams(scratch.state, moveCtx.params);
@@ -92,7 +95,7 @@ function createPaintAction(spec) {
92
95
  }
93
96
  scratch.previews.clear();
94
97
  },
95
- previewIds: () => scratch.previews.keys(),
98
+ previewIds: () => scratch.previews.size === 0 ? [] : [...scratch.previews.keys(), ...inheritors],
96
99
  previewData: (id) => scratch.previews.get(id) ?? null
97
100
  };
98
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createPaintAction.js","names":[],"sources":["../../../../src/interactions/actions/defaults/createPaintAction.ts"],"sourcesContent":["import type { Action } from '@weasel-js/routing';\nimport type { InvocationCtx, OngoingHandle, BindingOpts } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { Scene, NodeId } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createSetDataOp } from 'core/ops/setData';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\n\n/** The node data one paint action reads and writes: its own key, nothing else. */\ntype PaintData<K extends string, TValue> = { [P in K]?: TValue | null };\n\ntype Params = Record<string, unknown> | undefined;\n\n/** Read a param from the invocation, falling back to the binding's. */\nexport type PickParam = <T>(key: string) => T | undefined;\n\n/**\n * What distinguishes one paint action from another.\n *\n * `TState` is the action's gesture state. It is a reducer, not a paint:\n * `setFill` and `setStroke` supersede a paint with a later color, which no\n * per-field merge of the params can express.\n */\nexport interface PaintActionSpec<TState, TValue, K extends string> {\n id: string;\n label: string;\n /** The `data` key this action owns. */\n dataKey: K;\n /** Gesture state at start. */\n initialState(pick: PickParam): TState;\n /** The state one onMove tick moves to, or `null` when its params carry\n * nothing this action reads — the preview then stands. */\n readParams(prev: TState, params: Params): TState | null;\n /** The value to write for one node, from that node's value at gesture start.\n * `null` writes the absence of paint, which is a value like any other —\n * a node with `fill: null` paints no fill. */\n merge(prev: TValue | null | undefined, state: TState): TValue | null;\n}\n\ninterface Scratch<TState, TValue, K extends string> {\n ids: NodeId[];\n scene: Scene<PaintData<K, TValue>, string, unknown>;\n /** Data snapshot at gesture start, keyed by node id. */\n startData: Map<NodeId, PaintData<K, TValue>>;\n state: TState;\n /** Preview data entries — the merged value per selected node. */\n previews: Map<NodeId, PaintData<K, TValue>>;\n /** Consumer commit hook captured at gesture start; undefined falls back to\n * `scene.applyBatch`. */\n applyOps?: (ops: Op[], label: string) => void;\n}\n\n/**\n * The ongoing-action body the paint actions share: it previews without\n * touching the scene, and commits one batch (one undo entry) through the\n * consumer `applyOps` hook when present, else `scene.applyBatch`.\n *\n * The `from` data is re-read at commit rather than reused from the start\n * snapshot, so a concurrent edit to a field this action does not own is not\n * clobbered.\n */\nexport function createPaintAction<TState, TValue, K extends string>(\n spec: PaintActionSpec<TState, TValue, K>,\n): Action & { requires: string[] } {\n type Data = PaintData<K, TValue>;\n\n const refreshPreviews = (scratch: Scratch<TState, TValue, K>): void => {\n scratch.previews.clear();\n for (const id of scratch.ids) {\n const prev = scratch.startData.get(id);\n const next = spec.merge(prev?.[spec.dataKey], scratch.state);\n scratch.previews.set(id, { ...(prev ?? {}), [spec.dataKey]: next } as Data);\n }\n };\n\n return {\n id: spec.id,\n label: spec.label,\n eligible: { capability: 'applies-fill' },\n requires: ['selection', 'scene', 'applyOps'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, opts?: BindingOpts): OngoingHandle {\n const selection = ctx.deps.selection;\n const scene = ctx.deps.scene as Scene<Data, string, unknown> | undefined;\n const applyOps = ctx.deps.applyOps;\n\n if (!selection || !scene) return {};\n\n const ids = selection.get() as NodeId[];\n if (ids.length === 0) return {};\n\n const fallback = opts?.params as Params;\n // `??` would lose a `paint: null`, which is None, not \"no paint given\".\n const pick = (<T>(key: string) =>\n (ctx.params?.[key] !== undefined ? ctx.params[key] : fallback?.[key]) as T | undefined) as PickParam;\n\n const startData = new Map<NodeId, Data>();\n for (const id of ids) {\n const node = scene.get(id);\n if (node) startData.set(id, { ...(node.data as Data) });\n }\n\n const scratch: Scratch<TState, TValue, K> = {\n ids,\n scene,\n startData,\n state: spec.initialState(pick),\n previews: new Map(),\n applyOps,\n };\n refreshPreviews(scratch);\n\n return {\n onMove(moveCtx: InvocationCtx): void {\n const next = spec.readParams(scratch.state, moveCtx.params);\n if (next === null) return;\n scratch.state = next;\n refreshPreviews(scratch);\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n if (reason === 'cancel') {\n scratch.previews.clear();\n return;\n }\n const ops: Op[] = [];\n for (const id of scratch.ids) {\n const merged = spec.merge(\n scratch.startData.get(id)?.[spec.dataKey],\n scratch.state,\n );\n const nodeNow = scratch.scene.get(id);\n if (!nodeNow) continue;\n const from = { ...(nodeNow.data as object) } as Data;\n const to = { ...from, [spec.dataKey]: merged } as Data;\n ops.push(createSetDataOp<Data>({ id: id as string, from, to }));\n }\n if (ops.length > 0) {\n if (scratch.applyOps) scratch.applyOps(ops, spec.label);\n else scratch.scene.applyBatch(ops, spec.label, defaultCommitAdapter(scratch.scene, selection.adapterMethods));\n }\n scratch.previews.clear();\n },\n previewIds: () => scratch.previews.keys(),\n previewData: (id: string) => scratch.previews.get(id as unknown as NodeId) ?? null,\n };\n },\n },\n enabled: (deps) => {\n const sel = deps?.selection;\n if (!sel || (sel.get() as unknown[]).length === 0) {\n return ActionDisabledReason.SelectionRequired;\n }\n return true;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;AA6DA,SAAgB,kBACd,MACiC;CAGjC,MAAM,mBAAmB,YAA8C;EACrE,QAAQ,SAAS,MAAM;EACvB,KAAK,MAAM,MAAM,QAAQ,KAAK;GAC5B,MAAM,OAAO,QAAQ,UAAU,IAAI,EAAE;GACrC,MAAM,OAAO,KAAK,MAAM,OAAO,KAAK,UAAU,QAAQ,KAAK;GAC3D,QAAQ,SAAS,IAAI,IAAI;IAAE,GAAI,QAAQ,CAAC;KAAK,KAAK,UAAU;GAAK,CAAS;EAC5E;CACF;CAEA,OAAO;EACL,IAAI,KAAK;EACT,OAAO,KAAK;EACZ,UAAU,EAAE,YAAY,eAAe;EACvC,UAAU;GAAC;GAAa;GAAS;EAAU;EAC3C,SAAS;GACP,QAAQ;GACR,MAAM,KAAoB,MAAmC;IAC3D,MAAM,YAAY,IAAI,KAAK;IAC3B,MAAM,QAAQ,IAAI,KAAK;IACvB,MAAM,WAAW,IAAI,KAAK;IAE1B,IAAI,CAAC,aAAa,CAAC,OAAO,OAAO,CAAC;IAElC,MAAM,MAAM,UAAU,IAAI;IAC1B,IAAI,IAAI,WAAW,GAAG,OAAO,CAAC;IAE9B,MAAM,WAAW,MAAM;IAEvB,MAAM,SAAY,QACf,IAAI,SAAS,SAAS,SAAY,IAAI,OAAO,OAAO,WAAW;IAElE,MAAM,4BAAY,IAAI,IAAkB;IACxC,KAAK,MAAM,MAAM,KAAK;KACpB,MAAM,OAAO,MAAM,IAAI,EAAE;KACzB,IAAI,MAAM,UAAU,IAAI,IAAI,EAAE,GAAI,KAAK,KAAc,CAAC;IACxD;IAEA,MAAM,UAAsC;KAC1C;KACA;KACA;KACA,OAAO,KAAK,aAAa,IAAI;KAC7B,0BAAU,IAAI,IAAI;KAClB;IACF;IACA,gBAAgB,OAAO;IAEvB,OAAO;KACL,OAAO,SAA8B;MACnC,MAAM,OAAO,KAAK,WAAW,QAAQ,OAAO,QAAQ,MAAM;MAC1D,IAAI,SAAS,MAAM;MACnB,QAAQ,QAAQ;MAChB,gBAAgB,OAAO;KACzB;KACA,MAAM,SAAwB,QAAmC;MAC/D,IAAI,WAAW,UAAU;OACvB,QAAQ,SAAS,MAAM;OACvB;MACF;MACA,MAAM,MAAY,CAAC;MACnB,KAAK,MAAM,MAAM,QAAQ,KAAK;OAC5B,MAAM,SAAS,KAAK,MAClB,QAAQ,UAAU,IAAI,EAAE,CAAC,GAAG,KAAK,UACjC,QAAQ,KACV;OACA,MAAM,UAAU,QAAQ,MAAM,IAAI,EAAE;OACpC,IAAI,CAAC,SAAS;OACd,MAAM,OAAO,EAAE,GAAI,QAAQ,KAAgB;OAC3C,MAAM,KAAK;QAAE,GAAG;SAAO,KAAK,UAAU;OAAO;OAC7C,IAAI,KAAK,gBAAsB;QAAM;QAAc;QAAM;OAAG,CAAC,CAAC;MAChE;MACA,IAAI,IAAI,SAAS,GAAG;OAClB,IAAI,QAAQ,UAAU,QAAQ,SAAS,KAAK,KAAK,KAAK;YACjD,QAAQ,MAAM,WAAW,KAAK,KAAK,OAAO,qBAAqB,QAAQ,OAAO,UAAU,cAAc,CAAC;MAC9G;MACA,QAAQ,SAAS,MAAM;KACzB;KACA,kBAAkB,QAAQ,SAAS,KAAK;KACxC,cAAc,OAAe,QAAQ,SAAS,IAAI,EAAuB,KAAK;IAChF;GACF;EACF;EACA,UAAU,SAAS;GACjB,MAAM,MAAM,MAAM;GAClB,IAAI,CAAC,OAAQ,IAAI,IAAI,CAAC,CAAe,WAAW,GAC9C,OAAO,qBAAqB;GAE9B,OAAO;EACT;CACF;AACF"}
1
+ {"version":3,"file":"createPaintAction.js","names":[],"sources":["../../../../src/interactions/actions/defaults/createPaintAction.ts"],"sourcesContent":["import type { Action } from '@weasel-js/routing';\nimport type { InvocationCtx, OngoingHandle, BindingOpts } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { Scene, NodeId } from 'core/scene/types';\nimport type { Op } from 'core/ops/types';\nimport { createSetDataOp } from 'core/ops/setData';\nimport { defaultCommitAdapter } from '../defaultCommitAdapter';\nimport { paintInheritors } from 'core/scene/inheritedPaint';\n\n/** The node data one paint action reads and writes: its own key, nothing else. */\ntype PaintData<K extends string, TValue> = { [P in K]?: TValue | null };\n\ntype Params = Record<string, unknown> | undefined;\n\n/** Read a param from the invocation, falling back to the binding's. */\nexport type PickParam = <T>(key: string) => T | undefined;\n\n/**\n * What distinguishes one paint action from another.\n *\n * `TState` is the action's gesture state. It is a reducer, not a paint:\n * `setFill` and `setStroke` supersede a paint with a later color, which no\n * per-field merge of the params can express.\n */\nexport interface PaintActionSpec<TState, TValue, K extends string> {\n id: string;\n label: string;\n /** The `data` key this action owns. */\n dataKey: K;\n /** Gesture state at start. */\n initialState(pick: PickParam): TState;\n /** The state one onMove tick moves to, or `null` when its params carry\n * nothing this action reads — the preview then stands. */\n readParams(prev: TState, params: Params): TState | null;\n /** The value to write for one node, from that node's value at gesture start.\n * `null` writes the absence of paint, which is a value like any other —\n * a node with `fill: null` paints no fill. */\n merge(prev: TValue | null | undefined, state: TState): TValue | null;\n}\n\ninterface Scratch<TState, TValue, K extends string> {\n ids: NodeId[];\n scene: Scene<PaintData<K, TValue>, string, unknown>;\n /** Data snapshot at gesture start, keyed by node id. */\n startData: Map<NodeId, PaintData<K, TValue>>;\n state: TState;\n /** Preview data entries — the merged value per selected node. */\n previews: Map<NodeId, PaintData<K, TValue>>;\n /** Consumer commit hook captured at gesture start; undefined falls back to\n * `scene.applyBatch`. */\n applyOps?: (ops: Op[], label: string) => void;\n}\n\n/**\n * The ongoing-action body the paint actions share: it previews without\n * touching the scene, and commits one batch (one undo entry) through the\n * consumer `applyOps` hook when present, else `scene.applyBatch`.\n *\n * The `from` data is re-read at commit rather than reused from the start\n * snapshot, so a concurrent edit to a field this action does not own is not\n * clobbered.\n */\nexport function createPaintAction<TState, TValue, K extends string>(\n spec: PaintActionSpec<TState, TValue, K>,\n): Action & { requires: string[] } {\n type Data = PaintData<K, TValue>;\n\n const refreshPreviews = (scratch: Scratch<TState, TValue, K>): void => {\n scratch.previews.clear();\n for (const id of scratch.ids) {\n const prev = scratch.startData.get(id);\n const next = spec.merge(prev?.[spec.dataKey], scratch.state);\n scratch.previews.set(id, { ...(prev ?? {}), [spec.dataKey]: next } as Data);\n }\n };\n\n return {\n id: spec.id,\n label: spec.label,\n eligible: { capability: 'applies-fill' },\n requires: ['selection', 'scene', 'applyOps'],\n invoker: {\n timing: 'ongoing',\n start(ctx: InvocationCtx, opts?: BindingOpts): OngoingHandle {\n const selection = ctx.deps.selection;\n const scene = ctx.deps.scene as Scene<Data, string, unknown> | undefined;\n const applyOps = ctx.deps.applyOps;\n\n if (!selection || !scene) return {};\n\n const ids = selection.get() as NodeId[];\n if (ids.length === 0) return {};\n\n const fallback = opts?.params as Params;\n // `??` would lose a `paint: null`, which is None, not \"no paint given\".\n const pick = (<T>(key: string) =>\n (ctx.params?.[key] !== undefined ? ctx.params[key] : fallback?.[key]) as T | undefined) as PickParam;\n\n const startData = new Map<NodeId, Data>();\n for (const id of ids) {\n const node = scene.get(id);\n if (node) startData.set(id, { ...(node.data as Data) });\n }\n\n const scratch: Scratch<TState, TValue, K> = {\n ids,\n scene,\n startData,\n state: spec.initialState(pick),\n previews: new Map(),\n applyOps,\n };\n refreshPreviews(scratch);\n // Members that inherit the paint being changed preview with it.\n const key = spec.dataKey as string;\n const inheritors = key === 'fill' || key === 'stroke'\n ? [...new Set(ids.flatMap((id) => paintInheritors(scene, id, key)))].filter((id) => !startData.has(id as NodeId))\n : [];\n\n return {\n onMove(moveCtx: InvocationCtx): void {\n const next = spec.readParams(scratch.state, moveCtx.params);\n if (next === null) return;\n scratch.state = next;\n refreshPreviews(scratch);\n },\n onEnd(_endCtx: InvocationCtx, reason: 'commit' | 'cancel'): void {\n if (reason === 'cancel') {\n scratch.previews.clear();\n return;\n }\n const ops: Op[] = [];\n for (const id of scratch.ids) {\n const merged = spec.merge(\n scratch.startData.get(id)?.[spec.dataKey],\n scratch.state,\n );\n const nodeNow = scratch.scene.get(id);\n if (!nodeNow) continue;\n const from = { ...(nodeNow.data as object) } as Data;\n const to = { ...from, [spec.dataKey]: merged } as Data;\n ops.push(createSetDataOp<Data>({ id: id as string, from, to }));\n }\n if (ops.length > 0) {\n if (scratch.applyOps) scratch.applyOps(ops, spec.label);\n else scratch.scene.applyBatch(ops, spec.label, defaultCommitAdapter(scratch.scene, selection.adapterMethods));\n }\n scratch.previews.clear();\n },\n previewIds: () => (scratch.previews.size === 0 ? [] : [...scratch.previews.keys(), ...inheritors]),\n previewData: (id: string) => scratch.previews.get(id as unknown as NodeId) ?? null,\n };\n },\n },\n enabled: (deps) => {\n const sel = deps?.selection;\n if (!sel || (sel.get() as unknown[]).length === 0) {\n return ActionDisabledReason.SelectionRequired;\n }\n return true;\n },\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { pressTarget } from "../../../tools/builtin/pressTarget.js";
2
+ import { ActionDisabledReason } from "@weasel-js/routing";
3
+
4
+ //#region src/interactions/actions/defaults/enterGroup.ts
5
+ var inside = (b, p) => p.x >= b.x && p.x <= b.x + b.width && p.y >= b.y && p.y <= b.y + b.height;
6
+ /**
7
+ * Leaves every entered group whose box does not hold `p`, innermost first. A press that lands
8
+ * inside the entered group's box stays in it, and so does one on a group with no box to read.
9
+ */
10
+ function leaveGroupsOutside(entered, boxOf, p) {
11
+ for (let id = entered.get(); id !== null; id = entered.get()) {
12
+ const box = boxOf(id);
13
+ if (box === null || inside(box, p)) return;
14
+ entered.leave();
15
+ if (entered.get() === id) return;
16
+ }
17
+ }
18
+ /**
19
+ * `group.enter` — enters the group a press at the point would select. Bound to a double-click
20
+ * on a body by `useSelectTool`. It declines where that is not a group, so the double-click
21
+ * falls through to text editing, path editing and the mode triggers.
22
+ */
23
+ function createEnterGroupAction(opts) {
24
+ const targetAt = (deps, p) => {
25
+ const entered = deps?.enteredGroup;
26
+ if (!entered || !p) return null;
27
+ const hit = opts.pickHit(p.x, p.y);
28
+ if (hit === null) return null;
29
+ const target = pressTarget(opts.tree, hit, entered.get());
30
+ return opts.tree.getNode(target)?.kind === "group" ? target : null;
31
+ };
32
+ return {
33
+ id: "group.enter",
34
+ label: "Enter group",
35
+ eligible: { capability: "creates-selection" },
36
+ requires: ["enteredGroup"],
37
+ enabled: (deps, at) => targetAt(deps, at) !== null ? true : ActionDisabledReason.NotApplicable,
38
+ invoker: {
39
+ timing: "immediate",
40
+ run: (deps, params) => {
41
+ const x = params?.worldX, y = params?.worldY;
42
+ const target = typeof x === "number" && typeof y === "number" ? targetAt(deps, {
43
+ x,
44
+ y
45
+ }) : null;
46
+ if (target !== null) deps.enteredGroup?.enter(target);
47
+ }
48
+ }
49
+ };
50
+ }
51
+ /**
52
+ * `group.leave` — Escape leaves the entered group for the one above it; a press outside the
53
+ * entered group's box leaves every group that box does not hold. With nothing entered it
54
+ * declines, so Escape clears the selection as before, and it declines while path anchors are
55
+ * being edited, so that Escape exits the edit first.
56
+ */
57
+ function createLeaveGroupAction(opts) {
58
+ return {
59
+ id: "group.leave",
60
+ label: "Leave group",
61
+ eligible: { capability: "creates-selection" },
62
+ requires: ["enteredGroup", "editAnchors"],
63
+ enabled: (deps, at) => {
64
+ const here = deps?.enteredGroup?.get() ?? null;
65
+ if (here === null || deps?.editAnchors?.editingId) return ActionDisabledReason.NotApplicable;
66
+ if (!at) return true;
67
+ const box = opts.boxOf(here);
68
+ return box !== null && !inside(box, at) ? true : ActionDisabledReason.NotApplicable;
69
+ },
70
+ invoker: {
71
+ timing: "immediate",
72
+ run: (deps, params) => {
73
+ const entered = deps.enteredGroup;
74
+ if (!entered) return;
75
+ const x = params?.worldX, y = params?.worldY;
76
+ if (typeof x === "number" && typeof y === "number") leaveGroupsOutside(entered, opts.boxOf, {
77
+ x,
78
+ y
79
+ });
80
+ else entered.leave();
81
+ }
82
+ }
83
+ };
84
+ }
85
+
86
+ //#endregion
87
+ export { createEnterGroupAction, createLeaveGroupAction, leaveGroupsOutside };
88
+ //# sourceMappingURL=enterGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enterGroup.js","names":[],"sources":["../../../../src/interactions/actions/defaults/enterGroup.ts"],"sourcesContent":["import type { Action, ActionDeps } from '@weasel-js/routing';\nimport { ActionDisabledReason } from '@weasel-js/routing';\nimport type { EnteredGroupApi } from 'canvas/deps/enteredGroup';\nimport type { NodeId } from 'core/scene/types';\nimport { pressTarget, type PressTargetTree } from '../../../tools/builtin/pressTarget';\n\ntype Point = { x: number; y: number };\ntype Box = { x: number; y: number; width: number; height: number };\n\n/** What `group.enter` reads: the node under a point and the tree above it. */\nexport interface EnterGroupOptions {\n /** The node under the point, before any group above it is considered. */\n pickHit: (worldX: number, worldY: number) => string | null;\n tree: PressTargetTree;\n}\n\n/** What `group.leave` reads: where a group's box is. */\nexport interface LeaveGroupOptions {\n boxOf: (id: string) => Box | null;\n}\n\nconst inside = (b: Box, p: Point) =>\n p.x >= b.x && p.x <= b.x + b.width && p.y >= b.y && p.y <= b.y + b.height;\n\n/**\n * Leaves every entered group whose box does not hold `p`, innermost first. A press that lands\n * inside the entered group's box stays in it, and so does one on a group with no box to read.\n */\nexport function leaveGroupsOutside(\n entered: EnteredGroupApi,\n boxOf: LeaveGroupOptions['boxOf'],\n p: Point,\n): void {\n for (let id = entered.get(); id !== null; id = entered.get()) {\n const box = boxOf(id);\n if (box === null || inside(box, p)) return;\n entered.leave();\n if (entered.get() === id) return;\n }\n}\n\n/**\n * `group.enter` — enters the group a press at the point would select. Bound to a double-click\n * on a body by `useSelectTool`. It declines where that is not a group, so the double-click\n * falls through to text editing, path editing and the mode triggers.\n */\nexport function createEnterGroupAction(opts: EnterGroupOptions): Action {\n const targetAt = (deps: ActionDeps | undefined, p: Point | undefined): string | null => {\n const entered = deps?.enteredGroup;\n if (!entered || !p) return null;\n const hit = opts.pickHit(p.x, p.y);\n if (hit === null) return null;\n const target = pressTarget(opts.tree, hit, entered.get());\n return (opts.tree.getNode(target) as { kind?: string } | undefined)?.kind === 'group' ? target : null;\n };\n return {\n id: 'group.enter',\n label: 'Enter group',\n eligible: { capability: 'creates-selection' },\n requires: ['enteredGroup'],\n enabled: (deps, at) => (targetAt(deps, at) !== null ? true : ActionDisabledReason.NotApplicable),\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const x = params?.worldX, y = params?.worldY;\n const target = typeof x === 'number' && typeof y === 'number' ? targetAt(deps, { x, y }) : null;\n if (target !== null) deps.enteredGroup?.enter(target as NodeId);\n },\n },\n };\n}\n\n/**\n * `group.leave` — Escape leaves the entered group for the one above it; a press outside the\n * entered group's box leaves every group that box does not hold. With nothing entered it\n * declines, so Escape clears the selection as before, and it declines while path anchors are\n * being edited, so that Escape exits the edit first.\n */\nexport function createLeaveGroupAction(opts: LeaveGroupOptions): Action {\n return {\n id: 'group.leave',\n label: 'Leave group',\n eligible: { capability: 'creates-selection' },\n requires: ['enteredGroup', 'editAnchors'],\n enabled: (deps, at) => {\n const here = deps?.enteredGroup?.get() ?? null;\n if (here === null || deps?.editAnchors?.editingId) return ActionDisabledReason.NotApplicable;\n if (!at) return true;\n const box = opts.boxOf(here);\n return box !== null && !inside(box, at) ? true : ActionDisabledReason.NotApplicable;\n },\n invoker: {\n timing: 'immediate' as const,\n run: (deps, params) => {\n const entered = deps.enteredGroup;\n if (!entered) return;\n const x = params?.worldX, y = params?.worldY;\n if (typeof x === 'number' && typeof y === 'number') leaveGroupsOutside(entered, opts.boxOf, { x, y });\n else entered.leave();\n },\n },\n };\n}\n"],"mappings":";;;;AAqBA,IAAM,UAAU,GAAQ,MACtB,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE;;;;;AAMrE,SAAgB,mBACd,SACA,OACA,GACM;CACN,KAAK,IAAI,KAAK,QAAQ,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,IAAI,GAAG;EAC5D,MAAM,MAAM,MAAM,EAAE;EACpB,IAAI,QAAQ,QAAQ,OAAO,KAAK,CAAC,GAAG;EACpC,QAAQ,MAAM;EACd,IAAI,QAAQ,IAAI,MAAM,IAAI;CAC5B;AACF;;;;;;AAOA,SAAgB,uBAAuB,MAAiC;CACtE,MAAM,YAAY,MAA8B,MAAwC;EACtF,MAAM,UAAU,MAAM;EACtB,IAAI,CAAC,WAAW,CAAC,GAAG,OAAO;EAC3B,MAAM,MAAM,KAAK,QAAQ,EAAE,GAAG,EAAE,CAAC;EACjC,IAAI,QAAQ,MAAM,OAAO;EACzB,MAAM,SAAS,YAAY,KAAK,MAAM,KAAK,QAAQ,IAAI,CAAC;EACxD,OAAQ,KAAK,KAAK,QAAQ,MAAM,CAAC,EAAoC,SAAS,UAAU,SAAS;CACnG;CACA,OAAO;EACL,IAAI;EACJ,OAAO;EACP,UAAU,EAAE,YAAY,oBAAoB;EAC5C,UAAU,CAAC,cAAc;EACzB,UAAU,MAAM,OAAQ,SAAS,MAAM,EAAE,MAAM,OAAO,OAAO,qBAAqB;EAClF,SAAS;GACP,QAAQ;GACR,MAAM,MAAM,WAAW;IACrB,MAAM,IAAI,QAAQ,QAAQ,IAAI,QAAQ;IACtC,MAAM,SAAS,OAAO,MAAM,YAAY,OAAO,MAAM,WAAW,SAAS,MAAM;KAAE;KAAG;IAAE,CAAC,IAAI;IAC3F,IAAI,WAAW,MAAM,KAAK,cAAc,MAAM,MAAgB;GAChE;EACF;CACF;AACF;;;;;;;AAQA,SAAgB,uBAAuB,MAAiC;CACtE,OAAO;EACL,IAAI;EACJ,OAAO;EACP,UAAU,EAAE,YAAY,oBAAoB;EAC5C,UAAU,CAAC,gBAAgB,aAAa;EACxC,UAAU,MAAM,OAAO;GACrB,MAAM,OAAO,MAAM,cAAc,IAAI,KAAK;GAC1C,IAAI,SAAS,QAAQ,MAAM,aAAa,WAAW,OAAO,qBAAqB;GAC/E,IAAI,CAAC,IAAI,OAAO;GAChB,MAAM,MAAM,KAAK,MAAM,IAAI;GAC3B,OAAO,QAAQ,QAAQ,CAAC,OAAO,KAAK,EAAE,IAAI,OAAO,qBAAqB;EACxE;EACA,SAAS;GACP,QAAQ;GACR,MAAM,MAAM,WAAW;IACrB,MAAM,UAAU,KAAK;IACrB,IAAI,CAAC,SAAS;IACd,MAAM,IAAI,QAAQ,QAAQ,IAAI,QAAQ;IACtC,IAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU,mBAAmB,SAAS,KAAK,OAAO;KAAE;KAAG;IAAE,CAAC;SAC/F,QAAQ,MAAM;GACrB;EACF;CACF;AACF"}
@@ -12,7 +12,7 @@ var enterPathEditAction = {
12
12
  },
13
13
  opts: { id: "enterPathEdit.doubleClick" }
14
14
  }],
15
- eligible: { mode: { in: ["normal", "isolation"] } },
15
+ eligible: { mode: "normal" },
16
16
  requires: [
17
17
  "editAnchors",
18
18
  "selection",
@@ -1 +1 @@
1
- {"version":3,"file":"enterPathEdit.js","names":[],"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 * A selected path effect hiding its sources edits its path source.\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 { NodeId } from 'core/scene/types';\nimport { ActionDisabledReason, isBody } from '@weasel-js/routing';\nimport { effectSourceFor } from 'features/pathEffects/effectSources';\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 spec: {\n kind: 'doubleClick',\n target: { kindOf: isBody },\n },\n opts: { id: 'enterPathEdit.doubleClick' },\n }],\n eligible: { mode: { in: ['normal', 'isolation'] } },\n requires: ['editAnchors', 'selection', 'nodeAtPoint', 'hitAt', 'scene'],\n invoker: {\n timing: 'immediate',\n run(deps, params) {\n const editAnchors = deps.editAnchors;\n const selection = deps.selection;\n if (!editAnchors || !selection) return;\n // The path under the pointer wins: with several selected, the first may not be the one\n // double-clicked.\n const x = params?.worldX, y = params?.worldY;\n const pointed = typeof x === 'number' && typeof y === 'number';\n const under = pointed ? deps.nodeAtPoint?.({ x, y }) : null;\n if (under && editAnchors.getEditablePath(under)) {\n editAnchors.setEditingId(under);\n return;\n }\n const ids = selection.get() as NodeId[];\n const scene = deps.scene;\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 // An effect hiding its path edits that path when entered from the selection. A double-click never does: on the\n // effect's glyphs it is the text's, and between them it is aimed at nothing.\n const target = (!pointed && scene ? effectSourceFor(scene, id, 'path') : null) ?? id;\n if (editAnchors.getEditablePath(target)) {\n editAnchors.setEditingId(target);\n return;\n }\n }\n },\n } as ImmediateInvoker,\n // A double-click naming a group above the path under it is the group's, not this action's.\n enabled: (deps, at) => (at && deps?.hitAt?.(at)?.doubleClick ? ActionDisabledReason.NotApplicable : true),\n};\n"],"mappings":";;;;AAmBA,IAAa,sBAAuD;CAClE,IAAI;CACJ,OAAO;CAMP,gBAAgB,CAAC;EACf,MAAM;GACJ,MAAM;GACN,QAAQ,EAAE,QAAQ,OAAO;EAC3B;EACA,MAAM,EAAE,IAAI,4BAA4B;CAC1C,CAAC;CACD,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,WAAW,EAAE,EAAE;CAClD,UAAU;EAAC;EAAe;EAAa;EAAe;EAAS;CAAO;CACtE,SAAS;EACP,QAAQ;EACR,IAAI,MAAM,QAAQ;GAChB,MAAM,cAAc,KAAK;GACzB,MAAM,YAAY,KAAK;GACvB,IAAI,CAAC,eAAe,CAAC,WAAW;GAGhC,MAAM,IAAI,QAAQ,QAAQ,IAAI,QAAQ;GACtC,MAAM,UAAU,OAAO,MAAM,YAAY,OAAO,MAAM;GACtD,MAAM,QAAQ,UAAU,KAAK,cAAc;IAAE;IAAG;GAAE,CAAC,IAAI;GACvD,IAAI,SAAS,YAAY,gBAAgB,KAAK,GAAG;IAC/C,YAAY,aAAa,KAAK;IAC9B;GACF;GACA,MAAM,MAAM,UAAU,IAAI;GAC1B,MAAM,QAAQ,KAAK;GAInB,KAAK,MAAM,MAAM,KAAK;IAGpB,MAAM,UAAU,CAAC,WAAW,QAAQ,gBAAgB,OAAO,IAAI,MAAM,IAAI,SAAS;IAClF,IAAI,YAAY,gBAAgB,MAAM,GAAG;KACvC,YAAY,aAAa,MAAM;KAC/B;IACF;GACF;EACF;CACF;CAEA,UAAU,MAAM,OAAQ,MAAM,MAAM,QAAQ,EAAE,CAAC,EAAE,cAAc,qBAAqB,gBAAgB;AACtG"}
1
+ {"version":3,"file":"enterPathEdit.js","names":[],"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 * A selected path effect hiding its sources edits its path source.\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 { NodeId } from 'core/scene/types';\nimport { ActionDisabledReason, isBody } from '@weasel-js/routing';\nimport { effectSourceFor } from 'features/pathEffects/effectSources';\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 spec: {\n kind: 'doubleClick',\n target: { kindOf: isBody },\n },\n opts: { id: 'enterPathEdit.doubleClick' },\n }],\n eligible: { mode: 'normal' },\n requires: ['editAnchors', 'selection', 'nodeAtPoint', 'hitAt', 'scene'],\n invoker: {\n timing: 'immediate',\n run(deps, params) {\n const editAnchors = deps.editAnchors;\n const selection = deps.selection;\n if (!editAnchors || !selection) return;\n // The path under the pointer wins: with several selected, the first may not be the one\n // double-clicked.\n const x = params?.worldX, y = params?.worldY;\n const pointed = typeof x === 'number' && typeof y === 'number';\n const under = pointed ? deps.nodeAtPoint?.({ x, y }) : null;\n if (under && editAnchors.getEditablePath(under)) {\n editAnchors.setEditingId(under);\n return;\n }\n const ids = selection.get() as NodeId[];\n const scene = deps.scene;\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 // An effect hiding its path edits that path when entered from the selection. A double-click never does: on the\n // effect's glyphs it is the text's, and between them it is aimed at nothing.\n const target = (!pointed && scene ? effectSourceFor(scene, id, 'path') : null) ?? id;\n if (editAnchors.getEditablePath(target)) {\n editAnchors.setEditingId(target);\n return;\n }\n }\n },\n } as ImmediateInvoker,\n // A double-click naming a group above the path under it is the group's, not this action's.\n enabled: (deps, at) => (at && deps?.hitAt?.(at)?.doubleClick ? ActionDisabledReason.NotApplicable : true),\n};\n"],"mappings":";;;;AAmBA,IAAa,sBAAuD;CAClE,IAAI;CACJ,OAAO;CAMP,gBAAgB,CAAC;EACf,MAAM;GACJ,MAAM;GACN,QAAQ,EAAE,QAAQ,OAAO;EAC3B;EACA,MAAM,EAAE,IAAI,4BAA4B;CAC1C,CAAC;CACD,UAAU,EAAE,MAAM,SAAS;CAC3B,UAAU;EAAC;EAAe;EAAa;EAAe;EAAS;CAAO;CACtE,SAAS;EACP,QAAQ;EACR,IAAI,MAAM,QAAQ;GAChB,MAAM,cAAc,KAAK;GACzB,MAAM,YAAY,KAAK;GACvB,IAAI,CAAC,eAAe,CAAC,WAAW;GAGhC,MAAM,IAAI,QAAQ,QAAQ,IAAI,QAAQ;GACtC,MAAM,UAAU,OAAO,MAAM,YAAY,OAAO,MAAM;GACtD,MAAM,QAAQ,UAAU,KAAK,cAAc;IAAE;IAAG;GAAE,CAAC,IAAI;GACvD,IAAI,SAAS,YAAY,gBAAgB,KAAK,GAAG;IAC/C,YAAY,aAAa,KAAK;IAC9B;GACF;GACA,MAAM,MAAM,UAAU,IAAI;GAC1B,MAAM,QAAQ,KAAK;GAInB,KAAK,MAAM,MAAM,KAAK;IAGpB,MAAM,UAAU,CAAC,WAAW,QAAQ,gBAAgB,OAAO,IAAI,MAAM,IAAI,SAAS;IAClF,IAAI,YAAY,gBAAgB,MAAM,GAAG;KACvC,YAAY,aAAa,MAAM;KAC/B;IACF;GACF;EACF;CACF;CAEA,UAAU,MAAM,OAAQ,MAAM,MAAM,QAAQ,EAAE,CAAC,EAAE,cAAc,qBAAqB,gBAAgB;AACtG"}
@@ -11,7 +11,7 @@
11
11
  var enterTextEditAction = {
12
12
  id: "enterTextEdit",
13
13
  label: "Enter text edit",
14
- eligible: { mode: { in: ["normal", "isolation"] } },
14
+ eligible: { mode: "normal" },
15
15
  requires: ["textEdit", "selection"],
16
16
  invoker: {
17
17
  timing: "immediate",
@@ -1 +1 @@
1
- {"version":3,"file":"enterTextEdit.js","names":[],"sources":["../../../../src/interactions/actions/defaults/enterTextEdit.ts"],"sourcesContent":["import type { Action } from '@weasel-js/routing';\n\n/**\n * Starts in-place text editing on the single selected node. It has no\n * `defaultBinding`: it fires only via `Tool.bindings`.\n *\n * A `'selected-body'` target matches any selected node kind, so the action\n * skips a node `TextEditDep.isTextNode` rejects. With no `isTextNode` it fires\n * unconditionally, and the binding spec is the only gate; a binding can\n * pre-filter with `target: 'kind:text:selected'` instead.\n */\nexport const enterTextEditAction: Action & { requires: string[] } = {\n id: 'enterTextEdit',\n label: 'Enter text edit',\n eligible: { mode: { in: ['normal', 'isolation'] } },\n requires: ['textEdit', 'selection'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const sel = deps.selection?.get() ?? [];\n if (sel.length !== 1) return;\n\n const id = sel[0];\n const textEdit = deps.textEdit;\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":";;;;;;;;;;AAWA,IAAa,sBAAuD;CAClE,IAAI;CACJ,OAAO;CACP,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,WAAW,EAAE,EAAE;CAClD,UAAU,CAAC,YAAY,WAAW;CAClC,SAAS;EACP,QAAQ;EACR,MAAM,SAAS;GACb,MAAM,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC;GACtC,IAAI,IAAI,WAAW,GAAG;GAEtB,MAAM,KAAK,IAAI;GACf,MAAM,WAAW,KAAK;GACtB,IAAI,CAAC,UAAU;GAGf,IAAI,SAAS,cAAc,CAAC,SAAS,WAAW,EAAE,GAAG;GAErD,SAAS,UAAU,EAAE;EACvB;CACF;AACF"}
1
+ {"version":3,"file":"enterTextEdit.js","names":[],"sources":["../../../../src/interactions/actions/defaults/enterTextEdit.ts"],"sourcesContent":["import type { Action } from '@weasel-js/routing';\n\n/**\n * Starts in-place text editing on the single selected node. It has no\n * `defaultBinding`: it fires only via `Tool.bindings`.\n *\n * A `'selected-body'` target matches any selected node kind, so the action\n * skips a node `TextEditDep.isTextNode` rejects. With no `isTextNode` it fires\n * unconditionally, and the binding spec is the only gate; a binding can\n * pre-filter with `target: 'kind:text:selected'` instead.\n */\nexport const enterTextEditAction: Action & { requires: string[] } = {\n id: 'enterTextEdit',\n label: 'Enter text edit',\n eligible: { mode: 'normal' },\n requires: ['textEdit', 'selection'],\n invoker: {\n timing: 'immediate',\n run: (deps) => {\n const sel = deps.selection?.get() ?? [];\n if (sel.length !== 1) return;\n\n const id = sel[0];\n const textEdit = deps.textEdit;\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":";;;;;;;;;;AAWA,IAAa,sBAAuD;CAClE,IAAI;CACJ,OAAO;CACP,UAAU,EAAE,MAAM,SAAS;CAC3B,UAAU,CAAC,YAAY,WAAW;CAClC,SAAS;EACP,QAAQ;EACR,MAAM,SAAS;GACb,MAAM,MAAM,KAAK,WAAW,IAAI,KAAK,CAAC;GACtC,IAAI,IAAI,WAAW,GAAG;GAEtB,MAAM,KAAK,IAAI;GACf,MAAM,WAAW,KAAK;GACtB,IAAI,CAAC,UAAU;GAGf,IAAI,SAAS,cAAc,CAAC,SAAS,WAAW,EAAE,GAAG;GAErD,SAAS,UAAU,EAAE;EACvB;CACF;AACF"}
@@ -12,7 +12,7 @@ import { ActionDisabledReason } from "@weasel-js/routing";
12
12
 
13
13
  //#region src/interactions/actions/defaults/group.ts
14
14
  /**
15
- * Creates a structural `ContainerNode` and reparents the current selection
15
+ * Creates a structural `GroupNode` and reparents the current selection
16
16
  * under it as a single undoable batch.
17
17
  *
18
18
  * Grouping never moves a member on screen. The container takes the world
@@ -72,7 +72,7 @@ var groupAction = {
72
72
  const ops = [createInsertOp({
73
73
  node: {
74
74
  id: containerId,
75
- kind: "container",
75
+ kind: "group",
76
76
  layer,
77
77
  pose,
78
78
  data: {},
@@ -107,9 +107,9 @@ var groupAction = {
107
107
  enabled: requiresSelection
108
108
  };
109
109
  /**
110
- * Dissolves each selected container by reparenting its children up to the
110
+ * Dissolves each selected group by reparenting its children up to the
111
111
  * container's own parent (preserving z-order) and removing the now-empty
112
- * container, as a single undoable batch. Selected non-container nodes are
112
+ * container, as a single undoable batch. Selected marks, children or not, are
113
113
  * ignored. The freed children become the new selection, and nothing moves on
114
114
  * screen.
115
115
  */
@@ -139,7 +139,7 @@ var ungroupAction = {
139
139
  if (!selection || !scene) return;
140
140
  const ids = selection.get();
141
141
  if (ids.length === 0) return;
142
- const containers = ids.filter((id) => scene.get(id)?.kind === "container");
142
+ const containers = ids.filter((id) => scene.get(id)?.kind === "group");
143
143
  if (containers.length === 0) return;
144
144
  const frame = scenePoseFrame(scene);
145
145
  const absolutePoses = frame.pc.closure === "identity";
@@ -147,7 +147,7 @@ var ungroupAction = {
147
147
  const freed = [];
148
148
  for (const containerId of containers) {
149
149
  const container = scene.get(containerId);
150
- if (!container || container.kind !== "container") continue;
150
+ if (!container || container.kind !== "group") continue;
151
151
  const parent = container.parent ?? null;
152
152
  const baseIndex = parent === null ? scene.roots.indexOf(containerId) : scene.childrenOf(parent).indexOf(containerId);
153
153
  const children = [...scene.childrenOf(containerId)];
@@ -167,7 +167,7 @@ var ungroupAction = {
167
167
  enabled: (deps) => {
168
168
  const selection = deps?.selection;
169
169
  const scene = deps?.scene;
170
- return selection?.get().some((id) => scene?.get(id)?.kind === "container") ? true : ActionDisabledReason.NotApplicable;
170
+ return selection?.get().some((id) => scene?.get(id)?.kind === "group") ? true : ActionDisabledReason.NotApplicable;
171
171
  }
172
172
  };
173
173